webglmusti 0.0.0

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 (102) hide show
  1. package/.gitattributes +2 -0
  2. package/idea_list.txt +13 -0
  3. package/index.html +17 -0
  4. package/package.json +20 -0
  5. package/public/apple.png +0 -0
  6. package/public/base.png +0 -0
  7. package/public/car.png +0 -0
  8. package/public/drop.png +0 -0
  9. package/public/font16-Sheet.png +0 -0
  10. package/public/font16-Sheet.txt +52 -0
  11. package/public/letters-Sheet.png +0 -0
  12. package/public/letters-Sheet.txt +27 -0
  13. package/public/letters_Sheet.png +0 -0
  14. package/public/letters_Sheet.txt +4 -0
  15. package/public/vite.svg +1 -0
  16. package/src/App/ResourceSim/car.ts +172 -0
  17. package/src/App/ResourceSim/grid.ts +993 -0
  18. package/src/App/ResourceSim/grid_app.ts +1326 -0
  19. package/src/App/ResourceSim/grid_test.test.ts +18 -0
  20. package/src/App/ResourceSim/node_graph.ts +293 -0
  21. package/src/App/ResourceSim/nodes.ts +151 -0
  22. package/src/App/ResourceSim/resource.ts +8 -0
  23. package/src/App/ResourceSim/texts.ts +6 -0
  24. package/src/App/card/card.test.ts +22 -0
  25. package/src/App/card/card.ts +763 -0
  26. package/src/App/puzzle_box/app.ts +10 -0
  27. package/src/App/puzzle_box/engine.ts +374 -0
  28. package/src/App/puzzle_box/renderer.ts +102 -0
  29. package/src/App/puzzle_box/test.test.ts +49 -0
  30. package/src/App/water/water.ts +206 -0
  31. package/src/Interface/button.ts +345 -0
  32. package/src/Interface/interface_element.ts +30 -0
  33. package/src/Interface/internal_window.ts +100 -0
  34. package/src/Interface/options.ts +332 -0
  35. package/src/Interface/text_input.ts +183 -0
  36. package/src/WebGL/Matrix/matrix.test.ts +30 -0
  37. package/src/WebGL/Matrix/matrix.ts +293 -0
  38. package/src/WebGL/Shaders/Fragment/Program/circle.ts +49 -0
  39. package/src/WebGL/Shaders/Fragment/Program/circle_only.ts +47 -0
  40. package/src/WebGL/Shaders/Fragment/Program/circle_outline.ts +54 -0
  41. package/src/WebGL/Shaders/Fragment/Program/colour.ts +39 -0
  42. package/src/WebGL/Shaders/Fragment/Program/colour_alpha.ts +37 -0
  43. package/src/WebGL/Shaders/Fragment/Program/line.ts +39 -0
  44. package/src/WebGL/Shaders/Fragment/Program/multi_colour_centre_circle_path.ts +69 -0
  45. package/src/WebGL/Shaders/Fragment/Program/multi_colour_path.ts +69 -0
  46. package/src/WebGL/Shaders/Fragment/Program/path_centre_circle.ts +69 -0
  47. package/src/WebGL/Shaders/Fragment/Program/rect_outline.ts +39 -0
  48. package/src/WebGL/Shaders/Fragment/Program/solid_path.ts +64 -0
  49. package/src/WebGL/Shaders/Fragment/Program/sprite_sheet.ts +54 -0
  50. package/src/WebGL/Shaders/Fragment/Program/sprite_sheet_colour.ts +62 -0
  51. package/src/WebGL/Shaders/Fragment/Program/texture.ts +34 -0
  52. package/src/WebGL/Shaders/Fragment/Source/circle.frag +19 -0
  53. package/src/WebGL/Shaders/Fragment/Source/circle_only.frag +15 -0
  54. package/src/WebGL/Shaders/Fragment/Source/circle_outline.frag +23 -0
  55. package/src/WebGL/Shaders/Fragment/Source/colour.frag +9 -0
  56. package/src/WebGL/Shaders/Fragment/Source/colour_alpha.frag +7 -0
  57. package/src/WebGL/Shaders/Fragment/Source/fragment.frag +5 -0
  58. package/src/WebGL/Shaders/Fragment/Source/fragment_source.ts +15 -0
  59. package/src/WebGL/Shaders/Fragment/Source/line.frag +12 -0
  60. package/src/WebGL/Shaders/Fragment/Source/multi_colour_centre_circle_path.frag +36 -0
  61. package/src/WebGL/Shaders/Fragment/Source/multi_colour_path.frag +34 -0
  62. package/src/WebGL/Shaders/Fragment/Source/path_centre_circle.frag +29 -0
  63. package/src/WebGL/Shaders/Fragment/Source/rect_outline.frag +20 -0
  64. package/src/WebGL/Shaders/Fragment/Source/solid_path.frag +24 -0
  65. package/src/WebGL/Shaders/Fragment/Source/sprite_sheet.frag +17 -0
  66. package/src/WebGL/Shaders/Fragment/Source/sprite_sheet_colour.frag +19 -0
  67. package/src/WebGL/Shaders/Fragment/Source/texture.frag +11 -0
  68. package/src/WebGL/Shaders/Fragment/fragment.ts +43 -0
  69. package/src/WebGL/Shaders/Fragment/fragment_old.ts +261 -0
  70. package/src/WebGL/Shaders/Vertex/Program/mvp2d.ts +41 -0
  71. package/src/WebGL/Shaders/Vertex/Program/transform2d.ts +39 -0
  72. package/src/WebGL/Shaders/Vertex/Source/mvp2d.vert +17 -0
  73. package/src/WebGL/Shaders/Vertex/Source/mvp_i_2d.vert +18 -0
  74. package/src/WebGL/Shaders/Vertex/Source/simple.vert +9 -0
  75. package/src/WebGL/Shaders/Vertex/Source/transform2d.vert +13 -0
  76. package/src/WebGL/Shaders/Vertex/Source/transform2d_rel.vert +16 -0
  77. package/src/WebGL/Shaders/Vertex/Source/translate2d.vert +7 -0
  78. package/src/WebGL/Shaders/Vertex/Source/vertex_source.ts +13 -0
  79. package/src/WebGL/Shaders/Vertex/vertex.ts +10 -0
  80. package/src/WebGL/Shaders/Vertex/vertex_old.ts +289 -0
  81. package/src/WebGL/Shaders/custom.ts +129 -0
  82. package/src/WebGL/Shaders/shader.ts +197 -0
  83. package/src/WebGL/Shapes/Line.ts +29 -0
  84. package/src/WebGL/Shapes/Shapes.ts +189 -0
  85. package/src/WebGL/Texture/texture.ts +214 -0
  86. package/src/WebGL/Util/file.ts +24 -0
  87. package/src/WebGL/app.ts +150 -0
  88. package/src/WebGL/colour.ts +71 -0
  89. package/src/WebGL/globals.ts +353 -0
  90. package/src/WebGL/index.ts +3 -0
  91. package/src/WebGL/mixin.ts +2 -0
  92. package/src/global.d.ts +13 -0
  93. package/src/index.ts +4 -0
  94. package/src/main.ts +139 -0
  95. package/src/utils/array.ts +154 -0
  96. package/src/utils/assert.ts +8 -0
  97. package/src/utils/file.ts +0 -0
  98. package/src/utils/mixin.ts +22 -0
  99. package/src/utils/numbers.ts +11 -0
  100. package/src/utils/utils.test.ts +23 -0
  101. package/src/vite-env.d.ts +1 -0
  102. package/tsconfig.json +25 -0
@@ -0,0 +1,10 @@
1
+ import * as WebGL from "./../../WebGL/globals";
2
+ import { PuzzleEngine } from "./engine";
3
+ import { PuzzleRenderer } from "./renderer";
4
+
5
+ type Int32 = number;
6
+ export function newPuzzleApp(w: Int32, h:Int32): WebGL.App.App<PuzzleEngine>{
7
+ const engine = new PuzzleEngine();
8
+ const renderer = new PuzzleRenderer(w, h);
9
+ return new WebGL.App.App(engine, renderer);
10
+ }
@@ -0,0 +1,374 @@
1
+ import * as WebGL from "./../../WebGL/globals";
2
+ import * as Options from "./../../Interface/options";
3
+ import * as Button from "./../../Interface/button";
4
+ import * as InterfaceElement from "./../../Interface/interface_element";
5
+
6
+ type Int32 = number;
7
+ type Float = number;
8
+
9
+ class IdGrid{
10
+ width: Int32;
11
+ height: Int32;
12
+ object_id: (Int32 | undefined)[];
13
+ constructor(w: Int32, h: Int32){
14
+ this.width = w;
15
+ this.height = h;
16
+ this.object_id = Array.from({length: this.height*this.width}, () => undefined);
17
+ }
18
+ getId(x: Int32, y: Int32) : (Int32 | undefined){
19
+ return this.object_id[x + y*this.width];
20
+ }
21
+ }
22
+
23
+ export class ShapeGridInterface{
24
+ x: Int32;
25
+ y: Int32;
26
+ cell_size: Int32;
27
+ grid: ShapeIdGrid;
28
+ constructor(x: Int32, y: Int32, size: Int32, grid: ShapeIdGrid){
29
+ this.x = x;
30
+ this.y = y;
31
+ this.cell_size = size;
32
+ this.grid = grid;
33
+ }
34
+ isInside(point: WebGL.Matrix.Point2D): boolean{
35
+ const in_x = this.x < point.x && point.x < this.x+this.interfaceWidth();
36
+ const in_y = this.y < point.y && point.y < this.y+this.interfaceHeight();
37
+ return in_x && in_y;
38
+ }
39
+ interfaceWidth(): Int32{
40
+ return this.cell_size*this.grid.width;
41
+ }
42
+ interfaceHeight(): Int32{
43
+ return this.cell_size*this.grid.height;
44
+ }
45
+ getCoord(point: WebGL.Matrix.Point2D): Coord | undefined{
46
+ if(!this.isInside(point)) return undefined;
47
+ const x = Math.floor((point.x-this.x)/this.cell_size);
48
+ const y = Math.floor((point.y-this.y)/this.cell_size);
49
+ return {x, y};
50
+ }
51
+ trueCoord(point: WebGL.Matrix.Point2D): WebGL.Matrix.Point2D | undefined{
52
+ return new WebGL.Matrix.Point2D((point.x-this.x)/this.cell_size, (point.y-this.y)/this.cell_size);
53
+ }
54
+ }
55
+
56
+ class ShapeIdGrid extends IdGrid{
57
+ isFree(x: Int32, y: Int32): boolean{
58
+ return this.object_id[x+y*this.width] == undefined;
59
+ }
60
+ canFitShape(shape: GridShapeInstance, x: Int32, y: Int32): boolean{
61
+ //test borders
62
+ if(x < 0 || y < 0 || x+shape.width > this.width || y+shape.height > this.height){
63
+ return false;
64
+ }
65
+
66
+ //test individual parts
67
+ for(let py = 0; py < shape.height; py++){
68
+ for(let px = 0; px < shape.width; px++){
69
+ if(shape.getPart(px, py) && !this.isFree(x+px, y+py)){
70
+ return false;
71
+ }
72
+ }
73
+ }
74
+ return true;
75
+ }
76
+ addShape(shape: GridShapeInstance, x: Int32, y: Int32){
77
+ for(let py = 0; py < shape.height; py++){
78
+ for(let px = 0; px < shape.width; px++){
79
+ if(shape.getPart(px, py)){
80
+ this.object_id[(x+px)+(y+py)*this.width] = shape.id;
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+
88
+ export const RotationEnum = {
89
+ None: 0,
90
+ Clockwise: 1,
91
+ Opposite: 2,
92
+ AntiClockwise: 3
93
+ } as const;
94
+
95
+ export type Rotation = (typeof RotationEnum)[keyof typeof RotationEnum];
96
+
97
+ //shape made out of grid pieces
98
+ export class GridShape{
99
+ width: Int32;
100
+ height: Int32;
101
+ parts: boolean[];
102
+
103
+ constructor(w: Int32, h: Int32, parts?: boolean[]){
104
+ this.width = w;
105
+ this.height = h;
106
+ this.parts = parts != undefined ? parts : Array.from({length: this.height*this.width}, () => false);
107
+ }
108
+ addPart(x: Int32, y: Int32){
109
+ this.parts[this.getIndexKey(x, y)] = true;
110
+ }
111
+ private getIndexKey(x: Int32, y: Int32){
112
+ return x+(y*this.width);
113
+ }
114
+ hasPartAt(x: Int32, y: Int32){
115
+ return this.parts[this.getIndexKey(x, y)];
116
+ }
117
+
118
+ static equals(s1: GridShape, s2: GridShape){
119
+
120
+ }
121
+ }
122
+
123
+ export class GridShapeInstance{
124
+ static current_id = 0;
125
+ id: Int32;
126
+ shape: GridShape;
127
+ private rotation: Rotation;
128
+ width: Int32;
129
+ height: Int32;
130
+ constructor(shape: GridShape){
131
+ this.id = GridShapeInstance.current_id;
132
+ GridShapeInstance.current_id++;
133
+ this.shape = shape;
134
+ this.rotation = RotationEnum.None;
135
+ this.width = this.shape.width;
136
+ this.height = this.shape.height;
137
+ }
138
+ setRotation(rotation: Rotation){
139
+ this.rotation = rotation;
140
+ if(this.rotation == RotationEnum.Clockwise || this.rotation == RotationEnum.AntiClockwise){
141
+ this.width = this.shape.height;
142
+ this.height = this.shape.width;
143
+ }else{
144
+ this.width = this.shape.width;
145
+ this.height = this.shape.height;
146
+ }
147
+ }
148
+ isInside(x: Int32, y: Int32){
149
+ const in_x = 0 <= x && x < this.width;
150
+ const in_y = 0 <= y && y < this.height;
151
+ return in_x && in_y;
152
+ }
153
+ getTrueCoord(x: Int32, y: Int32, rotation: Rotation=RotationEnum.None): {x: Int32, y: Int32}{
154
+ switch(rotation){
155
+ case RotationEnum.AntiClockwise:
156
+ return {x: this.height-1-y, y: x};
157
+ case RotationEnum.Clockwise:
158
+ return {x: y, y: this.width-1-x};
159
+ case RotationEnum.Opposite:
160
+ return {x: this.width-1-x, y: this.height-1-y};
161
+ }
162
+ return {x, y};
163
+ }
164
+ getIndexKey(x: Int32, y: Int32, rotation: Rotation=RotationEnum.None){
165
+ switch(rotation){
166
+ case RotationEnum.AntiClockwise:
167
+ return (this.height-1-y) + x*this.height;
168
+ case RotationEnum.Clockwise:
169
+ return (y) + (this.width-1-x)*this.height;
170
+ case RotationEnum.Opposite:
171
+ return (this.width-1-x) + (this.height-1-y)*this.width;
172
+ }
173
+ return x + y*this.width;
174
+ }
175
+ getPart(x: Int32, y: Int32): boolean | undefined{
176
+ if(!this.isInside(x, y)) return undefined;
177
+ return this.shape.parts[this.getIndexKey(x, y, this.rotation)];
178
+ }
179
+ }
180
+
181
+
182
+ export class ShapeLabel extends InterfaceElement.InterfaceElement{
183
+ shape: GridShape;
184
+ is_hovered: boolean;
185
+ onSelect: ((shape: GridShape) => void) | undefined;
186
+ constructor(x: Int32, y: Int32, width: Int32, height: Int32, shape: GridShape, on_select?: () => void){
187
+ super(x, y, width, height);
188
+ this.shape = shape;
189
+ this.is_hovered = false;
190
+ this.onSelect = on_select;
191
+ }
192
+ onMouseDown(){
193
+ if(this.is_hovered){
194
+ if(this.onSelect) this.onSelect(this.shape);
195
+ }
196
+ }
197
+ onMouseOver(point: WebGL.Matrix.Point2D){
198
+ this.is_hovered = this.isInside(point);
199
+ }
200
+ draw(vp: WebGL.Matrix.TransformationMatrix3x3, colour_shader: WebGL.Shader.MVPColourProgram){
201
+ const bg = this.is_hovered ? WebGL.Colour.ColourUtils.blue() : WebGL.Colour.ColourUtils.red();
202
+ this.drawBackground(vp, colour_shader, bg);
203
+ const green = WebGL.Colour.ColourUtils.green();
204
+
205
+ //draw shape
206
+ const mx = this.x+(this.width*0.5);
207
+ const my = this.y+(this.height*0.5);
208
+ const cell_size = 24;
209
+ const rect_size = 20;
210
+ const clear_border = (cell_size-rect_size)*0.5;
211
+ let y = my-(cell_size*this.shape.height*0.5);
212
+ const sx = mx-(cell_size*this.shape.width*0.5);
213
+ let gx = sx;
214
+ for(let py = 0; py < this.shape.height; py++){
215
+ gx = sx;
216
+ for(let px = 0; px < this.shape.width; px++){
217
+ if(this.shape.hasPartAt(px, py)){
218
+ WebGL.WebGL.drawColourRect(vp, colour_shader,
219
+ gx+clear_border, y+clear_border,
220
+ rect_size, rect_size, green);
221
+ }
222
+ gx += cell_size;
223
+ }
224
+ y += cell_size;
225
+ }
226
+ //WebGL.WebGL.drawColourRect(vp, colour_shader, this.x, )
227
+ }
228
+ }
229
+
230
+ type LayoutPosition = WebGL.Matrix.Point2D;
231
+
232
+ class GridLayout{
233
+ start_x: Int32;
234
+ start_y: Int32;
235
+ cell_width: Int32;
236
+ cell_height: Int32;
237
+ layout_width: Int32;
238
+ layout_height: Int32;
239
+ constructor(start_x: Int32, start_y: Int32,
240
+ cell_width: Int32, cell_height: Int32,
241
+ layout_width: Int32, layout_height: Int32){
242
+ this.start_x = start_x;
243
+ this.start_y = start_y;
244
+ this.cell_width = cell_width;
245
+ this.cell_height = cell_height;
246
+ this.layout_width = layout_width;
247
+ this.layout_height = layout_height;
248
+ }
249
+ firstPosition(): LayoutPosition{
250
+ return new WebGL.Matrix.Point2D(this.start_x, this.start_y);
251
+ }
252
+ next(position: LayoutPosition): LayoutPosition | undefined{
253
+ let next_x = position.x + this.cell_width;
254
+ let next_y = position.y;
255
+ if(next_x > this.start_x + this.layout_width){
256
+ next_y = position.y + this.cell_height;
257
+ if(next_y > this.start_y + this.layout_height){
258
+ return undefined;
259
+ }
260
+ }
261
+ return new WebGL.Matrix.Point2D(next_x, next_y);
262
+ }
263
+ }
264
+ type Coord = {
265
+ x: Int32,
266
+ y: Int32
267
+ }
268
+
269
+ export class PuzzleEngine extends WebGL.App.BaseEngine{
270
+ option_select: Options.DropdownOptions;
271
+ mouse_point: WebGL.Matrix.Point2D | undefined;
272
+
273
+ my_shapes: GridShape[];
274
+
275
+ shape_label_layout: GridLayout;
276
+ shape_labels: ShapeLabel[];
277
+
278
+ dragged_shape: Int32 | undefined;
279
+
280
+ grid: ShapeIdGrid;
281
+ interface_grid: ShapeGridInterface;
282
+
283
+ hovered_coord: Coord | undefined;
284
+
285
+ pieces_on_grid: Map<Int32, GridShapeInstance>;
286
+ constructor(){
287
+ super();
288
+ this.option_select = new Options.DropdownOptions(100, 100, 150, 25, ["hello", "good", "bye"]);
289
+ this.my_shapes = this.createShapes();
290
+
291
+ this.shape_label_layout = new GridLayout(100, 100, 120, 80, 500, 500);
292
+ this.shape_labels = [];
293
+
294
+ let position: LayoutPosition | undefined = this.shape_label_layout.firstPosition();
295
+ for(const shape of this.my_shapes){
296
+ if(position == undefined) break;
297
+ const label = new ShapeLabel(position.x, position.y,
298
+ this.shape_label_layout.cell_width,
299
+ this.shape_label_layout.cell_height,
300
+ shape
301
+ );
302
+ this.shape_labels.push(label);
303
+ position = this.shape_label_layout.next(position);
304
+ }
305
+
306
+ this.grid = new ShapeIdGrid(10, 10);
307
+ this.interface_grid = new ShapeGridInterface(100, 250, 25, this.grid);
308
+ this.hovered_coord = undefined;
309
+
310
+ this.pieces_on_grid = new Map();
311
+ }
312
+ createShapes(): GridShape[]{
313
+ const one = new GridShape(1, 1, [true]);
314
+ const two = new GridShape(2, 1, [true, true]);
315
+ const l = new GridShape(3, 2, [false, false, true, true, true, true]);
316
+ const t = new GridShape(3, 2, [false, true, false, true, true, true]);
317
+ return [one, two, l, t];
318
+ }
319
+
320
+ override handleKeyDown(ev: KeyboardEvent){};
321
+ //to override
322
+ override handleKeyUp(ev: KeyboardEvent){};
323
+ //to override
324
+ override handleMouseMove(ev: MouseEvent){
325
+ const point = new WebGL.Matrix.Point2D(ev.clientX, ev.clientY);
326
+ this.mouse_point = point;
327
+ this.option_select.onMouseOver(point);
328
+
329
+ for(const label of this.shape_labels){
330
+ label.onMouseOver(point);
331
+ }
332
+ this.hovered_coord = this.interface_grid.getCoord(point);
333
+ //console.log(this.hovered_coord);
334
+ };
335
+ //to override
336
+ override handleMouseDown(ev: MouseEvent){
337
+ if(this.mouse_point != undefined){
338
+ this.option_select.onMouseDown(this.mouse_point);
339
+ }
340
+ for(let i = 0; i < this.shape_labels.length; i++){
341
+ const label = this.shape_labels[i];
342
+ label.onMouseDown();
343
+ if(label.is_hovered){
344
+ this.dragged_shape = i;
345
+ }
346
+ }
347
+ };
348
+ //to override
349
+ override handleMouseUp(ev: MouseEvent){
350
+ const shape = 0;
351
+ if(this.mouse_point != undefined){
352
+ const coord = this.interface_grid.trueCoord(this.mouse_point);
353
+ console.log(coord);
354
+ if(this.dragged_shape != undefined && coord != undefined){
355
+ const shape_label = this.shape_labels[this.dragged_shape];
356
+ coord.x -= (shape_label.shape.width*0.5 - 0.5);
357
+ coord.y -= (shape_label.shape.height*0.5 - 0.5);
358
+ const x = Math.floor(coord.x);
359
+ const y = Math.floor(coord.y);
360
+ console.log({x, y});
361
+ const new_shape = new GridShapeInstance(shape_label.shape);
362
+ if(this.grid.canFitShape(new_shape, x, y)){
363
+ this.grid.addShape(new_shape, x, y);
364
+ }else{
365
+ console.log("no room for shape");
366
+ }
367
+ }
368
+ }
369
+
370
+
371
+
372
+ this.dragged_shape = undefined;
373
+ };
374
+ }
@@ -0,0 +1,102 @@
1
+ import * as WebGL from "./../../WebGL/globals";
2
+ import * as PEngine from "./engine";
3
+ import { PuzzleEngine } from "./engine";
4
+
5
+ type Int32 = number;
6
+
7
+ export class PuzzleRenderer extends WebGL.App.SimpleAppRenderer<PuzzleEngine>{
8
+ colour_shader: WebGL.Shader.MVPColourProgram;
9
+
10
+ my_shape_colour: WebGL.Colour.ColourRGB;
11
+ grid_colours: WebGL.Colour.ColourRGB[];
12
+ constructor(w: Int32, h: Int32){
13
+ super(w, h);
14
+ this.font_names.push("font16-Sheet.png");
15
+
16
+ this.colour_shader = new WebGL.Shader.MVPColourProgram();
17
+ this.my_shape_colour = WebGL.Colour.ColourUtils.red();
18
+ this.grid_colours = [];
19
+ }
20
+ render(engine: PuzzleEngine){
21
+ engine.option_select.draw(this.orthographic, this.colour_shader, this.text_drawer);
22
+
23
+ //this.drawStaticShapeLabel(engine.my_shapes[2], 200, 200);
24
+
25
+ this.drawShapeGrid(engine, engine.interface_grid);
26
+
27
+ for(const label of engine.shape_labels){
28
+ this.drawShapeLabel(label);
29
+ }
30
+
31
+ if(engine.dragged_shape != undefined && engine.mouse_point != undefined){
32
+ this.drawShape(engine.shape_labels[engine.dragged_shape].shape, engine.mouse_point.x, engine.mouse_point.y);
33
+ }
34
+ if(engine.hovered_coord != undefined){
35
+ const id = engine.grid.getId(engine.hovered_coord.x, engine.hovered_coord.y);
36
+ if(id != undefined){
37
+ this.text_drawer.drawText(this.orthographic, 50, 50, id.toString(), 15);
38
+ }
39
+ }
40
+ }
41
+
42
+ fillColours(n_colours: Int32){
43
+ while(this.grid_colours.length < n_colours){
44
+ this.grid_colours.push(WebGL.Colour.ColourUtils.random());
45
+ }
46
+ }
47
+
48
+ drawShapeGrid(engine: PuzzleEngine, grid: PEngine.ShapeGridInterface){
49
+ const grey = WebGL.Colour.ColourUtils.grey();
50
+ WebGL.WebGL.drawColourRect(this.orthographic, this.colour_shader,
51
+ grid.x, grid.y,
52
+ grid.interfaceWidth(), grid.interfaceHeight(),
53
+ grey
54
+ );
55
+ const black = WebGL.Colour.ColourUtils.black();
56
+ const red = WebGL.Colour.ColourUtils.red();
57
+ const rect_size = grid.cell_size - 4;
58
+ const clear_border = (grid.cell_size-rect_size)*0.5;
59
+ for(let gy = 0; gy < grid.grid.height; gy++){
60
+ for(let gx = 0; gx < grid.grid.width; gx++){
61
+ const id = grid.grid.object_id[gx+gy*grid.grid.width];
62
+ let col = black;
63
+ if(id != undefined){
64
+ this.fillColours(id+1);
65
+ col = this.grid_colours[id];
66
+ }
67
+ WebGL.WebGL.drawColourRect(this.orthographic, this.colour_shader,
68
+ grid.x+gx*grid.cell_size+clear_border, grid.y+gy*grid.cell_size+clear_border,
69
+ rect_size, rect_size, col
70
+ );
71
+
72
+ }
73
+ }
74
+ }
75
+
76
+ drawShapeLabel(label: PEngine.ShapeLabel){
77
+ label.draw(this.orthographic, this.colour_shader);
78
+ }
79
+ drawShape(shape: PEngine.GridShape, x: Int32, y: Int32){
80
+ const mx = x+(shape.width*0.5);
81
+ const my = y+(shape.height*0.5);
82
+ const cell_size = 24;
83
+ const rect_size = 20;
84
+ const clear_border = (cell_size-rect_size)*0.5;
85
+ let sy = my-(cell_size*shape.height*0.5);
86
+ const sx = mx-(cell_size*shape.width*0.5);
87
+ let gx = sx;
88
+ for(let py = 0; py < shape.height; py++){
89
+ gx = sx;
90
+ for(let px = 0; px < shape.width; px++){
91
+ if(shape.hasPartAt(px, py)){
92
+ WebGL.WebGL.drawColourRect(this.orthographic, this.colour_shader,
93
+ gx+clear_border, sy+clear_border,
94
+ rect_size, rect_size, this.my_shape_colour);
95
+ }
96
+ gx += cell_size;
97
+ }
98
+ sy += cell_size;
99
+ }
100
+ }
101
+
102
+ }
@@ -0,0 +1,49 @@
1
+ import {test, expect} from "vitest";
2
+ import * as Puzzle from "./engine";
3
+
4
+ test("grid_shape", () => {
5
+ const shape = new Puzzle.GridShape(3, 2);
6
+ shape.addPart(0, 0);
7
+ shape.addPart(1, 0);
8
+ shape.addPart(2, 0);
9
+ shape.addPart(2, 1);
10
+
11
+ const i1 = new Puzzle.GridShapeInstance(shape);
12
+
13
+ expect(i1.getPart(0, 0)).toBe(true);
14
+ expect(i1.getPart(1, 0)).toBe(true);
15
+ expect(i1.getPart(2, 0)).toBe(true);
16
+ expect(i1.getPart(0, 1)).toBe(false);
17
+ expect(i1.getPart(1, 1)).toBe(false);
18
+ expect(i1.getPart(2, 1)).toBe(true);
19
+
20
+ const i2 = new Puzzle.GridShapeInstance(shape);
21
+ i2.setRotation(Puzzle.RotationEnum.Clockwise);
22
+ expect(i2.getPart(0, 0)).toBe(false);
23
+ expect(i2.getPart(1, 0)).toBe(true);
24
+ expect(i2.getPart(0, 1)).toBe(false);
25
+ expect(i2.getPart(1, 1)).toBe(true);
26
+ expect(i2.getPart(0, 2)).toBe(true);
27
+ expect(i2.getPart(1, 2)).toBe(true);
28
+ expect(i2.getPart(2, 2)).toBe(undefined);
29
+
30
+ const i3 = new Puzzle.GridShapeInstance(shape);
31
+ i3.setRotation(Puzzle.RotationEnum.AntiClockwise);
32
+ expect(i3.getPart(0, 0)).toBe(true);
33
+ expect(i3.getPart(1, 0)).toBe(true);
34
+ expect(i3.getPart(0, 1)).toBe(true);
35
+ expect(i3.getPart(1, 1)).toBe(false);
36
+ expect(i3.getPart(0, 2)).toBe(true);
37
+ expect(i3.getPart(1, 2)).toBe(false);
38
+ expect(i3.getPart(2, 2)).toBe(undefined);
39
+
40
+ const i4 = new Puzzle.GridShapeInstance(shape);
41
+ i4.setRotation(Puzzle.RotationEnum.Opposite);
42
+ expect(i4.getPart(0, 0)).toBe(true);
43
+ expect(i4.getPart(1, 0)).toBe(false);
44
+ expect(i4.getPart(2, 0)).toBe(false);
45
+ expect(i4.getPart(0, 1)).toBe(true);
46
+ expect(i4.getPart(1, 1)).toBe(true);
47
+ expect(i4.getPart(2, 1)).toBe(true);
48
+ expect(i4.getPart(2, 2)).toBe(undefined);
49
+ });