@scratch/scratch-render 11.0.0-beta.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/.nvmrc +1 -0
- package/CHANGELOG.md +2281 -0
- package/LICENSE +12 -0
- package/README.md +87 -0
- package/TRADEMARK +1 -0
- package/commitlint.config.js +4 -0
- package/docs/Rectangle-AABB-Matrix.md +192 -0
- package/package.json +84 -0
- package/release.config.js +10 -0
- package/src/BitmapSkin.js +120 -0
- package/src/Drawable.js +734 -0
- package/src/EffectTransform.js +197 -0
- package/src/PenSkin.js +350 -0
- package/src/Rectangle.js +196 -0
- package/src/RenderConstants.js +34 -0
- package/src/RenderWebGL.js +2029 -0
- package/src/SVGSkin.js +239 -0
- package/src/ShaderManager.js +187 -0
- package/src/Silhouette.js +257 -0
- package/src/Skin.js +235 -0
- package/src/TextBubbleSkin.js +284 -0
- package/src/index.js +7 -0
- package/src/playground/getMousePosition.js +37 -0
- package/src/playground/index.html +41 -0
- package/src/playground/playground.js +202 -0
- package/src/playground/queryPlayground.html +73 -0
- package/src/playground/queryPlayground.js +196 -0
- package/src/playground/style.css +11 -0
- package/src/shaders/sprite.frag +249 -0
- package/src/shaders/sprite.vert +75 -0
- package/src/util/canvas-measurement-provider.js +41 -0
- package/src/util/color-conversions.js +97 -0
- package/src/util/log.js +4 -0
- package/src/util/text-wrapper.js +112 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
const ScratchRender = require('../RenderWebGL');
|
|
2
|
+
const getMousePosition = require('./getMousePosition');
|
|
3
|
+
|
|
4
|
+
const canvas = document.getElementById('scratch-stage');
|
|
5
|
+
let fudge = 90;
|
|
6
|
+
const renderer = new ScratchRender(canvas);
|
|
7
|
+
renderer.setLayerGroupOrdering(['group1']);
|
|
8
|
+
|
|
9
|
+
const drawableID = renderer.createDrawable('group1');
|
|
10
|
+
renderer.updateDrawableProperties(drawableID, {
|
|
11
|
+
position: [0, 0],
|
|
12
|
+
scale: [100, 100],
|
|
13
|
+
direction: 90
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const WantedSkinType = {
|
|
17
|
+
bitmap: 'bitmap',
|
|
18
|
+
vector: 'vector',
|
|
19
|
+
pen: 'pen'
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const drawableID2 = renderer.createDrawable('group1');
|
|
23
|
+
const wantedSkin = WantedSkinType.vector;
|
|
24
|
+
|
|
25
|
+
// Bitmap (squirrel)
|
|
26
|
+
const image = new Image();
|
|
27
|
+
image.addEventListener('load', () => {
|
|
28
|
+
const bitmapSkinId = renderer.createBitmapSkin(image);
|
|
29
|
+
if (wantedSkin === WantedSkinType.bitmap) {
|
|
30
|
+
renderer.updateDrawableProperties(drawableID2, {
|
|
31
|
+
skinId: bitmapSkinId
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
image.crossOrigin = 'anonymous';
|
|
36
|
+
image.src = 'https://cdn.assets.scratch.mit.edu/internalapi/asset/7e24c99c1b853e52f8e7f9004416fa34.png/get/';
|
|
37
|
+
|
|
38
|
+
// SVG (cat 1-a)
|
|
39
|
+
const xhr = new XMLHttpRequest();
|
|
40
|
+
xhr.addEventListener('load', () => {
|
|
41
|
+
const skinId = renderer.createSVGSkin(xhr.responseText);
|
|
42
|
+
if (wantedSkin === WantedSkinType.vector) {
|
|
43
|
+
renderer.updateDrawableProperties(drawableID2, {
|
|
44
|
+
skinId: skinId
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
xhr.open('GET', 'https://cdn.assets.scratch.mit.edu/internalapi/asset/b7853f557e4426412e64bb3da6531a99.svg/get/');
|
|
49
|
+
xhr.send();
|
|
50
|
+
|
|
51
|
+
if (wantedSkin === WantedSkinType.pen) {
|
|
52
|
+
const penSkinID = renderer.createPenSkin();
|
|
53
|
+
|
|
54
|
+
renderer.updateDrawableProperties(drawableID2, {
|
|
55
|
+
skinId: penSkinID
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
canvas.addEventListener('click', event => {
|
|
59
|
+
const rect = canvas.getBoundingClientRect();
|
|
60
|
+
|
|
61
|
+
const x = event.clientX - rect.left;
|
|
62
|
+
const y = event.clientY - rect.top;
|
|
63
|
+
|
|
64
|
+
renderer.penLine(penSkinID, {
|
|
65
|
+
color4f: [Math.random(), Math.random(), Math.random(), 1],
|
|
66
|
+
diameter: 8
|
|
67
|
+
},
|
|
68
|
+
x - 240, 180 - y, (Math.random() * 480) - 240, (Math.random() * 360) - 180);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let posX = 0;
|
|
73
|
+
let posY = 0;
|
|
74
|
+
let scaleX = 100;
|
|
75
|
+
let scaleY = 100;
|
|
76
|
+
let fudgeProperty = 'posx';
|
|
77
|
+
|
|
78
|
+
const fudgeInput = document.getElementById('fudge');
|
|
79
|
+
const fudgePropertyInput = document.getElementById('fudgeproperty');
|
|
80
|
+
const fudgeMinInput = document.getElementById('fudgeMin');
|
|
81
|
+
const fudgeMaxInput = document.getElementById('fudgeMax');
|
|
82
|
+
|
|
83
|
+
/* eslint require-jsdoc: 0 */
|
|
84
|
+
const updateFudgeProperty = event => {
|
|
85
|
+
fudgeProperty = event.target.value;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const updateFudgeMin = event => {
|
|
89
|
+
fudgeInput.min = event.target.valueAsNumber;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const updateFudgeMax = event => {
|
|
93
|
+
fudgeInput.max = event.target.valueAsNumber;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
fudgePropertyInput.addEventListener('change', updateFudgeProperty);
|
|
97
|
+
fudgePropertyInput.addEventListener('init', updateFudgeProperty);
|
|
98
|
+
|
|
99
|
+
fudgeMinInput.addEventListener('change', updateFudgeMin);
|
|
100
|
+
fudgeMinInput.addEventListener('init', updateFudgeMin);
|
|
101
|
+
|
|
102
|
+
fudgeMaxInput.addEventListener('change', updateFudgeMax);
|
|
103
|
+
fudgeMaxInput.addEventListener('init', updateFudgeMax);
|
|
104
|
+
|
|
105
|
+
// Ugly hack to properly set the values of the inputs on page load,
|
|
106
|
+
// since they persist across reloads, at least in Firefox.
|
|
107
|
+
// The best ugly hacks are the ones that reduce code duplication!
|
|
108
|
+
fudgePropertyInput.dispatchEvent(new CustomEvent('init'));
|
|
109
|
+
fudgeMinInput.dispatchEvent(new CustomEvent('init'));
|
|
110
|
+
fudgeMaxInput.dispatchEvent(new CustomEvent('init'));
|
|
111
|
+
fudgeInput.dispatchEvent(new CustomEvent('init'));
|
|
112
|
+
|
|
113
|
+
const handleFudgeChanged = function (event) {
|
|
114
|
+
fudge = event.target.valueAsNumber;
|
|
115
|
+
const props = {};
|
|
116
|
+
switch (fudgeProperty) {
|
|
117
|
+
case 'posx':
|
|
118
|
+
props.position = [fudge, posY];
|
|
119
|
+
posX = fudge;
|
|
120
|
+
break;
|
|
121
|
+
case 'posy':
|
|
122
|
+
props.position = [posX, fudge];
|
|
123
|
+
posY = fudge;
|
|
124
|
+
break;
|
|
125
|
+
case 'direction':
|
|
126
|
+
props.direction = fudge;
|
|
127
|
+
break;
|
|
128
|
+
case 'scalex':
|
|
129
|
+
props.scale = [fudge, scaleY];
|
|
130
|
+
scaleX = fudge;
|
|
131
|
+
break;
|
|
132
|
+
case 'scaley':
|
|
133
|
+
props.scale = [scaleX, fudge];
|
|
134
|
+
scaleY = fudge;
|
|
135
|
+
break;
|
|
136
|
+
case 'scaleboth':
|
|
137
|
+
props.scale = [fudge, fudge];
|
|
138
|
+
scaleX = fudge;
|
|
139
|
+
scaleY = fudge;
|
|
140
|
+
break;
|
|
141
|
+
case 'color':
|
|
142
|
+
props.color = fudge;
|
|
143
|
+
break;
|
|
144
|
+
case 'whirl':
|
|
145
|
+
props.whirl = fudge;
|
|
146
|
+
break;
|
|
147
|
+
case 'fisheye':
|
|
148
|
+
props.fisheye = fudge;
|
|
149
|
+
break;
|
|
150
|
+
case 'pixelate':
|
|
151
|
+
props.pixelate = fudge;
|
|
152
|
+
break;
|
|
153
|
+
case 'mosaic':
|
|
154
|
+
props.mosaic = fudge;
|
|
155
|
+
break;
|
|
156
|
+
case 'brightness':
|
|
157
|
+
props.brightness = fudge;
|
|
158
|
+
break;
|
|
159
|
+
case 'ghost':
|
|
160
|
+
props.ghost = fudge;
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
renderer.updateDrawableProperties(drawableID2, props);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
fudgeInput.addEventListener('input', handleFudgeChanged);
|
|
167
|
+
fudgeInput.addEventListener('change', handleFudgeChanged);
|
|
168
|
+
fudgeInput.addEventListener('init', handleFudgeChanged);
|
|
169
|
+
|
|
170
|
+
const updateStageScale = event => {
|
|
171
|
+
renderer.resize(480 * event.target.valueAsNumber, 360 * event.target.valueAsNumber);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const stageScaleInput = document.getElementById('stage-scale');
|
|
175
|
+
|
|
176
|
+
stageScaleInput.addEventListener('input', updateStageScale);
|
|
177
|
+
stageScaleInput.addEventListener('change', updateStageScale);
|
|
178
|
+
|
|
179
|
+
canvas.addEventListener('mousemove', event => {
|
|
180
|
+
const mousePos = getMousePosition(event, canvas);
|
|
181
|
+
renderer.extractColor(mousePos.x, mousePos.y, 30);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
canvas.addEventListener('click', event => {
|
|
185
|
+
const mousePos = getMousePosition(event, canvas);
|
|
186
|
+
const pickID = renderer.pick(mousePos.x, mousePos.y);
|
|
187
|
+
console.log(`You clicked on ${(pickID < 0 ? 'nothing' : `ID# ${pickID}`)}`);
|
|
188
|
+
if (pickID >= 0) {
|
|
189
|
+
console.dir(renderer.extractDrawableScreenSpace(pickID, mousePos.x, mousePos.y));
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
const drawStep = function () {
|
|
194
|
+
renderer.draw();
|
|
195
|
+
// renderer.getBounds(drawableID2);
|
|
196
|
+
// renderer.isTouchingColor(drawableID2, [255,255,255]);
|
|
197
|
+
requestAnimationFrame(drawStep);
|
|
198
|
+
};
|
|
199
|
+
drawStep();
|
|
200
|
+
|
|
201
|
+
const debugCanvas = /** @type {canvas} */ document.getElementById('debug-canvas');
|
|
202
|
+
renderer.setDebugCanvas(debugCanvas);
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Scratch WebGL Query Playground</title>
|
|
6
|
+
<link rel="stylesheet" type="text/css" href="style.css">
|
|
7
|
+
<style>
|
|
8
|
+
input[type=range][orient=vertical] {
|
|
9
|
+
writing-mode: bt-lr; /* IE */
|
|
10
|
+
-webkit-appearance: slider-vertical;
|
|
11
|
+
width: 1rem;
|
|
12
|
+
padding: 0 0.5rem;
|
|
13
|
+
}
|
|
14
|
+
canvas {
|
|
15
|
+
/* https://stackoverflow.com/a/7665647 */
|
|
16
|
+
image-rendering: optimizeSpeed; /* Older versions of FF */
|
|
17
|
+
image-rendering: -moz-crisp-edges; /* FF 6.0+ */
|
|
18
|
+
image-rendering: -webkit-optimize-contrast; /* Safari */
|
|
19
|
+
image-rendering: -o-crisp-edges; /* OS X & Windows Opera (12.02+) */
|
|
20
|
+
image-rendering: pixelated; /* Awesome future-browsers */
|
|
21
|
+
-ms-interpolation-mode: nearest-neighbor; /* IE */
|
|
22
|
+
}
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<div>
|
|
27
|
+
<fieldset>
|
|
28
|
+
<legend>Query Canvases</legend>
|
|
29
|
+
<table>
|
|
30
|
+
<tr>
|
|
31
|
+
<td>
|
|
32
|
+
<fieldset>
|
|
33
|
+
<legend>GPU</legend>
|
|
34
|
+
<div>Touching color A? <span id="gpuTouchingA">maybe</span></div>
|
|
35
|
+
<div>Touching color B? <span id="gpuTouchingB">maybe</span></div>
|
|
36
|
+
<canvas id="gpuQueryCanvas" width="480" height="360" style="height: 20rem"></canvas>
|
|
37
|
+
</fieldset>
|
|
38
|
+
</td>
|
|
39
|
+
<td>
|
|
40
|
+
<fieldset>
|
|
41
|
+
<legend>CPU</legend>
|
|
42
|
+
<div>Touching color A? <span id="cpuTouchingA">maybe</span></div>
|
|
43
|
+
<div>Touching color B? <span id="cpuTouchingB">maybe</span></div>
|
|
44
|
+
<canvas id="cpuQueryCanvas" width="480" height="360" style="height: 20rem"></canvas>
|
|
45
|
+
</fieldset>
|
|
46
|
+
</td>
|
|
47
|
+
</tr>
|
|
48
|
+
</table>
|
|
49
|
+
</fieldset>
|
|
50
|
+
<fieldset>
|
|
51
|
+
<legend>Render Canvas</legend>
|
|
52
|
+
<div>Cursor Position: <span id="cursorPosition">somewhere</span></div>
|
|
53
|
+
<table>
|
|
54
|
+
<tr>
|
|
55
|
+
<td></td>
|
|
56
|
+
<td>
|
|
57
|
+
<input id="cursorX" type="range" step="0.25" value="0" />
|
|
58
|
+
</td>
|
|
59
|
+
</tr>
|
|
60
|
+
<tr>
|
|
61
|
+
<td>
|
|
62
|
+
<input id="cursorY" type="range" orient="vertical" step="0.25" value="0" />
|
|
63
|
+
</td>
|
|
64
|
+
<td>
|
|
65
|
+
<canvas id="renderCanvas" width="480" height="360"></canvas>
|
|
66
|
+
</td>
|
|
67
|
+
</tr>
|
|
68
|
+
</table>
|
|
69
|
+
</fieldset>
|
|
70
|
+
</div>
|
|
71
|
+
</body>
|
|
72
|
+
<script src="queryPlayground.js"></script>
|
|
73
|
+
</html>
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const ScratchRender = require('../RenderWebGL');
|
|
2
|
+
const getMousePosition = require('./getMousePosition');
|
|
3
|
+
|
|
4
|
+
const renderCanvas = document.getElementById('renderCanvas');
|
|
5
|
+
const gpuQueryCanvas = document.getElementById('gpuQueryCanvas');
|
|
6
|
+
const cpuQueryCanvas = document.getElementById('cpuQueryCanvas');
|
|
7
|
+
const inputCursorX = document.getElementById('cursorX');
|
|
8
|
+
const inputCursorY = document.getElementById('cursorY');
|
|
9
|
+
const labelCursorPosition = document.getElementById('cursorPosition');
|
|
10
|
+
const labelGpuTouchingA = document.getElementById('gpuTouchingA');
|
|
11
|
+
const labelGpuTouchingB = document.getElementById('gpuTouchingB');
|
|
12
|
+
const labelCpuTouchingA = document.getElementById('cpuTouchingA');
|
|
13
|
+
const labelCpuTouchingB = document.getElementById('cpuTouchingB');
|
|
14
|
+
|
|
15
|
+
const drawables = {
|
|
16
|
+
testPattern: -1,
|
|
17
|
+
cursor: -1
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const colors = {
|
|
21
|
+
cursor: [255, 0, 0],
|
|
22
|
+
patternA: [0, 255, 0],
|
|
23
|
+
patternB: [0, 0, 255]
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const renderer = new ScratchRender(renderCanvas);
|
|
27
|
+
|
|
28
|
+
const handleResizeRenderCanvas = () => {
|
|
29
|
+
const halfWidth = renderCanvas.clientWidth / 2;
|
|
30
|
+
const halfHeight = renderCanvas.clientHeight / 2;
|
|
31
|
+
|
|
32
|
+
inputCursorX.style.width = `${renderCanvas.clientWidth}px`;
|
|
33
|
+
inputCursorY.style.height = `${renderCanvas.clientHeight}px`;
|
|
34
|
+
inputCursorX.min = -halfWidth;
|
|
35
|
+
inputCursorX.max = halfWidth;
|
|
36
|
+
inputCursorY.min = -halfHeight;
|
|
37
|
+
inputCursorY.max = halfHeight;
|
|
38
|
+
};
|
|
39
|
+
renderCanvas.addEventListener('resize', handleResizeRenderCanvas);
|
|
40
|
+
handleResizeRenderCanvas();
|
|
41
|
+
|
|
42
|
+
const handleCursorPositionChanged = () => {
|
|
43
|
+
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
44
|
+
const cursorX = inputCursorX.valueAsNumber / devicePixelRatio;
|
|
45
|
+
const cursorY = inputCursorY.valueAsNumber / devicePixelRatio;
|
|
46
|
+
const positionHTML = `${cursorX}, ${cursorY}`;
|
|
47
|
+
labelCursorPosition.innerHTML = positionHTML;
|
|
48
|
+
if (drawables.cursor >= 0) {
|
|
49
|
+
renderer.draw();
|
|
50
|
+
renderer.updateDrawableProperties(drawables.cursor, {
|
|
51
|
+
position: [cursorX, cursorY]
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
renderer.setUseGpuMode(ScratchRender.UseGpuModes.ForceGPU);
|
|
55
|
+
renderer.setDebugCanvas(gpuQueryCanvas);
|
|
56
|
+
const isGpuTouchingA = renderer.isTouchingColor(drawables.cursor, colors.patternA);
|
|
57
|
+
const isGpuTouchingB = renderer.isTouchingColor(drawables.cursor, colors.patternB);
|
|
58
|
+
labelGpuTouchingA.innerHTML = isGpuTouchingA ? 'yes' : 'no';
|
|
59
|
+
labelGpuTouchingB.innerHTML = isGpuTouchingB ? 'yes' : 'no';
|
|
60
|
+
|
|
61
|
+
renderer.setUseGpuMode(ScratchRender.UseGpuModes.ForceCPU);
|
|
62
|
+
renderer.setDebugCanvas(cpuQueryCanvas);
|
|
63
|
+
const isCpuTouchingA = renderer.isTouchingColor(drawables.cursor, colors.patternA);
|
|
64
|
+
const isCpuTouchingB = renderer.isTouchingColor(drawables.cursor, colors.patternB);
|
|
65
|
+
labelCpuTouchingA.innerHTML = isCpuTouchingA ? 'yes' : 'no';
|
|
66
|
+
labelCpuTouchingB.innerHTML = isCpuTouchingB ? 'yes' : 'no';
|
|
67
|
+
|
|
68
|
+
renderer.setUseGpuMode(ScratchRender.UseGpuModes.Automatic);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
inputCursorX.addEventListener('change', handleCursorPositionChanged);
|
|
72
|
+
inputCursorY.addEventListener('change', handleCursorPositionChanged);
|
|
73
|
+
inputCursorX.addEventListener('input', handleCursorPositionChanged);
|
|
74
|
+
inputCursorY.addEventListener('input', handleCursorPositionChanged);
|
|
75
|
+
handleCursorPositionChanged();
|
|
76
|
+
|
|
77
|
+
let trackingMouse = true;
|
|
78
|
+
const handleMouseMove = event => {
|
|
79
|
+
if (trackingMouse) {
|
|
80
|
+
const mousePosition = getMousePosition(event, renderCanvas);
|
|
81
|
+
inputCursorX.value = mousePosition.x - (renderCanvas.clientWidth / 2);
|
|
82
|
+
inputCursorY.value = (renderCanvas.clientHeight / 2) - mousePosition.y;
|
|
83
|
+
handleCursorPositionChanged();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
renderCanvas.addEventListener('mousemove', handleMouseMove);
|
|
87
|
+
|
|
88
|
+
renderCanvas.addEventListener('click', event => {
|
|
89
|
+
trackingMouse = !trackingMouse;
|
|
90
|
+
if (trackingMouse) {
|
|
91
|
+
handleMouseMove(event);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const rgb2fillStyle = rgb => (
|
|
96
|
+
`rgb(${rgb[0]},${rgb[1]},${rgb[2]})`
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const makeCursorImage = () => {
|
|
100
|
+
const canvas = document.createElement('canvas');
|
|
101
|
+
canvas.width = canvas.height = 1;
|
|
102
|
+
|
|
103
|
+
const context = canvas.getContext('2d');
|
|
104
|
+
context.fillStyle = rgb2fillStyle(colors.cursor);
|
|
105
|
+
context.fillRect(0, 0, 1, 1);
|
|
106
|
+
|
|
107
|
+
return canvas;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const makeTestPatternImage = () => {
|
|
111
|
+
const canvas = document.createElement('canvas');
|
|
112
|
+
canvas.width = 480;
|
|
113
|
+
canvas.height = 360;
|
|
114
|
+
|
|
115
|
+
const patternA = rgb2fillStyle(colors.patternA);
|
|
116
|
+
const patternB = rgb2fillStyle(colors.patternB);
|
|
117
|
+
|
|
118
|
+
const context = canvas.getContext('2d');
|
|
119
|
+
context.fillStyle = patternA;
|
|
120
|
+
context.fillRect(0, 0, canvas.width, canvas.height);
|
|
121
|
+
|
|
122
|
+
context.fillStyle = patternB;
|
|
123
|
+
const xSplit1 = Math.floor(canvas.width * 0.25);
|
|
124
|
+
const xSplit2 = Math.floor(canvas.width * 0.5);
|
|
125
|
+
const xSplit3 = Math.floor(canvas.width * 0.75);
|
|
126
|
+
const ySplit = Math.floor(canvas.height * 0.5);
|
|
127
|
+
for (let y = 0; y < ySplit; y += 2) {
|
|
128
|
+
context.fillRect(0, y, xSplit2, 1);
|
|
129
|
+
}
|
|
130
|
+
for (let x = xSplit2; x < canvas.width; x += 2) {
|
|
131
|
+
context.fillRect(x, 0, 1, ySplit);
|
|
132
|
+
}
|
|
133
|
+
for (let x = 0; x < xSplit1; x += 2) {
|
|
134
|
+
for (let y = ySplit; y < canvas.height; y += 2) {
|
|
135
|
+
context.fillRect(x, y, 1, 1);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
for (let x = xSplit1; x < xSplit2; x += 3) {
|
|
139
|
+
for (let y = ySplit; y < canvas.height; y += 3) {
|
|
140
|
+
context.fillRect(x, y, 2, 2);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
for (let x = xSplit2; x < xSplit3; ++x) {
|
|
144
|
+
for (let y = ySplit; y < canvas.height; ++y) {
|
|
145
|
+
context.fillStyle = (x + y) % 2 ? patternB : patternA;
|
|
146
|
+
context.fillRect(x, y, 1, 1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (let x = xSplit3; x < canvas.width; x += 2) {
|
|
150
|
+
for (let y = ySplit; y < canvas.height; y += 2) {
|
|
151
|
+
context.fillStyle = (x + y) % 4 ? patternB : patternA;
|
|
152
|
+
context.fillRect(x, y, 2, 2);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return canvas;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const makeTestPatternDrawable = function (group) {
|
|
160
|
+
const image = makeTestPatternImage();
|
|
161
|
+
const skinId = renderer.createBitmapSkin(image, 1);
|
|
162
|
+
const drawableId = renderer.createDrawable(group);
|
|
163
|
+
renderer.updateDrawableProperties(drawableId, {skinId});
|
|
164
|
+
return drawableId;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const makeCursorDrawable = function (group) {
|
|
168
|
+
const image = makeCursorImage();
|
|
169
|
+
const skinId = renderer.createBitmapSkin(image, 1, [0, 0]);
|
|
170
|
+
const drawableId = renderer.createDrawable(group);
|
|
171
|
+
renderer.updateDrawableProperties(drawableId, {skinId});
|
|
172
|
+
return drawableId;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const initRendering = () => {
|
|
176
|
+
const layerGroup = {
|
|
177
|
+
testPattern: 'testPattern',
|
|
178
|
+
cursor: 'cursor'
|
|
179
|
+
};
|
|
180
|
+
renderer.setLayerGroupOrdering([layerGroup.testPattern, layerGroup.cursor]);
|
|
181
|
+
drawables.testPattern = makeTestPatternDrawable(layerGroup.testPattern);
|
|
182
|
+
drawables.cursor = makeCursorDrawable(layerGroup.cursor);
|
|
183
|
+
|
|
184
|
+
const corner00 = makeCursorDrawable(layerGroup.cursor);
|
|
185
|
+
const corner01 = makeCursorDrawable(layerGroup.cursor);
|
|
186
|
+
const corner10 = makeCursorDrawable(layerGroup.cursor);
|
|
187
|
+
const corner11 = makeCursorDrawable(layerGroup.cursor);
|
|
188
|
+
|
|
189
|
+
renderer.updateDrawableProperties(corner00, {position: [-240, -179]});
|
|
190
|
+
renderer.updateDrawableProperties(corner01, {position: [-240, 180]});
|
|
191
|
+
renderer.updateDrawableProperties(corner10, {position: [239, -179]});
|
|
192
|
+
renderer.updateDrawableProperties(corner11, {position: [239, 180]});
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
initRendering();
|
|
196
|
+
renderer.draw();
|