motiondeveloper / create-expression-lib

🐱‍👤 CLI to create an After Effects expression library in TypeScript
MIT License
35 stars 0 forks source link

Cannot define `thisLayer` in multiple files #1

Open kenashcraft opened 3 years ago

kenashcraft commented 3 years ago

I'm just getting started with this setup, and it looks amazing! Unfortunately, I quickly ran into a problem when trying to decompose my code into multiple files. I created a new repo using create-expression-lib and left everything as it was. Then I added a new file in src/ for my function. Here is a simplified example: layer.ts

import { Layer } from 'expression-globals-typescript';
const thisLayer = new Layer();

function colorDepth(): number {
  return thisLayer.colorDepth;
}
export { colorDepth };

I modified index.ts to import this:

// Importing object bases (CompBase, LayerBase, PropertyBase)
// TypeScript types (Layer, Comp, Value, Color etc)
// and global functions from 'expression-globals-typescript'
import { Comp, Layer } from 'expression-globals-typescript';
import { fromOtherFile } from './otherFile';
import { colorDepth } from './layer';  // <<<<<< this is new

// Creating a new composition object from CompBase
const thisComp = new Comp();
const thisLayer = new Layer();

// Using the expression types in a function
function getLayerDuration(layerName: string) {
  const layer: Layer = thisComp.layer(layerName);
  return layer.outPoint - layer.inPoint;
}

// Using expressions global functions
function remap(value: number) {
  return thisLayer.linear(value, 0, 10, 0, 1);
}

function welcome(name: string): string {
  return `Welcome ${name}!`;
}

const someValue: number = 25;

const version: string = '_npmVersion';

// Export values to appear in jsx files
export {
  getLayerDuration,
  remap,
  welcome,
  someValue,
  version,
  fromOtherFile,
  colorDepth, // <<< this is new
};

The generated code includes thisLayer$1 and After Effects obviously chokes on that.

{
    fromOtherFile: 'value in another file',
    colorDepth() {
        return thisLayer$1.colorDepth;
    },

    // Importing object bases (CompBase, LayerBase, PropertyBase)
    // Creating a new composition object from CompBase
    // Using the expression types in a function
    getLayerDuration(layerName) {
        const layer = thisComp.layer(layerName);
        return layer.outPoint - layer.inPoint;
    },
    // Using expressions global functions
    remap(value) {
        return thisLayer.linear(value, 0, 10, 0, 1);
    },
    welcome(name) {
        return `Welcome ${name}!`;
    },
    someValue: 25,
    version: '1.0.1',
}

If I import another file that defines thisLayer, the generated code will end up with thisLayer, thisLayer$1, and thisLayer$2.

The workaround is to keep all of my code in index.ts.

fartinmartin commented 2 years ago

Hey @kenashcraft I noticed this too! I found that if you create a globals.ts file to export single instance of thisLayer, you can use it in any number of additional files:

// globals.ts
import { Layer } from 'expression-globals-typescript';

const thisLayer = new Layer();

export { thisLayer };
// layer.ts
import { thisLayer } from './globals';

function colorDepth(): number {
  return thisLayer.colorDepth;
}

export { colorDepth };
// index.ts
import { thisLayer } from './globals';
import { colorDepth } from './layer';

function layerName(): string {
  return thisLayer.name;
}

export { layerName, colorDepth };

Output:

// ./dist/script.jsx
{
    colorDepth() {
        return thisLayer.colorDepth;
    },

    layerName() {
        return thisLayer.name;
    },
}

Update: as I was chuggin' along the $1 suffix started up again for some reason, but extending the @rollup/plugin-replace options in the rollup.config.js file seemed to do the trick (there's probably a smarter fix):

// rollup.config.js
plugins: [
    replace({
      preventAssignment: true,
      values: {
        _npmVersion: pkg.version,
        thisComp$1: 'thisComp',
        thisLayer$1: 'thisLayer',
      },
    }),
    // ... 
]
lcolok commented 2 years ago

Hey @kenashcraft I noticed this too! I found that if you create a globals.ts file to export single instance of thisLayer, you can use it in any number of additional files:

// globals.ts
import { Layer } from 'expression-globals-typescript';

const thisLayer = new Layer();

export { thisLayer };
// layer.ts
import { thisLayer } from './globals';

function colorDepth(): number {
  return thisLayer.colorDepth;
}

export { colorDepth };
// index.ts
import { thisLayer } from './globals';
import { colorDepth } from './layer';

function layerName(): string {
  return thisLayer.name;
}

export { layerName, colorDepth };

Output:

// ./dist/script.jsx
{
    colorDepth() {
        return thisLayer.colorDepth;
    },

    layerName() {
        return thisLayer.name;
    },
}

Update: as I was chuggin' along the $1 suffix started up again for some reason, but extending the @rollup/plugin-replace options in the rollup.config.js file seemed to do the trick (there's probably a smarter fix):

// rollup.config.js
plugins: [
    replace({
      preventAssignment: true,
      values: {
        _npmVersion: pkg.version,
        thisComp$1: 'thisComp',
        thisLayer$1: 'thisLayer',
      },
    }),
    // ... 
]

It's work! But still cannot import below code from globals.ts

  const ease = thisLayer.ease;
  const easeIn = thisLayer.easeIn;
  const easeOut = thisLayer.easeOut;
  const timeToFrames = thisLayer.timeToFrames;
  const time = thisLayer.time;