flow
This commit is contained in:
parent
455a7dacf3
commit
89278f1d9c
|
@ -1,6 +1,9 @@
|
|||
export {
|
||||
default as fastApply,
|
||||
} from './fast-apply';
|
||||
export {
|
||||
default as mapValuesAsync,
|
||||
} from './map-values-async';
|
||||
export {
|
||||
mergeDiff,
|
||||
mergeDiffArray,
|
||||
|
|
3
packages/core/src/map-values-async.js
Normal file
3
packages/core/src/map-values-async.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export default async (o, f) => Object.fromEntries(
|
||||
await Promise.all(Object.entries(o).map(async ([key, v]) => [key, await f(v)])),
|
||||
);
|
|
@ -29,6 +29,9 @@ export default class Container extends Renderable {
|
|||
if (this.container.isFake) {
|
||||
return;
|
||||
}
|
||||
if (-1 !== this._children.indexOf(child)) {
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
child.parent = this;
|
||||
this.isDirty = true;
|
||||
|
|
91
packages/sound/src/traits/audible.js
Normal file
91
packages/sound/src/traits/audible.js
Normal file
|
@ -0,0 +1,91 @@
|
|||
import {Trait} from '@avocado/traits';
|
||||
|
||||
import Sound from '../sound';
|
||||
|
||||
const {
|
||||
SIDE,
|
||||
} = process.env;
|
||||
|
||||
export default class Audible extends Trait {
|
||||
|
||||
#sounds;
|
||||
|
||||
constructor(json) {
|
||||
super(json);
|
||||
this.#sounds = json.sounds || {};
|
||||
}
|
||||
|
||||
static behaviorTypes() {
|
||||
return {
|
||||
hasSound: {
|
||||
type: 'bool',
|
||||
label: 'Has $1 sound',
|
||||
args: [
|
||||
['key', {
|
||||
type: 'string',
|
||||
}],
|
||||
],
|
||||
},
|
||||
playSound: {
|
||||
type: 'void',
|
||||
label: 'Play the $1 sound.',
|
||||
args: [
|
||||
['key', {
|
||||
type: 'string',
|
||||
options: (entity) => this.optionsForSounds(entity),
|
||||
}],
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static defaultParams() {
|
||||
return {
|
||||
sounds: {},
|
||||
};
|
||||
}
|
||||
|
||||
static describeParams() {
|
||||
return {
|
||||
sounds: {
|
||||
type: 'object',
|
||||
label: 'Sounds',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
destroy() {
|
||||
Object.values(this.#sounds).forEach((sound) => {
|
||||
sound.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
async extendJson(json) {
|
||||
const extended = await super.extendJson(json);
|
||||
if (this.params.sounds && 'client' === SIDE) {
|
||||
extended.sounds = Object.fromEntries(
|
||||
await Promise.all(
|
||||
Object.entries(this.params.sounds)
|
||||
.map(async ([key, sound]) => [key, await Sound.load(sound.uri)]),
|
||||
),
|
||||
);
|
||||
}
|
||||
return extended;
|
||||
}
|
||||
|
||||
methods() {
|
||||
return {
|
||||
|
||||
hasSound: (key) => !!this.#sounds[key],
|
||||
|
||||
playSound: (key) => this.hasSound(key) && this.#sounds[key].play(),
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
static optionsForSounds(entity) {
|
||||
return Object.keys(entity.trait('Audible').params.sounds)
|
||||
.reduce((r, key) => ({...r, [key]: key}), {});
|
||||
}
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
import {Trait} from '@avocado/traits';
|
||||
|
||||
import Sound from '../sound';
|
||||
|
||||
export default class Audible extends Trait {
|
||||
|
||||
static behaviorTypes() {
|
||||
return {
|
||||
hasSound: {
|
||||
type: 'bool',
|
||||
label: 'Has $1 sound',
|
||||
args: [
|
||||
['key', {
|
||||
type: 'string',
|
||||
}],
|
||||
],
|
||||
},
|
||||
playSound: {
|
||||
type: 'void',
|
||||
label: 'Play the $1 sound.',
|
||||
args: [
|
||||
['key', {
|
||||
type: 'string',
|
||||
options: (entity) => this.optionsForSounds(entity),
|
||||
}],
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
static defaultParams() {
|
||||
return {
|
||||
sounds: {},
|
||||
};
|
||||
}
|
||||
|
||||
static describeParams() {
|
||||
return {
|
||||
sounds: {
|
||||
type: 'object',
|
||||
label: 'Sounds',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
hydrate() {
|
||||
if (AVOCADO_CLIENT) {
|
||||
this.loadSounds();
|
||||
}
|
||||
}
|
||||
|
||||
constructor(entity, params, state) {
|
||||
super(entity, params, state);
|
||||
this._sounds = this.params.sounds;
|
||||
this.sounds = {};
|
||||
}
|
||||
|
||||
destroy() {
|
||||
const sounds = Object.values(this.sounds);
|
||||
for (let i = 0; i < sounds.length; i++) {
|
||||
sounds[i].destroy();
|
||||
}
|
||||
}
|
||||
|
||||
loadSounds() {
|
||||
const keys = Object.keys(this._sounds);
|
||||
const soundPromises = [];
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
const soundJSON = this._sounds[key];
|
||||
soundPromises.push(Sound.load(soundJSON.uri));
|
||||
}
|
||||
const soundsPromise = Promise.all(soundPromises);
|
||||
soundsPromise.then((sounds) => {
|
||||
for (let i = 0; i < sounds.length; i++) {
|
||||
const key = keys[i];
|
||||
const sound = sounds[i];
|
||||
this.sounds[key] = sound;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
methods() {
|
||||
return {
|
||||
|
||||
hasSound: (key) => !!this.sounds[key],
|
||||
|
||||
playSound: (key) => {
|
||||
const sound = this.sounds[key];
|
||||
if (!sound) {
|
||||
return;
|
||||
}
|
||||
sound.play();
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
static optionsForSounds(entity) {
|
||||
return Object.keys(entity.trait('Audible').params.sounds)
|
||||
.reduce((r, key) => ({...r, [key]: key}), {});
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,8 @@
|
|||
"@avocado/traits": "^2.0.0",
|
||||
"@latus/core": "2.0.0",
|
||||
"@latus/socket": "2.0.0",
|
||||
"debug": "4.3.1"
|
||||
"debug": "4.3.1",
|
||||
"lodash.mapvalues": "^4.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@neutrinojs/airbnb-base": "^9.4.0",
|
||||
|
|
|
@ -9,4 +9,4 @@ export {default as Animation} from './animation';
|
|||
export {default as Lfo} from './lfo';
|
||||
export {default as Ticker} from './ticker';
|
||||
export {default as TimedIndex} from './timed-index';
|
||||
export {TransitionMixin as Transition, TransitionResult} from './transition';
|
||||
export {default as Transition, TransitionResult} from './transition';
|
||||
|
|
|
@ -2,13 +2,10 @@ import {Packet} from '@latus/socket';
|
|||
|
||||
export default class TraitUpdateAnimatedPacket extends Packet {
|
||||
|
||||
static get schema() {
|
||||
static get data() {
|
||||
return {
|
||||
...super.schema,
|
||||
data: {
|
||||
currentAnimation: 'string',
|
||||
isAnimating: 'bool',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import {mapValuesAsync} from '@avocado/core';
|
||||
import {StateProperty, Trait} from '@avocado/traits';
|
||||
import {Rectangle, Vector} from '@avocado/math';
|
||||
import {compose} from '@latus/core';
|
||||
import mapValues from 'lodash.mapvalues';
|
||||
|
||||
import Animation from '../animation';
|
||||
import AnimationView from '../animation-view';
|
||||
|
@ -16,6 +18,34 @@ const decorate = compose(
|
|||
|
||||
export default class Animated extends decorate(Trait) {
|
||||
|
||||
#animations = {};
|
||||
|
||||
#animationViews = {};
|
||||
|
||||
#cachedAabbs = {};
|
||||
|
||||
#currentAnimation;
|
||||
|
||||
constructor(json) {
|
||||
super(json);
|
||||
if (json.animations) {
|
||||
Object.values(json.animations).forEach((animation) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
animation.direction = this.entity.direction;
|
||||
});
|
||||
this.#animations = json.animations;
|
||||
this.#animationViews = json.animationViews;
|
||||
}
|
||||
this.#currentAnimation = this.state.currentAnimation;
|
||||
}
|
||||
|
||||
acceptPacket(packet) {
|
||||
if ('TraitUpdateAnimated' === packet.constructor.type) {
|
||||
this.entity.currentAnimation = packet.data.currentAnimation;
|
||||
this.entity.isAnimating = packet.data.isAnimating;
|
||||
}
|
||||
}
|
||||
|
||||
static defaultParams() {
|
||||
return {
|
||||
animations: {},
|
||||
|
@ -55,134 +85,153 @@ export default class Animated extends decorate(Trait) {
|
|||
};
|
||||
}
|
||||
|
||||
constructor(entity, params, state) {
|
||||
super(entity, params, state);
|
||||
this._animations = this.params.animations;
|
||||
this.animations = {};
|
||||
this.animationViews = undefined;
|
||||
this.animationsPromise = undefined;
|
||||
this._cachedAabbs = {};
|
||||
this._currentAnimation = this.state.currentAnimation;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
if (this.animationViews) {
|
||||
const animationViews = Object.entries(this.animationViews);
|
||||
if (this.#animationViews) {
|
||||
const animationViews = Object.entries(this.#animationViews);
|
||||
for (let i = 0; i < animationViews.length; i++) {
|
||||
const [key, animationView] = animationViews[i];
|
||||
this.hideAnimation(key);
|
||||
animationView.destroy();
|
||||
}
|
||||
this.animationViews = undefined;
|
||||
this.#animationViews = undefined;
|
||||
}
|
||||
const animations = Object.values(this.animations);
|
||||
const animations = Object.values(this.#animations);
|
||||
for (let i = 0; i < animations.length; i++) {
|
||||
animations[i].destroy();
|
||||
}
|
||||
this.animations = {};
|
||||
this.animationsPromise = undefined;
|
||||
this._cachedAabbs = {};
|
||||
this.#animations = {};
|
||||
this.#cachedAabbs = {};
|
||||
}
|
||||
|
||||
acceptPacket(packet) {
|
||||
if ('TraitUpdateAnimated' === packet.constructor.type) {
|
||||
this.entity.currentAnimation = packet.data.currentAnimation;
|
||||
this.entity.isAnimating = packet.data.isAnimating;
|
||||
static async extendJson(json) {
|
||||
const extended = await super.extendJson(json);
|
||||
if (Object.keys(this.params.animations).length > 0) {
|
||||
extended.animations = await mapValuesAsync(
|
||||
this.params.animations,
|
||||
(json) => Animation.load(json),
|
||||
);
|
||||
extended.animationViews = mapValues(
|
||||
extended.animations,
|
||||
(animation) => new AnimationView(animation),
|
||||
);
|
||||
}
|
||||
return extended;
|
||||
}
|
||||
|
||||
hideAnimation(key) {
|
||||
if (!this.animationViews) {
|
||||
if (!this.#animationViews) {
|
||||
return;
|
||||
}
|
||||
const animationView = this.animationViews[key];
|
||||
const animationView = this.#animationViews[key];
|
||||
if (!animationView) {
|
||||
return;
|
||||
}
|
||||
if (!this.entity.container) {
|
||||
return;
|
||||
}
|
||||
this.entity.container.removeChild(animationView);
|
||||
}
|
||||
|
||||
hydrate() {
|
||||
return Promise.all([
|
||||
this.loadAnimations(),
|
||||
this.loadAnimationImagesIfPossible(),
|
||||
]);
|
||||
hooks() {
|
||||
return {
|
||||
|
||||
visibleAabbs: () => {
|
||||
const key = this.#currentAnimation;
|
||||
if (key in this.#cachedAabbs) {
|
||||
return this.#cachedAabbs[key];
|
||||
}
|
||||
if (!(key in this.#animations)) {
|
||||
return [0, 0, 0, 0];
|
||||
}
|
||||
const {frameSize} = this.#animations[key];
|
||||
const scaledSize = Vector.mul(frameSize, this.entity.rawVisibleScale);
|
||||
const viewPosition = Vector.sub(
|
||||
this.offsetFor(key),
|
||||
Vector.scale(scaledSize, 0.5),
|
||||
);
|
||||
const rectangle = Rectangle.compose(viewPosition, frameSize);
|
||||
const expanded = Rectangle.expand(
|
||||
rectangle,
|
||||
Vector.sub(scaledSize, frameSize),
|
||||
);
|
||||
this.#cachedAabbs[key] = expanded;
|
||||
return expanded;
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
jitterFor(key) {
|
||||
if (!(key in this._animations) || !this._animations[key].jitter) {
|
||||
if (!(key in this.params.animations) || !this.params.animations[key].jitter) {
|
||||
return 0;
|
||||
}
|
||||
return this._animations[key].jitter;
|
||||
return this.params.animations[key].jitter;
|
||||
}
|
||||
|
||||
async loadAnimations() {
|
||||
if (this.animationsPromise) {
|
||||
return;
|
||||
listeners() {
|
||||
return {
|
||||
|
||||
currentAnimationChanged: (oldKey, currentAnimation) => {
|
||||
this.#currentAnimation = currentAnimation;
|
||||
// Reset old animation.
|
||||
if (oldKey in this.#animations) {
|
||||
const oldAnimation = this.#animations[oldKey];
|
||||
oldAnimation.reset();
|
||||
}
|
||||
if (!this.animationsPromise) {
|
||||
const animationPromises = [];
|
||||
// Load all animations.
|
||||
const animations = Object.entries(this._animations);
|
||||
for (let i = 0; i < animations.length; i++) {
|
||||
const [key, {uri}] = animations[i];
|
||||
const promise = Animation.load(uri).then((animation) => ({animation, key}));
|
||||
animationPromises.push(promise);
|
||||
}
|
||||
this.animationsPromise = Promise.all(animationPromises);
|
||||
}
|
||||
// Store keyed animations.
|
||||
this.animations = {};
|
||||
const animations = await this.animationsPromise;
|
||||
animations.forEach(({animation, key}) => {
|
||||
this.animations[key] = animation;
|
||||
// Set direction upfront.
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
animation.direction = this.entity.direction;
|
||||
});
|
||||
// Bounding box update.
|
||||
this.entity.updateVisibleBoundingBox();
|
||||
// Only client/graphics.
|
||||
if (!this.#animationViews) {
|
||||
return;
|
||||
}
|
||||
// Swap the animation.
|
||||
this.hideAnimation(oldKey);
|
||||
this.showAnimation(this.#currentAnimation);
|
||||
},
|
||||
|
||||
async loadAnimationImagesIfPossible() {
|
||||
if (!this.entity.container) {
|
||||
return;
|
||||
directionChanged: () => {
|
||||
// All animations track direction.
|
||||
const animations = Object.values(this.#animations);
|
||||
for (let i = 0; i < animations.length; i++) {
|
||||
animations[i].direction = this.entity.direction;
|
||||
}
|
||||
if (!this.animationsPromise) {
|
||||
return;
|
||||
}
|
||||
if (this.animationViews) {
|
||||
return;
|
||||
}
|
||||
// Store keyed animation views.
|
||||
this.animationViews = {};
|
||||
const animations = await this.animationsPromise;
|
||||
animations.forEach(({animation, key}) => {
|
||||
this.animationViews[key] = new AnimationView(animation);
|
||||
// Calculate any offset.
|
||||
const animationView = this.animationViews[key];
|
||||
animationView.position = this.offsetFor(key);
|
||||
// Ensure animation is made visible upfront.
|
||||
const isCurrentAnimation = key === this._currentAnimation;
|
||||
if (isCurrentAnimation) {
|
||||
this.showAnimation(key);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
isDyingChanged: (_, isDying) => {
|
||||
this.isAnimating = !isDying;
|
||||
},
|
||||
|
||||
traitAdded: () => {
|
||||
this.entity.updateVisibleBoundingBox();
|
||||
this.setSpriteScale();
|
||||
Object.keys(this.#animations).forEach((key) => {
|
||||
const method = key === this.#currentAnimation
|
||||
? 'showAnimation'
|
||||
: 'hideAnimation';
|
||||
this[method](key);
|
||||
});
|
||||
},
|
||||
|
||||
visibleScaleChanged: () => {
|
||||
this.#cachedAabbs = {};
|
||||
this.setSpriteScale();
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
offsetFor(key) {
|
||||
if (!(key in this._animations) || !this._animations[key].offset) {
|
||||
if (!(key in this.params.animations) || !this.params.animations[key].offset) {
|
||||
return [0, 0];
|
||||
}
|
||||
return this._animations[key].offset;
|
||||
return this.params.animations[key].offset;
|
||||
}
|
||||
|
||||
packets() {
|
||||
const {currentAnimation, isAnimating} = this.stateDifferences();
|
||||
if (currentAnimation || isAnimating) {
|
||||
return [
|
||||
'TraitUpdateAnimatedPacket',
|
||||
'TraitUpdateAnimated',
|
||||
{
|
||||
currentAnimation: this.state.currentAnimation,
|
||||
isAnimating: this.state.isAnimating,
|
||||
|
@ -193,107 +242,39 @@ export default class Animated extends decorate(Trait) {
|
|||
}
|
||||
|
||||
setSpriteScale() {
|
||||
if (!this.animationViews) {
|
||||
if (!this.#animationViews) {
|
||||
return;
|
||||
}
|
||||
const animationViews = Object.values(this.animationViews);
|
||||
const animationViews = Object.values(this.#animationViews);
|
||||
for (let i = 0; i < animationViews.length; i++) {
|
||||
animationViews[i].scale = this.entity.rawVisibleScale;
|
||||
}
|
||||
}
|
||||
|
||||
showAnimation(key) {
|
||||
if (!this.animationViews) {
|
||||
if (!this.#animationViews) {
|
||||
return;
|
||||
}
|
||||
if (!(key in this.animationViews)) {
|
||||
const animationView = this.#animationViews[key];
|
||||
if (!animationView) {
|
||||
return;
|
||||
}
|
||||
if (!this.entity.container) {
|
||||
return;
|
||||
}
|
||||
const animationView = this.animationViews[key];
|
||||
this.entity.container.addChild(animationView);
|
||||
}
|
||||
|
||||
hooks() {
|
||||
return {
|
||||
|
||||
visibleAabbs: () => {
|
||||
const key = this._currentAnimation;
|
||||
if (key in this._cachedAabbs) {
|
||||
return this._cachedAabbs[key];
|
||||
}
|
||||
if (!(key in this.animations)) {
|
||||
return [0, 0, 0, 0];
|
||||
}
|
||||
const animation = this.animations[key];
|
||||
const size = animation.frameSize;
|
||||
const scaledSize = Vector.mul(size, this.entity.rawVisibleScale);
|
||||
const viewPosition = Vector.sub(
|
||||
this.offsetFor(key),
|
||||
Vector.scale(scaledSize, 0.5),
|
||||
);
|
||||
const rectangle = Rectangle.compose(viewPosition, size);
|
||||
const expanded = Rectangle.expand(
|
||||
rectangle,
|
||||
Vector.sub(scaledSize, size),
|
||||
);
|
||||
this._cachedAabbs[key] = expanded;
|
||||
return expanded;
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
listeners() {
|
||||
return {
|
||||
|
||||
currentAnimationChanged: (oldKey, currentAnimation) => {
|
||||
this._currentAnimation = currentAnimation;
|
||||
// Reset old animation.
|
||||
if (oldKey in this.animations) {
|
||||
const oldAnimation = this.animations[oldKey];
|
||||
oldAnimation.reset();
|
||||
}
|
||||
// Bounding box update.
|
||||
this.entity.updateVisibleBoundingBox();
|
||||
// Only client/graphics.
|
||||
if (!this.animationViews) {
|
||||
return;
|
||||
}
|
||||
// Swap the animation.
|
||||
this.hideAnimation(oldKey);
|
||||
this.showAnimation(this._currentAnimation);
|
||||
},
|
||||
|
||||
directionChanged: () => {
|
||||
// All animations track direction.
|
||||
const animations = Object.values(this.animations);
|
||||
for (let i = 0; i < animations.length; i++) {
|
||||
animations[i].direction = this.entity.direction;
|
||||
}
|
||||
},
|
||||
|
||||
isDyingChanged: (_, isDying) => {
|
||||
this.isAnimating = !isDying;
|
||||
},
|
||||
|
||||
visibleScaleChanged: () => {
|
||||
this._cachedAabbs = {};
|
||||
this.setSpriteScale();
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
tick(elapsed) {
|
||||
if (!this.isAnimating) {
|
||||
return;
|
||||
}
|
||||
// Only tick current animation.
|
||||
const currentAnimation = this._currentAnimation;
|
||||
if (!(currentAnimation in this.animations)) {
|
||||
const currentAnimation = this.#currentAnimation;
|
||||
if (!(currentAnimation in this.#animations)) {
|
||||
return;
|
||||
}
|
||||
const animation = this.animations[currentAnimation];
|
||||
const animation = this.#animations[currentAnimation];
|
||||
const jitterAmount = this.jitterFor(currentAnimation);
|
||||
if (jitterAmount > 0) {
|
||||
const jitter = Math.random() * jitterAmount;
|
|
@ -31,7 +31,7 @@ import TransitionResult from './result';
|
|||
|
||||
export {TransitionResult};
|
||||
|
||||
export function TransitionMixin(Superclass) {
|
||||
export default function TransitionMixin(Superclass) {
|
||||
return class Transition extends Superclass {
|
||||
|
||||
transition(props, duration, easing) {
|
||||
|
|
|
@ -9,20 +9,18 @@ const decorate = compose(
|
|||
export default class TransitionResult extends decorate(Class) {
|
||||
|
||||
constructor(subject, props, duration, easing) {
|
||||
super(subject, props, duration, easing);
|
||||
// Speed might not get passed. If it doesn't, default to 100
|
||||
// milliseconds.
|
||||
super();
|
||||
// Speed might not get passed. If it doesn't, default to 100 milliseconds.
|
||||
this.duration = parseFloat(duration || 0.1);
|
||||
this.elapsed = 0;
|
||||
this._isEmittingProgress = false;
|
||||
this.isEmittingProgress = false;
|
||||
this.props = props;
|
||||
this.subject = subject;
|
||||
if ('function' === typeof easing) {
|
||||
this.easing = easing;
|
||||
}
|
||||
// If easing isn't passed in as a function, attempt to look it up
|
||||
// as a string key into Transition.easing. If that fails, then
|
||||
// default to 'easeOutQuad'.
|
||||
// If easing isn't passed in as a function, attempt to look it up as a string key into
|
||||
// Transition.easing. If that fails, then default to 'easeOutQuad'.
|
||||
else {
|
||||
this.easing = easingFunctions[easing] || easingFunctions.easeOutQuad;
|
||||
}
|
||||
|
@ -36,44 +34,33 @@ export default class TransitionResult extends decorate(Class) {
|
|||
this.change[key] = prop - value;
|
||||
}
|
||||
this.promise = new Promise((resolve) => {
|
||||
this.once('stopped', () => resolve());
|
||||
this.once('stopped', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
get isEmittingProgress() {
|
||||
return this._isEmittingProgress;
|
||||
}
|
||||
|
||||
set isEmittingProgress(isEmittingProgress) {
|
||||
this._isEmittingProgress = isEmittingProgress;
|
||||
}
|
||||
|
||||
// Immediately finish the transition. This will leave the object
|
||||
// in the fully transitioned state.
|
||||
// Immediately finish the transition. This will leave the object in the fully transitioned state.
|
||||
skipTransition() {
|
||||
// Just trick it into thinking the time passed and do one last
|
||||
// tick.
|
||||
// Just trick it into thinking the time passed and do one last tick.
|
||||
this.elapsed = this.duration;
|
||||
this.tick(0);
|
||||
}
|
||||
|
||||
// Immediately stop the transition. This will leave the object in
|
||||
// its current state; potentially partially transitioned.
|
||||
// Immediately stop the transition. This will leave the object in its current state;
|
||||
// potentially partially transitioned.
|
||||
stopTransition() {
|
||||
// Let any listeners know that the transition is complete.
|
||||
if (this._isEmittingProgress) {
|
||||
if (this.isEmittingProgress) {
|
||||
this.emit('progress', [this.elapsed, this.duration]);
|
||||
}
|
||||
this.emit('stopped');
|
||||
}
|
||||
|
||||
// Tick callback. Called repeatedly while this transition is
|
||||
// running.
|
||||
// Tick callback. Called repeatedly while this transition is running.
|
||||
tick(elapsed) {
|
||||
// Update the transition's elapsed time.
|
||||
this.elapsed += elapsed;
|
||||
// If we've overshot the duration, we'll fix it up here, so
|
||||
// things never transition too far (through the end point).
|
||||
// If we've overshot the duration, we'll fix it up here, so things never transition too far
|
||||
// (through the end point).
|
||||
if (this.elapsed >= this.duration) {
|
||||
this.elapsed = this.duration;
|
||||
const changes = Object.entries(this.change);
|
||||
|
@ -103,7 +90,7 @@ export default class TransitionResult extends decorate(Class) {
|
|||
if (this.elapsed === this.duration) {
|
||||
this.stopTransition();
|
||||
}
|
||||
if (this._isEmittingProgress) {
|
||||
if (this.isEmittingProgress) {
|
||||
this.emit('progress', [this.elapsed, this.duration]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
"@avocado/core@2.0.0", "@avocado/core@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://npm.i12e.cha0s.io/@avocado%2fcore/-/core-2.0.0.tgz#636ea3c3b54a38538c59485080f6a0e48f1798e7"
|
||||
integrity sha512-VW+ygRHaQQwaL5rKZGm0n0DNfvj+H89qQx+67veCUmUuRav3XAeE0iYs8Lgfc3CJLPz/alqt/dVPMXd5QDR+Mg==
|
||||
resolved "https://npm.i12e.cha0s.io/@avocado%2fcore/-/core-2.0.0.tgz#ee56331fb389deb196f0184d798d72b5d0fe6015"
|
||||
integrity sha512-AynteHSxM7TTzzGGRWrn3qvHi1Cru2Yhg1z4ZgJgh0FE2yxXRefIVe2PPRCTeYoRXvIpE7c+QtJjrJIvuApViQ==
|
||||
dependencies:
|
||||
debug "4.3.1"
|
||||
|
||||
|
@ -4796,6 +4796,11 @@ lodash.flatten@^4.4.0:
|
|||
resolved "https://npm.i12e.cha0s.io/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
|
||||
integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
|
||||
|
||||
lodash.mapvalues@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://npm.i12e.cha0s.io/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c"
|
||||
integrity sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=
|
||||
|
||||
lodash.omit@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://npm.i12e.cha0s.io/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60"
|
||||
|
|
|
@ -89,9 +89,6 @@ export default class Trait extends decorate(JsonResource) {
|
|||
return {};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this, no-empty-function
|
||||
async hydrate() {}
|
||||
|
||||
get isDirty() {
|
||||
const keys = Object.keys(this.state);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user