Giter Site home page Giter Site logo

alexharri / animation-editor Goto Github PK

View Code? Open in Web Editor NEW
66.0 66.0 14.0 13.29 MB

Web-based animation editor and runtime written in React, Redux, PIXI.js and HTML Canvas.

License: MIT License

TypeScript 87.33% JavaScript 10.86% HTML 0.03% CSS 1.79%

animation-editor's People

Contributors

alexharri avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

animation-editor's Issues

Open Property Shortcuts

In After Effects, you can press certain keys to open certain properties on selected layers.

  • A - Anchor Point
  • P - Position
  • S - Scale
  • R - Rotation
  • T - Opacity

By holding Shift, properties can be toggled in and out of view.

Similar behavior would benefit this project.

Delete Keyframes

Currently it's not possible to delete existing keyframes. The only way to remove keyframes right now is to merge them (drag one over the other).

The user should be able to delete selected keyframes via a keyboard shortcut (e.g. Delete, Backspace) and by right clicking the graph/track editor.

If a timeline has no keyframes left after deleting keyframes, the timeline should be deleted and then layer should be set to static.

Layer Parenting & Anchor Points

When layer transform have been implemented (see #9) this feature can be worked on.

A layer should be able to specify a "parent layer". When specified, the child layer should follow the transform of the parent layer according to the transforms of both layers when the parent layer was specified.

Chains of parenting should be supported. E.g.

  • Layer A has no parent
  • Layer B has A as parent
  • Layer C has B as parent

This would mean that A's transform is applied to itself and B. B's transform is then applied to itself and C. And C's transform is applied only to itself. The order in which these are applied matter.

Move Timeline Keyframe Control Points Together

The user should be able to move the control points of keyframes together.

If the user is dragging the controlPointRight of a keyframe, the controlPointRight of all selected keyframes should move according to the same move vector. The same goes for controlPointLeft.

The opposite control points should follow reflectControlPoints. This is determined on an individual keyframe basis rather than "all the keyframes being moved" basis. If the user toggles the reflectControlPoints via option move, each individual keyframe should be toggled.

Array Modifier (& other modifiers)

AE has effects for layers, Blender has modifiers for objects.

As discussed in #9, AE's effects tend to operate on pixels rather than vector objects. Since I don't expect us to support a canvas-based renderer (see #9) effects that operate on pixels will probably not be supported.

But Blender's modifier system operates on geometry rather than pixels.

Array Modifier

Modifiers like Blender's array modifier could prove to be very useful in an SVG-like renderer.

For example, it would be really useful when creating patterns to be able to add an array modifier to create a repeating pattern.

Every layer in the comp would have an index of 0 by default, but for copies created by an array modifier the index would increase by 1 for each subsequent copy.

This index could be used to modify the layer via the Node Editor. I imagine a layer_index node that can reference an array modifier and get the current index. This could be used change the position by adding a Vec2 that has been multiplied by an index.

image

In the above example, the layer would be repeated N times, and each copy would be moved 100 on the X axis.

We could also apply two array modifiers to create a two dimensional grid of items.

image

You see where this is going. We could rotate, scale, and transform the layer in different ways to create repeating patterns.

Other modifiers?

The array modifier is the most obviously useful example, but are there other modifiers that we can apply to this project?

I'm not sure yet.

There are some that seem promising (e.g. the curve modifier), but for a lot of them it's not immediately obvious how they could be translated from Blender to this project. It is also a question of whether the functionality introduced by a modifier should be in the form of a modifier in the first place.

The array modifier feels like it should be a modifier, but should the curve modifier be? The curve modifier feels like it should rather be a curve layer in our case, since multiple layers should be able to reference a single curve.

I'm 100% determined to add the array modifier in some form, but I have mixed opinions on other modifier.

What do we call effects/modifiers/custom properties

In #9 I call them custom properties, since it's in the context of nested properties.

I don't like the name "custom properties" since it doesn't describe anything.

I definitely don't like using the name "effect", since it is heavily associated with AE and it's specific effects. And since we are not supporting AE's effects, the name may feel confusing.

I like the name "modifiers" since modifiers modify the layer that they live on. But if we add "Expression Control"-like modifiers, then they are not directly modifying the layer so the name becomes technically incorrect. I don't think this is a big issue though, especially since we may add "Expression Control"-like layers whose only purpose is to have animated controls.

So for now, we will call this concept "modifiers".

Angle breaks if there is not enough space on the timeline's X axis for reflection

New control points were dragged as the blue arrow illustrates.

image

There is not enough space on the X axis (t would exceed 1) to reflect the amplitude of the left keyframe to the right. We should consider how much t is capped and adjust the value according to the that.

This is also a problem when angle-only reflecting keyframes after they have been created.

Rect Select in Timeline

You currently have to individually shift select different keyframes if you want to move them together. Being able to drag a rect around a group of keyframes would be really helpful.

The user should be able to rect select keyframes of different timelines together.

Composition Center Node

Since the composition dimensions are dynamic, I can imagine a lot of cases where a node that just outputs the current center of the composition is useful.

For example, setting the anchor point of something as the center of the comp (maybe +/- some amount) would probably be a very common operation.

Maybe we should add Offset X and Offset Y inputs to the node?

Delete Shape Stroke

Strokes within Shapes should be deletable.

This should be doable via:

  • Right click on Stroke property -> Remove Stroke
  • Select Stroke property -> Delete/Backspace keydown

Index Transform Anchors & Origins

Currently, it's not very obvious how anchoring and origins behave for index transforms.

I imagine two separate but related properties.

  • Transform Origin
  • Anchor

The anchor should work the same as it currently does for normal layers. It offsets the rendering.

The origin should be the point around which index transformations are applied. Currently index transforms' origins are the translate of the previous index transform.

There should be two ways to define the origin.

  • Relative to the previous index transform origin.
  • Absolute point, like the position of a null layer.

Delete Shapes

Shapes within Shape layers should be deletable.

This should be doable via:

  • Right click on Shape property -> Remove Shape
  • Select Shape property -> Delete/Backspace keydown

Create and Delete Layer Graphs

We currently have a small "graph icon" for each layer.

image

When click, this icon should toggle the existence of the graph.

  1. If the graph exists, delete it.
  2. If no graph exists, create on which references the layer via layerId.

Multiple Layer Transforms

In AE, layer transforms are applied in a specific order (translate then scale and rotate). You can get around this with parenting (e.g. parenting to a null layer that controls rotation from an anchor point).

Replicating this behavior may be sufficient, but another option to consider is allowing users to specify multiple transforms of any type in any order.

I don't think we will pursue this option, but it's something to consider.

Invalid Expression Nodes

A few things can be wrong with expression nodes:

  • Some of its inputs do not have pointers (i.e. some variables are missing)
  • Expression cannot be evaluated (syntax error)
  • Type mismatch (either in inputs or ouputs)

When any of these occur, they either fail silently or freeze up the app (until Esc is pressed).

This issue can be closed when invalid expression nodes are communicated to the user in some way and do not cause errors.

Unexpected behaviour on Boot

Hey. I was trying to setup the editor on my local and when it starts, the logs say, compiled successfully but its not displaying the editor properly.

Screen Shot 2021-12-19 at 9 15 15 PM

any help would be appreciated. Thanks

Clip Composition Content

Originally a section in #29.

And one that I feel may be interesting is a "Clip content" boolean. This will be useful for showing elements positioned based on the composition width/height that can overflow.

image

In this example, the white rectangle fills the width and height of the composition. The blue rectangle exceeds the width of the composition (e.g. the X position is -20 and the width is the composition width + 40). The green circle's X and Y positions would be the width and height of the composition respectively.

Shift move Keyframes

Holding Shift should lock the moveVector to the larger of the x and y axes.

If x > y, then y = 0 and reverse.

Circular Layer Graph Dependencies

There are two types of potential circular dependencies.

1. Cross-layer circular dependency

  • Layer A's property PA references property PB from Layer B
  • Layer B's property PB references property PA from Layer A

2. Same-layer circular dependency

  • Property A references property B
  • Property B references property A

Solution

There are valid reasons for two different layers to both reference properties of the other. This use case should work as expected. It also makes perfect sense for a layer's property to reference another of that layer's properties.

However, for layer A's transform to reference a computed value from layer B's transform and for B to do the same for A where both layers only have a single property_output node we will have to compute one first. We will have to figure out a smart way to go about this, at least if we want to avoid recomputing the same things multiple times.

We will need to topologically sort these cross-layer dependencies somehow so that the computed value is what we want it to be when we read its value.

Circular dependencies will also have to be detected and communicated to the user. They shouldn't stop us from rendering (we can use the raw value), but they should be resolved by the user (maybe a third null layer)?

Or maybe we want to disallow cross-layer dependencies? Cross-layer dependencies can always be solved by null layers, but that solution is less convenient and perhaps not as intuitive.

We can probably start by disallowing circular cross-layer dependencies whilst allowing circular same-layer dependencies. If we detect a circular same-layer dependency we can decide to use the raw value for both and warn the user that this is what is happening.

Composition Layer Dimensions in Node Editor

The composition node exposes the composition dimensions (width, height).

image

Within composition layers, the width and height properties of the dimension property group should be applied instead of the composition's width (which is just a default/preview width).

Separate X and Y Scale

Transforms currently separate the X and Y position, but the Scale is just one property.

There should be an X and Y scale.

N Paths per Shape

Each shape should be able to have any amount of paths (0 included).

Paths should be draggable between shapes (similar to layer reordering). They should even be draggable between different shape layers (should probably adjust to transform(?)).

Paths should also be deletable via:

  • Right click on Path property -> Remove Path
  • Select Path property -> Delete/Backspace keydown

Recover from Exceptions

Currently if we encounter an uncaught exception, the app "crashes".

Instead, we should attempt to recover gracefully.

  1. If we are in the middle of an action, attempt to cancel that action.
  2. If we just completed an action, undo that action.

If neither of those works, the app should enter an "irrecoverable error" state.

Dynamic Composition Length

I would like to support dynamic-length compositions. For example if we have a composition where something animates in, then transitions into an idle-ish state.

This is similar to the loop feature in AE's expressions. For example, you can play keyframes in the composition, then choose to pingpong between the 4 last keyframes of the animation until the end of the composition.

It would be lovely if compositions had no specific length and could be played indefinitely with a variety of loop-like behaviors. And via the node editor we could transform the animations via real-time input from the user.

Not entirely sure how we should choose to display non-fixed length compositions in the timeline editor. The view bounds kinda stop meaning anything when we remove the composition length. We could choose to give compositions a "reference length" that the view bounds abide by, but we would allow users to pan and zoom past them.

Create New Layers

Users should be able to right click on the empty space in the CompositionTimeline and create a new layer.

For this change, the only layer type supported should be rects. Other layer types are a separate issue.

Clipboard

Currently we don't support copy pasting in any way.

Clipboard Implementation

I don't believe we can (or should) make use of the native clipboard for copy-pasting layers, properties, keyframes etc. We also don't want the copied data types (e.g. when copying a layer) to be pasted as JSON or some other format in other programs/inputs.

Creating a "virtual clipboard" in memory where we store copied objects gives us much more control and flexibility over how copy paste behaves. And more interestingly, it allows us to have multiple objects in the clipboard at the same time (e.g. some text, a layer, nodes).

Clipboard Behavior

I imagine us separating the clipboard into a few slots.

  • Text (native clipboard)
  • Composition (includes workspace AND timeline)
  • Node Editor
  • Project

The text clipboard (native clipboard) should not be handled specifically by us. Our custom copy paste handler should only fire if an input/textarea does not currently have focus. This allows us to copy and paste between programs.

More can be added in the future, but I see these as the current logical separation since none of these share much overlap in data types.

"Other" Layer Properties

Currently each layer just has a flat list of properties. This is fine while layers have a fixed number of properties, but when we add support for non-transform and custom properties this should be changed.

Categories

Properties should probably be separated into three categories.

1. Transform

Every single layer has transform properties. Those are:

  • Position
  • Rotation
  • Scale
  • Anchor point
  • Opacity

The transform is really performant to animate.

2. Native Layer properties

There is a better name than "native" out there, I just can't think of it right now. These are properties specific to a layer type.

For example a rect layer might have width and height properties while a circle layer might have a radius property.

These are properties that can not be removed, but are not present on every layer.

3. Other properties

These are non-layer specific properties that can be added to or removed from any layer.

In AE, these are called "Effects". They may operate on the layer (e.g. modify it visually) or exist as reference (e.g. Expression Controls).

I don't believe that we will significant support "effect like" properties because effects in AE operate on pixels rather than vector objects.

There are some that may be useful (color transforms, blurs, masks) but most effects (distort, generate, roughen edges, etc) are either way to computationally expensive to run in realtime or just don't work as well with vector objects.

I am not 100% certain that we will never support effects that operate on pixels though. If we end up with WebGL rendering support, then vector shapes can be converted to pixels and then operated on on the fly.

The reason I think that we will not go for WebGL rendering is because I expect us to support injecting arbitrary DOM nodes in our animation. This is just a rough idea in my head at the moment, but being able to render components within so-called "slices" of our animation may prove useful. This would only be possible via an SVG-like renderer.

The only custom properties I see us adding in the near future are "Expression Control" like properties that the Node Editor can hook into, but there is a big discussion to be had about other effects/modifiers that operate on the layer they are added to. That discussion will take place in another issue.

There is also the question of whether we want first-level support for "Control Layers", which exists purely for other layers to reference. This is similar to nulls in AE and empties in Blender.

For this reason, I don't think we should support custom properties to being with. Only transforms and native properties should be supported until we decide on a route for custom properties.

Node Editor

In the node editor, the layer_input and layer_output nodes should be updated to reflect the new categories.

I expect us to have the following Layer IO nodes:

  • layer_transform_input and layer_transform_output
  • layer_property_input and layer_property_output (native layer properties)
  • layer_{name for custom properties}_input and layer_{name for custom properties}_output

Reorder Layers

The user should be able to reorder layers by dragging them around.

Read Property Errors in Sub-Compositions

The errors of sub-compositions (composition layers) are currently not read and thus not displayed. Only errors in the top-level composition are read and displayed.

Add more Layer properties

Most layers should contain the following properties.

  • Fill
  • Stroke
  • Stroke Width
  • Opacity
  • Rotation
  • Anchor Point

I believe all of these apply to layers of type rect, oval, polygon, shape and text.

Nested Compositions

A composition should be able to include a composition via a "composition layer".

Circular references

Compositions may not include circular composition layer references. E.g. if comp A includes comp B as a composition layer, comp B cannot include comp A. Same goes for A -> B -> C -> A.

Properties

The obvious properties that a composition layer should have, aside from transforms are:

  • Width
  • Height

And one that I feel may be interesting is a "Clip content" boolean. This will be useful for showing elements positioned based on the composition width/height that can overflow.

image

In this example, the white rectangle fills the width and height of the composition. The blue rectangle exceeds the width of the composition (e.g. the X position is -20 and the width is the composition width + 40). The green circle's X and Y positions would be the width and height of the composition respectively.

Nodes

A new node that exposes the composition dimensions should be introduced. I imagine a node called Composition Dimensions that has two outputs, width and height.

Array Modifier Offset

The user should be able to set the offset of an array modifier, which acts as a start index.

Given that count is 5, an offset of 5 would result in rendering the elements at indices:

5, 6, 7, 8, 9

An offset of -2 would result in rendering the elements at indices:

-2, -1, 0, 1, 2

Offset should be a property next to count.

Delete Shape Fill

Fills within Shapes should be deletable.

This should be doable via:

  • Right click on Fill property -> Remove Fill
  • Select Fill property -> Delete/Backspace keydown

Select Layer for `property_input` nodes

Graphs have a layerId which dictates the layer that the property_input nodes can work with. However, this node should allow any layer in the composition of the graph's layer to be selectable.

This selection should be done via the node's state (similar to propertyId). When changed, existing pointers should be maintained if possible (e.g. if both layers have the property referenced by propertyId).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.