Skip to content

Commit 4427001

Browse files
authored
Merge pull request #5815 from AnalyticalGraphicsInc/model-animation-names
Fix discrepency between ids and names in AnimationCollection
2 parents 10f78b5 + d50a63e commit 4427001

File tree

5 files changed

+127
-76
lines changed

5 files changed

+127
-76
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Change Log
22
==========
33
### 1.38 - 2017-10-02
44

5+
* Added ability to add an animation to `ModelAnimationCollection` by its index. [#5815](https://github.com/AnalyticalGraphicsInc/cesium/pull/5815)
6+
* Fixed a bug in `ModelAnimationCollection` that caused adding an animation by its name to throw an error. [#5815](https://github.com/AnalyticalGraphicsInc/cesium/pull/5815)
57
* Zoom about mouse now maintains camera heading, pitch, and roll [#4639](https://github.com/AnalyticalGraphicsInc/cesium/pull/5603)
68

79
### 1.37 - 2017-09-01

Source/Scene/Model.js

+30-46
Original file line numberDiff line numberDiff line change
@@ -289,20 +289,6 @@ define([
289289
this.ready = true;
290290
};
291291

292-
function getAnimationIds(cachedGltf) {
293-
var animationIds = [];
294-
if (defined(cachedGltf)) {
295-
var animations = cachedGltf.animations;
296-
for (var id in animations) {
297-
if (animations.hasOwnProperty(id)) {
298-
animationIds.push(id);
299-
}
300-
}
301-
}
302-
303-
return animationIds;
304-
}
305-
306292
var gltfCache = {};
307293

308294
///////////////////////////////////////////////////////////////////////////
@@ -368,7 +354,6 @@ define([
368354
this._cacheKey = cacheKey;
369355
this._cachedGltf = undefined;
370356
this._releaseGltfJson = defaultValue(options.releaseGltfJson, false);
371-
this._animationIds = undefined;
372357

373358
var cachedGltf;
374359
if (defined(cacheKey) && defined(gltfCache[cacheKey]) && gltfCache[cacheKey].ready) {
@@ -2523,48 +2508,48 @@ define([
25232508
}
25242509
loadResources.createRuntimeAnimations = false;
25252510

2526-
model._runtime.animations = {};
2511+
model._runtime.animations = [];
25272512

25282513
var runtimeNodes = model._runtime.nodes;
25292514
var animations = model.gltf.animations;
25302515
var accessors = model.gltf.accessors;
25312516

2532-
for (var animationId in animations) {
2533-
if (animations.hasOwnProperty(animationId)) {
2534-
var animation = animations[animationId];
2535-
var channels = animation.channels;
2536-
var samplers = animation.samplers;
2537-
2538-
// Find start and stop time for the entire animation
2539-
var startTime = Number.MAX_VALUE;
2540-
var stopTime = -Number.MAX_VALUE;
2517+
var length = animations.length;
2518+
for (var i = 0; i < length; ++i) {
2519+
var animation = animations[i];
2520+
var channels = animation.channels;
2521+
var samplers = animation.samplers;
25412522

2542-
var length = channels.length;
2543-
var channelEvaluators = new Array(length);
2523+
// Find start and stop time for the entire animation
2524+
var startTime = Number.MAX_VALUE;
2525+
var stopTime = -Number.MAX_VALUE;
25442526

2545-
for (var i = 0; i < length; ++i) {
2546-
var channel = channels[i];
2547-
var target = channel.target;
2548-
var path = target.path;
2549-
var sampler = samplers[channel.sampler];
2550-
var input = ModelAnimationCache.getAnimationParameterValues(model, accessors[sampler.input]);
2551-
var output = ModelAnimationCache.getAnimationParameterValues(model, accessors[sampler.output]);
2527+
var channelsLength = channels.length;
2528+
var channelEvaluators = new Array(channelsLength);
25522529

2553-
startTime = Math.min(startTime, input[0]);
2554-
stopTime = Math.max(stopTime, input[input.length - 1]);
2530+
for (var j = 0; j < channelsLength; ++j) {
2531+
var channel = channels[j];
2532+
var target = channel.target;
2533+
var path = target.path;
2534+
var sampler = samplers[channel.sampler];
2535+
var input = ModelAnimationCache.getAnimationParameterValues(model, accessors[sampler.input]);
2536+
var output = ModelAnimationCache.getAnimationParameterValues(model, accessors[sampler.output]);
25552537

2556-
var spline = ModelAnimationCache.getAnimationSpline(model, animationId, animation, channel.sampler, sampler, input, path, output);
2538+
startTime = Math.min(startTime, input[0]);
2539+
stopTime = Math.max(stopTime, input[input.length - 1]);
25572540

2558-
// GLTF_SPEC: Support more targets like materials. https://github.com/KhronosGroup/glTF/issues/142
2559-
channelEvaluators[i] = getChannelEvaluator(model, runtimeNodes[target.node], target.path, spline);
2560-
}
2541+
var spline = ModelAnimationCache.getAnimationSpline(model, i, animation, channel.sampler, sampler, input, path, output);
25612542

2562-
model._runtime.animations[animationId] = {
2563-
startTime : startTime,
2564-
stopTime : stopTime,
2565-
channelEvaluators : channelEvaluators
2566-
};
2543+
// GLTF_SPEC: Support more targets like materials. https://github.com/KhronosGroup/glTF/issues/142
2544+
channelEvaluators[j] = getChannelEvaluator(model, runtimeNodes[target.node], target.path, spline);
25672545
}
2546+
2547+
model._runtime.animations[i] = {
2548+
name : animation.name,
2549+
startTime : startTime,
2550+
stopTime : stopTime,
2551+
channelEvaluators : channelEvaluators
2552+
};
25682553
}
25692554
}
25702555

@@ -4551,7 +4536,6 @@ define([
45514536
processPbrMetallicRoughness(this.gltf, options);
45524537
// We do this after to make sure that the ids don't change
45534538
addBuffersToLoadResources(this);
4554-
this._animationIds = getAnimationIds(this.gltf);
45554539

45564540
if (!this._loadRendererResourcesFromCache) {
45574541
parseBufferViews(this);

Source/Scene/ModelAnimation.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ define([
3030
* @see ModelAnimationCollection#add
3131
*/
3232
function ModelAnimation(options, model, runtimeAnimation) {
33-
this._name = options.name;
33+
this._name = runtimeAnimation.name;
3434
this._startTime = JulianDate.clone(options.startTime);
3535
this._delay = defaultValue(options.delay, 0.0); // in seconds
3636
this._stopTime = options.stopTime;

Source/Scene/ModelAnimationCollection.js

+49-19
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,25 @@ define([
8282
}
8383
});
8484

85+
function add(collection, index, options) {
86+
var model = collection._model;
87+
var animations = model._runtime.animations;
88+
var animation = animations[index];
89+
var scheduledAnimation = new ModelAnimation(options, model, animation);
90+
collection._scheduledAnimations.push(scheduledAnimation);
91+
collection.animationAdded.raiseEvent(model, scheduledAnimation);
92+
return scheduledAnimation;
93+
}
94+
8595
/**
8696
* Creates and adds an animation with the specified initial properties to the collection.
8797
* <p>
8898
* This raises the {@link ModelAnimationCollection#animationAdded} event so, for example, a UI can stay in sync.
8999
* </p>
90100
*
91101
* @param {Object} options Object with the following properties:
92-
* @param {String} options.name The glTF animation name that identifies the animation.
102+
* @param {String} [options.name] The glTF animation name that identifies the animation. Must be defined if <code>options.id</code> is <code>undefined</code>.
103+
* @param {Number} [options.index] The glTF animation index that identifies the animation. Must be defined if <code>options.name</code> is <code>undefined</code>.
93104
* @param {JulianDate} [options.startTime] The scene time to start playing the animation. When this is <code>undefined</code>, the animation starts at the next frame.
94105
* @param {Number} [options.delay=0.0] The delay, in seconds, from <code>startTime</code> to start playing.
95106
* @param {JulianDate} [options.stopTime] The scene time to stop playing the animation. When this is <code>undefined</code>, the animation is played for its full duration.
@@ -101,16 +112,23 @@ define([
101112
*
102113
* @exception {DeveloperError} Animations are not loaded. Wait for the {@link Model#readyPromise} to resolve.
103114
* @exception {DeveloperError} options.name must be a valid animation name.
115+
* @exception {DeveloperError} options.index must be a valid animation index.
116+
* @exception {DeveloperError} Either options.name or options.index must be defined.
104117
* @exception {DeveloperError} options.speedup must be greater than zero.
105118
*
106119
* @example
107-
* // Example 1. Add an animation
120+
* // Example 1. Add an animation by name
108121
* model.activeAnimations.add({
109122
* name : 'animation name'
110123
* });
111124
*
125+
* // Example 2. Add an animation by index
126+
* model.activeAnimations.add({
127+
* index : 0
128+
* });
129+
*
112130
* @example
113-
* // Example 2. Add an animation and provide all properties and events
131+
* // Example 3. Add an animation and provide all properties and events
114132
* var startTime = Cesium.JulianDate.now();
115133
*
116134
* var animation = model.activeAnimations.add({
@@ -144,24 +162,38 @@ define([
144162
if (!defined(animations)) {
145163
throw new DeveloperError('Animations are not loaded. Wait for Model.readyPromise to resolve.');
146164
}
165+
if (!defined(options.name) && !defined(options.index)) {
166+
throw new DeveloperError('Either options.name or options.index must be defined.');
167+
}
168+
if (defined(options.speedup) && (options.speedup <= 0.0)) {
169+
throw new DeveloperError('options.speedup must be greater than zero.');
170+
}
171+
if (defined(options.index) && (options.index >= animations.length || options.index < 0)) {
172+
throw new DeveloperError('options.index must be a valid animation index.');
173+
}
147174
//>>includeEnd('debug');
148175

149-
var animation = animations[options.name];
176+
if (defined(options.index)) {
177+
return add(this, options.index, options);
178+
}
150179

151-
//>>includeStart('debug', pragmas.debug);
152-
if (!defined(animation)) {
153-
throw new DeveloperError('options.name must be a valid animation name.');
180+
// Find the index of the animation with the given name
181+
var index;
182+
var length = animations.length;
183+
for (var i = 0; i < length; ++i) {
184+
if (animations[i].name === options.name) {
185+
index = i;
186+
break;
187+
}
154188
}
155189

156-
if (defined(options.speedup) && (options.speedup <= 0.0)) {
157-
throw new DeveloperError('options.speedup must be greater than zero.');
190+
//>>includeStart('debug', pragmas.debug);
191+
if (!defined(index)) {
192+
throw new DeveloperError('options.name must be a valid animation name.');
158193
}
159194
//>>includeEnd('debug');
160195

161-
var scheduledAnimation = new ModelAnimation(options, model, animation);
162-
this._scheduledAnimations.push(scheduledAnimation);
163-
this.animationAdded.raiseEvent(model, scheduledAnimation);
164-
return scheduledAnimation;
196+
return add(this, index, options);
165197
};
166198

167199
/**
@@ -203,14 +235,12 @@ define([
203235
}
204236
//>>includeEnd('debug');
205237

206-
options = clone(options);
207-
208238
var scheduledAnimations = [];
209-
var animationIds = this._model._animationIds;
210-
var length = animationIds.length;
239+
var model = this._model;
240+
var animations = model._runtime.animations;
241+
var length = animations.length;
211242
for (var i = 0; i < length; ++i) {
212-
options.name = animationIds[i];
213-
scheduledAnimations.push(this.add(options));
243+
scheduledAnimations.push(add(this, i, options));
214244
}
215245
return scheduledAnimations;
216246
};

Specs/Scene/ModelSpec.js

+45-10
Original file line numberDiff line numberDiff line change
@@ -1135,10 +1135,10 @@ defineSuite([
11351135
var spyAdd = jasmine.createSpy('listener');
11361136
animations.animationAdded.addEventListener(spyAdd);
11371137
var a = animations.add({
1138-
name : 1
1138+
name : 'animation_1'
11391139
});
11401140
expect(a).toBeDefined();
1141-
expect(a.name).toEqual(1);
1141+
expect(a.name).toEqual('animation_1');
11421142
expect(a.startTime).not.toBeDefined();
11431143
expect(a.delay).toEqual(0.0);
11441144
expect(a.stopTime).not.toBeDefined();
@@ -1166,6 +1166,41 @@ defineSuite([
11661166
animations.animationRemoved.removeEventListener(spyRemove);
11671167
});
11681168

1169+
it('adds an animation by index', function() {
1170+
var animations = animBoxesModel.activeAnimations;
1171+
expect(animations.length).toEqual(0);
1172+
1173+
var spyAdd = jasmine.createSpy('listener');
1174+
animations.animationAdded.addEventListener(spyAdd);
1175+
var a = animations.add({
1176+
index : 1
1177+
});
1178+
expect(a).toBeDefined();
1179+
expect(a.name).toEqual('animation_1');
1180+
animations.remove(a);
1181+
});
1182+
1183+
it('add throws when name and index are not defined', function() {
1184+
var m = new Model();
1185+
expect(function() {
1186+
return m.activeAnimations.add();
1187+
}).toThrowDeveloperError();
1188+
});
1189+
1190+
it('add throws when index is invalid', function() {
1191+
var m = new Model();
1192+
expect(function() {
1193+
return m.activeAnimations.add({
1194+
index : -1
1195+
});
1196+
}).toThrowDeveloperError();
1197+
expect(function() {
1198+
return m.activeAnimations.add({
1199+
index : 2
1200+
});
1201+
}).toThrowDeveloperError();
1202+
});
1203+
11691204
it('add throws when model is not loaded', function() {
11701205
var m = new Model();
11711206
expect(function() {
@@ -1207,7 +1242,7 @@ defineSuite([
12071242
var time = JulianDate.fromDate(new Date('January 1, 2014 12:00:00 UTC'));
12081243
var animations = animBoxesModel.activeAnimations;
12091244
var a = animations.add({
1210-
name : 1,
1245+
name : 'animation_1',
12111246
startTime : time,
12121247
removeOnStop : true
12131248
});
@@ -1253,7 +1288,7 @@ defineSuite([
12531288

12541289
var animations = animBoxesModel.activeAnimations;
12551290
var a = animations.add({
1256-
name : 1,
1291+
name : 'animation_1',
12571292
startTime : time,
12581293
delay : 1.0
12591294
});
@@ -1277,7 +1312,7 @@ defineSuite([
12771312

12781313
var animations = animBoxesModel.activeAnimations;
12791314
var a = animations.add({
1280-
name : 1,
1315+
name : 'animation_1',
12811316
startTime : time,
12821317
stopTime : stopTime
12831318
});
@@ -1301,7 +1336,7 @@ defineSuite([
13011336
var time = JulianDate.fromDate(new Date('January 1, 2014 12:00:00 UTC'));
13021337
var animations = animBoxesModel.activeAnimations;
13031338
var a = animations.add({
1304-
name : 1,
1339+
name : 'animation_1',
13051340
startTime : time,
13061341
speedup : 1.5
13071342
});
@@ -1326,7 +1361,7 @@ defineSuite([
13261361
var time = JulianDate.fromDate(new Date('January 1, 2014 12:00:00 UTC'));
13271362
var animations = animBoxesModel.activeAnimations;
13281363
var a = animations.add({
1329-
name : 1,
1364+
name : 'animation_1',
13301365
startTime : time,
13311366
reverse : true
13321367
});
@@ -1353,7 +1388,7 @@ defineSuite([
13531388
var time = JulianDate.fromDate(new Date('January 1, 2014 12:00:00 UTC'));
13541389
var animations = animBoxesModel.activeAnimations;
13551390
var a = animations.add({
1356-
name : 1,
1391+
name : 'animation_1',
13571392
startTime : time,
13581393
loop : ModelAnimationLoop.REPEAT
13591394
});
@@ -1383,7 +1418,7 @@ defineSuite([
13831418
var time = JulianDate.fromDate(new Date('January 1, 2014 12:00:00 UTC'));
13841419
var animations = animBoxesModel.activeAnimations;
13851420
var a = animations.add({
1386-
name : 1,
1421+
name : 'animation_1',
13871422
startTime : time,
13881423
loop : ModelAnimationLoop.MIRRORED_REPEAT
13891424
});
@@ -1417,7 +1452,7 @@ defineSuite([
14171452
var time = JulianDate.fromDate(new Date('January 1, 2014 12:00:00 UTC'));
14181453
var animations = m.activeAnimations;
14191454
var a = animations.add({
1420-
name : 1,
1455+
name : 'animation_1',
14211456
startTime : time
14221457
});
14231458

0 commit comments

Comments
 (0)