1 | "use strict";
|
2 |
|
3 | const utilities = require("extra-utilities");
|
4 | const Tile = require("./tile.js");
|
5 | const TileAttribute = require("./tile-attribute.js");
|
6 |
|
7 | class TileAttributes {
|
8 | constructor(xOffset, yOffset, numberOfFrames, animationType, animationSpeed, extra) {
|
9 | let self = this;
|
10 |
|
11 | let _properties = { };
|
12 |
|
13 | for(let i = 0; i < TileAttributes.Attribute.Attributes.length; i++) {
|
14 | const attribute = TileAttributes.Attribute.Attributes[i];
|
15 |
|
16 | Object.defineProperty(self, attribute.attributeName, {
|
17 | enumerable: true,
|
18 | get() {
|
19 | return _properties[attribute.attributeName];
|
20 | },
|
21 | set(value) {
|
22 | const newValue = utilities.parseInteger(value);
|
23 |
|
24 | if(isNaN(newValue)) {
|
25 | throw new Error("Invalid " + attribute.name + " value: " + value + " expected valid integer value.");
|
26 | }
|
27 |
|
28 | if(newValue < attribute.min || newValue > attribute.max) {
|
29 | throw new Error(attribute.name + " value: " + newValue + " out of range, expected integer value between " + attribute.min + " and " + attribute.max + ", inclusively.");
|
30 | }
|
31 |
|
32 | _properties[attribute.attributeName] = newValue;
|
33 | }
|
34 | });
|
35 | }
|
36 |
|
37 | self.xOffset = xOffset;
|
38 | self.yOffset = yOffset;
|
39 | self.numberOfFrames = numberOfFrames;
|
40 | self.animationType = animationType;
|
41 | self.animationSpeed = animationSpeed;
|
42 | self.extra = extra;
|
43 | }
|
44 |
|
45 | getAnimationType() {
|
46 | let self = this;
|
47 |
|
48 | const animationType = Tile.AnimationType.Types[self.animationType];
|
49 |
|
50 | return Tile.AnimationType.isValid(animationType) ? animationType : Tile.AnimationType.Invalid;
|
51 | }
|
52 |
|
53 | getMetadata() {
|
54 | let self = this;
|
55 |
|
56 | return {
|
57 | xOffset: self.xOffset,
|
58 | yOffset: self.yOffset,
|
59 | numberOfFrames: self.numberOfFrames,
|
60 | animationType: self.getAnimationType().name,
|
61 | animationSpeed: self.animationSpeed,
|
62 | extra: self.extra
|
63 | };
|
64 | }
|
65 |
|
66 | pack() {
|
67 | let self = this;
|
68 |
|
69 | let packedValue = 0;
|
70 |
|
71 | for(let i = 0; i < TileAttributes.Attribute.Attributes.length; i++) {
|
72 | const attribute = TileAttributes.Attribute.Attributes[i];
|
73 |
|
74 | packedValue += utilities.leftShift(self[attribute.attributeName] & attribute.mask, attribute.offset);
|
75 | }
|
76 |
|
77 | return packedValue;
|
78 | }
|
79 |
|
80 | static unpack(packedValue) {
|
81 | packedValue = utilities.parseInteger(packedValue);
|
82 |
|
83 | if(!Number.isInteger(packedValue)) {
|
84 | return null;
|
85 | }
|
86 |
|
87 | let tileAttributes = [];
|
88 |
|
89 | for(let i = 0; i < TileAttributes.Attribute.Attributes.length; i++) {
|
90 | const attribute = TileAttributes.Attribute.Attributes[i];
|
91 |
|
92 | tileAttributes[i] = utilities.rightShift((packedValue & attribute.offsetMask), attribute.offset) & attribute.mask;
|
93 |
|
94 | if(attribute.signed) {
|
95 | tileAttributes[i] = ((tileAttributes[i] & attribute.signBitMask) === attribute.signBitMask) ? -(attribute.mask - tileAttributes[i] + 1) : tileAttributes[i];
|
96 | }
|
97 | }
|
98 |
|
99 | return new (Function.prototype.bind.apply(TileAttributes, [null].concat(tileAttributes)));
|
100 | }
|
101 |
|
102 | equals(value) {
|
103 | let self = this;
|
104 |
|
105 | if(!TileAttributes.isTileAttributes(value)) {
|
106 | return false;
|
107 | }
|
108 |
|
109 | return self.xOffset === value.xOffset &&
|
110 | self.yOffset === value.yOffset &&
|
111 | self.numberOfFrames === value.numberOfFrames &&
|
112 | self.animationType === value.animationType &&
|
113 | self.animationSpeed === value.animationSpeed;
|
114 | }
|
115 |
|
116 | toString() {
|
117 | let self = this;
|
118 |
|
119 | let tileAttributeString = "Tile Attributes (";
|
120 |
|
121 | for(let i = 0; i < TileAttributes.Attribute.Attributes.length; i++) {
|
122 | const attribute = TileAttributes.Attribute.Attributes[i];
|
123 |
|
124 | if(i !== 0) {
|
125 | tileAttributeString += ", ";
|
126 | }
|
127 |
|
128 | tileAttributeString += attribute.name + ": ";
|
129 |
|
130 | if(attribute === TileAttributes.AnimationType) {
|
131 | tileAttributeString += self.getAnimationType().name;
|
132 | }
|
133 | else {
|
134 | tileAttributeString += self[attribute.attributeName];
|
135 | }
|
136 | }
|
137 |
|
138 | tileAttributeString += ")";
|
139 |
|
140 | return tileAttributeString;
|
141 | }
|
142 |
|
143 | clone() {
|
144 | const self = this;
|
145 |
|
146 | return new TileAttributes(self.xOffset, self.yOffset, self.numberOfFrames, self.animationType, self.animationSpeed, self.extra);
|
147 | }
|
148 |
|
149 | static isTileAttributes(value) {
|
150 | return value instanceof TileAttributes;
|
151 | }
|
152 | }
|
153 |
|
154 | Object.defineProperty(TileAttributes, "Attribute", {
|
155 | value: TileAttribute,
|
156 | enumerable: true
|
157 | });
|
158 |
|
159 | module.exports = TileAttributes;
|