mnml/client/src/components/construct.jsx
2019-11-06 19:02:15 +10:00

121 lines
3.9 KiB
JavaScript

const preact = require('preact');
const { Component } = require('preact');
const { connect } = require('preact-redux');
// const { match } = require('./../utils');
const banish = require('./anims/banish');
const idleAnimation = require('./anims/idle');
const invert = require('./anims/invert');
const wiggle = require('./anims/wiggle');
const sourceCast = require('./anims/source.cast');
const { ConstructAnimation } = require('./animations');
const addState = connect(
function receiveState(state) {
const { animSource, animTarget, animText } = state;
return { animSource, animTarget, animText };
}
);
class ConstructAvatar extends Component {
constructor(props) {
super();
// The animation ids are a check to ensure that animations are not repeated
// When a new construct animation is communicated with state it will have a corresponding Id
// which is a count of how many resoluttions have passed
this.animations = [];
this.resetAnimations = this.resetAnimations.bind(this);
}
render() {
const { construct, mouseOver } = this.props;
return (
<div
class="avatar"
id={construct.id}
onMouseDown={this.onClick.bind(this)}
onMouseOver={mouseOver ? mouseOver : null}
style={{ 'background-image': `url(/imgs/${construct.img}.svg)` }}>
<ConstructAnimation construct={construct} />
</div>
);
}
onClick() {
return this.animations.push(wiggle(this.props.construct.id, this.idle));
}
componentDidMount() {
this.idle = idleAnimation(this.props.construct.id);
return this.animations.push(this.idle);
}
resetAnimations() {
for (let i = this.animations.length - 1; i >= 0; i--) {
this.animations[i].reset();
}
}
componentWillUnmount() {
this.resetAnimations();
}
componentDidUpdate(prevProps) {
const { animSource, animTarget, animText, construct } = this.props;
// a different text object and text construct
if (animText && animText !== prevProps.animText && animText.constructId === construct.id) {
return wiggle(construct.id, this.idle);
}
// different source object and source construct
if (animSource && animSource !== prevProps.animSource && animSource.constructId === construct.id) {
return sourceCast(animSource.constructId, animSource.direction, this.idle);
}
// different target object and target construct
if (animTarget && animTarget !== prevProps.animTarget && animTarget.constructId.includes(construct.id)) {
switch (animTarget.skill) {
case 'Banish': return banish(construct.id, this.idle);
case 'Invert': return invert(construct.id, this.idle);
default: return null;
}
}
return true;
}
shouldComponentUpdate(newProps) {
const { animSource, animTarget, animText, construct } = newProps;
if (animSource !== this.props.animSource) return true;
if (animTarget !== this.props.animTarget) return true;
if (animText !== this.props.animText) return true;
if (construct !== this.props.construct) return true;
return false;
}
}
const addStateText = connect(
function receiveState(state) {
const { animText } = state;
return { animText };
}
);
function constructText(props) {
const { construct, animText } = props;
if (!construct) return false;
const text = animText && animText.constructId === construct.id
? animText.text
: construct.name;
return <h3 class={'name'}><span>{text}</span></h3>;
}
module.exports = {
ConstructAvatar: addState(ConstructAvatar),
ConstructText: addStateText(constructText),
};