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.
Files changed (107) hide show
  1. package/core/ActivatedTreeNode.js +187 -0
  2. package/core/Collection.js +156 -0
  3. package/core/Dictionary.js +83 -0
  4. package/core/animation/3d/AnimatedVector3.js +35 -0
  5. package/core/animation/3d/AnimationHelper.js +103 -0
  6. package/core/animation/3d/ProgressVector3.js +26 -0
  7. package/core/animation/AnimatedRotation.js +44 -0
  8. package/core/animation/AnimatedValue.js +33 -0
  9. package/core/animation/AnimatedVector2.js +35 -0
  10. package/core/animation/ProgressRotation.js +40 -0
  11. package/core/animation/ProgressValue.js +27 -0
  12. package/core/animation/ProgressVector2.js +23 -0
  13. package/core/audio/AudioModel.js +36 -0
  14. package/core/audio/AudioRenderer.js +120 -0
  15. package/core/audio/global/GlobalAudioModel.js +88 -0
  16. package/core/audio/global/GlobalAudioRenderer.js +108 -0
  17. package/core/controller/AnimationController.js +37 -0
  18. package/core/controller/AnimationFloatController.js +39 -0
  19. package/core/controller/AnimationVector2Controller.js +39 -0
  20. package/core/controller/CollectionController.js +47 -0
  21. package/core/controller/ConditionalNodeController.js +51 -0
  22. package/core/controller/ControllerBase.js +64 -0
  23. package/core/controller/ControllerWithSaveGame.js +27 -0
  24. package/core/controller/ControllerWithTimeout.js +10 -0
  25. package/core/controller/NullableNodeController.js +35 -0
  26. package/core/controller/TimeoutController.js +26 -0
  27. package/core/helper/ArrayHelper.js +19 -0
  28. package/core/helper/DOMHelper.js +167 -0
  29. package/core/helper/GUIHelper.js +53 -0
  30. package/core/helper/HttpHelper.js +33 -0
  31. package/core/helper/ImageHelper.js +36 -0
  32. package/core/helper/NumberHelper.js +28 -0
  33. package/core/helper/ObjectHelper.js +10 -0
  34. package/core/helper/StringHelper.js +59 -0
  35. package/core/model/ModelBase.js +91 -0
  36. package/core/model/ObjectModel.js +97 -0
  37. package/core/model/collection/ModelNodeCollection.js +232 -0
  38. package/core/model/collection/table/IdentifiedModelNode.js +24 -0
  39. package/core/model/collection/table/ModelNodeTable.js +53 -0
  40. package/core/model/event/ChangeEvent.js +24 -0
  41. package/core/model/event/EventManager.js +44 -0
  42. package/core/model/event/NodeWithEvents.js +32 -0
  43. package/core/model/template/TemplateNode.js +45 -0
  44. package/core/model/value/BoolValue.js +17 -0
  45. package/core/model/value/CapacityValue.js +49 -0
  46. package/core/model/value/DirtyValue.js +66 -0
  47. package/core/model/value/FloatValue.js +8 -0
  48. package/core/model/value/IntValue.js +20 -0
  49. package/core/model/value/NullableNode.js +66 -0
  50. package/core/model/value/StringValue.js +21 -0
  51. package/core/model/vector/Quaternion.js +82 -0
  52. package/core/model/vector/Rotation.js +61 -0
  53. package/core/model/vector/Vector2.js +177 -0
  54. package/core/model/vector/Vector3.js +98 -0
  55. package/core/renderer/RendererBase.js +46 -0
  56. package/core/renderer/canvas/CanvasRenderer.js +60 -0
  57. package/core/renderer/canvas/ImageToCanvasRenderer.js +94 -0
  58. package/core/renderer/dom/DirtyValueRenderer.js +36 -0
  59. package/core/renderer/dom/DomRenderer.js +32 -0
  60. package/core/renderer/dom/ImageRenderer.js +41 -0
  61. package/core/renderer/dom/Vector2Renderer.js +37 -0
  62. package/core/renderer/generic/CollectionRenderer.js +50 -0
  63. package/core/renderer/generic/ConditionalNodeRenderer.js +57 -0
  64. package/core/renderer/generic/NullableNodeRenderer.js +43 -0
  65. package/core/renderer/svg/SvgRenderer.js +130 -0
  66. package/editor/EditorController.js +135 -0
  67. package/editor/EditorModel.js +38 -0
  68. package/editor/EditorRenderer.js +116 -0
  69. package/editor/form/NodeFormRenderer.js +180 -0
  70. package/editor/material/MaterialPreviewRenderer.js +136 -0
  71. package/editor/table/TableRenderer.js +123 -0
  72. package/editor/table/lookup/TableLookupRenderer.js +120 -0
  73. package/editor/table/row/TableRowRenderer.js +97 -0
  74. package/game/GameController.js +144 -0
  75. package/game/GameModel.js +73 -0
  76. package/game/GameRenderer.js +108 -0
  77. package/game/controls/ControlsController.js +104 -0
  78. package/game/controls/ControlsModel.js +60 -0
  79. package/game/menu/MenuModel.js +25 -0
  80. package/game/menu/MenuRenderer.js +37 -0
  81. package/game/menu/item/MenuItemModel.js +31 -0
  82. package/game/menu/item/MenuItemRenderer.js +40 -0
  83. package/game/resources/3d/3DModel.js +30 -0
  84. package/game/resources/ResourcesModel.js +26 -0
  85. package/game/resources/assets/AssetCache.js +193 -0
  86. package/game/resources/assets/loader/AssetLoader.js +56 -0
  87. package/game/resources/assets/loader/AudioLoader.js +15 -0
  88. package/game/resources/assets/loader/GlbLoader.js +16 -0
  89. package/game/resources/assets/loader/ImageLoader.js +15 -0
  90. package/game/resources/assets/loader/MaterialLoader.js +49 -0
  91. package/game/resources/assets/loader/Model3dLoader.js +21 -0
  92. package/game/resources/assets/loader/SpriteLoader.js +40 -0
  93. package/game/resources/image/DualImageModel.js +34 -0
  94. package/game/resources/image/ImageModel.js +43 -0
  95. package/game/resources/material/MaterialModel.js +69 -0
  96. package/game/save/SaveGameController.js +21 -0
  97. package/game/save/SaveGameModel.js +5 -0
  98. package/game/save/SaveGameRenderer.js +17 -0
  99. package/game/save/editor/SaveGameEditorRenderer.js +17 -0
  100. package/index.html +42 -0
  101. package/index.js +73 -0
  102. package/package.json +35 -0
  103. package/style/basic/editor.less +290 -0
  104. package/style/basic/game.less +149 -0
  105. package/style/basic/utilities.less +215 -0
  106. package/style/style.less +3 -0
  107. package/webpack.config.js +29 -0
@@ -0,0 +1,97 @@
1
+ import DomRenderer from "../../../core/renderer/dom/DomRenderer";
2
+ import DOMHelper from "../../../core/helper/DOMHelper";
3
+ import NumberHelper from "../../../core/helper/NumberHelper";
4
+
5
+ export default class TableRowRenderer extends DomRenderer {
6
+
7
+ /**
8
+ * @type ObjectModel
9
+ */
10
+ model;
11
+
12
+ /**
13
+ * @type ModelNodeTable|ModelNodeCollection
14
+ */
15
+ table;
16
+
17
+ constructor(game, model, dom, collection) {
18
+ super(game, model, dom);
19
+
20
+ this.model = model;
21
+ this.collection = collection;
22
+
23
+ this.container = null;
24
+
25
+ this.addAutoEvent(
26
+ this.collection.selectedNode,
27
+ 'change',
28
+ () => {
29
+ if (this.collection.selectedNode.equalsTo(this.model)) {
30
+ DOMHelper.addClass(this.container, 'active');
31
+ } else {
32
+ DOMHelper.removeClass(this.container, 'active');
33
+ }
34
+ },
35
+ true
36
+ );
37
+ }
38
+
39
+ activateInternal() {
40
+ this.container = this.addElement('tr');
41
+ this.container.addEventListener('click', () => this.collection.selectedNode.set(this.model));
42
+
43
+ this.updateRow();
44
+ }
45
+
46
+ deactivateInternal() {
47
+ this.removeElement(this.container);
48
+ }
49
+
50
+ renderInternal() {
51
+ this.updateRow();
52
+ }
53
+
54
+ updateRow() {
55
+ DOMHelper.emptyElement(this.container);
56
+
57
+ const grab = DOMHelper.createElement(this.container, 'td');
58
+ const icon = DOMHelper.createElement(grab, 'div', 'grab-icon');
59
+ icon.setAttribute('draggable', "true");
60
+ icon.addEventListener('dragstart', (e) => {
61
+ this.collection.triggerEvent('drag-start', this.model);
62
+ });
63
+ this.container.addEventListener('dragover', (e) => e.preventDefault());
64
+ this.container.addEventListener('drop', (e) => {
65
+ e.preventDefault();
66
+ this.collection.triggerEvent('drag-drop', this.model);
67
+ });
68
+
69
+ this.model.properties.forEach((name, value) => {
70
+ const cell = DOMHelper.createElement(this.container, 'td');
71
+ let text = '';
72
+ if (value !== undefined && value !== null) {
73
+ if (typeof value === 'object') {
74
+ if (value.value !== undefined) {
75
+ text = NumberHelper.shorten(value.value);
76
+ } else if (value.x !== undefined && value.y !== undefined) {
77
+ text = '[' + NumberHelper.round(value.x, 2) + ',' + NumberHelper.round(value.y, 2);
78
+ if (value.z !== undefined) {
79
+ text += ',' + NumberHelper.round(value.z, 2);
80
+ }
81
+ if (value.w !== undefined) {
82
+ text += ',' + NumberHelper.round(value.w, 2);
83
+ }
84
+ text += ']';
85
+ } else {
86
+ text = NumberHelper.shorten(value.toString());
87
+ }
88
+ } else {
89
+ text = NumberHelper.shorten(value);
90
+ }
91
+ }
92
+ cell.innerText = text;
93
+ });
94
+
95
+ }
96
+
97
+ }
@@ -0,0 +1,144 @@
1
+ import * as localForage from "localforage";
2
+ import ControllerBase from "../core/controller/ControllerBase";
3
+ import EditorController from "../editor/EditorController";
4
+ import ControlsController from "./controls/ControlsController";
5
+
6
+ export default class GameController extends ControllerBase {
7
+
8
+ /**
9
+ * @type GameModel
10
+ */
11
+ model;
12
+
13
+ constructor(model) {
14
+ super(model, model);
15
+
16
+ this.model = model;
17
+
18
+ this.isResourcesDirty = false;
19
+ this.resourcesTimeOut = null;
20
+
21
+ this.addChild(new ControlsController(this.game, this.model.controls));
22
+ this.addChild(new EditorController(this.game, this.model.editor));
23
+
24
+ this.addAutoEvent(
25
+ this.model,
26
+ 'new-game',
27
+ () => this.runOnUpdate(() => this.startNewGame())
28
+ );
29
+
30
+ this.addAutoEvent(
31
+ this.model,
32
+ 'show-main-menu',
33
+ () => this.showMainMenu()
34
+ );
35
+
36
+ this.addAutoEvent(
37
+ window,
38
+ 'resize',
39
+ () => {
40
+ this.runOnUpdate(() => this.model.viewBoxSize.set(window.innerWidth, window.innerHeight));
41
+ },
42
+ true
43
+ );
44
+
45
+ this.addAutoEvent(
46
+ this.model.controls,
47
+ 'debug-key',
48
+ () => {
49
+ this.model.isInDebugMode.invert();
50
+ }
51
+ );
52
+
53
+ this.addAutoEvent(
54
+ this.model,
55
+ 'save-ui',
56
+ () => {
57
+ this.saveGameToStorage().then(() => {
58
+ console.log('savegame saved');
59
+ });
60
+ this.saveResourcesToStorage().then(() => {
61
+ console.log('resources saved');
62
+ });
63
+ }
64
+ );
65
+
66
+ }
67
+
68
+ activateInternal() {
69
+ this.loadResourcesFromStorage().then(() => {
70
+ this.model.resources.addOnDirtyListener(() => this.isResourcesDirty = true);
71
+ this.showMainMenu();
72
+ });
73
+ }
74
+
75
+ updateInternal(delta) {
76
+
77
+ // saving of resources during debugging
78
+ if (this.game.isInDebugMode.get()) {
79
+ this.resourcesTimeOut = (this.resourcesTimeOut === null) ? 3000 : this.resourcesTimeOut - delta;
80
+ if (this.isResourcesDirty && this.resourcesTimeOut <= 0) {
81
+ this.resourcesTimeOut = null;
82
+ this.isResourcesDirty = false;
83
+ this.saveResourcesToStorage().then(() => {
84
+ this.resourcesTimeOut = null;
85
+ console.log('resources saved');
86
+ });
87
+ }
88
+ }
89
+ }
90
+
91
+ async loadResourcesFromStorage() {
92
+ try {
93
+ const state = await localForage.getItem('wegge-resources');
94
+ if (state) {
95
+ this.model.resources.restoreState(state);
96
+ } else {
97
+ console.log('nothing in storage');
98
+ }
99
+ } catch (err) {
100
+ console.error(err);
101
+ }
102
+ }
103
+
104
+ async saveResourcesToStorage() {
105
+ const state = this.model.resources.getState();
106
+ try {
107
+ await localForage.setItem('wegge-resources', state);
108
+ } catch (err) {
109
+ console.error(err);
110
+ }
111
+ }
112
+
113
+ async loadGameFromStorage() {
114
+ try {
115
+ const state = await localForage.getItem('wegge-autosave');
116
+ if (state) {
117
+ const saveGame = this.saveGameFactory();
118
+ saveGame.restoreState(state);
119
+ this.model.saveGame.set(saveGame);
120
+ this.model.menu.set(null);
121
+ } else {
122
+ console.log('no saved game in storage');
123
+ }
124
+ } catch (err) {
125
+ console.error('Error when loading saved game.', err);
126
+ }
127
+ }
128
+
129
+ async saveGameToStorage() {
130
+ const saveGame = this.model.saveGame.get();
131
+ if (!saveGame) return;
132
+ const state = saveGame.getState();
133
+ try {
134
+ await localForage.setItem('wegge-autosave', state);
135
+ } catch (err) {
136
+ console.error(err);
137
+ }
138
+ }
139
+
140
+ hideMenu() {
141
+ this.model.menu.set(null);
142
+ }
143
+
144
+ }
@@ -0,0 +1,73 @@
1
+ import ObjectModel from "../core/model/ObjectModel";
2
+ import Vector2 from "../core/model/vector/Vector2";
3
+ import ControlsModel from "./controls/ControlsModel";
4
+ import ResourcesModel from "./resources/ResourcesModel";
5
+ import EditorModel from "../editor/EditorModel";
6
+ import NullableNode from "../core/model/value/NullableNode";
7
+ import BoolValue from "../core/model/value/BoolValue";
8
+ import GlobalAudioModel from "../core/audio/global/GlobalAudioModel";
9
+ import AssetCache from "./resources/assets/AssetCache";
10
+
11
+ export default class GameModel extends ObjectModel {
12
+
13
+ /**
14
+ * @type BoolValue
15
+ */
16
+ isInDebugMode;
17
+
18
+ /**
19
+ * @type EditorModel
20
+ */
21
+ editor;
22
+
23
+ /**
24
+ * @type NullableNode<MenuModel>
25
+ */
26
+ menu;
27
+
28
+ /**
29
+ * @type Vector2
30
+ */
31
+ viewBoxSize;
32
+
33
+ /**
34
+ * @type NullableNode<SaveGameModel>
35
+ */
36
+ saveGame;
37
+
38
+ /**
39
+ * @type ResourcesModel
40
+ */
41
+ resources;
42
+
43
+ /**
44
+ * @type AssetCache
45
+ */
46
+ assets;
47
+
48
+ /**
49
+ * @type GlobalAudioModel
50
+ */
51
+ audio;
52
+
53
+ /**
54
+ * @type ControlsModel
55
+ */
56
+ controls;
57
+
58
+ constructor(debugModeEnabled = true) {
59
+ super(false);
60
+
61
+ this.isInDebugMode = this.addProperty('isInDebugMode', new BoolValue(debugModeEnabled));
62
+ this.editor = this.addProperty('editor', new EditorModel());
63
+ this.menu = this.addProperty('menu', new NullableNode());
64
+
65
+ this.viewBoxSize = this.addProperty('viewBoxSize', new Vector2());
66
+ this.saveGame = this.addProperty('saveGame', new NullableNode());
67
+ this.resources = this.addProperty('resources', new ResourcesModel());
68
+ this.assets = new AssetCache(this.resources);
69
+ this.audio = this.addProperty('audio', new GlobalAudioModel());
70
+ this.controls = this.addProperty('controls', new ControlsModel());
71
+ }
72
+
73
+ }
@@ -0,0 +1,108 @@
1
+ import DomRenderer from "../core/renderer/dom/DomRenderer";
2
+ import EditorRenderer from "../editor/EditorRenderer";
3
+ import NullableNodeRenderer from "../core/renderer/generic/NullableNodeRenderer";
4
+ import GlobalAudioRenderer from "../core/audio/global/GlobalAudioRenderer";
5
+ import MenuRenderer from "./menu/MenuRenderer";
6
+ import ConditionalNodeRenderer from "../core/renderer/generic/ConditionalNodeRenderer";
7
+ import DOMHelper from "../core/helper/DOMHelper";
8
+
9
+ export default class GameRenderer extends DomRenderer {
10
+
11
+ /**
12
+ * @type GameModel
13
+ */
14
+ model;
15
+
16
+ constructor(model, dom) {
17
+ super(model, model, dom);
18
+
19
+ this.model = model;
20
+ this.loading = null;
21
+ this.addClass('wegge-host');
22
+
23
+ this.addChild(
24
+ new GlobalAudioRenderer(
25
+ this.model,
26
+ this.model.audio
27
+ )
28
+ );
29
+
30
+ this.addChild(
31
+ new NullableNodeRenderer(
32
+ this.game,
33
+ this.model.menu,
34
+ (m) => new MenuRenderer(this.game, m, this.menuLayer)
35
+ )
36
+ );
37
+
38
+ this.addChild(
39
+ new ConditionalNodeRenderer(
40
+ this.game,
41
+ this.model.isInDebugMode,
42
+ () => this.model.isInDebugMode.get(),
43
+ () => new EditorRenderer(this.game, this.model.editor, this.editorLayer)
44
+ )
45
+ );
46
+
47
+ this.addAutoEvents(
48
+ this.model.assets,
49
+ ['session-finished-loaders-changed', 'session-total-loaders-changed'],
50
+ () => this.updateLoading(),
51
+ true
52
+ );
53
+
54
+ this.addAutoEvent(
55
+ window,
56
+ 'resize',
57
+ () => this.model.triggerEvent('resize'),
58
+ true
59
+ );
60
+ }
61
+
62
+ activateInternal() {
63
+ const initLoading = document.getElementById('initial_loading');
64
+ if (initLoading) DOMHelper.destroyElement(initLoading);
65
+
66
+ this.container = this.addElement('div', 'wegge-game-container container container-host');
67
+
68
+ this.saveGameLayer = DOMHelper.createElement(this.container, 'div', 'savegame-layer container container-host');
69
+ this.loadingLayer = DOMHelper.createElement(this.container, 'div', 'loading-layer');
70
+ this.menuLayer = DOMHelper.createElement(this.container, 'div', 'menu-layer');
71
+ this.editorLayer = DOMHelper.createElement(this.container, 'div', 'editor-layer');
72
+
73
+ this.model.assets.preload(this.model.getResourcesForPreload());
74
+ }
75
+
76
+ deactivateInternal() {
77
+ this.removeElement(this.container);
78
+ this.container = null;
79
+ this.saveGameLayer = null;
80
+ this.loadingLayer = null;
81
+ this.menuLayer = null;
82
+ this.editorLayer = null;
83
+ }
84
+
85
+ updateLoading() {
86
+ const isLoading = this.model.assets.blockingLoaders > 0;
87
+ if (this.loading && !isLoading) {
88
+ this.removeElement(this.loading);
89
+ this.loading = null;
90
+ }
91
+ if (isLoading) {
92
+ if (!this.loading) {
93
+ this.loading = DOMHelper.createElement(this.loadingLayer, 'div', 'loading');
94
+ const paper = DOMHelper.createElement(this.loading, 'div');
95
+ const inner = DOMHelper.createElement(paper, 'div', 'inner p-3');
96
+ const content = DOMHelper.createElement(inner, 'div', 'm-3 p-3');
97
+ const label1 = DOMHelper.createElement(content, 'h2', null, 'Nahrávám');
98
+ this.label2 = DOMHelper.createElement(content, 'div', 'center');
99
+ const progressWrapper = DOMHelper.createElement(content, 'div', 'progress-wrapper mt-2');
100
+ this.loadingProgress = DOMHelper.createElement(progressWrapper, 'div', 'stretch');
101
+ }
102
+ const portion = this.game.assets.sessionFinishedLoaders / this.game.assets.sessionTotalLoaders;
103
+ this.loadingProgress.style.width = `${Math.round(portion * 100)}%`;
104
+ this.label2.innerText = `${this.game.assets.sessionFinishedLoaders}/${this.game.assets.sessionTotalLoaders}`;
105
+ }
106
+ }
107
+
108
+ }
@@ -0,0 +1,104 @@
1
+ import ControllerBase from "../../core/controller/ControllerBase";
2
+
3
+ export default class ControlsController extends ControllerBase {
4
+ dom;
5
+
6
+ /**
7
+ * @type ControlsModel
8
+ */
9
+ model;
10
+
11
+ constructor(game, model, dom) {
12
+ super(game, model);
13
+
14
+ this.model = model;
15
+ this.dom = dom || window.document.body;
16
+ }
17
+
18
+ activateInternal() {
19
+ this.deactivateInternal();
20
+ this.dom.addEventListener('mousemove', (e) => this.onMouseMove(e));
21
+ this.dom.addEventListener('mouseenter', (e) => this.onMouseEnter(e));
22
+ this.dom.addEventListener('mouseleave', (e) => this.onMouseLeave(e));
23
+ this.dom.addEventListener('mousedown', (e) => this.updateMouseButtons(e));
24
+ this.dom.addEventListener('mouseup', (e) => this.updateMouseButtons(e));
25
+ this.dom.addEventListener('wheel', (e) => this.onZoom(e), {passive: true});
26
+ window.addEventListener('keydown', (e) => this.onKeyDown(e), false);
27
+ window.addEventListener('keyup', (e) => this.onKeyUp(e), false);
28
+ window.addEventListener('contextmenu', (e) => this.onContextMenu(e), false);
29
+ }
30
+
31
+ deactivateInternal() {
32
+
33
+ }
34
+
35
+ onKeyDown(event) {
36
+ //this.caps = event.getModifierState("CapsLock");
37
+ //console.log(event);
38
+ const key = event.keyCode ? event.keyCode : event.charCode;
39
+ //console.log(key);
40
+
41
+ switch (key) {
42
+ case 13: /*Enter*/
43
+ //this.model.interacting.set(true);
44
+ break;
45
+ case 192: /*~*/ //this.model.triggerEvent('debug-key'); break;default:
46
+ default:
47
+ this.model.triggerEvent(`key-down-${key}`);
48
+ }
49
+ }
50
+
51
+ onKeyUp(event) {
52
+ //this.caps = event.getModifierState("CapsLock");
53
+ const key = event.keyCode ? event.keyCode : event.charCode;
54
+ //console.log("key:" + key);
55
+ switch (key) {
56
+ case 13: /*Enter*/
57
+ //this.model.interacting.set(false);
58
+ break;
59
+ case 27: /*Esc*/
60
+ this.model.triggerEvent('esc-key');
61
+ break;
62
+ case 192: /*~*/
63
+ this.model.triggerEvent('debug-key');
64
+ break;
65
+ default:
66
+ this.model.triggerEvent(`key-up-${key}`);
67
+ }
68
+ }
69
+
70
+ onMouseMove(e) {
71
+ this.model.mouseCoordinates.set(e.clientX, e.clientY);
72
+ this.model.isMouseOver.set(true);
73
+ }
74
+
75
+ onMouseEnter() {
76
+ this.model.isMouseOver.set(true);
77
+ }
78
+
79
+ onMouseLeave() {
80
+ this.model.isMouseOver.set(false);
81
+ this.model.mouseDownLeft.set(false);
82
+ this.model.mouseDownRight.set(false);
83
+ }
84
+
85
+ onContextMenu(e) {
86
+ if (!(e.ctrlKey && this.game.isInDebugMode.get())) {
87
+ e.preventDefault();
88
+ }
89
+ e.stopPropagation();
90
+ return false;
91
+ }
92
+
93
+ updateMouseButtons(e) {
94
+ const left = ((e.buttons === 1) || (e.buttons === 3));
95
+ const right = (e.buttons === 2);
96
+ this.model.mouseDownLeft.set(left);
97
+ this.model.mouseDownRight.set(right);
98
+ }
99
+
100
+ onZoom(e) {
101
+ this.model.triggerEvent('zoom', e.deltaY > 0 ? 1 : -1);
102
+ }
103
+
104
+ }
@@ -0,0 +1,60 @@
1
+ import Vector2 from "../../core/model/vector/Vector2";
2
+ import ObjectModel from "../../core/model/ObjectModel";
3
+ import BoolValue from "../../core/model/value/BoolValue";
4
+
5
+ const CLICK_TIMEOUT = 250;
6
+
7
+ export default class ControlsModel extends ObjectModel {
8
+
9
+ /**
10
+ * @type BoolValue
11
+ */
12
+ isMouseOver;
13
+
14
+ /**
15
+ * @type Vector2
16
+ */
17
+ mouseCoordinates;
18
+
19
+ mouseDownLeft;
20
+ mouseDownRight;
21
+ leftClickTime;
22
+ rightClickTime;
23
+
24
+ constructor() {
25
+ super();
26
+
27
+ this.isMouseOver = this.addProperty('isMouseOver', new BoolValue(false));
28
+ this.mouseCoordinates = this.addProperty('mouseCoordinates', new Vector2());
29
+ this.mouseDownLeft = this.addProperty('mouseDownLeft', new BoolValue(false));
30
+ this.mouseDownLeft.addOnChangeListener((params) => this.onMouseLeftChange(params.newValue));
31
+ this.mouseDownRight = this.addProperty('mouseDownRight', new BoolValue(false));
32
+ this.mouseDownRight.addOnChangeListener((params) => this.onMouseRightChange(params.newValue));
33
+
34
+ this.leftClickTime = 0;
35
+ this.rightClickTime = 0;
36
+ }
37
+
38
+ onMouseLeftChange(down) {
39
+ const time = performance.now();
40
+ if (down) {
41
+ this.leftClickTime = time;
42
+ } else {
43
+ if ((time - this.leftClickTime) < CLICK_TIMEOUT) {
44
+ this.triggerEvent('left-click', this.mouseCoordinates.clone());
45
+ }
46
+ }
47
+ }
48
+
49
+ onMouseRightChange(down) {
50
+ const time = performance.now();
51
+ if (down) {
52
+ this.rightClickTime = time;
53
+ } else {
54
+ if ((time - this.rightClickTime) < CLICK_TIMEOUT) {
55
+ this.triggerEvent('right-click', this.mouseCoordinates.clone());
56
+ }
57
+ }
58
+ }
59
+
60
+ }
@@ -0,0 +1,25 @@
1
+ import ModelNodeCollection from "../../core/model/collection/ModelNodeCollection";
2
+ import ObjectModel from "../../core/model/ObjectModel";
3
+ import StringValue from "../../core/model/value/StringValue";
4
+
5
+ export default class MenuModel extends ObjectModel {
6
+
7
+ /**
8
+ * @type StringValue
9
+ */
10
+ name;
11
+
12
+ /**
13
+ * @type ModelNodeCollection<MenuItemModel>
14
+ */
15
+ items;
16
+
17
+ constructor(name = '', persistent = false) {
18
+ super(persistent);
19
+
20
+ this.name = this.addProperty('name', new StringValue(name));
21
+ this.items = this.addProperty('items', new ModelNodeCollection());
22
+
23
+ }
24
+
25
+ }
@@ -0,0 +1,37 @@
1
+ import DomRenderer from "../../core/renderer/dom/DomRenderer";
2
+ import CollectionRenderer from "../../core/renderer/generic/CollectionRenderer";
3
+ import MenuItemRenderer from "./item/MenuItemRenderer";
4
+ import DOMHelper from "../../core/helper/DOMHelper";
5
+
6
+ export default class MenuRenderer extends DomRenderer {
7
+
8
+ /**
9
+ * @type MenuModel
10
+ */
11
+ model;
12
+
13
+ constructor(game, model, dom) {
14
+ super(game, model, dom);
15
+
16
+ this.model = model;
17
+
18
+ this.addChild(
19
+ new CollectionRenderer(
20
+ this.game,
21
+ this.model.items,
22
+ (m) => new MenuItemRenderer(this.game, m, this.items)
23
+ )
24
+ );
25
+ }
26
+
27
+ activateInternal() {
28
+ this.container = this.addElement('div', 'main-menu-layer');
29
+ this.paper = DOMHelper.createElement(this.container, 'div', 'main-menu paper');
30
+ this.inner = DOMHelper.createElement(this.paper, 'div', 'inner p-3');
31
+ this.items = DOMHelper.createElement(this.inner, 'div', 'items m-3');
32
+ }
33
+
34
+ deactivateInternal() {
35
+ this.removeElement(this.container);
36
+ }
37
+ }
@@ -0,0 +1,31 @@
1
+ import ObjectModel from "../../../core/model/ObjectModel";
2
+ import StringValue from "../../../core/model/value/StringValue";
3
+ import BoolValue from "../../../core/model/value/BoolValue";
4
+
5
+ export default class MenuItemModel extends ObjectModel {
6
+
7
+ /**
8
+ * @type StringValue
9
+ */
10
+ text;
11
+
12
+ /**
13
+ * @type BoolValue
14
+ */
15
+ isActive;
16
+
17
+ constructor(text = '', onClick = null, persistent = false) {
18
+ super(persistent);
19
+
20
+ this.text = this.addProperty('text', new StringValue(text));
21
+ this.isActive = this.addProperty('isActive', new BoolValue(false));
22
+
23
+ if (onClick) {
24
+ this.addEventListener(
25
+ 'click',
26
+ onClick
27
+ );
28
+ }
29
+ }
30
+
31
+ }