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,116 @@
1
+ import DomRenderer from "../core/renderer/dom/DomRenderer";
2
+ import TableRenderer from "./table/TableRenderer";
3
+ import NullableNodeRenderer from "../core/renderer/generic/NullableNodeRenderer";
4
+ import NodeFormRenderer from "./form/NodeFormRenderer";
5
+ import DOMHelper from "../core/helper/DOMHelper";
6
+
7
+ export default class EditorRenderer extends DomRenderer {
8
+
9
+ /**
10
+ * @type EditorModel
11
+ */
12
+ model;
13
+
14
+ constructor(game, model, dom) {
15
+ super(game, model, dom);
16
+
17
+ this.model = model;
18
+
19
+ this.container = null;
20
+
21
+ this.tableRenderer = new NullableNodeRenderer(this.game, this.model.activeTable, (model) => new TableRenderer(this.game, model, this.table));
22
+ this.addChild(this.tableRenderer);
23
+
24
+ this.formRenderer = new NullableNodeRenderer(this.game, this.model.activeForm, (model) => new NodeFormRenderer(this.game, model, this.form));
25
+ this.addChild(this.formRenderer);
26
+
27
+ this.addAutoEvent(
28
+ this.model.activeTable,
29
+ 'change',
30
+ () => this.updateTables()
31
+ );
32
+
33
+ this.addAutoEvent(
34
+ this.model.isVisible,
35
+ 'change',
36
+ () => {
37
+ if (this.model.isVisible.get()) {
38
+ DOMHelper.removeClass(this.dock, 'hidden');
39
+ DOMHelper.removeClass(this.buttonsLeft, 'hidden');
40
+ DOMHelper.removeClass(this.buttonsRight, 'hidden');
41
+ } else {
42
+ DOMHelper.addClass(this.dock, 'hidden');
43
+ DOMHelper.addClass(this.buttonsLeft, 'hidden');
44
+ DOMHelper.addClass(this.buttonsRight, 'hidden');
45
+ }
46
+ },
47
+ true
48
+ );
49
+
50
+ this.stopEventPropagationHandler = (e) => e.stopPropagation();
51
+ }
52
+
53
+ activateInternal() {
54
+ this.container = this.addElement('div', 'editor');
55
+ this.nav = DOMHelper.createElement(this.container, 'nav', 'bg row');
56
+
57
+ const buttons = DOMHelper.createElement(this.nav, 'div', 'buttons row');
58
+ this.switch = DOMHelper.createElement(buttons, 'input');
59
+ this.switch.setAttribute('type', 'checkbox');
60
+ this.switch.setAttribute('name', 'switch');
61
+ this.switch.setAttribute('checked', this.model.isVisible.get());
62
+ this.switch.addEventListener('change', () => this.model.triggerEvent('switch-options'));
63
+
64
+ this.buttonsLeft = DOMHelper.createElement(buttons, 'div');
65
+
66
+ DOMHelper.createElement(
67
+ this.buttonsLeft,
68
+ 'button',
69
+ 'special',
70
+ 'Save Resources',
71
+ () => this.model.triggerEvent('save-resources')
72
+ );
73
+
74
+ this.buttonsRight = DOMHelper.createElement(this.nav, 'div');
75
+
76
+ this.dock = DOMHelper.createElement(this.container, 'div', 'dock bg');
77
+ this.tables = DOMHelper.createElement(this.dock, 'div', 'table-selection bg');
78
+ this.table = DOMHelper.createElement(this.dock, 'div', 'active-table');
79
+ this.form = DOMHelper.createElement(this.dock, 'div', 'active-form');
80
+ this.item = DOMHelper.createElement(this.dock, 'div', 'active-item');
81
+
82
+ const events = ['click', 'mousemove', 'mousedown', 'mouseup', 'wheel'];
83
+ const elements = [this.nav, this.tables, this.table, this.form, this.item];
84
+ for (const eli in elements) {
85
+ for (const evi in events) {
86
+ this.addAutoEvent(elements[eli], events[evi], this.stopEventPropagationHandler);
87
+ }
88
+ }
89
+
90
+ this.updateTables();
91
+ }
92
+
93
+ deactivateInternal() {
94
+ this.removeElement(this.container);
95
+ }
96
+
97
+ updateTables() {
98
+ DOMHelper.emptyElement(this.tables);
99
+ const wrapper = DOMHelper.createElement(this.tables, 'div', 'inner');
100
+ this.addMenuSection(wrapper, this.game.resources, 'Resources');
101
+ }
102
+
103
+ addMenuSection(wrapper, node, name) {
104
+ DOMHelper.createElement(wrapper, 'h3', null, name);
105
+ const menu = DOMHelper.createElement(wrapper, 'ul', 'menu');
106
+ node.properties.forEach(
107
+ (name, property) => {
108
+ const isActive = this.model.activeTable.equalsTo(property);
109
+ const item = DOMHelper.createElement(menu, 'li', isActive ? 'active' : '');
110
+ const link = DOMHelper.createElement(item, 'a', null, name);
111
+ link.addEventListener('click', () => this.model.triggerEvent('table-selected', property));
112
+ }
113
+ );
114
+ }
115
+
116
+ }
@@ -0,0 +1,180 @@
1
+ import DomRenderer from "../../core/renderer/dom/DomRenderer";
2
+ import TableRenderer from "../table/TableRenderer";
3
+ import TableLookupRenderer from "../table/lookup/TableLookupRenderer";
4
+ import DOMHelper from "../../core/helper/DOMHelper";
5
+
6
+ export default class NodeFormRenderer extends DomRenderer {
7
+
8
+ /**
9
+ * @type ObjectModel
10
+ */
11
+ model;
12
+
13
+ constructor(game, model, dom, collection = null) {
14
+ super(game, model, dom);
15
+
16
+ this.model = model;
17
+ this.collection = collection;
18
+ this.container = null;
19
+ this.fields = null;
20
+ }
21
+
22
+ activateInternal() {
23
+ this.container = this.addElement('form', 'bg');
24
+
25
+ const buttons = DOMHelper.createElement(this.container, 'div', 'buttons');
26
+ const buttonsLeft = DOMHelper.createElement(buttons, 'div');
27
+ const buttonsRight = DOMHelper.createElement(buttons, 'div');
28
+
29
+ const submit = DOMHelper.createElement(buttonsLeft, 'button');
30
+ submit.innerText = 'Save';
31
+ submit.addEventListener('click', (e) => {
32
+ e.preventDefault();
33
+ this.save();
34
+ });
35
+
36
+ if (this.collection) {
37
+ DOMHelper.createElement(buttonsLeft, 'button', null, 'Clone',
38
+ (e) => {
39
+ e.preventDefault();
40
+ this.game.editor.triggerEvent('node-clone', {table: this.collection, node: this.model});
41
+ }
42
+ );
43
+ DOMHelper.createElement(buttonsLeft, 'button', 'red', 'Delete',
44
+ (e) => {
45
+ e.preventDefault();
46
+ this.game.editor.triggerEvent('node-delete', {table: this.collection, node: this.model});
47
+ }
48
+ );
49
+ }
50
+
51
+ DOMHelper.createElement(
52
+ buttonsRight,
53
+ 'button',
54
+ null,
55
+ 'Close',
56
+ (e) => {
57
+ e.preventDefault();
58
+ if (this.game.editor.activeForm.equalsTo(this.model)) {
59
+ this.game.editor.triggerEvent('form-closed');
60
+ }
61
+ if (this.collection) {
62
+ this.collection.selectedNode.set(null);
63
+ }
64
+ }
65
+ );
66
+
67
+ this.fields = DOMHelper.createElement(this.container, 'div', 'fields scroll');
68
+ this.renderFields();
69
+ }
70
+
71
+ deactivateInternal() {
72
+ this.removeElement(this.container);
73
+ }
74
+
75
+ renderInternal() {
76
+ this.renderFields();
77
+ }
78
+
79
+ renderInput(container, name, value) {
80
+ if (value === undefined) {
81
+ DOMHelper.createElement(container, 'span', null, '--undefined--');
82
+ return;
83
+ }
84
+
85
+ if (value === null) {
86
+ DOMHelper.createElement(container, 'span', null, '--null--');
87
+ return;
88
+ }
89
+
90
+ if (name === 'color' && typeof value === 'string') {
91
+ const input = DOMHelper.createElement(container, 'input', 'color');
92
+ input.setAttribute('type', 'color');
93
+ input.setAttribute('name', name);
94
+ input.value = value;
95
+ return;
96
+ }
97
+
98
+ if (typeof value === 'object' && value.x !== undefined && value.y !== undefined) {
99
+ DOMHelper.addClass(container, 'vector');
100
+ this.renderInput(container, `${name}[]`, value.x);
101
+ this.renderInput(container, `${name}[]`, value.y);
102
+ if (value.z !== undefined) {
103
+ this.renderInput(container, `${name}[]`, value.z);
104
+ if (value.w !== undefined) {
105
+ this.renderInput(container, `${name}[]`, value.w);
106
+ }
107
+ }
108
+ return;
109
+ }
110
+
111
+ if (typeof value === 'object' && (value.constructor.name === 'ModelNodeTable' || value.constructor.name === 'ModelNodeCollection')) {
112
+ const tableRenderer = new TableRenderer(this.game, value, container);
113
+ tableRenderer.activate();
114
+ return;
115
+ }
116
+
117
+ if (typeof value === 'object' && value.value !== undefined) {
118
+ this.renderInput(container, name, value.value);
119
+ if (value.constructor.name === 'IntValue' && TableLookupRenderer.isTableLookupField(name)) {
120
+ DOMHelper.addClass(container, 'with-lookup');
121
+ const lookupRenderer = new TableLookupRenderer(this.game, value, container, name);
122
+ DOMHelper.createElement(container, 'div', 'pr-1', lookupRenderer.getPreview());
123
+ DOMHelper.createElement(
124
+ container,
125
+ 'button',
126
+ 'lookup-button',
127
+ 'Select...',
128
+ (e) => {
129
+ e.preventDefault();
130
+ value.addEventListener('table-closed', () => {
131
+ lookupRenderer.deactivate();
132
+ });
133
+ lookupRenderer.activate();
134
+ }
135
+ );
136
+ }
137
+ return;
138
+ }
139
+
140
+ if (typeof value === 'object') {
141
+ DOMHelper.createElement(container, 'span', null, '[Object]');
142
+ return;
143
+ }
144
+
145
+ if (typeof value === 'boolean') {
146
+ const input = DOMHelper.createElement(container, 'input');
147
+ input.setAttribute('type', 'checkbox');
148
+ input.setAttribute('name', name);
149
+ input.checked = value;
150
+ return;
151
+ }
152
+
153
+ const input = DOMHelper.createElement(container, 'input');
154
+ input.setAttribute('type', 'text');
155
+ input.setAttribute('name', name);
156
+ input.value = value.toString();
157
+ }
158
+
159
+ renderField(container, name, value) {
160
+ const row = DOMHelper.createElement(container, 'div', 'row');
161
+ const label = DOMHelper.createElement(row, 'label', null, name);
162
+ label.setAttribute('for', name);
163
+ const item = DOMHelper.createElement(row, 'div', 'field');
164
+ this.renderInput(item, name, value);
165
+ }
166
+
167
+ renderFields() {
168
+ DOMHelper.emptyElement(this.fields);
169
+ this.model.properties.forEach((name, value) => {
170
+ this.renderField(this.fields, name, value);
171
+ });
172
+ }
173
+
174
+ save() {
175
+ const data = new FormData(this.container);
176
+ this.game.editor.triggerEvent('node-saved', {node: this.model, data: data});
177
+ this.game.editor.triggerEvent('form-closed');
178
+ }
179
+
180
+ }
@@ -0,0 +1,136 @@
1
+ import DomRenderer from "../../core/renderer/dom/DomRenderer";
2
+ import * as THREE from "three";
3
+ import {BoxGeometry, SphereGeometry} from "three";
4
+ import {EffectComposer} from "three/examples/jsm/postprocessing/EffectComposer";
5
+ import {RenderPass} from "three/examples/jsm/postprocessing/RenderPass";
6
+ import {ShaderPass} from "three/examples/jsm/postprocessing/ShaderPass";
7
+ import {FXAAShader} from "three/examples/jsm/shaders/FXAAShader";
8
+ import Vector2 from "../../core/model/vector/Vector2";
9
+ import Vector3 from "../../core/model/vector/Vector3";
10
+ import DOMHelper from "../../core/helper/DOMHelper";
11
+
12
+ const PREVIEW_SIZE = new Vector2(350, 350);
13
+
14
+ export default class MaterialPreviewRenderer extends DomRenderer {
15
+
16
+ /**
17
+ * @type MaterialModel
18
+ */
19
+ model;
20
+
21
+ constructor(game, model, dom) {
22
+ super(game, model, dom);
23
+
24
+ this.model = model;
25
+ this.container = null;
26
+ this.scene = null;
27
+ }
28
+
29
+ activateInternal() {
30
+ this.container = this.addElement('div', 'bg item-def');
31
+ this.buttons = DOMHelper.createElement(this.container, 'div', 'buttons');
32
+ this.close = DOMHelper.createElement(this.buttons, 'button', null, 'Close', () => this.game.editor.activeMaterial.set(null));
33
+
34
+ this.paper = DOMHelper.createElement(this.container, 'div', 'paper');
35
+ this.inner = DOMHelper.createElement(this.paper, 'div', 'inner');
36
+
37
+ this.renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
38
+ this.inner.appendChild(this.renderer.domElement);
39
+ this.renderer.setSize(PREVIEW_SIZE.x, PREVIEW_SIZE.y);
40
+ this.scene = new THREE.Scene();
41
+
42
+ const horizontal = 3;
43
+ const vertical = 3;
44
+
45
+ this.camera = new THREE.OrthographicCamera(-horizontal, horizontal, -vertical, vertical);
46
+ this.camera.updateProjectionMatrix();
47
+
48
+ const camPosition = new Vector3(-100, 100, -100);
49
+ this.camera.position.set(camPosition.x, camPosition.y, camPosition.z);
50
+ this.camera.lookAt(0, 0, 0);
51
+
52
+ this.ambientLight = new THREE.AmbientLight(0xe0e0e0);
53
+ this.scene.add(this.ambientLight);
54
+
55
+ this.directLight = new THREE.DirectionalLight(0xe0e0e0, 1);
56
+ this.directLight.position.set(0, 10, 0);
57
+ this.directLight.castShadow = true;
58
+ this.directLight.shadow.bias = 0;
59
+ this.directLight.shadow.camera.near = 0.5;
60
+ this.directLight.shadow.camera.far = 25;
61
+ this.directLight.shadow.camera.right = 15;
62
+ this.directLight.shadow.camera.left = -15;
63
+ this.directLight.shadow.camera.top = 15;
64
+ this.directLight.shadow.camera.bottom = -15;
65
+ this.directLight.shadow.mapSize.width = 1024;
66
+ this.directLight.shadow.mapSize.height = 1024;
67
+ this.scene.add(this.directLight);
68
+
69
+ this.composer = new EffectComposer(this.renderer);
70
+ this.composer.setSize(PREVIEW_SIZE.x, PREVIEW_SIZE.y);
71
+
72
+ const renderPass = new RenderPass(this.scene, this.camera);
73
+ renderPass.clearColor = new THREE.Color(0, 0, 0);
74
+ renderPass.clearAlpha = 0;
75
+ this.composer.addPass(renderPass);
76
+
77
+ this.effectFXAA = new ShaderPass(FXAAShader);
78
+ this.effectFXAA.uniforms['resolution'].value.set(1 / PREVIEW_SIZE.x, 1 / PREVIEW_SIZE.y);
79
+ this.effectFXAA.material.transparent = true;
80
+ this.composer.addPass(this.effectFXAA);
81
+
82
+ const pixelRatio = this.renderer.getPixelRatio();
83
+ this.effectFXAA.material.uniforms['resolution'].value.x = 1 / (PREVIEW_SIZE.x * pixelRatio);
84
+ this.effectFXAA.material.uniforms['resolution'].value.y = 1 / (PREVIEW_SIZE.y * pixelRatio);
85
+
86
+ this.updatePreview();
87
+ }
88
+
89
+ deactivateInternal() {
90
+ this.ambientLight.dispose();
91
+ this.ambientLight = null;
92
+ this.directLight.dispose();
93
+ this.directLight = null;
94
+ this.scene = null;
95
+ this.renderer.dispose();
96
+ this.renderer = false;
97
+ this.removeElement(this.container);
98
+ if (this.gui) {
99
+ this.gui.destroy();
100
+ this.gui = null;
101
+ }
102
+ }
103
+
104
+ renderInternal() {
105
+ this.updatePreview();
106
+ }
107
+
108
+ updatePreview() {
109
+ this.game.assets.resetMaterial(this.model.id.get());
110
+ this.game.assets.loadMaterial(
111
+ this.model.id.get(),
112
+ (material) => {
113
+ if (this.ball) {
114
+ this.ball.removeFromParent();
115
+ }
116
+ this.ball = new THREE.Mesh(
117
+ new SphereGeometry(),
118
+ material
119
+ );
120
+ this.scene.add(this.ball);
121
+
122
+ if (this.box) {
123
+ this.box.removeFromParent();
124
+ }
125
+ this.box = new THREE.Mesh(
126
+ new BoxGeometry(),
127
+ material
128
+ );
129
+ this.box.position.set(-10, -10, -10);
130
+ this.scene.add(this.box);
131
+ this.composer.render();
132
+ }
133
+ )
134
+ }
135
+
136
+ }
@@ -0,0 +1,123 @@
1
+ import CollectionRenderer from "../../core/renderer/generic/CollectionRenderer";
2
+ import TableRowRenderer from "./row/TableRowRenderer";
3
+ import NodeFormRenderer from "../form/NodeFormRenderer";
4
+ import NullableNodeRenderer from "../../core/renderer/generic/NullableNodeRenderer";
5
+ import DomRenderer from "../../core/renderer/dom/DomRenderer";
6
+ import DOMHelper from "../../core/helper/DOMHelper";
7
+
8
+ export default class TableRenderer extends DomRenderer {
9
+
10
+ /**
11
+ * @type ModelNodeTable|ModelNodeCollection
12
+ */
13
+ model;
14
+
15
+ constructor(game, model, dom) {
16
+ super(game, model, dom);
17
+
18
+ this.model = model;
19
+ this.dom = dom;
20
+ this.container = null;
21
+
22
+ this.addChild(
23
+ new NullableNodeRenderer(
24
+ this.game,
25
+ this.model.selectedNode,
26
+ (m) => new NodeFormRenderer(this.game, m, this.dom, this.model)
27
+ )
28
+ );
29
+
30
+ this.addChild(
31
+ new CollectionRenderer(
32
+ this.game,
33
+ this.model,
34
+ (m) => new TableRowRenderer(game, m, this.tbody, this.model)
35
+ )
36
+ );
37
+
38
+ }
39
+
40
+ activateInternal() {
41
+ this.container = DOMHelper.createElement(this.dom, 'div', 'table bg');
42
+
43
+ this.buttons = DOMHelper.createElement(this.container, 'div', 'buttons');
44
+ const buttonsLeft = DOMHelper.createElement(this.buttons, 'div');
45
+ const buttonsRight = DOMHelper.createElement(this.buttons, 'div');
46
+
47
+ DOMHelper.createElement(
48
+ buttonsLeft,
49
+ 'button',
50
+ null,
51
+ 'Add',
52
+ (e) => {
53
+ e.preventDefault();
54
+ this.model.selectedNode.set(this.model.add());
55
+ }
56
+ );
57
+
58
+ this.input = DOMHelper.createElement(buttonsLeft, 'input', 'flex-1')
59
+ this.input.setAttribute('type', 'text');
60
+ this.input.addEventListener('input', () => this.updateItems());
61
+ DOMHelper.createElement(buttonsLeft, 'button', null, 'Reset', () => {
62
+ this.input.value = '';
63
+ this.updateItems();
64
+ });
65
+
66
+ DOMHelper.createElement(
67
+ buttonsRight,
68
+ 'button',
69
+ null,
70
+ 'Close',
71
+ (e) => {
72
+ e.preventDefault();
73
+ if (this.game.editor.activeTable.equalsTo(this.model)) {
74
+ this.game.editor.triggerEvent('table-closed');
75
+ }
76
+ }
77
+ );
78
+
79
+ this.scrollable = DOMHelper.createElement(this.container, 'div', 'scroll');
80
+ this.table = DOMHelper.createElement(this.scrollable, 'table');
81
+
82
+ let dummy = null;
83
+
84
+ if (typeof this.model.nodeFactory === 'function') {
85
+ dummy = this.model.nodeFactory();
86
+ } else if (this.model.count() > 0) {
87
+ dummy = this.model.first();
88
+ }
89
+
90
+ if (dummy) {
91
+ const thead = DOMHelper.createElement(this.table, 'thead');
92
+ const header = DOMHelper.createElement(thead, 'tr');
93
+ DOMHelper.createElement(header, 'th');
94
+ dummy.properties.forEach((name) => {
95
+ const cell = DOMHelper.createElement(header, 'th');
96
+ cell.innerText = name;
97
+ });
98
+ }
99
+
100
+ this.tbody = DOMHelper.createElement(this.table, 'tbody');
101
+
102
+ super.activateInternal();
103
+ }
104
+
105
+ deactivateInternal() {
106
+ super.deactivateInternal();
107
+ DOMHelper.destroyElement(this.container);
108
+ }
109
+
110
+ updateItems() {
111
+ const rows = this.tbody.querySelectorAll('tr');
112
+ const search = this.input.value.toLowerCase();
113
+ rows.forEach((row) => {
114
+ const str = row.innerText.toLowerCase();
115
+ const visible = (search === '') || str.includes(search);
116
+ if (visible) {
117
+ DOMHelper.removeClass(row, 'hidden');
118
+ } else {
119
+ DOMHelper.addClass(row, 'hidden');
120
+ }
121
+ });
122
+ }
123
+ }
@@ -0,0 +1,120 @@
1
+ import DomRenderer from "../../../core/renderer/dom/DomRenderer";
2
+ import DOMHelper from "../../../core/helper/DOMHelper";
3
+
4
+ const FIELD_TABLE_MAPPINGS = {
5
+ modelId: 'models3d',
6
+ materialId: 'materials',
7
+ spriteId: 'sprites'
8
+ }
9
+
10
+ const RENDER_FIELDS = ['id', 'name'];
11
+
12
+ export default class TableLookupRenderer extends DomRenderer {
13
+
14
+ /**
15
+ * @type IntValue
16
+ */
17
+ model;
18
+
19
+ constructor(game, model, dom, fieldName) {
20
+ super(game, model, dom);
21
+
22
+ this.model = model;
23
+ this.lookupTable = this.getTableByField(fieldName);
24
+ if (!this.lookupTable) {
25
+ console.error('Not found lookup table for field', fieldName);
26
+ }
27
+ this.container = null;
28
+ }
29
+
30
+ activateInternal() {
31
+ this.container = this.addElement('div', 'table-lookup force-foreground p-2');
32
+ this.container.addEventListener('wheel', (e) => e.stopPropagation());
33
+
34
+ this.buttons = DOMHelper.createElement(this.container, 'div', 'buttons row stretch');
35
+ this.input = DOMHelper.createElement(this.buttons, 'input', 'flex-1')
36
+ this.input.setAttribute('type', 'text');
37
+ this.input.addEventListener('input', () => this.renderItems());
38
+ DOMHelper.createElement(this.buttons, 'button', null, 'Reset', (e) => {
39
+ e.preventDefault();
40
+ this.input.value = '';
41
+ this.renderItems();
42
+ });
43
+ DOMHelper.createElement(this.buttons, 'button', null, 'NaN', (e) => {
44
+ e.preventDefault();
45
+ this.model.set(Number.NaN);
46
+ this.model.triggerEvent('table-closed');
47
+ });
48
+ DOMHelper.createElement(this.buttons, 'button', 'ml-1', 'Close', () => this.model.triggerEvent('table-closed'));
49
+
50
+ this.scrollable = DOMHelper.createElement(this.container, 'div', 'scroll p-1');
51
+ this.table = DOMHelper.createElement(this.scrollable, 'table');
52
+
53
+ const thead = DOMHelper.createElement(this.table, 'thead');
54
+ const header = DOMHelper.createElement(thead, 'tr');
55
+ RENDER_FIELDS.forEach((name) => {
56
+ const cell = DOMHelper.createElement(header, 'th');
57
+ cell.innerText = name;
58
+ });
59
+
60
+ this.tbody = DOMHelper.createElement(this.table, 'tbody');
61
+ this.renderItems();
62
+ }
63
+
64
+ deactivateInternal() {
65
+ this.removeElement(this.container);
66
+ }
67
+
68
+ getTableByField(name) {
69
+ return this.game.getTableByName(FIELD_TABLE_MAPPINGS[name]);
70
+ }
71
+
72
+ static isTableLookupField(name) {
73
+ return Object.keys(FIELD_TABLE_MAPPINGS).includes(name);
74
+ }
75
+
76
+ getPreview() {
77
+ const element = this.lookupTable.getById(this.model.get());
78
+ if (element) {
79
+ if (typeof element.name === 'object' && typeof element.name.get === 'function') {
80
+ return element.name.get();
81
+ }
82
+ return this.model.get();
83
+ }
84
+ }
85
+
86
+ renderItems() {
87
+ DOMHelper.emptyElement(this.tbody);
88
+ const search = this.input.value.toLowerCase();
89
+ const searchId = Number(search);
90
+ this.lookupTable
91
+ .filter((m) => {
92
+ if (search === '') {
93
+ return true;
94
+ }
95
+ if (!Number.isNaN(searchId)) {
96
+ return m.id.equalsTo(searchId);
97
+ }
98
+ const name = m.name.get();
99
+ return name.toLowerCase().includes(search);
100
+ })
101
+ .forEach(
102
+ (node) => {
103
+ const tr = DOMHelper.createElement(
104
+ this.tbody,
105
+ 'tr',
106
+ node.id.equalsTo(this.model.get()) ? 'active' : null,
107
+ null,
108
+ () => {
109
+ this.model.set(node.id.get());
110
+ this.model.triggerEvent('table-closed');
111
+ }
112
+ );
113
+ RENDER_FIELDS.forEach((name) => {
114
+ const cell = DOMHelper.createElement(tr, 'td');
115
+ cell.innerText = node[name].get();
116
+ });
117
+ }
118
+ );
119
+ }
120
+ }