Files
pixel.horse/src/ts/components/tools/tools-states/tools-states.ts
T
2019-08-30 01:52:40 -07:00

140 lines
4.9 KiB
TypeScript

import { Component } from '@angular/core';
import { fromPairs } from 'lodash';
import { faHome } from '../../../client/icons';
import { ponyStates, } from '../../../client/ponyStates';
import { AgDragEvent } from '../../shared/directives/agDrag';
import { AnimatorState } from '../../../common/animator';
import { distance, flatten } from '../../../common/utils';
function getPos(key: string, type: 'x' | 'y', defaultValue = 100) {
const item = localStorage.getItem(`tools-stats-${key}-${type}`);
return item ? parseInt(item, 10) : defaultValue;
}
function setPos(key: string, type: 'x' | 'y', value: number) {
localStorage.setItem(`tools-stats-${key}-${type}`, value.toString());
}
const defaultPositions: any = {
'any': { 'x': 917, 'y': 43 },
'standing': { 'x': 317, 'y': 300 },
'trotting': { 'x': 660, 'y': 304 },
'swimming': { 'x': 988, 'y': 435 },
'swimming-to-trotting': { 'x': 747, 'y': 548 },
'trotting-to-swimming': { 'x': 805, 'y': 413 },
'booping': { 'x': 106, 'y': 301 },
'booping-sitting': { 'x': 111, 'y': 569 },
'booping-lying': { 'x': 127, 'y': 821 },
'booping-flying': { 'x': 110, 'y': 64 },
'sitting': { 'x': 312, 'y': 569 },
'sitting-down': { 'x': 186, 'y': 437 },
'standing-up': { 'x': 313, 'y': 436 },
'sitting-to-trotting': { 'x': 517, 'y': 500 },
'lying': { 'x': 326, 'y': 818 },
'lying-down': { 'x': 254, 'y': 692 },
'sitting-up': { 'x': 385, 'y': 682 },
'lying-to-trotting': { 'x': 541, 'y': 731 },
'hovering': { 'x': 334, 'y': 21 },
'flying': { 'x': 641, 'y': 29 },
'flying-up': { 'x': 378, 'y': 182 },
'flying-down': { 'x': 247, 'y': 177 },
'trotting-to-flying': { 'x': 601, 'y': 188 },
'flying-to-trotting': { 'x': 805, 'y': 270 },
'swinging': { 'x': 484, 'y': 238 },
'swimming-to-flying': { 'x': 1063, 'y': 182 },
'flying-to-swimming': { 'x': 938, 'y': 232 },
'booping-swimming': { 'x': 1144, 'y': 432 }
};
@Component({
selector: 'tools-states',
templateUrl: 'tools-states.pug',
styleUrls: ['tools-states.scss'],
})
export class ToolsStates {
readonly homeIcon = faHome;
private startX = 0;
private startY = 0;
arrowColors = ['orange', 'red', 'lime'];
states = ponyStates.map(state => {
const def = defaultPositions[state.name] || { x: 0, y: 0 };
return {
color: state.name === 'any' ? 'orange' : (state.animation.loop ? 'LightSeaGreen' : 'cornflowerblue'),
name: state.name,
variants: Object.keys(state.variants || {}).join(', '),
state,
x: getPos(state.name, 'x', def.x),
y: getPos(state.name, 'y', def.y),
};
});
arrows: { path: string; color: string; }[] = [];
times: { x: number; y: number; color: string; text: string; title?: string; }[] = [];
constructor() {
this.updateArrows();
}
drag(state: any, { dx, dy, type }: AgDragEvent) {
if (type === 'start') {
this.startX = state.x;
this.startY = state.y;
}
setPos(state.name, 'x', state.x = this.startX + dx);
setPos(state.name, 'y', state.y = this.startY + dy);
this.updateArrows();
}
logPositions() {
const positions = fromPairs(this.states.map(({ name, x, y }) => [name, { x, y }]));
console.log(JSON.stringify(positions).replace(/"/g, `'`).replace(/},/g, '},\n'));
}
private updateArrows() {
this.times = [];
this.arrows = flatten(this.states.map(s => s.state.from.map(f => ({
to: s,
from: this.findState(f.state),
color: f.exitAfter === 0 ? (f.keepTime ? 'orange' : 'red') : 'lime',
exitAfter: f.exitAfter,
enterTime: f.enterTime,
onlyDirectTo: f.onlyDirectTo,
}))))
.filter(({ from, to }) => from && to)
.map(({ from, to, color, exitAfter, enterTime, onlyDirectTo }) => {
const length = distance(from, to) || 1;
const r1 = 50;
const nx1 = ((to.x - from.x) / length) * r1;
const ny1 = ((to.y - from.y) / length) * r1;
const r2 = 60;
const nx2 = ((to.x - from.x) / length) * r2;
const ny2 = ((to.y - from.y) / length) * r2;
const r3 = 75;
const nx3 = ((to.x - from.x) / length) * r3;
const ny3 = ((to.y - from.y) / length) * r3;
const r4 = 80;
const nx4 = ((to.x - from.x) / length) * r4;
const ny4 = ((to.y - from.y) / length) * r4;
const fromX = from.x + nx1;
const fromY = from.y + ny1;
if (exitAfter) {
this.times.push({ x: fromX, y: fromY, color, text: exitAfter.toFixed(1) });
}
if (enterTime) {
this.times.push({ x: to.x - nx3, y: to.y - ny3, color, text: enterTime.toFixed(1) });
}
if (onlyDirectTo) {
this.times.push({
x: from.x + nx4, y: from.y + ny4, color, text: '?', title: `only directly to: ${onlyDirectTo.name}`
});
}
return { path: `M ${fromX} ${fromY} L ${to.x - nx2} ${to.y - ny2}`, color };
});
}
private findState(state: AnimatorState<any>) {
return this.states.find(s => s.state === state)!;
}
}