| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 | import clone from "../Core/clone.js";import defaultValue from "../Core/defaultValue.js";import defined from "../Core/defined.js";import DeveloperError from "../Core/DeveloperError.js";import EasingFunction from "../Core/EasingFunction.js";import getTimestamp from "../Core/getTimestamp.js";import TimeConstants from "../Core/TimeConstants.js";import TweenJS from "../ThirdParty/Tween.js";/** * A tween is an animation that interpolates the properties of two objects using an {@link EasingFunction}.  Create * one using {@link Scene#tweens} and {@link TweenCollection#add} and related add functions. * * @alias Tween * @constructor * * @private */function Tween(  tweens,  tweenjs,  startObject,  stopObject,  duration,  delay,  easingFunction,  update,  complete,  cancel) {  this._tweens = tweens;  this._tweenjs = tweenjs;  this._startObject = clone(startObject);  this._stopObject = clone(stopObject);  this._duration = duration;  this._delay = delay;  this._easingFunction = easingFunction;  this._update = update;  this._complete = complete;  /**   * The callback to call if the tween is canceled either because {@link Tween#cancelTween}   * was called or because the tween was removed from the collection.   *   * @type {TweenCollection.TweenCancelledCallback}   */  this.cancel = cancel;  /**   * @private   */  this.needsStart = true;}Object.defineProperties(Tween.prototype, {  /**   * An object with properties for initial values of the tween.  The properties of this object are changed during the tween's animation.   * @memberof Tween.prototype   *   * @type {Object}   * @readonly   */  startObject: {    get: function () {      return this._startObject;    },  },  /**   * An object with properties for the final values of the tween.   * @memberof Tween.prototype   *   * @type {Object}   * @readonly   */  stopObject: {    get: function () {      return this._stopObject;    },  },  /**   * The duration, in seconds, for the tween.  The tween is automatically removed from the collection when it stops.   * @memberof Tween.prototype   *   * @type {Number}   * @readonly   */  duration: {    get: function () {      return this._duration;    },  },  /**   * The delay, in seconds, before the tween starts animating.   * @memberof Tween.prototype   *   * @type {Number}   * @readonly   */  delay: {    get: function () {      return this._delay;    },  },  /**   * Determines the curve for animtion.   * @memberof Tween.prototype   *   * @type {EasingFunction}   * @readonly   */  easingFunction: {    get: function () {      return this._easingFunction;    },  },  /**   * The callback to call at each animation update (usually tied to the a rendered frame).   * @memberof Tween.prototype   *   * @type {TweenCollection.TweenUpdateCallback}   * @readonly   */  update: {    get: function () {      return this._update;    },  },  /**   * The callback to call when the tween finishes animating.   * @memberof Tween.prototype   *   * @type {TweenCollection.TweenCompleteCallback}   * @readonly   */  complete: {    get: function () {      return this._complete;    },  },  /**   * @memberof Tween.prototype   *   * @private   */  tweenjs: {    get: function () {      return this._tweenjs;    },  },});/** * Cancels the tween calling the {@link Tween#cancel} callback if one exists.  This * has no effect if the tween finished or was already canceled. */Tween.prototype.cancelTween = function () {  this._tweens.remove(this);};/** * A collection of tweens for animating properties.  Commonly accessed using {@link Scene#tweens}. * * @alias TweenCollection * @constructor * * @private */function TweenCollection() {  this._tweens = [];}Object.defineProperties(TweenCollection.prototype, {  /**   * The number of tweens in the collection.   * @memberof TweenCollection.prototype   *   * @type {Number}   * @readonly   */  length: {    get: function () {      return this._tweens.length;    },  },});/** * Creates a tween for animating between two sets of properties.  The tween starts animating at the next call to {@link TweenCollection#update}, which * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene. * * @param {Object} [options] Object with the following properties: * @param {Object} options.startObject An object with properties for initial values of the tween.  The properties of this object are changed during the tween's animation. * @param {Object} options.stopObject An object with properties for the final values of the tween. * @param {Number} options.duration The duration, in seconds, for the tween.  The tween is automatically removed from the collection when it stops. * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame). * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating. * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection. * @returns {Tween} The tween. * * @exception {DeveloperError} options.duration must be positive. */TweenCollection.prototype.add = function (options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  //>>includeStart('debug', pragmas.debug);  if (!defined(options.startObject) || !defined(options.stopObject)) {    throw new DeveloperError(      "options.startObject and options.stopObject are required."    );  }  if (!defined(options.duration) || options.duration < 0.0) {    throw new DeveloperError(      "options.duration is required and must be positive."    );  }  //>>includeEnd('debug');  if (options.duration === 0.0) {    if (defined(options.complete)) {      options.complete();    }    return new Tween(this);  }  const duration = options.duration / TimeConstants.SECONDS_PER_MILLISECOND;  const delayInSeconds = defaultValue(options.delay, 0.0);  const delay = delayInSeconds / TimeConstants.SECONDS_PER_MILLISECOND;  const easingFunction = defaultValue(    options.easingFunction,    EasingFunction.LINEAR_NONE  );  const value = options.startObject;  const tweenjs = new TweenJS.Tween(value);  tweenjs.to(clone(options.stopObject), duration);  tweenjs.delay(delay);  tweenjs.easing(easingFunction);  if (defined(options.update)) {    tweenjs.onUpdate(function () {      options.update(value);    });  }  tweenjs.onComplete(defaultValue(options.complete, null));  tweenjs.repeat(defaultValue(options._repeat, 0.0));  const tween = new Tween(    this,    tweenjs,    options.startObject,    options.stopObject,    options.duration,    delayInSeconds,    easingFunction,    options.update,    options.complete,    options.cancel  );  this._tweens.push(tween);  return tween;};/** * Creates a tween for animating a scalar property on the given object.  The tween starts animating at the next call to {@link TweenCollection#update}, which * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene. * * @param {Object} [options] Object with the following properties: * @param {Object} options.object The object containing the property to animate. * @param {String} options.property The name of the property to animate. * @param {Number} options.startValue The initial value. * @param {Number} options.stopValue The final value. * @param {Number} [options.duration=3.0] The duration, in seconds, for the tween.  The tween is automatically removed from the collection when it stops. * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame). * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating. * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection. * @returns {Tween} The tween. * * @exception {DeveloperError} options.object must have the specified property. * @exception {DeveloperError} options.duration must be positive. */TweenCollection.prototype.addProperty = function (options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  const object = options.object;  const property = options.property;  const startValue = options.startValue;  const stopValue = options.stopValue;  //>>includeStart('debug', pragmas.debug);  if (!defined(object) || !defined(options.property)) {    throw new DeveloperError(      "options.object and options.property are required."    );  }  if (!defined(object[property])) {    throw new DeveloperError(      "options.object must have the specified property."    );  }  if (!defined(startValue) || !defined(stopValue)) {    throw new DeveloperError(      "options.startValue and options.stopValue are required."    );  }  //>>includeEnd('debug');  function update(value) {    object[property] = value.value;  }  return this.add({    startObject: {      value: startValue,    },    stopObject: {      value: stopValue,    },    duration: defaultValue(options.duration, 3.0),    delay: options.delay,    easingFunction: options.easingFunction,    update: update,    complete: options.complete,    cancel: options.cancel,    _repeat: options._repeat,  });};/** * Creates a tween for animating the alpha of all color uniforms on a {@link Material}.  The tween starts animating at the next call to {@link TweenCollection#update}, which * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene. * * @param {Object} [options] Object with the following properties: * @param {Material} options.material The material to animate. * @param {Number} [options.startValue=0.0] The initial alpha value. * @param {Number} [options.stopValue=1.0] The final alpha value. * @param {Number} [options.duration=3.0] The duration, in seconds, for the tween.  The tween is automatically removed from the collection when it stops. * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame). * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating. * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection. * @returns {Tween} The tween. * * @exception {DeveloperError} material has no properties with alpha components. * @exception {DeveloperError} options.duration must be positive. */TweenCollection.prototype.addAlpha = function (options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  const material = options.material;  //>>includeStart('debug', pragmas.debug);  if (!defined(material)) {    throw new DeveloperError("options.material is required.");  }  //>>includeEnd('debug');  const properties = [];  for (const property in material.uniforms) {    if (      material.uniforms.hasOwnProperty(property) &&      defined(material.uniforms[property]) &&      defined(material.uniforms[property].alpha)    ) {      properties.push(property);    }  }  //>>includeStart('debug', pragmas.debug);  if (properties.length === 0) {    throw new DeveloperError(      "material has no properties with alpha components."    );  }  //>>includeEnd('debug');  function update(value) {    const length = properties.length;    for (let i = 0; i < length; ++i) {      material.uniforms[properties[i]].alpha = value.alpha;    }  }  return this.add({    startObject: {      alpha: defaultValue(options.startValue, 0.0), // Default to fade in    },    stopObject: {      alpha: defaultValue(options.stopValue, 1.0),    },    duration: defaultValue(options.duration, 3.0),    delay: options.delay,    easingFunction: options.easingFunction,    update: update,    complete: options.complete,    cancel: options.cancel,  });};/** * Creates a tween for animating the offset uniform of a {@link Material}.  The tween starts animating at the next call to {@link TweenCollection#update}, which * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene. * * @param {Object} [options] Object with the following properties: * @param {Material} options.material The material to animate. * @param {Number} options.startValue The initial alpha value. * @param {Number} options.stopValue The final alpha value. * @param {Number} [options.duration=3.0] The duration, in seconds, for the tween.  The tween is automatically removed from the collection when it stops. * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame). * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection. * @returns {Tween} The tween. * * @exception {DeveloperError} material.uniforms must have an offset property. * @exception {DeveloperError} options.duration must be positive. */TweenCollection.prototype.addOffsetIncrement = function (options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  const material = options.material;  //>>includeStart('debug', pragmas.debug);  if (!defined(material)) {    throw new DeveloperError("material is required.");  }  if (!defined(material.uniforms.offset)) {    throw new DeveloperError("material.uniforms must have an offset property.");  }  //>>includeEnd('debug');  const uniforms = material.uniforms;  return this.addProperty({    object: uniforms,    property: "offset",    startValue: uniforms.offset,    stopValue: uniforms.offset + 1,    duration: options.duration,    delay: options.delay,    easingFunction: options.easingFunction,    update: options.update,    cancel: options.cancel,    _repeat: Infinity,  });};/** * Removes a tween from the collection. * <p> * This calls the {@link Tween#cancel} callback if the tween has one. * </p> * * @param {Tween} tween The tween to remove. * @returns {Boolean} <code>true</code> if the tween was removed; <code>false</code> if the tween was not found in the collection. */TweenCollection.prototype.remove = function (tween) {  if (!defined(tween)) {    return false;  }  const index = this._tweens.indexOf(tween);  if (index !== -1) {    tween.tweenjs.stop();    if (defined(tween.cancel)) {      tween.cancel();    }    this._tweens.splice(index, 1);    return true;  }  return false;};/** * Removes all tweens from the collection. * <p> * This calls the {@link Tween#cancel} callback for each tween that has one. * </p> */TweenCollection.prototype.removeAll = function () {  const tweens = this._tweens;  for (let i = 0; i < tweens.length; ++i) {    const tween = tweens[i];    tween.tweenjs.stop();    if (defined(tween.cancel)) {      tween.cancel();    }  }  tweens.length = 0;};/** * Determines whether this collection contains a given tween. * * @param {Tween} tween The tween to check for. * @returns {Boolean} <code>true</code> if this collection contains the tween, <code>false</code> otherwise. */TweenCollection.prototype.contains = function (tween) {  return defined(tween) && this._tweens.indexOf(tween) !== -1;};/** * Returns the tween in the collection at the specified index.  Indices are zero-based * and increase as tweens are added.  Removing a tween shifts all tweens after * it to the left, changing their indices.  This function is commonly used to iterate over * all the tween in the collection. * * @param {Number} index The zero-based index of the tween. * @returns {Tween} The tween at the specified index. * * @example * // Output the duration of all the tweens in the collection. * const tweens = scene.tweens; * const length = tweens.length; * for (let i = 0; i < length; ++i) { *   console.log(tweens.get(i).duration); * } */TweenCollection.prototype.get = function (index) {  //>>includeStart('debug', pragmas.debug);  if (!defined(index)) {    throw new DeveloperError("index is required.");  }  //>>includeEnd('debug');  return this._tweens[index];};/** * Updates the tweens in the collection to be at the provide time.  When a tween finishes, it is removed * from the collection. * * @param {Number} [time=getTimestamp()] The time in seconds.  By default tweens are synced to the system clock. */TweenCollection.prototype.update = function (time) {  const tweens = this._tweens;  let i = 0;  time = defined(time)    ? time / TimeConstants.SECONDS_PER_MILLISECOND    : getTimestamp();  while (i < tweens.length) {    const tween = tweens[i];    const tweenjs = tween.tweenjs;    if (tween.needsStart) {      tween.needsStart = false;      tweenjs.start(time);    } else if (tweenjs.update(time)) {      i++;    } else {      tweenjs.stop();      tweens.splice(i, 1);    }  }};/** * A function that will execute when a tween completes. * @callback TweenCollection.TweenCompleteCallback *//** * A function that will execute when a tween updates. * @callback TweenCollection.TweenUpdateCallback *//** * A function that will execute when a tween is cancelled. * @callback TweenCollection.TweenCancelledCallback */export default TweenCollection;
 |