superfly-timeline
Advanced tools
Comparing version 7.2.1 to 7.2.2
@@ -5,2 +5,12 @@ # Changelog | ||
### [7.2.2](https://github.com/SuperFlyTV/supertimeline/compare/7.2.1...7.2.2) (2019-08-09) | ||
### Bug Fixes | ||
* Handle keyframes that begin or end outside of their parents ([1eb1f50](https://github.com/SuperFlyTV/supertimeline/commit/1eb1f50)) | ||
* lookupExpression should return [], not null, when a reference yields zero results ([0d6586d](https://github.com/SuperFlyTV/supertimeline/commit/0d6586d)) | ||
* make child in group-behaviour constistent... ([95af8c3](https://github.com/SuperFlyTV/supertimeline/commit/95af8c3)) | ||
* while: 1 and while: '1' should return same result ([7ca9452](https://github.com/SuperFlyTV/supertimeline/commit/7ca9452)) | ||
### [7.2.1](https://github.com/SuperFlyTV/supertimeline/compare/7.2.0...7.2.1) (2019-07-30) | ||
@@ -7,0 +17,0 @@ |
@@ -51,2 +51,7 @@ import { InstanceEvent, TimelineObjectInstance, ResolveOptions, ValueWithReference, Cap } from './api/api'; | ||
export declare function applyRepeatingInstances(instances: TimelineObjectInstance[], repeatTime0: ValueWithReference | null, options: ResolveOptions): TimelineObjectInstance[]; | ||
/** | ||
* Cap instances so that they are within their parentInstances | ||
* @param instances | ||
* @param parentInstances | ||
*/ | ||
export declare function capInstances(instances: TimelineObjectInstance[], parentInstances: ValueWithReference | TimelineObjectInstance[] | null): TimelineObjectInstance[]; | ||
@@ -53,0 +58,0 @@ export declare function isReference(ref: any): ref is ValueWithReference; |
@@ -361,2 +361,7 @@ "use strict"; | ||
exports.applyRepeatingInstances = applyRepeatingInstances; | ||
/** | ||
* Cap instances so that they are within their parentInstances | ||
* @param instances | ||
* @param parentInstances | ||
*/ | ||
function capInstances(instances, parentInstances) { | ||
@@ -363,0 +368,0 @@ if (isReference(parentInstances) || |
@@ -24,3 +24,15 @@ import { TimelineObject, ResolvedTimeline, ResolveOptions, Expression, ResolvedTimelineObject, TimelineObjectInstance, Time, TimelineState, ValueWithReference, ResolvedStates } from '../api/api'; | ||
declare type ObjectRefType = 'start' | 'end' | 'duration'; | ||
/** | ||
* Look up a reference on the timeline | ||
* Return values: | ||
* Array<TimelineObjectInstance>: Instances on the timeline where the reference expression is true | ||
* ValueWithReference: A singular value which can be combined arithmetically with Instances | ||
* null: Means "something is invalid", an null-value will always return null when combined with other values | ||
* | ||
* @param resolvedTimeline | ||
* @param obj | ||
* @param expr | ||
* @param context | ||
*/ | ||
export declare function lookupExpression(resolvedTimeline: ResolvedTimeline, obj: TimelineObject, expr: Expression | null, context: ObjectRefType): Array<TimelineObjectInstance> | ValueWithReference | null; | ||
export {}; |
@@ -118,6 +118,6 @@ "use strict"; | ||
''); | ||
if (obj.enable.while === '1') { | ||
if (obj.enable.while + '' === '1') { | ||
start = 'true'; | ||
} | ||
else if (obj.enable.while === '0') { | ||
else if (obj.enable.while + '' === '0') { | ||
start = 'false'; | ||
@@ -131,3 +131,3 @@ } | ||
hasParent = true; | ||
parentInstances = lookupExpression(resolvedTimeline, obj, expression_1.interpretExpression("#" + obj.resolved.parentId), 'start'); | ||
parentInstances = lookupExpression(resolvedTimeline, obj, expression_1.interpretExpression("#" + obj.resolved.parentId), 'start'); // a start-reference will always return an array, or null | ||
if (lib_1.isConstant(startExpr)) { | ||
@@ -253,11 +253,10 @@ // Only use parent if the expression resolves to a number (ie doesn't contain any references) | ||
_.each(instances, function (instance) { | ||
if (_.isArray(parentInstances)) { | ||
if (parentInstances) { | ||
var parentInstance = _.find(parentInstances, function (parentInstance) { | ||
return instance.references.indexOf(parentInstance.id) !== -1; | ||
}); | ||
var cappedInstance = (parentInstance ? | ||
lib_1.capInstances([instance], [parentInstance])[0] : | ||
instance); | ||
if (cappedInstance) { | ||
if (parentInstance) { | ||
if (parentInstance) { | ||
// If the child refers to its parent, there should be one specific instance to cap into | ||
var cappedInstance = lib_1.capInstances([instance], [parentInstance])[0]; | ||
if (cappedInstance) { | ||
if (!cappedInstance.caps) | ||
@@ -270,5 +269,23 @@ cappedInstance.caps = []; | ||
}); | ||
cappedInstances_1.push(cappedInstance); | ||
} | ||
cappedInstances_1.push(cappedInstance); | ||
} | ||
else { | ||
// If the child doesn't refer to its parent, it should be capped within all of its parent instances | ||
_.each(parentInstances, function (parentInstance) { | ||
var cappedInstance = lib_1.capInstances([instance], [parentInstance])[0]; | ||
if (cappedInstance) { | ||
if (parentInstance) { | ||
if (!cappedInstance.caps) | ||
cappedInstance.caps = []; | ||
cappedInstance.caps.push({ | ||
id: parentInstance.id, | ||
start: parentInstance.start, | ||
end: parentInstance.end | ||
}); | ||
} | ||
cappedInstances_1.push(cappedInstance); | ||
} | ||
}); | ||
} | ||
} | ||
@@ -304,2 +321,14 @@ }); | ||
exports.resolveTimelineObj = resolveTimelineObj; | ||
/** | ||
* Look up a reference on the timeline | ||
* Return values: | ||
* Array<TimelineObjectInstance>: Instances on the timeline where the reference expression is true | ||
* ValueWithReference: A singular value which can be combined arithmetically with Instances | ||
* null: Means "something is invalid", an null-value will always return null when combined with other values | ||
* | ||
* @param resolvedTimeline | ||
* @param obj | ||
* @param expr | ||
* @param context | ||
*/ | ||
function lookupExpression(resolvedTimeline, obj, expr, context) { | ||
@@ -341,2 +370,3 @@ if (expr === null) | ||
var objIdsToReference = []; | ||
var referenceIsOk = false; | ||
// Match id, example: "#objectId.start" | ||
@@ -347,2 +377,3 @@ var m = expr.match(/^\W*#([^.]+)(.*)/); | ||
rest = m[2]; | ||
referenceIsOk = true; | ||
objIdsToReference = [id]; | ||
@@ -356,2 +387,3 @@ } | ||
rest = m_1[2]; | ||
referenceIsOk = true; | ||
objIdsToReference = resolvedTimeline.classes[className] || []; | ||
@@ -365,2 +397,3 @@ } | ||
rest = m_2[2]; | ||
referenceIsOk = true; | ||
objIdsToReference = resolvedTimeline.layers[layer] || []; | ||
@@ -376,2 +409,4 @@ } | ||
}); | ||
if (!referenceIsOk) | ||
return null; | ||
if (referencedObjs_1.length) { | ||
@@ -444,3 +479,3 @@ if (rest.match(/start/)) | ||
else { | ||
return null; | ||
return []; | ||
} | ||
@@ -450,3 +485,3 @@ } | ||
else { | ||
return null; | ||
return []; | ||
} | ||
@@ -463,3 +498,3 @@ } | ||
// Discard l, invert and return r: | ||
if (lookupExpr.r && _.isArray(lookupExpr.r) && lookupExpr.r.length) { | ||
if (lookupExpr.r && _.isArray(lookupExpr.r)) { | ||
return lib_1.invertInstances(lookupExpr.r); | ||
@@ -466,0 +501,0 @@ } |
@@ -55,2 +55,7 @@ "use strict"; | ||
var pointsInTime = {}; | ||
var addPointInTime = function (time, enable, obj, instance) { | ||
if (!pointsInTime[time + '']) | ||
pointsInTime[time + ''] = []; | ||
pointsInTime[time + ''].push({ obj: obj, instance: instance, enable: enable }); | ||
}; | ||
var eventObjectTimes = {}; | ||
@@ -83,5 +88,3 @@ _.each(resolvedObjects, function (obj) { | ||
_.each(timeEvents_1, function (timeEvent) { | ||
if (!pointsInTime[timeEvent.time + '']) | ||
pointsInTime[timeEvent.time + ''] = []; | ||
pointsInTime[timeEvent.time + ''].push({ obj: obj, instance: instance, enable: timeEvent.enable }); | ||
addPointInTime(timeEvent.time, timeEvent.enable, obj, instance); | ||
}); | ||
@@ -100,6 +103,8 @@ } | ||
_.each(obj.resolved.instances, function (instance) { | ||
var timeEvent = { time: instance.start, enable: true }; | ||
if (!pointsInTime[timeEvent.time + '']) | ||
pointsInTime[timeEvent.time + ''] = []; | ||
pointsInTime[timeEvent.time + ''].push({ obj: obj, instance: instance, enable: timeEvent.enable }); | ||
// Keyframe start time | ||
addPointInTime(instance.start, true, obj, instance); | ||
// Keyframe end time | ||
if (instance.end !== null) { | ||
addPointInTime(instance.end, false, obj, instance); | ||
} | ||
}); | ||
@@ -114,2 +119,4 @@ } | ||
var activeObjIds = {}; | ||
var activeKeyframes = {}; | ||
var activeKeyframesChecked = {}; | ||
/** The objects in aspiringInstances */ | ||
@@ -128,7 +135,7 @@ var aspiringInstances = {}; | ||
if (a.obj.resolved && b.obj.resolved) { | ||
// Keyframes comes last: | ||
// Keyframes comes first: | ||
if (a.obj.resolved.isKeyframe && !b.obj.resolved.isKeyframe) | ||
return -1; | ||
if (!a.obj.resolved.isKeyframe && b.obj.resolved.isKeyframe) | ||
return 1; | ||
if (!a.obj.resolved.isKeyframe && b.obj.resolved.isKeyframe) | ||
return -1; | ||
// Ending events come before starting events: | ||
@@ -282,31 +289,53 @@ if (a.enable && !b.enable) | ||
resolvedStates.objects[keyframe.id] = keyframe; | ||
// Check if the keyframe's parent is currently active? | ||
if (keyframe.resolved.parentId) { | ||
var parentObj = activeObjIds[keyframe.resolved.parentId]; | ||
if (parentObj && parentObj.layer) { // keyframe is on an active object | ||
var parentObjInstance = currentState[parentObj.layer]; | ||
if (parentObjInstance) { | ||
var keyframeInstance = tslib_1.__assign({}, keyframe, { instance: instance, isKeyframe: true, keyframeEndTime: instance.end }); | ||
// Note: The keyframes are a little bit special, since their contents are applied to their parents. | ||
// That application is done in the getStateAtTime function. | ||
// Add keyframe to the tracking state: | ||
addKeyframeAtTime(resolvedStates.state, parentObj.layer + '', time, keyframeInstance); | ||
// Add keyframe to nextEvents: | ||
var toBeEnabled_1 = ((instance.start || 0) <= time && | ||
(instance.end || Infinity) > time); | ||
if (toBeEnabled_1) { | ||
var newObjInstance = tslib_1.__assign({}, obj, { instance: instance }); | ||
activeKeyframes[obj.id] = newObjInstance; | ||
} | ||
else { | ||
delete activeKeyframes[obj.id]; | ||
} | ||
} | ||
} | ||
}); | ||
// Go through keyframes: | ||
_.each(activeKeyframes, function (objInstance, objId) { | ||
var keyframe = objInstance; | ||
var instance = objInstance.instance; | ||
// Check if the keyframe's parent is currently active? | ||
if (keyframe.resolved.parentId) { | ||
var parentObj = activeObjIds[keyframe.resolved.parentId]; | ||
if (parentObj && parentObj.layer) { // keyframe is on an active object | ||
var parentObjInstance = currentState[parentObj.layer]; | ||
if (parentObjInstance) { | ||
if (!activeKeyframesChecked[objId]) { // hasn't started before | ||
activeKeyframesChecked[objId] = true; | ||
var keyframeInstance = tslib_1.__assign({}, keyframe, { instance: instance, isKeyframe: true, keyframeEndTime: instance.end }); | ||
// Note: The keyframes are a little bit special, since their contents are applied to their parents. | ||
// That application is done in the getStateAtTime function. | ||
// Add keyframe to the tracking state: | ||
addKeyframeAtTime(resolvedStates.state, parentObj.layer + '', time, keyframeInstance); | ||
// Add keyframe to nextEvents: | ||
keyframeEvents.push({ | ||
type: enums_1.EventType.KEYFRAME, | ||
time: instance.start, | ||
objId: keyframe.id | ||
}); | ||
if (instance.end !== null && (parentObjInstance.instance.end === null || | ||
instance.end < parentObjInstance.instance.end // Only add the keyframe if it ends before its parent | ||
)) { | ||
keyframeEvents.push({ | ||
type: enums_1.EventType.KEYFRAME, | ||
time: instance.start, | ||
time: instance.end, | ||
objId: keyframe.id | ||
}); | ||
if (instance.end !== null) { | ||
keyframeEvents.push({ | ||
type: enums_1.EventType.KEYFRAME, | ||
time: instance.end, | ||
objId: keyframe.id | ||
}); | ||
} | ||
} | ||
} | ||
return; | ||
} | ||
} | ||
} | ||
// else: the keyframe:s parent isn't active, remove/stop the keyframe then: | ||
delete activeKeyframesChecked[objId]; | ||
}); | ||
@@ -313,0 +342,0 @@ }); |
{ | ||
"name": "superfly-timeline", | ||
"version": "7.2.1", | ||
"version": "7.2.2", | ||
"description": "A collection of rules as well as a resolver for placing objects on a virtual timeline.", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
226902
2244