Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Findings re: cloning #160

Open
Aierie opened this issue Nov 30, 2022 · 0 comments
Open

Findings re: cloning #160

Aierie opened this issue Nov 30, 2022 · 0 comments

Comments

@Aierie
Copy link
Contributor

Aierie commented Nov 30, 2022

Problems

  1. Cloning has side effects on visibility of sprites to contexts. But visibility of sprites to contexts also has an effect on cloning. This makes it hard to determine upfront what is cloned for the whole UI, so we have to adjust visibility of sprites to contexts as we go through the list of contexts from top to bottom.
  2. "Lowest stable context" rules limit visibility of descendant sprites that are within a descendant context. Right now, this means that cloning a sprite does not provide the animator with control of the sprite's descendants, if they are contained within another stable context. It's possible to fix this, but within the use argument, users may have to account for side effects from cloning (or lack of expected side effects because cloning did not happen) as they execute imperative conditionals. Another way is to execute sprite matching first, before executing animations only with matched sprites.
  3. Clones should not have interactivity. A long-lived clone that stays on top of its original will cause an unresponsive (area of the) app. The situation where this happens is having a short clone animation while also running a separate long animation in the same animator. This might mean that clone cleanup needs to happen on a per-sprite basis, as soon as the sprite's animation ends.
  4. Side effects of animations on their parents might be difficult to propagate to clones. (This seems like something the user would have to handle themselves - if you want something to move when its parent does, don't clone it, or add an animation that moves it at the same time)

Decision to be made re: effect of cloning on descendant contexts

  1. Disable cloned contexts so they cannot animate their contents.
  2. Allow cloned contexts to animate if stable, within their clones (and their clones' orphan/clone elements). <-- no guarantee that the clone element will stay visible long enough, or stay in the same position.

One way to implement cloning

  1. make each sprite and animator have the DOMRefNode for the element that it represents (right now we pass elements to sprites, and contexts to animators, we could also pass the DOMRefNode in).
  2. create a way to clone a subtree of DOMRefNodes. make each original DOMRefNode aware of its clones, and able to identify the most shallow clone (clone that is closest to the root of the cloned subtree it is a part of).
  3. when a sprite is cloned, clone the subtree under and including its DOMRefNode. append it to the animator's DOMRefNode (cloning will only happen when an animator tries to animate things, so there should always be an animator).
  4. when an animator is cloned, it should not be able to animate things. this condition can be derived from its DOMRefNode having clones.
  5. when a sprite is animated, use its DOMRefNode to find out what elements should be hidden and what should be animated (since DOMRefNodes keep track of their clones).
  6. clones should hang around long enough to affect visibility of sprites to animators, so we will need to add a separate cleanup step to remove all clones after the creation of sprites and animators, but before the adding on of animations. note that right now, DOM cleanup is separate from the concept of DOMRefNode cleanup, which does make things easier to think about - we remove all clones attached to the DOM each time we animate, and reattach them if they need to continue being animated.
Draft notes
effects of a clone:
- when a sprite says that it wants to be cloned, what should happen?
  - where does it want to be cloned to?
    - it needs to know the DOMRef that the root of the clone is going to be attached to
  - who handles this cloning? it has to be something that can see and own the DOMRef tree
    - AnimationParticipantManager
    - Animations service
  - how do we represent clones in the DOMRef tree?
    - still a DOMRefNode
    - add a cloneOf property to say what DOMRefNode it is a clone of
    - make adding children a method of a DOMRefNode
    - make adding children throw if the parent is a clone
    - make the original for a clone keep track of its clones <-- this needs to be cleared in a post-distribution cleanup
  - how does the cloning of the DOMRefNode work?
    - DOMRefNode elements are cloned separately and parts of the new element reassigned to new DOMRefNodes
      - create a map that allows lookup of each DOMRefNode in old tree by its element
      - create a map that allows lookup of each DOMRefNode in old tree by serialized path from root
      - deep clone the DOMRefNode, while recording the relationship of each DOMRefNode to its clone in a Map. We will also need to set the cloneDepth, set cloneOf, and record the clones in the original DOMRefNode here. <-- these 3 points can be done in one traversal that SKIPS CLONES
      - traverse the element of the root of clone target, record path to each descendant DOMRefNode in a serializable way (eg.map of stringified index chains, "0-1-1-1": DOMRefNode, root is "0": DOMRefNode)
      - deep clone the root element
        - possibly have to perform some style recording/capture too, because of the cascade
      - traverse the cloned element, and when we hit the right path, assign the element to the cloned node
      - the end result is DOMRefNodes that are assigned to the same participant, have the original in their the `cloneOf` value,
        and point to the cloned element in the element field, while the hierarchy is preserved
      - append the clone to the DOMRefNode of the context that wants to clone it
  - we've updated the DOMRefNode tree, now what?
    - in the subtree that was cloned (original), update each Sprite with a clone to have an animatorList = subset of [...ancestors from top till Animator that cloned]; change defaultAnimator to a getter for the last animator in this list.
      - subset, because multiple animators can ask to clone, we need to take the highest one that cloned as the controller
    - update the clone root Sprite to have its parent state be from the Animator that asked to clone it. The rest can remain the same
    - in the subtree that was cloned (original), update each Animator to not be able to clone or animate
      - if an Animator has a reference to its DOMRefs, we should be able to tell whether it can animate, but since Animators are only per-render, we can also put the state there
      - the act of cloning or appending a detached counterpart for an Animator may also want to do this
    - update each AnimationParticipant involved in the cloning to be aware of the cloned DOMRefNode. Store a cloned subtree depth variable together with a reference to the clone. This will inform what DOMRefNode should be animated as a sprite (smallest cloned subtree depth), and what should get hidden (everything else).
  - sprites need to grab their element from the DOMRefNodes they were created to animate. we shouldn't need to care about this element until the very last minute when we apply keyframes to the elements.
  - sprites should automatically hide all clones that are not animated. For now the hiding can go on indefinitely
- how important is immediate cleanup for clones? (probably important)
- is it possible to do immediate cleanup?
- where is it critical to do immediate cleanup?
  - if the context has an animation that can last really long?
- where is it impossible to do immediate cleanup?

Macro? changes

  1. Cloning has to happen before we run use as it is now, because otherwise the Changeset will not have the sprites it expects to have - this means you can clone things, but if there's another context in between you will not be able to see the sprites inside.
  2. DOMRefNode keeps track of its clones. Clones keep track of the depth of the subtree that was cloned from root to the node. The clone depth helps us know which clone to use.
  3. DOMRefNode keeps track of animations. AnimationParticipant will look to DOMRefNode for the animation. Unsure whether the DOMRefNode will keep track of its measurements...?
  4. Sprite receives the original DOMRefNode.
  5. Sprite asks the DOMRefNode for the element to animate, DOMRefNode gives it the one with the smallest clone depth
  6. When the animation starts, a callback created by the Sprite will inform the DOMRefNode of it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant