@woosh/meep-engine 2.39.9 → 2.39.12
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/editor/ecs/component/createFieldEditor.js +2 -0
- package/editor/ecs/component/editors/Sampler2DEditor.js +163 -49
- package/editor/ecs/component/editors/three/TextureEditor.js +81 -3
- package/engine/ecs/terrain/ecs/Terrain.d.ts +10 -0
- package/engine/ecs/terrain/ecs/Terrain.js +9 -4
- package/engine/ecs/terrain/ecs/TerrainSystem.d.ts +2 -1
- package/engine/ecs/terrain/ecs/TerrainSystem.js +0 -1
- package/engine/ecs/terrain/overlay/TerrainOverlay.js +20 -0
- package/engine/graphics/ecs/camera/Camera.js +5 -4
- package/engine/graphics/ecs/path/testPathDisplaySystem.js +8 -2
- package/engine/graphics/ecs/path/tube/TubePathStyle.js +17 -0
- package/engine/graphics/ecs/path/tube/TubePathStyle.spec.js +5 -0
- package/engine/graphics/texture/sampler/Sampler2D2Canvas.js +42 -14
- package/engine/graphics/texture/sampler/convertSampler2D2DataURL.js +7 -1
- package/engine/graphics/texture/sampler/copy_Sampler2D_channel_data.js +3 -0
- package/engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.js +47 -0
- package/package.json +1 -1
- package/view/View.js +3 -3
|
@@ -6,74 +6,169 @@ import { Sampler2D } from "../../../../engine/graphics/texture/sampler/Sampler2D
|
|
|
6
6
|
import {
|
|
7
7
|
typedArrayConstructorByInstance
|
|
8
8
|
} from "../../../../engine/graphics/texture/sampler/typedArrayConstructorByInstance.js";
|
|
9
|
-
import { typedArrayToDataType } from "../../../../core/collection/array/typedArrayToDataType.js";
|
|
10
|
-
import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
11
|
-
import { min2 } from "../../../../core/math/min2.js";
|
|
12
|
-
import { max2 } from "../../../../core/math/max2.js";
|
|
13
|
-
import { isTypedArray } from "../../../../core/collection/array/typed/isTypedArray.js";
|
|
14
9
|
import { FrameRunner } from "../../../../engine/graphics/FrameRunner.js";
|
|
10
|
+
import canvas2Sampler2D from "../../../../engine/graphics/texture/Canvas2Sampler2D.js";
|
|
11
|
+
import {
|
|
12
|
+
copy_Sampler2D_channel_data
|
|
13
|
+
} from "../../../../engine/graphics/texture/sampler/copy_Sampler2D_channel_data.js";
|
|
14
|
+
import { MouseEvents } from "../../../../engine/input/devices/events/MouseEvents.js";
|
|
15
|
+
import { downloadSampler2DAsPNG } from "../../../../engine/graphics/texture/sampler/downloadSamplerAsPNG.js";
|
|
16
|
+
import {
|
|
17
|
+
sampler2d_compute_texel_value_conversion_scale_to_uint8
|
|
18
|
+
} from "../../../../engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.js";
|
|
19
|
+
import EmptyView from "../../../../view/elements/EmptyView.js";
|
|
15
20
|
|
|
16
21
|
const UPDATE_DELAY = 200;
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param {Sampler2D} sampler
|
|
26
|
+
* @param {HTMLCanvasElement} domElement
|
|
27
|
+
*/
|
|
28
|
+
function draw_sampler(sampler, domElement) {
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
let TypedArrayConstructor = typedArrayConstructorByInstance(sampler.data);
|
|
32
|
+
|
|
33
|
+
if (TypedArrayConstructor === Uint8Array) {
|
|
34
|
+
// use clamped array to avoid filtering artifacts
|
|
35
|
+
TypedArrayConstructor = Uint8ClampedArray;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const res = 32;
|
|
39
|
+
const result_sampler = new Sampler2D(new TypedArrayConstructor(sampler.itemSize * res * res), sampler.itemSize, res, res);
|
|
40
|
+
|
|
41
|
+
scaleSampler2D(sampler, result_sampler);
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
const { scale, offset } = sampler2d_compute_texel_value_conversion_scale_to_uint8(result_sampler);
|
|
45
|
+
|
|
46
|
+
sampler2D2Canvas(result_sampler, scale, offset, domElement);
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param {*} parent
|
|
53
|
+
* @param {HTMLCanvasElement} element
|
|
54
|
+
* @param {FieldDescriptor} field
|
|
55
|
+
*/
|
|
56
|
+
function enable_drop(parent, element, field) {
|
|
57
|
+
/**
|
|
58
|
+
*
|
|
59
|
+
* @param {DragEvent} ev
|
|
60
|
+
*/
|
|
61
|
+
function handleDrop(ev) {
|
|
62
|
+
ev.preventDefault();
|
|
63
|
+
|
|
64
|
+
let processed = false;
|
|
20
65
|
|
|
21
66
|
/**
|
|
22
|
-
*
|
|
67
|
+
*
|
|
68
|
+
* @param {File} file
|
|
23
69
|
*/
|
|
24
|
-
|
|
70
|
+
function processFile(file) {
|
|
71
|
+
if (processed) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
25
74
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
75
|
+
var img = new Image();
|
|
76
|
+
// URL @ Mozilla, webkitURL @ Chrome
|
|
77
|
+
img.src = (window.webkitURL ? webkitURL : URL).createObjectURL(file);
|
|
29
78
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
79
|
+
// call ctx.drawImage when the image got loaded
|
|
80
|
+
img.onload = function () {
|
|
81
|
+
var canvas = document.createElement("canvas");
|
|
82
|
+
var ctx = canvas.getContext("2d");
|
|
34
83
|
|
|
35
|
-
|
|
36
|
-
|
|
84
|
+
const width = img.width;
|
|
85
|
+
const height = img.height;
|
|
37
86
|
|
|
38
|
-
|
|
87
|
+
canvas.style.width = `${width}px`;
|
|
88
|
+
canvas.style.height = `${height}px`;
|
|
39
89
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
} else {
|
|
43
|
-
dataType = DataType.Float32;
|
|
44
|
-
}
|
|
90
|
+
canvas.width = width;
|
|
91
|
+
canvas.height = height;
|
|
45
92
|
|
|
46
|
-
|
|
93
|
+
// ctx.drawImage(img, 0, 0);
|
|
94
|
+
ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height); // stretch img to canvas size
|
|
47
95
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
96
|
+
const file_data_sampler = canvas2Sampler2D(canvas);
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @type {Sampler2D}
|
|
100
|
+
*/
|
|
101
|
+
const sampler = field.adapter.read(parent, field.name);
|
|
102
|
+
|
|
103
|
+
sampler.resize(width, height, false);
|
|
52
104
|
|
|
53
|
-
|
|
54
|
-
|
|
105
|
+
copy_Sampler2D_channel_data(file_data_sampler, sampler);
|
|
106
|
+
};
|
|
55
107
|
|
|
56
|
-
scaleSampler2D(sampler, result_sampler);
|
|
57
108
|
|
|
109
|
+
processed = true;
|
|
110
|
+
}
|
|
58
111
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
112
|
+
if (ev.dataTransfer.items) {
|
|
113
|
+
// Use DataTransferItemList interface to access the file(s)
|
|
114
|
+
for (var i = 0; i < ev.dataTransfer.items.length; i++) {
|
|
115
|
+
// If dropped items aren't files, reject them
|
|
116
|
+
if (ev.dataTransfer.items[i].kind === 'file') {
|
|
117
|
+
var file = ev.dataTransfer.items[i].getAsFile();
|
|
64
118
|
|
|
65
|
-
|
|
66
|
-
max = max2(min, result_sampler.computeMax(i).value)
|
|
119
|
+
processFile(file);
|
|
67
120
|
}
|
|
68
|
-
} else if (dataType === DataType.Uint8) {
|
|
69
|
-
min = 0;
|
|
70
|
-
max = 255;
|
|
71
121
|
}
|
|
122
|
+
} else {
|
|
123
|
+
// Use DataTransfer interface to access the file(s)
|
|
124
|
+
for (var i = 0; i < ev.dataTransfer.files.length; i++) {
|
|
125
|
+
const file = ev.dataTransfer.files[i];
|
|
126
|
+
|
|
127
|
+
processFile(file);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function handleDragOver(ev) {
|
|
133
|
+
|
|
134
|
+
// Prevent default behavior (Prevent file from being opened)
|
|
135
|
+
ev.preventDefault();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
element.addEventListener('dragover', handleDragOver);
|
|
139
|
+
element.addEventListener('drop', handleDrop);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export class Sampler2DEditor extends TypeEditor {
|
|
143
|
+
|
|
144
|
+
build(parent, field, context) {
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @type {Sampler2D}
|
|
148
|
+
*/
|
|
149
|
+
const sampler = field.adapter.read(parent, field.name);
|
|
150
|
+
|
|
151
|
+
let last_version = -1;
|
|
152
|
+
let last_update_time = 0;
|
|
153
|
+
let last_update_duration = 0;
|
|
154
|
+
|
|
155
|
+
const view_container = new EmptyView({
|
|
156
|
+
css:{
|
|
157
|
+
width: "min-content",
|
|
158
|
+
height:"min-content"
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const canvas_view = new CanvasView();
|
|
163
|
+
canvas_view.css({
|
|
164
|
+
background: 'black',
|
|
165
|
+
position: 'relative',
|
|
166
|
+
});
|
|
72
167
|
|
|
73
|
-
|
|
74
|
-
const
|
|
168
|
+
function draw() {
|
|
169
|
+
const draw_start_time = performance.now();
|
|
75
170
|
|
|
76
|
-
|
|
171
|
+
draw_sampler(sampler, canvas_view.el);
|
|
77
172
|
|
|
78
173
|
last_version = sampler.version;
|
|
79
174
|
|
|
@@ -84,7 +179,7 @@ export class Sampler2DEditor extends TypeEditor {
|
|
|
84
179
|
}
|
|
85
180
|
|
|
86
181
|
|
|
87
|
-
|
|
182
|
+
canvas_view.on.linked.add(try_update);
|
|
88
183
|
|
|
89
184
|
function try_update() {
|
|
90
185
|
if (sampler.version !== last_version) {
|
|
@@ -99,9 +194,28 @@ export class Sampler2DEditor extends TypeEditor {
|
|
|
99
194
|
|
|
100
195
|
const frameRunner = new FrameRunner(try_update);
|
|
101
196
|
|
|
102
|
-
|
|
103
|
-
|
|
197
|
+
canvas_view.on.linked.add(frameRunner.startup, frameRunner);
|
|
198
|
+
canvas_view.on.unlinked.add(frameRunner.shutdown, frameRunner);
|
|
199
|
+
|
|
200
|
+
//drop target
|
|
201
|
+
const allow_drop = true;
|
|
202
|
+
if (allow_drop) {
|
|
203
|
+
|
|
204
|
+
enable_drop(parent, canvas_view.el, field);
|
|
205
|
+
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const allow_download = true;
|
|
209
|
+
if (allow_download) {
|
|
210
|
+
canvas_view.el.addEventListener(MouseEvents.Click, () => {
|
|
211
|
+
downloadSampler2DAsPNG(sampler, field.name);
|
|
212
|
+
});
|
|
213
|
+
// add download marker
|
|
214
|
+
view_container.addClass('downloadable');
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
view_container.addChild(canvas_view);
|
|
104
218
|
|
|
105
|
-
return
|
|
219
|
+
return view_container;
|
|
106
220
|
}
|
|
107
221
|
}
|
|
@@ -3,6 +3,12 @@ import { convertTexture2Sampler2D } from "../../../../../engine/graphics/texture
|
|
|
3
3
|
import { Sampler2D } from "../../../../../engine/graphics/texture/sampler/Sampler2D.js";
|
|
4
4
|
import { CanvasView } from "../../../../../view/elements/CanvasView.js";
|
|
5
5
|
import sampler2D2Canvas from "../../../../../engine/graphics/texture/sampler/Sampler2D2Canvas.js";
|
|
6
|
+
import { MouseEvents } from "../../../../../engine/input/devices/events/MouseEvents.js";
|
|
7
|
+
import { downloadSampler2DAsPNG } from "../../../../../engine/graphics/texture/sampler/downloadSamplerAsPNG.js";
|
|
8
|
+
import EmptyView from "../../../../../view/elements/EmptyView.js";
|
|
9
|
+
import { FrameRunner } from "../../../../../engine/graphics/FrameRunner.js";
|
|
10
|
+
|
|
11
|
+
const UPDATE_DELAY = 200;
|
|
6
12
|
|
|
7
13
|
export class TextureEditor extends TypeEditor {
|
|
8
14
|
inline = true;
|
|
@@ -10,7 +16,7 @@ export class TextureEditor extends TypeEditor {
|
|
|
10
16
|
build(parent, field, registry) {
|
|
11
17
|
const size = 32;
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
let texture = field.adapter.read(parent, field.name);
|
|
14
20
|
let sampler;
|
|
15
21
|
if (texture) {
|
|
16
22
|
|
|
@@ -21,12 +27,84 @@ export class TextureEditor extends TypeEditor {
|
|
|
21
27
|
sampler.fill_channel(3, 255);
|
|
22
28
|
}
|
|
23
29
|
|
|
30
|
+
const vContainer = new EmptyView({
|
|
31
|
+
css: {
|
|
32
|
+
width: "min-content",
|
|
33
|
+
height: "min-content"
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
24
37
|
const canvasView = new CanvasView();
|
|
38
|
+
canvasView.css({
|
|
39
|
+
position: "relative",
|
|
40
|
+
background: 'black'
|
|
41
|
+
});
|
|
42
|
+
vContainer.addChild(canvasView);
|
|
25
43
|
|
|
26
44
|
canvasView.size.set(sampler.width, sampler.height);
|
|
27
45
|
|
|
28
|
-
sampler2D2Canvas(sampler, 1, 0, canvasView.el);
|
|
29
46
|
|
|
30
|
-
|
|
47
|
+
let last_version = -1;
|
|
48
|
+
let last_update_time = 0;
|
|
49
|
+
let last_update_duration = 0;
|
|
50
|
+
|
|
51
|
+
function draw() {
|
|
52
|
+
const draw_start_time = performance.now();
|
|
53
|
+
|
|
54
|
+
sampler = convertTexture2Sampler2D(texture, size, size);
|
|
55
|
+
sampler2D2Canvas(sampler, 1, 0, canvasView.el);
|
|
56
|
+
|
|
57
|
+
last_version = texture.version;
|
|
58
|
+
|
|
59
|
+
const draw_end_time = performance.now();
|
|
60
|
+
last_update_duration = draw_end_time - draw_start_time;
|
|
61
|
+
|
|
62
|
+
last_update_time = draw_end_time;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
function try_update() {
|
|
67
|
+
const time_now = performance.now();
|
|
68
|
+
|
|
69
|
+
if ((time_now - last_update_time) < UPDATE_DELAY) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
texture = field.adapter.read(parent, field.name);
|
|
74
|
+
|
|
75
|
+
if (texture === undefined || texture === null) {
|
|
76
|
+
sampler.fill(0);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (texture.version !== last_version) {
|
|
81
|
+
draw();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const frameRunner = new FrameRunner(try_update);
|
|
86
|
+
|
|
87
|
+
canvasView.on.linked.add(frameRunner.startup, frameRunner);
|
|
88
|
+
canvasView.on.unlinked.add(frameRunner.shutdown, frameRunner);
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
const allow_download = true;
|
|
92
|
+
if (allow_download) {
|
|
93
|
+
vContainer.el.addEventListener(MouseEvents.Click, () => {
|
|
94
|
+
const texture = field.adapter.read(parent, field.name);
|
|
95
|
+
if (texture === undefined || texture == null) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const sampler = convertTexture2Sampler2D(texture);
|
|
100
|
+
|
|
101
|
+
downloadSampler2DAsPNG(sampler, field.name);
|
|
102
|
+
});
|
|
103
|
+
// add download marker
|
|
104
|
+
vContainer.addClass('downloadable');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
return vContainer;
|
|
31
109
|
}
|
|
32
110
|
}
|
|
@@ -30,7 +30,6 @@ import { SplatMapping } from "./splat/SplatMapping.js";
|
|
|
30
30
|
import { OffsetScaleTransform2D } from "./OffsetScaleTransform2D.js";
|
|
31
31
|
import { GridTransformKind } from "./GridTransformKind.js";
|
|
32
32
|
import { makeTerrainWorkerProxy } from "./makeTerrainWorkerProxy.js";
|
|
33
|
-
import { MeepSettings } from "../../../MeepSettings.js";
|
|
34
33
|
import { loadLegacyTerrainLayers } from "./layers/loadLegacyTerrainLayers.js";
|
|
35
34
|
import { TerrainFlags } from "./TerrainFlags.js";
|
|
36
35
|
import { IllegalStateException } from "../../../../core/fsm/exceptions/IllegalStateException.js";
|
|
@@ -798,8 +797,6 @@ class Terrain {
|
|
|
798
797
|
//
|
|
799
798
|
this.overlay.size.copy(this.size);
|
|
800
799
|
|
|
801
|
-
this.overlay.tileImage.set(MeepSettings.ecs.Terrain['tile-decal']);
|
|
802
|
-
|
|
803
800
|
this.__tiles.totalSize.copy(this.size);
|
|
804
801
|
this.__tiles.scale.set(this.gridScale, this.gridScale);
|
|
805
802
|
this.__tiles.resolution.set(this.resolution);
|
|
@@ -960,12 +957,19 @@ class Terrain {
|
|
|
960
957
|
this.layers.fromJSON(opt.layers);
|
|
961
958
|
this.splat.fromJSON(opt.splat);
|
|
962
959
|
|
|
960
|
+
if (opt.overlayTileImage !== undefined) {
|
|
961
|
+
|
|
962
|
+
this.overlay.baseTileImage(opt.overlayTileImage);
|
|
963
|
+
|
|
964
|
+
}
|
|
965
|
+
|
|
963
966
|
|
|
964
967
|
// debugSamplers(this);
|
|
965
968
|
this.build(engine.assetManager);
|
|
966
969
|
}
|
|
967
970
|
|
|
968
971
|
toJSON() {
|
|
972
|
+
|
|
969
973
|
const result = {
|
|
970
974
|
size: this.size.toJSON(),
|
|
971
975
|
scale: this.gridScale,
|
|
@@ -974,7 +978,8 @@ class Terrain {
|
|
|
974
978
|
preview: this.preview.toJSON(),
|
|
975
979
|
heights: this.samplerHeight.toJSON(),
|
|
976
980
|
layers: this.layers.toJSON(),
|
|
977
|
-
splat: this.splat.toJSON()
|
|
981
|
+
splat: this.splat.toJSON(),
|
|
982
|
+
overlayTileImage: this.overlay.baseTileImage
|
|
978
983
|
};
|
|
979
984
|
|
|
980
985
|
return result;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {System} from "../../System";
|
|
2
2
|
import {GraphicsEngine} from "../../../graphics/GraphicsEngine";
|
|
3
3
|
import {AssetManager} from "../../../asset/AssetManager";
|
|
4
|
+
import Terrain from "./Terrain";
|
|
4
5
|
|
|
5
|
-
export default class TerrainSystem extends System {
|
|
6
|
+
export default class TerrainSystem extends System<Terrain> {
|
|
6
7
|
constructor(graphics: GraphicsEngine, assetManager: AssetManager)
|
|
7
8
|
}
|
|
@@ -116,6 +116,26 @@ export class TerrainOverlay {
|
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @returns {string}
|
|
122
|
+
*/
|
|
123
|
+
get baseTileImage(){
|
|
124
|
+
return this.stack.length === 0 ? this.tileImage.getValue() : this.stack[0].tileImage
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
* @param {string} v
|
|
130
|
+
*/
|
|
131
|
+
set baseTileImage(v){
|
|
132
|
+
if (this.stack.length === 0) {
|
|
133
|
+
this.tileImage.set(v);
|
|
134
|
+
} else {
|
|
135
|
+
this.stack[0].tileImage = v;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
119
139
|
/**
|
|
120
140
|
* @returns {HTMLCanvasElement}
|
|
121
141
|
*/
|
|
@@ -23,6 +23,9 @@ export const ProjectionType = {
|
|
|
23
23
|
Orthographic: "orthographic"
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @class
|
|
28
|
+
*/
|
|
26
29
|
export class Camera {
|
|
27
30
|
constructor() {
|
|
28
31
|
/**
|
|
@@ -176,7 +179,7 @@ export class Camera {
|
|
|
176
179
|
// assert.ok(y >= -1, `Y(=${y}) must be greater than or equal to -1.0, not a clip-space coordinate`);
|
|
177
180
|
// assert.ok(y <= 1, `Y(=${y}) must be less than or equal to 1.0, not a clip-space coordinate`);
|
|
178
181
|
|
|
179
|
-
if (camera.isPerspectiveCamera) {
|
|
182
|
+
if (camera.isPerspectiveCamera || camera.isOrthographicCamera) {
|
|
180
183
|
scratch_v3_1.setFromMatrixPosition(camera.matrixWorld.elements);
|
|
181
184
|
|
|
182
185
|
scratch_v3_0.set(x, y, 0.5);
|
|
@@ -197,9 +200,7 @@ export class Camera {
|
|
|
197
200
|
source.copy(scratch_v3_1);
|
|
198
201
|
direction.copy(scratch_v3_0);
|
|
199
202
|
|
|
200
|
-
}
|
|
201
|
-
throw new Error('Unsupported camera type: "Orthographic" ');
|
|
202
|
-
} else {
|
|
203
|
+
} else {
|
|
203
204
|
throw new Error('Unsupported camera type');
|
|
204
205
|
}
|
|
205
206
|
}
|
|
@@ -70,6 +70,7 @@ import { BasicMaterialDefinition } from "./tube/BasicMaterialDefinition.js";
|
|
|
70
70
|
import '../../../../../../../css/game.scss';
|
|
71
71
|
import { GizmoRenderingPlugin } from "../../render/gizmo/GizmoRenderingPlugin.js";
|
|
72
72
|
import { PathNormalType } from "./tube/PathNormalType.js";
|
|
73
|
+
import { Camera } from "../camera/Camera.js";
|
|
73
74
|
|
|
74
75
|
const engineHarness = new EngineHarness();
|
|
75
76
|
|
|
@@ -427,6 +428,11 @@ function makePath({
|
|
|
427
428
|
function main(engine) {
|
|
428
429
|
EngineHarness.buildBasics({ engine });
|
|
429
430
|
|
|
431
|
+
const ecd = engine.entityManager.dataset;
|
|
432
|
+
|
|
433
|
+
const cam = ecd.getAnyComponent(Camera);
|
|
434
|
+
// cam.component.projectionType.set(ProjectionType.Orthographic);
|
|
435
|
+
|
|
430
436
|
makePath({
|
|
431
437
|
points: [
|
|
432
438
|
3, 1, 1,
|
|
@@ -437,7 +443,7 @@ function main(engine) {
|
|
|
437
443
|
3, 1, 8
|
|
438
444
|
],
|
|
439
445
|
interp: InterpolationType.Linear
|
|
440
|
-
}).build(
|
|
446
|
+
}).build(ecd);
|
|
441
447
|
|
|
442
448
|
makePath({
|
|
443
449
|
points: [
|
|
@@ -447,7 +453,7 @@ function main(engine) {
|
|
|
447
453
|
16.719999313354492, 3.130000114440918, -6.889999866485596
|
|
448
454
|
],
|
|
449
455
|
interp: InterpolationType.Linear
|
|
450
|
-
}).build(
|
|
456
|
+
}).build(ecd);
|
|
451
457
|
}
|
|
452
458
|
|
|
453
459
|
init(engineHarness);
|
|
@@ -116,6 +116,23 @@ export class TubePathStyle {
|
|
|
116
116
|
return r;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
*
|
|
121
|
+
* @param {string|{r:number,g:number,b:number}} color
|
|
122
|
+
* @param material_type
|
|
123
|
+
* @param material
|
|
124
|
+
* @param opacity
|
|
125
|
+
* @param width
|
|
126
|
+
* @param radial_resolution
|
|
127
|
+
* @param resolution
|
|
128
|
+
* @param cast_shadow
|
|
129
|
+
* @param receive_shadow
|
|
130
|
+
* @param path_mask
|
|
131
|
+
* @param cap_type
|
|
132
|
+
* @param shape
|
|
133
|
+
* @param path_normal
|
|
134
|
+
* @param path_normal_type
|
|
135
|
+
*/
|
|
119
136
|
fromJSON({
|
|
120
137
|
color = DEFAULT_COLOR,
|
|
121
138
|
material_type,
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
* @param {function(index:int, array:ArrayLike<number>, x:int, y:int)} [fillDD] allows you to supply mapping function, if none is given - one will be created from sampler using {@link Sampler2D#makeArrayFiller}
|
|
13
13
|
* @returns {HTMLCanvasElement} canvas
|
|
14
14
|
*/
|
|
15
|
-
function convertSampler2D2Canvas(sampler, scale, offset, canvas, fillDD) {
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
function convertSampler2D2Canvas(sampler, scale=255, offset=0, canvas, fillDD) {
|
|
16
|
+
const source_data = sampler.data;
|
|
17
|
+
|
|
18
18
|
//generate canvas
|
|
19
19
|
if (canvas === undefined) {
|
|
20
20
|
canvas = document.createElement("canvas");
|
|
@@ -39,11 +39,12 @@ function convertSampler2D2Canvas(sampler, scale, offset, canvas, fillDD) {
|
|
|
39
39
|
const imageData = context.createImageData(width, height);
|
|
40
40
|
const array = imageData.data;
|
|
41
41
|
//
|
|
42
|
-
|
|
42
|
+
const source_channel_count = sampler.itemSize;
|
|
43
|
+
if (source_channel_count === 4 && offset === 0 && scale === 1) {
|
|
43
44
|
// shortcut or straight forward case
|
|
44
|
-
array.set(
|
|
45
|
+
array.set(source_data);
|
|
45
46
|
} else {
|
|
46
|
-
if (
|
|
47
|
+
if (source_channel_count < 4) {
|
|
47
48
|
//sampler lacks alpha channel, set alpha values to fully opaque
|
|
48
49
|
const n = width * height * 4;
|
|
49
50
|
|
|
@@ -53,17 +54,44 @@ function convertSampler2D2Canvas(sampler, scale, offset, canvas, fillDD) {
|
|
|
53
54
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
if (fillDD === undefined) {
|
|
57
|
-
fillDD = sampler.makeArrayFiller(scale, offset);
|
|
58
|
-
}
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for (let
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
if (source_channel_count === 1) {
|
|
59
|
+
let index = 0;
|
|
60
|
+
for (let y = 0; y < height; y++) {
|
|
61
|
+
for (let x = 0; x < width; x++) {
|
|
62
|
+
const texel_address = (y * width + x);
|
|
63
|
+
|
|
64
|
+
const source_value = source_data[texel_address];
|
|
65
|
+
const transformed_value = Math.round((source_value + offset) * scale);
|
|
66
|
+
|
|
67
|
+
// write identical RGB for grayscale image
|
|
68
|
+
array[index + 0] = transformed_value;
|
|
69
|
+
array[index + 1] = transformed_value;
|
|
70
|
+
array[index + 2] = transformed_value;
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
index += 4;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
|
|
78
|
+
let index = 0;
|
|
79
|
+
for (let y = 0; y < height; y++) {
|
|
80
|
+
for (let x = 0; x < width; x++) {
|
|
81
|
+
const texel_address = (y * width + x) * source_channel_count;
|
|
82
|
+
|
|
83
|
+
for (let i = 0; i < source_channel_count; i++) {
|
|
84
|
+
const source_value = source_data[texel_address + i];
|
|
85
|
+
const transformed_value = Math.round((source_value + offset) * scale);
|
|
86
|
+
array[index + i] = transformed_value;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
index += 4;
|
|
91
|
+
}
|
|
65
92
|
}
|
|
66
93
|
}
|
|
94
|
+
|
|
67
95
|
}
|
|
68
96
|
|
|
69
97
|
context.putImageData(imageData, 0, 0);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import convertSampler2D2Canvas from "./Sampler2D2Canvas.js";
|
|
2
|
+
import {
|
|
3
|
+
sampler2d_compute_texel_value_conversion_scale_to_uint8
|
|
4
|
+
} from "./sampler2d_compute_texel_value_conversion_scale_to_uint8.js";
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
*
|
|
@@ -11,7 +14,10 @@ export function convertSampler2D2DataURL(sampler) {
|
|
|
11
14
|
|
|
12
15
|
var ctx = canvasElement.getContext("2d");
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
|
|
18
|
+
const { scale, offset } = sampler2d_compute_texel_value_conversion_scale_to_uint8(sampler);
|
|
19
|
+
|
|
20
|
+
convertSampler2D2Canvas(sampler, scale, offset, canvasElement);
|
|
15
21
|
|
|
16
22
|
return ctx.canvas.toDataURL('image/png');
|
|
17
23
|
|
package/engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { DataType } from "../../../../core/collection/table/DataType.js";
|
|
2
|
+
import { min2 } from "../../../../core/math/min2.js";
|
|
3
|
+
import { max2 } from "../../../../core/math/max2.js";
|
|
4
|
+
import { isTypedArray } from "../../../../core/collection/array/typed/isTypedArray.js";
|
|
5
|
+
import { typedArrayToDataType } from "../../../../core/collection/array/typedArrayToDataType.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {Sampler2D} sampler
|
|
10
|
+
* @returns {{offset: number, scale: number}}
|
|
11
|
+
*/
|
|
12
|
+
export function sampler2d_compute_texel_value_conversion_scale_to_uint8(sampler) {
|
|
13
|
+
|
|
14
|
+
let dataType;
|
|
15
|
+
|
|
16
|
+
if (isTypedArray(sampler.data)) {
|
|
17
|
+
dataType = typedArrayToDataType(sampler.data);
|
|
18
|
+
} else {
|
|
19
|
+
// plain numeric array
|
|
20
|
+
dataType = DataType.Float32;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let min = 0, max = 0;
|
|
24
|
+
|
|
25
|
+
if (dataType === DataType.Uint8) {
|
|
26
|
+
min = 0;
|
|
27
|
+
max = 255;
|
|
28
|
+
} else {
|
|
29
|
+
// unknown input type, compute min and max
|
|
30
|
+
min = Infinity;
|
|
31
|
+
max = -Infinity;
|
|
32
|
+
for (let i = 0; i < sampler.itemSize; i++) {
|
|
33
|
+
|
|
34
|
+
min = min2(min, sampler.computeMin(i).value)
|
|
35
|
+
max = max2(min, sampler.computeMax(i).value)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const span = max - min;
|
|
40
|
+
|
|
41
|
+
const scale = span === 0 ? 0 : 255 / span;
|
|
42
|
+
const offset = min;
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
scale, offset
|
|
46
|
+
};
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"productName": "Meep",
|
|
6
6
|
"description": "production-ready JavaScript game engine based on Entity Component System Architecture",
|
|
7
7
|
"author": "Alexander Goldring",
|
|
8
|
-
"version": "2.39.
|
|
8
|
+
"version": "2.39.12",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"gl-matrix": "3.4.3",
|
|
11
11
|
"fast-levenshtein": "2.0.6",
|
package/view/View.js
CHANGED
|
@@ -26,7 +26,7 @@ function setElementTransform(domElement, position, scale, rotation) {
|
|
|
26
26
|
|
|
27
27
|
const m3 = scratch_m3_0;
|
|
28
28
|
|
|
29
|
-
m3_cm_compose_transform(m3, position.x, position.y, scale.x, scale.y,0,0, rotation);
|
|
29
|
+
m3_cm_compose_transform(m3, position.x, position.y, scale.x, scale.y, 0, 0, rotation);
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
/*
|
|
@@ -644,7 +644,7 @@ class View {
|
|
|
644
644
|
* @param {string} name
|
|
645
645
|
*/
|
|
646
646
|
addClass(name) {
|
|
647
|
-
assert.
|
|
647
|
+
assert.isString(name, 'name');
|
|
648
648
|
|
|
649
649
|
this.el.classList.add(name);
|
|
650
650
|
}
|
|
@@ -660,7 +660,7 @@ class View {
|
|
|
660
660
|
for (let i = 0; i < n; i++) {
|
|
661
661
|
const name = names[i];
|
|
662
662
|
|
|
663
|
-
assert.
|
|
663
|
+
assert.isString(name, 'name');
|
|
664
664
|
|
|
665
665
|
classList.add(name);
|
|
666
666
|
}
|