wgge 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/ActivatedTreeNode.js +187 -0
- package/core/Collection.js +156 -0
- package/core/Dictionary.js +83 -0
- package/core/animation/3d/AnimatedVector3.js +35 -0
- package/core/animation/3d/AnimationHelper.js +103 -0
- package/core/animation/3d/ProgressVector3.js +26 -0
- package/core/animation/AnimatedRotation.js +44 -0
- package/core/animation/AnimatedValue.js +33 -0
- package/core/animation/AnimatedVector2.js +35 -0
- package/core/animation/ProgressRotation.js +40 -0
- package/core/animation/ProgressValue.js +27 -0
- package/core/animation/ProgressVector2.js +23 -0
- package/core/audio/AudioModel.js +36 -0
- package/core/audio/AudioRenderer.js +120 -0
- package/core/audio/global/GlobalAudioModel.js +88 -0
- package/core/audio/global/GlobalAudioRenderer.js +108 -0
- package/core/controller/AnimationController.js +37 -0
- package/core/controller/AnimationFloatController.js +39 -0
- package/core/controller/AnimationVector2Controller.js +39 -0
- package/core/controller/CollectionController.js +47 -0
- package/core/controller/ConditionalNodeController.js +51 -0
- package/core/controller/ControllerBase.js +64 -0
- package/core/controller/ControllerWithSaveGame.js +27 -0
- package/core/controller/ControllerWithTimeout.js +10 -0
- package/core/controller/NullableNodeController.js +35 -0
- package/core/controller/TimeoutController.js +26 -0
- package/core/helper/ArrayHelper.js +19 -0
- package/core/helper/DOMHelper.js +167 -0
- package/core/helper/GUIHelper.js +53 -0
- package/core/helper/HttpHelper.js +33 -0
- package/core/helper/ImageHelper.js +36 -0
- package/core/helper/NumberHelper.js +28 -0
- package/core/helper/ObjectHelper.js +10 -0
- package/core/helper/StringHelper.js +59 -0
- package/core/model/ModelBase.js +91 -0
- package/core/model/ObjectModel.js +97 -0
- package/core/model/collection/ModelNodeCollection.js +232 -0
- package/core/model/collection/table/IdentifiedModelNode.js +24 -0
- package/core/model/collection/table/ModelNodeTable.js +53 -0
- package/core/model/event/ChangeEvent.js +24 -0
- package/core/model/event/EventManager.js +44 -0
- package/core/model/event/NodeWithEvents.js +32 -0
- package/core/model/template/TemplateNode.js +45 -0
- package/core/model/value/BoolValue.js +17 -0
- package/core/model/value/CapacityValue.js +49 -0
- package/core/model/value/DirtyValue.js +66 -0
- package/core/model/value/FloatValue.js +8 -0
- package/core/model/value/IntValue.js +20 -0
- package/core/model/value/NullableNode.js +66 -0
- package/core/model/value/StringValue.js +21 -0
- package/core/model/vector/Quaternion.js +82 -0
- package/core/model/vector/Rotation.js +61 -0
- package/core/model/vector/Vector2.js +177 -0
- package/core/model/vector/Vector3.js +98 -0
- package/core/renderer/RendererBase.js +46 -0
- package/core/renderer/canvas/CanvasRenderer.js +60 -0
- package/core/renderer/canvas/ImageToCanvasRenderer.js +94 -0
- package/core/renderer/dom/DirtyValueRenderer.js +36 -0
- package/core/renderer/dom/DomRenderer.js +32 -0
- package/core/renderer/dom/ImageRenderer.js +41 -0
- package/core/renderer/dom/Vector2Renderer.js +37 -0
- package/core/renderer/generic/CollectionRenderer.js +50 -0
- package/core/renderer/generic/ConditionalNodeRenderer.js +57 -0
- package/core/renderer/generic/NullableNodeRenderer.js +43 -0
- package/core/renderer/svg/SvgRenderer.js +130 -0
- package/editor/EditorController.js +135 -0
- package/editor/EditorModel.js +38 -0
- package/editor/EditorRenderer.js +116 -0
- package/editor/form/NodeFormRenderer.js +180 -0
- package/editor/material/MaterialPreviewRenderer.js +136 -0
- package/editor/table/TableRenderer.js +123 -0
- package/editor/table/lookup/TableLookupRenderer.js +120 -0
- package/editor/table/row/TableRowRenderer.js +97 -0
- package/game/GameController.js +144 -0
- package/game/GameModel.js +73 -0
- package/game/GameRenderer.js +108 -0
- package/game/controls/ControlsController.js +104 -0
- package/game/controls/ControlsModel.js +60 -0
- package/game/menu/MenuModel.js +25 -0
- package/game/menu/MenuRenderer.js +37 -0
- package/game/menu/item/MenuItemModel.js +31 -0
- package/game/menu/item/MenuItemRenderer.js +40 -0
- package/game/resources/3d/3DModel.js +30 -0
- package/game/resources/ResourcesModel.js +26 -0
- package/game/resources/assets/AssetCache.js +193 -0
- package/game/resources/assets/loader/AssetLoader.js +56 -0
- package/game/resources/assets/loader/AudioLoader.js +15 -0
- package/game/resources/assets/loader/GlbLoader.js +16 -0
- package/game/resources/assets/loader/ImageLoader.js +15 -0
- package/game/resources/assets/loader/MaterialLoader.js +49 -0
- package/game/resources/assets/loader/Model3dLoader.js +21 -0
- package/game/resources/assets/loader/SpriteLoader.js +40 -0
- package/game/resources/image/DualImageModel.js +34 -0
- package/game/resources/image/ImageModel.js +43 -0
- package/game/resources/material/MaterialModel.js +69 -0
- package/game/save/SaveGameController.js +21 -0
- package/game/save/SaveGameModel.js +5 -0
- package/game/save/SaveGameRenderer.js +17 -0
- package/game/save/editor/SaveGameEditorRenderer.js +17 -0
- package/index.html +42 -0
- package/index.js +73 -0
- package/package.json +35 -0
- package/style/basic/editor.less +290 -0
- package/style/basic/game.less +149 -0
- package/style/basic/utilities.less +215 -0
- package/style/style.less +3 -0
- package/webpack.config.js +29 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import DirtyValue from "./DirtyValue";
|
|
2
|
+
|
|
3
|
+
export default class IntValue extends DirtyValue {
|
|
4
|
+
|
|
5
|
+
set(value) {
|
|
6
|
+
if (value === null || value === undefined || value === '') {
|
|
7
|
+
super.set(Number.NaN);
|
|
8
|
+
} else {
|
|
9
|
+
super.set(Number(value));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
isEmpty() {
|
|
14
|
+
return super.isEmpty() || Number.isNaN(this.value);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
increase(num) {
|
|
18
|
+
this.set(this.get() + num);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import DirtyValue from "./DirtyValue";
|
|
2
|
+
|
|
3
|
+
export default class NullableNode extends DirtyValue {
|
|
4
|
+
nodeFactory;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @type {ObjectModel}
|
|
8
|
+
*/
|
|
9
|
+
value;
|
|
10
|
+
|
|
11
|
+
constructor(nodeFactory = null, persistent = true) {
|
|
12
|
+
super(null, persistent);
|
|
13
|
+
|
|
14
|
+
this.nodeFactory = nodeFactory;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param {ObjectModel} value
|
|
20
|
+
*/
|
|
21
|
+
set(value) {
|
|
22
|
+
if (this.isSet()) {
|
|
23
|
+
this.unsubscribeFromOnDirtyEvent(this.value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
super.set(value);
|
|
27
|
+
|
|
28
|
+
if (this.isSet()) {
|
|
29
|
+
this.subscribeToOnDirtyEvent(this.value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getStateInternal() {
|
|
34
|
+
if (this.isSet()) {
|
|
35
|
+
return this.value.getState();
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
restoreStateInternal(state) {
|
|
41
|
+
this.set(null);
|
|
42
|
+
if (state && this.isPersistent) {
|
|
43
|
+
if (!this.nodeFactory) {
|
|
44
|
+
console.log('No nodeFactory to restore NullableNode');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const node = this.nodeFactory();
|
|
48
|
+
node.restoreState(state);
|
|
49
|
+
this.set(node);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
clean() {
|
|
54
|
+
if (super.clean()) {
|
|
55
|
+
if (this.value && typeof this.value.clean === 'function') this.value.clean();
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getResourcesForPreload() {
|
|
61
|
+
if (this.isSet()) {
|
|
62
|
+
return this.value.getResourcesForPreload();
|
|
63
|
+
}
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import DirtyValue from "./DirtyValue";
|
|
2
|
+
|
|
3
|
+
export default class StringValue extends DirtyValue {
|
|
4
|
+
|
|
5
|
+
set(value) {
|
|
6
|
+
if (typeof value === 'string') {
|
|
7
|
+
super.set(value);
|
|
8
|
+
} else {
|
|
9
|
+
if (value && typeof value === 'object') {
|
|
10
|
+
super.set(value.toString());
|
|
11
|
+
} else {
|
|
12
|
+
super.set('');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
isEmpty() {
|
|
18
|
+
return super.isEmpty() || this.value === '';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import ObjectModel from "../ObjectModel";
|
|
2
|
+
|
|
3
|
+
export default class Quaternion extends ObjectModel {
|
|
4
|
+
x;
|
|
5
|
+
y;
|
|
6
|
+
z;
|
|
7
|
+
w;
|
|
8
|
+
|
|
9
|
+
constructor(x, y, z, w) {
|
|
10
|
+
super();
|
|
11
|
+
|
|
12
|
+
this.x = 0;
|
|
13
|
+
this.y = 0;
|
|
14
|
+
this.z = 0;
|
|
15
|
+
this.w = 0;
|
|
16
|
+
|
|
17
|
+
if (y === undefined && typeof x === 'object') {
|
|
18
|
+
if (x.length === 4) {
|
|
19
|
+
this.setFromArray(x);
|
|
20
|
+
} else {
|
|
21
|
+
this.set(x);
|
|
22
|
+
}
|
|
23
|
+
} else if (x !== undefined && w !== undefined) {
|
|
24
|
+
this.set(x, y, z, w);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
equalsTo(v) {
|
|
29
|
+
return (v) ? this.x === v.x && this.y === v.y && this.z === v.z && this.w === v.w : false;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set(x, y, z, w) {
|
|
33
|
+
if (y === undefined && typeof x === 'object') {
|
|
34
|
+
this.set(x.x, x.y, x.z, x.w);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
x = Number(x);
|
|
39
|
+
y = Number(y);
|
|
40
|
+
z = Number(z);
|
|
41
|
+
w = Number(w);
|
|
42
|
+
|
|
43
|
+
if ((this.x !== x || this.y !== y || this.z !== z || this.w !== w)) {
|
|
44
|
+
const old = this.clone();
|
|
45
|
+
this.x = x;
|
|
46
|
+
this.y = y;
|
|
47
|
+
this.z = z;
|
|
48
|
+
this.w = w;
|
|
49
|
+
this.makeDirty();
|
|
50
|
+
this.triggerEvent('change', {oldValue: old, newValue: this});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
toArray() {
|
|
55
|
+
return [this.x, this.y, this.z, this.w];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setFromArray(arr) {
|
|
59
|
+
if (typeof arr === 'object' && arr.length === 4) {
|
|
60
|
+
this.set(arr[0], arr[1], arr[2], arr[3]);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static fromArray(arr) {
|
|
65
|
+
const v = new Quaternion();
|
|
66
|
+
v.setFromArray(arr);
|
|
67
|
+
return v;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
clone() {
|
|
71
|
+
return new Quaternion(this);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
getStateInternal() {
|
|
75
|
+
return this.toArray();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
restoreStateInternal(state) {
|
|
79
|
+
this.setFromArray(state);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import DirtyValue from "../value/DirtyValue";
|
|
2
|
+
|
|
3
|
+
const ROTATION_RANGE = 2 * Math.PI;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Keeps track of rotation in radians that is always in interval (-pi, +pi> which equals to (-180, 180> degrees
|
|
7
|
+
*/
|
|
8
|
+
export default class Rotation extends DirtyValue {
|
|
9
|
+
|
|
10
|
+
static normalizeValue(rads) {
|
|
11
|
+
let result = rads % ROTATION_RANGE;
|
|
12
|
+
if (result > (ROTATION_RANGE / 2)) {
|
|
13
|
+
result = result - ROTATION_RANGE;
|
|
14
|
+
}
|
|
15
|
+
if (result <= (-ROTATION_RANGE / 2)) {
|
|
16
|
+
result = result + ROTATION_RANGE;
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static diff(a, b) {
|
|
22
|
+
return Rotation.normalizeValue(Rotation.normalizeValue(a) - Rotation.normalizeValue(b));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static radToDeg(rads) {
|
|
26
|
+
return rads * 180 / Math.PI;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
static degToRad(degs) {
|
|
30
|
+
return degs * Math.PI / 180;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
set(value) {
|
|
34
|
+
super.set(Rotation.normalizeValue(value));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
add(value) {
|
|
38
|
+
return new Rotation(this.get() + value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
subtract(value) {
|
|
42
|
+
return new Rotation(Rotation.diff(this.get(), value));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
equalsTo(value) {
|
|
46
|
+
return (this.value === Rotation.normalizeValue(value));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
clone() {
|
|
50
|
+
return new Rotation(this.value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setDegrees(value) {
|
|
54
|
+
this.set(Rotation.degToRad(value));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getDegrees() {
|
|
58
|
+
return Rotation.radToDeg(this.get());
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import ObjectModel from "../ObjectModel";
|
|
2
|
+
import Rotation from "./Rotation";
|
|
3
|
+
|
|
4
|
+
export default class Vector2 extends ObjectModel {
|
|
5
|
+
x;
|
|
6
|
+
y;
|
|
7
|
+
|
|
8
|
+
constructor(x, y, persistent) {
|
|
9
|
+
super(persistent);
|
|
10
|
+
|
|
11
|
+
this.x = 0;
|
|
12
|
+
this.y = 0;
|
|
13
|
+
|
|
14
|
+
if (y === undefined && typeof x === 'object') {
|
|
15
|
+
if (x.length === 2) {
|
|
16
|
+
this.setFromArray(x);
|
|
17
|
+
} else {
|
|
18
|
+
this.set(x);
|
|
19
|
+
}
|
|
20
|
+
} else if (x !== undefined) {
|
|
21
|
+
this.set(x, y);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
distanceTo(v) {
|
|
26
|
+
return Math.sqrt(Math.pow(this.x - v.x, 2) + Math.pow(this.y - v.y, 2));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
equalsTo(v) {
|
|
30
|
+
return (v) ? this.x === v.x && this.y === v.y : false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
*
|
|
35
|
+
* @param x Number|Vector2
|
|
36
|
+
* @param y Number|undefined
|
|
37
|
+
*/
|
|
38
|
+
set(x, y = undefined) {
|
|
39
|
+
if (y === undefined && typeof x === 'object') {
|
|
40
|
+
this.set(x.x, x.y);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
x = Number(x);
|
|
45
|
+
y = Number(y);
|
|
46
|
+
|
|
47
|
+
if (this.x !== x || this.y !== y) {
|
|
48
|
+
const old = this.clone();
|
|
49
|
+
this.x = x;
|
|
50
|
+
this.y = y;
|
|
51
|
+
this.makeDirty();
|
|
52
|
+
this.triggerEvent('change', {oldValue: old, newValue: this});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
size() {
|
|
57
|
+
return this.distanceTo(new Vector2(0, 0));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setSize(size) {
|
|
61
|
+
const currentSize = this.size();
|
|
62
|
+
if (currentSize !== 0) {
|
|
63
|
+
const ratio = size / currentSize;
|
|
64
|
+
this.set(this.x * ratio, this.y * ratio);
|
|
65
|
+
}
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
round() {
|
|
70
|
+
return new Vector2(Math.round(this.x), Math.round(this.y));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
add(v) {
|
|
74
|
+
return new Vector2(this.x + v.x, this.y + v.y);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
multiply(s) {
|
|
78
|
+
return new Vector2(this.x * s, this.y * s);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
subtract(v) {
|
|
82
|
+
return new Vector2(this.x - v.x, this.y - v.y);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
sub(v) {
|
|
86
|
+
return this.subtract(v);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
toArray() {
|
|
90
|
+
return [this.x, this.y];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
setFromArray(arr) {
|
|
94
|
+
if (typeof arr === 'object' && arr.length === 2) {
|
|
95
|
+
this.set(arr[0], arr[1]);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
clone() {
|
|
100
|
+
return new Vector2(this.x, this.y);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getStateInternal() {
|
|
104
|
+
return this.toArray();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
restoreStateInternal(state) {
|
|
108
|
+
this.setFromArray(state);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/***
|
|
112
|
+
* Return angle between AB and Y axis in radians
|
|
113
|
+
* @param {Vector2} b
|
|
114
|
+
* @returns {number}
|
|
115
|
+
*/
|
|
116
|
+
getAngleToYAxis(b) {
|
|
117
|
+
const diff = b.subtract(this);
|
|
118
|
+
const down = diff.y < 0;
|
|
119
|
+
const sinX = diff.x / diff.size();
|
|
120
|
+
const angle = Math.asin(sinX);
|
|
121
|
+
const result = down ?
|
|
122
|
+
Math.PI - angle :
|
|
123
|
+
angle;
|
|
124
|
+
return result || 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getNeighborPositions(size = 1, includeCenter = false) {
|
|
128
|
+
const neighbors = [];
|
|
129
|
+
const maxX = this.x + size;
|
|
130
|
+
for (let x = this.x - size; x <= maxX; x++) {
|
|
131
|
+
const maxY = this.y + size;
|
|
132
|
+
for (let y = this.y - size; y <= maxY; y++) {
|
|
133
|
+
const n = new Vector2(x, y);
|
|
134
|
+
if (includeCenter || !this.equalsTo(n)) {
|
|
135
|
+
neighbors.push(n);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return neighbors;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getClosest(positions) {
|
|
143
|
+
if ((!positions) || positions.length === 0) return null;
|
|
144
|
+
if (positions.length === 1) return positions[0];
|
|
145
|
+
let closest = positions[0];
|
|
146
|
+
let distance = this.distanceTo(closest);
|
|
147
|
+
for (let i = 1, max = positions.length; i < max; i++) {
|
|
148
|
+
const d = this.distanceTo(positions[i]);
|
|
149
|
+
if (d < distance) {
|
|
150
|
+
closest = positions[i];
|
|
151
|
+
distance = d;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return closest;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* If you are standing at this vector and looking at target vector, this will be rotation that you have to Y axis.
|
|
159
|
+
* @param {Vector2} target
|
|
160
|
+
* @returns {Rotation}
|
|
161
|
+
*/
|
|
162
|
+
getRotationFromYAxis(target) {
|
|
163
|
+
return new Rotation(this.getAngleToYAxis(target));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
addOnChangeListener(eventHandler) {
|
|
167
|
+
this.addEventListener('change', eventHandler);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
removeOnChangeListener(eventHandler) {
|
|
171
|
+
this.removeEventListener('change', eventHandler);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
toString() {
|
|
175
|
+
return `[${this.x},${this.y}]`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import ObjectModel from "../ObjectModel";
|
|
2
|
+
import {Vector3 as ThreeVector3} from "three";
|
|
3
|
+
|
|
4
|
+
export default class Vector3 extends ObjectModel {
|
|
5
|
+
x;
|
|
6
|
+
y;
|
|
7
|
+
z;
|
|
8
|
+
|
|
9
|
+
constructor(x, y, z) {
|
|
10
|
+
super();
|
|
11
|
+
|
|
12
|
+
this.x = 0;
|
|
13
|
+
this.y = 0;
|
|
14
|
+
this.z = 0;
|
|
15
|
+
|
|
16
|
+
if (y === undefined && typeof x === 'object') {
|
|
17
|
+
if (x.length === 3) {
|
|
18
|
+
this.setFromArray(x);
|
|
19
|
+
} else {
|
|
20
|
+
this.set(x);
|
|
21
|
+
}
|
|
22
|
+
} else if (x !== undefined && z !== undefined) {
|
|
23
|
+
this.set(x, y, z);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
equalsTo(v) {
|
|
28
|
+
return (v) ? this.x === v.x && this.y === v.y && this.z === v.z : false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
set(x, y, z) {
|
|
32
|
+
if (y === undefined && typeof x === 'object') {
|
|
33
|
+
this.set(x.x, x.y, x.z);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
x = Number(x);
|
|
38
|
+
y = Number(y);
|
|
39
|
+
z = Number(z);
|
|
40
|
+
|
|
41
|
+
if ((this.x !== x || this.y !== y || this.z !== z)) {
|
|
42
|
+
const old = this.clone();
|
|
43
|
+
this.x = x;
|
|
44
|
+
this.y = y;
|
|
45
|
+
this.z = z;
|
|
46
|
+
this.makeDirty();
|
|
47
|
+
this.triggerEvent('change', {oldValue: old, newValue: this});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
add(v) {
|
|
52
|
+
return new Vector3(this.x + v.x, this.y + v.y, this.z + v.z);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
multiply(s) {
|
|
56
|
+
return new Vector3(this.x * s, this.y * s, this.z * s);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
subtract(v) {
|
|
60
|
+
return new Vector3(this.x - v.x, this.y - v.y, this.z - v.z);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
toArray() {
|
|
64
|
+
return [this.x, this.y, this.z];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
setFromArray(arr) {
|
|
68
|
+
if (typeof arr === 'object' && arr.length === 3) {
|
|
69
|
+
this.set(arr[0], arr[1], arr[2]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static fromArray(arr) {
|
|
74
|
+
const v = new Vector3();
|
|
75
|
+
v.setFromArray(arr);
|
|
76
|
+
return v;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
clone() {
|
|
80
|
+
return new Vector3(this);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
getStateInternal() {
|
|
84
|
+
return this.toArray();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
restoreStateInternal(state) {
|
|
88
|
+
this.setFromArray(state);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
getThree() {
|
|
92
|
+
return new ThreeVector3(this.x, this.y, this.z);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
asRgbColor() {
|
|
96
|
+
return `rgb(${Math.round(this.x)}, ${Math.round(this.y)}, ${Math.round(this.z)})`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import ActivatedTreeNode from "../ActivatedTreeNode";
|
|
2
|
+
|
|
3
|
+
export default class RendererBase extends ActivatedTreeNode {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @type GameModel
|
|
7
|
+
*/
|
|
8
|
+
game;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @type ModelBase
|
|
12
|
+
*/
|
|
13
|
+
model;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {GameModel} game
|
|
17
|
+
* @param {ModelBase} model
|
|
18
|
+
*/
|
|
19
|
+
constructor(game, model) {
|
|
20
|
+
super();
|
|
21
|
+
this.game = game;
|
|
22
|
+
this.model = model;
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
render() {
|
|
27
|
+
if (!this.model.isDirty) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!this.isActivated) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
this.renderInternal();
|
|
34
|
+
this.children.forEach((c) => c.render());
|
|
35
|
+
if (this.isRoot()) {
|
|
36
|
+
this.model.clean();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Override this
|
|
42
|
+
*/
|
|
43
|
+
renderInternal() {
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import RendererBase from "../RendererBase";
|
|
2
|
+
|
|
3
|
+
export default class CanvasRenderer extends RendererBase {
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @type HTMLCanvasElement
|
|
7
|
+
*/
|
|
8
|
+
canvas;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @type CanvasRenderingContext2D
|
|
12
|
+
*/
|
|
13
|
+
context2d;
|
|
14
|
+
|
|
15
|
+
constructor(game, model, canvas) {
|
|
16
|
+
super(game, model);
|
|
17
|
+
|
|
18
|
+
this.canvas = canvas;
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
activateInternal() {
|
|
23
|
+
this.context2d = this.canvas.getContext('2d');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
deactivateInternal() {
|
|
27
|
+
this.context2d = null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
*
|
|
32
|
+
* @param {Vector2} start
|
|
33
|
+
* @param {Vector2} size
|
|
34
|
+
* @param {CanvasGradient|string} fill
|
|
35
|
+
*/
|
|
36
|
+
drawRect(start, size, fill = 'black') {
|
|
37
|
+
const end = start.add(size);
|
|
38
|
+
this.context2d.fillStyle = fill;
|
|
39
|
+
this.context2d.fillRect(start.x, start.y, end.x, end.y);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @param {Vector2} gradientStart
|
|
45
|
+
* @param {Vector2} gradientSize
|
|
46
|
+
* @param {Vector2} start
|
|
47
|
+
* @param {Vector2} size
|
|
48
|
+
* @param {[[Number, string|color]]} stops
|
|
49
|
+
*/
|
|
50
|
+
drawGradient(start, size, gradientStart, gradientSize, stops) {
|
|
51
|
+
const gradientEnd = gradientStart.add(gradientSize);
|
|
52
|
+
const grd = this.context2d.createLinearGradient(gradientStart.x, gradientStart.y, gradientEnd.x, gradientEnd.y);
|
|
53
|
+
stops.forEach((s) => {
|
|
54
|
+
grd.addColorStop(s[0], s[1]);
|
|
55
|
+
});
|
|
56
|
+
this.drawRect(start, size, grd);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
}
|