@@ -21,7 +21,11 @@ export class LayerStateHandler {
2121 constructor (
2222 private resolvedTimeline : ResolvedTimelineHandler ,
2323 private instance : InstanceHandler ,
24- private layer : string
24+ private layer : string ,
25+ /**
26+ * Maps an array of object ids to an object id (objects that directly reference an reference).
27+ */
28+ private directReferenceMap : Map < string , string [ ] >
2529 ) {
2630 this . objectsOnLayer = [ ]
2731 this . objectIdsOnLayer = this . resolvedTimeline . getLayerObjects ( layer )
@@ -117,7 +121,7 @@ export class LayerStateHandler {
117121
118122 /** List of the instances to check at this point in time. */
119123 const instancesToCheck : InstanceAtPointInTime [ ] = this . pointsInTime [ time ]
120- instancesToCheck . sort ( compareInstancesToCheck )
124+ instancesToCheck . sort ( this . compareInstancesToCheck )
121125
122126 for ( let j = 0 ; j < instancesToCheck . length ; j ++ ) {
123127 const o = instancesToCheck [ j ]
@@ -268,6 +272,45 @@ export class LayerStateHandler {
268272 if ( ! this . pointsInTime [ time + '' ] ) this . pointsInTime [ time + '' ] = [ ]
269273 this . pointsInTime [ time + '' ] . push ( { obj, instance, instanceEvent } )
270274 }
275+ private compareInstancesToCheck = ( a : InstanceAtPointInTime , b : InstanceAtPointInTime ) => {
276+ // Note: we assume that there are no keyframes here. (if there where, they would be sorted first)
277+
278+ if (
279+ a . instance . id === b . instance . id &&
280+ a . instance . start === b . instance . start &&
281+ a . instance . end === b . instance . end
282+ ) {
283+ // A & B are the same instance, it is a zero-length instance!
284+ // In this case, put the start before the end:
285+ if ( a . instanceEvent === 'start' && b . instanceEvent === 'end' ) return - 1
286+ if ( a . instanceEvent === 'end' && b . instanceEvent === 'start' ) return 1
287+ }
288+
289+ // Handle ending instances first:
290+ if ( a . instanceEvent === 'start' && b . instanceEvent === 'end' ) return 1
291+ if ( a . instanceEvent === 'end' && b . instanceEvent === 'start' ) return - 1
292+
293+ if ( a . instance . start === a . instance . end || b . instance . start === b . instance . end ) {
294+ // Put later-ending instances last (in the case of zero-length vs non-zero-length instance):
295+ const difference = ( a . instance . end ?? Infinity ) - ( b . instance . end ?? Infinity )
296+ if ( difference ) return difference
297+ }
298+
299+ // If A references B, A should be handled after B, (B might resolve into a zero-length instance)
300+ const aRefObjIds = this . directReferenceMap . get ( a . obj . id )
301+ if ( aRefObjIds ?. includes ( b . obj . id ) ) return - 1
302+ const bRefObjIds = this . directReferenceMap . get ( b . obj . id )
303+ if ( bRefObjIds ?. includes ( a . obj . id ) ) return 1
304+
305+ if ( a . obj . resolved && b . obj . resolved ) {
306+ // Deeper objects (children in groups) comes later, we want to check the parent groups first:
307+ const difference = a . obj . resolved . levelDeep - b . obj . resolved . levelDeep
308+ if ( difference ) return difference
309+ }
310+
311+ // Last resort, sort by id to make it deterministic:
312+ return compareStrings ( a . obj . id , b . obj . id ) || compareStrings ( a . instance . id , b . instance . id )
313+ }
271314}
272315export interface TimeEvent {
273316 time : number
@@ -292,36 +335,6 @@ function compareObjectsOnLayer(a: ResolvedTimelineObject, b: ResolvedTimelineObj
292335 return a . resolved . levelDeep - b . resolved . levelDeep || compareStrings ( a . id , b . id )
293336}
294337
295- function compareInstancesToCheck ( a : InstanceAtPointInTime , b : InstanceAtPointInTime ) {
296- // Note: we assume that there are no keyframes here. (if there where, they would be sorted first)
297-
298- if ( a . instance . id === b . instance . id && a . instance . start === b . instance . start && a . instance . end === b . instance . end ) {
299- // A & B are the same instance, it is a zero-length instance!
300- // In this case, put the start before the end:
301- if ( a . instanceEvent === 'start' && b . instanceEvent === 'end' ) return - 1
302- if ( a . instanceEvent === 'end' && b . instanceEvent === 'start' ) return 1
303- }
304-
305- // Handle ending instances first:
306- if ( a . instanceEvent === 'start' && b . instanceEvent === 'end' ) return 1
307- if ( a . instanceEvent === 'end' && b . instanceEvent === 'start' ) return - 1
308-
309- if ( a . instance . start === a . instance . end || b . instance . start === b . instance . end ) {
310- // Put later-ending instances last (in the case of zero-length vs non-zero-length instance):
311- const difference = ( a . instance . end ?? Infinity ) - ( b . instance . end ?? Infinity )
312- if ( difference ) return difference
313- }
314-
315- if ( a . obj . resolved && b . obj . resolved ) {
316- // Deeper objects (children in groups) comes later, we want to check the parent groups first:
317- const difference = a . obj . resolved . levelDeep - b . obj . resolved . levelDeep
318- if ( difference ) return difference
319- }
320-
321- // Last resort, sort by id to make it deterministic:
322- return compareStrings ( a . obj . id , b . obj . id ) || compareStrings ( a . instance . id , b . instance . id )
323- }
324-
325338const removeFromAspiringInstances = ( aspiringInstances : AspiringInstance [ ] , objId : string ) : AspiringInstance [ ] => {
326339 const returnInstances : AspiringInstance [ ] = [ ]
327340 for ( let i = 0 ; i < aspiringInstances . length ; i ++ ) {
0 commit comments