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.
- package/.gitattributes +2 -0
- package/idea_list.txt +13 -0
- package/index.html +17 -0
- package/package.json +20 -0
- package/public/apple.png +0 -0
- package/public/base.png +0 -0
- package/public/car.png +0 -0
- package/public/drop.png +0 -0
- package/public/font16-Sheet.png +0 -0
- package/public/font16-Sheet.txt +52 -0
- package/public/letters-Sheet.png +0 -0
- package/public/letters-Sheet.txt +27 -0
- package/public/letters_Sheet.png +0 -0
- package/public/letters_Sheet.txt +4 -0
- package/public/vite.svg +1 -0
- package/src/App/ResourceSim/car.ts +172 -0
- package/src/App/ResourceSim/grid.ts +993 -0
- package/src/App/ResourceSim/grid_app.ts +1326 -0
- package/src/App/ResourceSim/grid_test.test.ts +18 -0
- package/src/App/ResourceSim/node_graph.ts +293 -0
- package/src/App/ResourceSim/nodes.ts +151 -0
- package/src/App/ResourceSim/resource.ts +8 -0
- package/src/App/ResourceSim/texts.ts +6 -0
- package/src/App/card/card.test.ts +22 -0
- package/src/App/card/card.ts +763 -0
- package/src/App/puzzle_box/app.ts +10 -0
- package/src/App/puzzle_box/engine.ts +374 -0
- package/src/App/puzzle_box/renderer.ts +102 -0
- package/src/App/puzzle_box/test.test.ts +49 -0
- package/src/App/water/water.ts +206 -0
- package/src/Interface/button.ts +345 -0
- package/src/Interface/interface_element.ts +30 -0
- package/src/Interface/internal_window.ts +100 -0
- package/src/Interface/options.ts +332 -0
- package/src/Interface/text_input.ts +183 -0
- package/src/WebGL/Matrix/matrix.test.ts +30 -0
- package/src/WebGL/Matrix/matrix.ts +293 -0
- package/src/WebGL/Shaders/Fragment/Program/circle.ts +49 -0
- package/src/WebGL/Shaders/Fragment/Program/circle_only.ts +47 -0
- package/src/WebGL/Shaders/Fragment/Program/circle_outline.ts +54 -0
- package/src/WebGL/Shaders/Fragment/Program/colour.ts +39 -0
- package/src/WebGL/Shaders/Fragment/Program/colour_alpha.ts +37 -0
- package/src/WebGL/Shaders/Fragment/Program/line.ts +39 -0
- package/src/WebGL/Shaders/Fragment/Program/multi_colour_centre_circle_path.ts +69 -0
- package/src/WebGL/Shaders/Fragment/Program/multi_colour_path.ts +69 -0
- package/src/WebGL/Shaders/Fragment/Program/path_centre_circle.ts +69 -0
- package/src/WebGL/Shaders/Fragment/Program/rect_outline.ts +39 -0
- package/src/WebGL/Shaders/Fragment/Program/solid_path.ts +64 -0
- package/src/WebGL/Shaders/Fragment/Program/sprite_sheet.ts +54 -0
- package/src/WebGL/Shaders/Fragment/Program/sprite_sheet_colour.ts +62 -0
- package/src/WebGL/Shaders/Fragment/Program/texture.ts +34 -0
- package/src/WebGL/Shaders/Fragment/Source/circle.frag +19 -0
- package/src/WebGL/Shaders/Fragment/Source/circle_only.frag +15 -0
- package/src/WebGL/Shaders/Fragment/Source/circle_outline.frag +23 -0
- package/src/WebGL/Shaders/Fragment/Source/colour.frag +9 -0
- package/src/WebGL/Shaders/Fragment/Source/colour_alpha.frag +7 -0
- package/src/WebGL/Shaders/Fragment/Source/fragment.frag +5 -0
- package/src/WebGL/Shaders/Fragment/Source/fragment_source.ts +15 -0
- package/src/WebGL/Shaders/Fragment/Source/line.frag +12 -0
- package/src/WebGL/Shaders/Fragment/Source/multi_colour_centre_circle_path.frag +36 -0
- package/src/WebGL/Shaders/Fragment/Source/multi_colour_path.frag +34 -0
- package/src/WebGL/Shaders/Fragment/Source/path_centre_circle.frag +29 -0
- package/src/WebGL/Shaders/Fragment/Source/rect_outline.frag +20 -0
- package/src/WebGL/Shaders/Fragment/Source/solid_path.frag +24 -0
- package/src/WebGL/Shaders/Fragment/Source/sprite_sheet.frag +17 -0
- package/src/WebGL/Shaders/Fragment/Source/sprite_sheet_colour.frag +19 -0
- package/src/WebGL/Shaders/Fragment/Source/texture.frag +11 -0
- package/src/WebGL/Shaders/Fragment/fragment.ts +43 -0
- package/src/WebGL/Shaders/Fragment/fragment_old.ts +261 -0
- package/src/WebGL/Shaders/Vertex/Program/mvp2d.ts +41 -0
- package/src/WebGL/Shaders/Vertex/Program/transform2d.ts +39 -0
- package/src/WebGL/Shaders/Vertex/Source/mvp2d.vert +17 -0
- package/src/WebGL/Shaders/Vertex/Source/mvp_i_2d.vert +18 -0
- package/src/WebGL/Shaders/Vertex/Source/simple.vert +9 -0
- package/src/WebGL/Shaders/Vertex/Source/transform2d.vert +13 -0
- package/src/WebGL/Shaders/Vertex/Source/transform2d_rel.vert +16 -0
- package/src/WebGL/Shaders/Vertex/Source/translate2d.vert +7 -0
- package/src/WebGL/Shaders/Vertex/Source/vertex_source.ts +13 -0
- package/src/WebGL/Shaders/Vertex/vertex.ts +10 -0
- package/src/WebGL/Shaders/Vertex/vertex_old.ts +289 -0
- package/src/WebGL/Shaders/custom.ts +129 -0
- package/src/WebGL/Shaders/shader.ts +197 -0
- package/src/WebGL/Shapes/Line.ts +29 -0
- package/src/WebGL/Shapes/Shapes.ts +189 -0
- package/src/WebGL/Texture/texture.ts +214 -0
- package/src/WebGL/Util/file.ts +24 -0
- package/src/WebGL/app.ts +150 -0
- package/src/WebGL/colour.ts +71 -0
- package/src/WebGL/globals.ts +353 -0
- package/src/WebGL/index.ts +3 -0
- package/src/WebGL/mixin.ts +2 -0
- package/src/global.d.ts +13 -0
- package/src/index.ts +4 -0
- package/src/main.ts +139 -0
- package/src/utils/array.ts +154 -0
- package/src/utils/assert.ts +8 -0
- package/src/utils/file.ts +0 -0
- package/src/utils/mixin.ts +22 -0
- package/src/utils/numbers.ts +11 -0
- package/src/utils/utils.test.ts +23 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import * as Matrix from "./../../WebGL/Matrix/matrix";
|
|
2
|
+
import * as App from "./../../WebGL/app";
|
|
3
|
+
import * as Grid from "../ResourceSim/grid"
|
|
4
|
+
import * as Shader from "./../../WebGL/Shaders/custom";
|
|
5
|
+
import * as Shapes from './../../WebGL/Shapes/Shapes';
|
|
6
|
+
import * as Colour from './../../WebGL/colour';
|
|
7
|
+
import WebGL from "./../../WebGL/globals";
|
|
8
|
+
|
|
9
|
+
type Int32 = number;
|
|
10
|
+
|
|
11
|
+
const WaterStateEnum = {
|
|
12
|
+
Nothing: 0,
|
|
13
|
+
Wall: 1,
|
|
14
|
+
Still: 2,
|
|
15
|
+
Flow: 3,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type WaterState = typeof WaterStateEnum[keyof typeof WaterStateEnum];
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export class WaterEngine extends App.BaseEngine{
|
|
22
|
+
grid: Grid.RectGrid;
|
|
23
|
+
|
|
24
|
+
hovered: Grid.GridPosition | undefined;
|
|
25
|
+
|
|
26
|
+
private state: WaterState[][];
|
|
27
|
+
constructor(){
|
|
28
|
+
super();
|
|
29
|
+
const w = 30;
|
|
30
|
+
const h = 30;
|
|
31
|
+
this.grid = new Grid.RectGrid(w, h, 20);
|
|
32
|
+
this.state = Array.from({length: w}, () => Array.from({length: h}, () => WaterStateEnum.Nothing));
|
|
33
|
+
|
|
34
|
+
this.hovered = undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
drop(x: Int32, y: Int32){
|
|
38
|
+
//check below
|
|
39
|
+
if(this.grid.isInsideGrid(x, y)){
|
|
40
|
+
while(y < this.grid.height && this.state[y][x] == WaterStateEnum.Nothing){
|
|
41
|
+
y++;
|
|
42
|
+
}
|
|
43
|
+
const my = y-1;
|
|
44
|
+
if(y == this.grid.height){
|
|
45
|
+
this.state[my][x] = WaterStateEnum.Flow;
|
|
46
|
+
}else{
|
|
47
|
+
if(this.state[y][x] == WaterStateEnum.Flow){
|
|
48
|
+
this.state[my][x] = WaterStateEnum.Flow;
|
|
49
|
+
}else{
|
|
50
|
+
//hit a wall or still
|
|
51
|
+
if(x-1 >= 0 && this.state[my][x-1] == WaterStateEnum.Nothing){
|
|
52
|
+
//check left
|
|
53
|
+
while(x-1 >= 0 && this.state[my][x-1] == WaterStateEnum.Nothing){
|
|
54
|
+
//check below
|
|
55
|
+
if(this.state[y][x-1] == WaterStateEnum.Nothing){
|
|
56
|
+
console.log("drop left");
|
|
57
|
+
this.drop(x-1, y);
|
|
58
|
+
return;
|
|
59
|
+
}else if(this.state[y][x-1] == WaterStateEnum.Flow){
|
|
60
|
+
this.state[my][x-1] = WaterStateEnum.Flow;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
x--;
|
|
64
|
+
}
|
|
65
|
+
if(x == 0){ // on left edge of map, water is flow
|
|
66
|
+
this.state[my][0] = WaterStateEnum.Flow;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
else if(x > 0){
|
|
70
|
+
if(this.state[my][x-1] == WaterStateEnum.Flow){
|
|
71
|
+
this.state[my][x] = WaterStateEnum.Flow;
|
|
72
|
+
}else{
|
|
73
|
+
this.state[my][x] = WaterStateEnum.Still;
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if(x+1 < this.grid.width && this.state[my][x+1] == WaterStateEnum.Nothing){
|
|
79
|
+
//console.log("right");
|
|
80
|
+
//check right
|
|
81
|
+
while(x+1 < this.grid.width && this.state[my][x+1] == WaterStateEnum.Nothing){
|
|
82
|
+
if(this.state[y][x+1] == WaterStateEnum.Nothing){
|
|
83
|
+
console.log("drop right");
|
|
84
|
+
this.drop(x+1, y);
|
|
85
|
+
return;
|
|
86
|
+
}else if(this.state[y][x+1] == WaterStateEnum.Flow){
|
|
87
|
+
this.state[my][x+1] = WaterStateEnum.Flow;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
x++;
|
|
91
|
+
}
|
|
92
|
+
if(x == this.grid.width){
|
|
93
|
+
console.log("right lim");
|
|
94
|
+
}else if(x < this.grid.width){
|
|
95
|
+
if(this.state[my][x+1] == WaterStateEnum.Flow){
|
|
96
|
+
this.state[my][x] = WaterStateEnum.Flow;
|
|
97
|
+
}else{
|
|
98
|
+
this.state[my][x] = WaterStateEnum.Still;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}else{
|
|
102
|
+
//
|
|
103
|
+
console.log("open spot");
|
|
104
|
+
if(this.state[my][x+1] == WaterStateEnum.Flow || this.state[my][x-1] == WaterStateEnum.Flow){
|
|
105
|
+
this.state[my][x] = WaterStateEnum.Flow;
|
|
106
|
+
}else{
|
|
107
|
+
this.state[my][x] = WaterStateEnum.Still;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private toggleWallAtHovered(){
|
|
116
|
+
if(this.hovered != undefined){
|
|
117
|
+
switch(this.state[this.hovered.y][this.hovered.x]){
|
|
118
|
+
case WaterStateEnum.Nothing:
|
|
119
|
+
this.state[this.hovered.y][this.hovered.x] = WaterStateEnum.Wall;
|
|
120
|
+
break;
|
|
121
|
+
case WaterStateEnum.Wall:
|
|
122
|
+
this.state[this.hovered.y][this.hovered.x] = WaterStateEnum.Nothing;
|
|
123
|
+
break;
|
|
124
|
+
default:
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
stateAt(x: Int32, y: Int32): WaterState{
|
|
130
|
+
return this.state[y][x];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
protected handleKeyDown(ev: KeyboardEvent): void {
|
|
134
|
+
if(this.hovered != undefined){
|
|
135
|
+
this.drop(this.hovered.x, this.hovered.y);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
protected handleKeyUp(ev: KeyboardEvent): void {
|
|
139
|
+
|
|
140
|
+
}
|
|
141
|
+
protected handleMouseMove(ev: MouseEvent): void {
|
|
142
|
+
const x = ev.clientX;
|
|
143
|
+
const y = ev.clientY;
|
|
144
|
+
const coll = this.grid.getPosition(x, y);
|
|
145
|
+
this.hovered = coll;
|
|
146
|
+
}
|
|
147
|
+
protected handleMouseDown(ev: MouseEvent): void {
|
|
148
|
+
console.log(this.hovered);
|
|
149
|
+
this.toggleWallAtHovered();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export class WaterRenderer implements App.IEngineRenderer<WaterEngine>{
|
|
155
|
+
private perspective: Matrix.TransformationMatrix3x3;
|
|
156
|
+
private solid_shader: Shader.MVPColourProgram;
|
|
157
|
+
|
|
158
|
+
private cell_colours: Map<WaterState, Colour.ColourRGB>;
|
|
159
|
+
|
|
160
|
+
private width: Int32;
|
|
161
|
+
private height: Int32;
|
|
162
|
+
|
|
163
|
+
constructor(width: Int32, height: Int32){
|
|
164
|
+
this.width = width;
|
|
165
|
+
this.height = height;
|
|
166
|
+
this.perspective = Matrix.TransformationMatrix3x3.orthographic(0, width, height, 0);
|
|
167
|
+
this.solid_shader = new Shader.MVPColourProgram();
|
|
168
|
+
|
|
169
|
+
this.cell_colours = new Map();
|
|
170
|
+
this.cell_colours.set(WaterStateEnum.Nothing, Colour.ColourUtils.black());
|
|
171
|
+
this.cell_colours.set(WaterStateEnum.Wall, Colour.ColourUtils.white());
|
|
172
|
+
this.cell_colours.set(WaterStateEnum.Still, Colour.ColourUtils.blue());
|
|
173
|
+
this.cell_colours.set(WaterStateEnum.Flow , Colour.ColourUtils.red());
|
|
174
|
+
}
|
|
175
|
+
render(engine: WaterEngine){
|
|
176
|
+
//background
|
|
177
|
+
this.solid_shader.use();
|
|
178
|
+
this.solid_shader.setColour(0.1, 0.2, 0.3);
|
|
179
|
+
const bg_sq = WebGL.rectangleModel(0, 0, this.width, this.height);
|
|
180
|
+
this.solid_shader.setMvp(this.perspective.multiplyCopy(bg_sq));
|
|
181
|
+
Shapes.Quad.draw();
|
|
182
|
+
|
|
183
|
+
const scale = Matrix.TransformationMatrix3x3.scale(engine.grid.size, engine.grid.size);
|
|
184
|
+
for(let y = 0; y < engine.grid.height; y++){
|
|
185
|
+
for(let x = 0; x < engine.grid.width; x++){
|
|
186
|
+
const tr = Matrix.TransformationMatrix3x3.translate(x*engine.grid.size, y*engine.grid.size);
|
|
187
|
+
|
|
188
|
+
//set colour depending on water state enum
|
|
189
|
+
const colour = this.cell_colours.get(engine.stateAt(x, y))!;
|
|
190
|
+
this.solid_shader.setColour(colour.red, colour.green, colour.blue);
|
|
191
|
+
const model = tr.multiplyCopy(scale);
|
|
192
|
+
this.solid_shader.setMvp(this.perspective.multiplyCopy(model));
|
|
193
|
+
Shapes.Quad.draw();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if(engine.hovered){
|
|
198
|
+
this.solid_shader.setColour(1, 0.5, 1);
|
|
199
|
+
const tr = Matrix.TransformationMatrix3x3.translate(engine.hovered.x*engine.grid.size, engine.hovered.y*engine.grid.size);
|
|
200
|
+
const model = tr.multiplyCopy(scale);
|
|
201
|
+
this.solid_shader.setMvp(this.perspective.multiplyCopy(model));
|
|
202
|
+
Shapes.Quad.draw();
|
|
203
|
+
}
|
|
204
|
+
requestAnimationFrame(() => this.render(engine));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import * as WebGL from "./../WebGL/globals";
|
|
2
|
+
|
|
3
|
+
type Int32 = number;
|
|
4
|
+
type Float = number;
|
|
5
|
+
type VoidFunction = () => void;
|
|
6
|
+
const EmptyFunction = () => {};
|
|
7
|
+
|
|
8
|
+
export interface Point{
|
|
9
|
+
x: Int32;
|
|
10
|
+
y: Int32;
|
|
11
|
+
equals:(p:Point) => boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const ButtonStateEnum = {
|
|
15
|
+
Off: 0,
|
|
16
|
+
Disabled: 1,
|
|
17
|
+
Hovered: 2,
|
|
18
|
+
Pressed: 3,
|
|
19
|
+
PressedHovered: 4,
|
|
20
|
+
Selected: 5,
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export type ButtonState = (typeof ButtonStateEnum)[keyof typeof ButtonStateEnum];
|
|
26
|
+
|
|
27
|
+
interface Button{
|
|
28
|
+
mouseDown: VoidFunction;
|
|
29
|
+
mouseUp: VoidFunction;
|
|
30
|
+
updateMouse: (point: Point) => void;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class BasicButton{
|
|
34
|
+
x: Int32;
|
|
35
|
+
y: Int32;
|
|
36
|
+
text: string;
|
|
37
|
+
width: Int32;
|
|
38
|
+
height: Int32;
|
|
39
|
+
text_size: Int32;
|
|
40
|
+
|
|
41
|
+
state: ButtonState;
|
|
42
|
+
|
|
43
|
+
colours: Map<ButtonState, WebGL.Colour.ColourRGB>;
|
|
44
|
+
text_colour: WebGL.Colour.ColourRGB;
|
|
45
|
+
onHoveredOver: VoidFunction;
|
|
46
|
+
onHoveredOut: VoidFunction;
|
|
47
|
+
onPressed: VoidFunction;
|
|
48
|
+
onPressedOut: VoidFunction;
|
|
49
|
+
|
|
50
|
+
constructor(x: Int32, y: Int32, w: Int32, h: Int32, ts: Int32=h){
|
|
51
|
+
this.text = "";
|
|
52
|
+
this.x = x;
|
|
53
|
+
this.y = y;
|
|
54
|
+
this.width = w;
|
|
55
|
+
this.height = h;
|
|
56
|
+
this.text_size = ts;
|
|
57
|
+
this.state = ButtonStateEnum.Off;
|
|
58
|
+
this.colours = new Map();
|
|
59
|
+
this.colours.set(ButtonStateEnum.Off, WebGL.Colour.ColourUtils.blue());
|
|
60
|
+
this.colours.set(ButtonStateEnum.Hovered, WebGL.Colour.ColourUtils.red());
|
|
61
|
+
this.colours.set(ButtonStateEnum.Pressed, WebGL.Colour.ColourUtils.green());
|
|
62
|
+
this.colours.set(ButtonStateEnum.PressedHovered, WebGL.Colour.ColourUtils.cyan());
|
|
63
|
+
this.text_colour = WebGL.Colour.ColourUtils.white();
|
|
64
|
+
this.onHoveredOver = EmptyFunction;
|
|
65
|
+
this.onHoveredOut = EmptyFunction;
|
|
66
|
+
this.onPressed = EmptyFunction;
|
|
67
|
+
this.onPressedOut = EmptyFunction;
|
|
68
|
+
}
|
|
69
|
+
setTextColour(colour: WebGL.Colour.ColourRGB){
|
|
70
|
+
|
|
71
|
+
}
|
|
72
|
+
setButtonColour(){
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
private isInside(x: Int32, y: Int32): boolean{
|
|
76
|
+
const sx = x - this.x;
|
|
77
|
+
const sy = y - this.y;
|
|
78
|
+
return 0 < sx && sx < this.width && 0 < sy && sy < this.height;
|
|
79
|
+
}
|
|
80
|
+
mouseDown(){
|
|
81
|
+
if(this.state == ButtonStateEnum.Hovered){
|
|
82
|
+
this.state = ButtonStateEnum.PressedHovered;
|
|
83
|
+
this.onPressed();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
mouseUp(){
|
|
87
|
+
if(this.state === ButtonStateEnum.Pressed){
|
|
88
|
+
this.state = ButtonStateEnum.Off;
|
|
89
|
+
this.onPressedOut();
|
|
90
|
+
}else if(this.state === ButtonStateEnum.PressedHovered){
|
|
91
|
+
this.state = ButtonStateEnum.Hovered;
|
|
92
|
+
this.onPressedOut();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
updateMouse(point: Point){
|
|
96
|
+
if(this.isInside(point.x, point.y)){
|
|
97
|
+
if(this.state == ButtonStateEnum.Off){
|
|
98
|
+
this.state = ButtonStateEnum.Hovered;
|
|
99
|
+
}else if(this.state == ButtonStateEnum.Pressed){
|
|
100
|
+
this.state = ButtonStateEnum.PressedHovered;
|
|
101
|
+
}
|
|
102
|
+
this.onHoveredOver();
|
|
103
|
+
}else{
|
|
104
|
+
if(this.state === ButtonStateEnum.Hovered){
|
|
105
|
+
this.state = ButtonStateEnum.Off;
|
|
106
|
+
}else if(this.state === ButtonStateEnum.PressedHovered){
|
|
107
|
+
this.state = ButtonStateEnum.Pressed;
|
|
108
|
+
}
|
|
109
|
+
this.onHoveredOut();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
draw(vp: WebGL.Matrix.TransformationMatrix3x3, colour_shader: WebGL.Shader.MVPColourProgram, text_drawer: WebGL.TextDrawer){
|
|
113
|
+
colour_shader.use();
|
|
114
|
+
const transformation = WebGL.WebGL.rectangleModel(this.x, this.y, this.width, this.height);
|
|
115
|
+
colour_shader.setMvp(vp.multiplyCopy(transformation));
|
|
116
|
+
if(this.colours.has(this.state)){
|
|
117
|
+
colour_shader.setColourFromColourRGB(this.colours.get(this.state)!);
|
|
118
|
+
}
|
|
119
|
+
WebGL.Shapes.Quad.draw();
|
|
120
|
+
|
|
121
|
+
if(this.text.length > 0){
|
|
122
|
+
const text_width = this.text_size*this.text.length;
|
|
123
|
+
const tx = this.x + (this.width/2) - (text_width/2);
|
|
124
|
+
const ty = this.y + (this.height/2) - (this.text_size/2);
|
|
125
|
+
text_drawer.drawTextColour(vp, tx, ty, this.text, this.text_size, this.text_colour);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export class ButtonSet{
|
|
131
|
+
buttons: BasicButton[];
|
|
132
|
+
constructor(){
|
|
133
|
+
this.buttons = [];
|
|
134
|
+
}
|
|
135
|
+
addButton(b: BasicButton){
|
|
136
|
+
this.buttons.push(b);
|
|
137
|
+
}
|
|
138
|
+
updateMouse(pt: Point){
|
|
139
|
+
for(const button of this.buttons){
|
|
140
|
+
button.updateMouse(pt);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
mouseDown(){
|
|
144
|
+
for(const button of this.buttons){
|
|
145
|
+
button.mouseDown();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
mouseUp(){
|
|
149
|
+
for(const button of this.buttons){
|
|
150
|
+
button.mouseUp();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
draw(vp: WebGL.Matrix.TransformationMatrix3x3, colour_shader: WebGL.Shader.MVPColourProgram, text_drawer: WebGL.TextDrawer){
|
|
154
|
+
for(const button of this.buttons){
|
|
155
|
+
button.draw(vp, colour_shader, text_drawer);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const ToggleButtonStateEnum = {
|
|
161
|
+
Off: 0,
|
|
162
|
+
On: 1,
|
|
163
|
+
OffHovered: 2,
|
|
164
|
+
OnHovered: 3,
|
|
165
|
+
|
|
166
|
+
} as const;
|
|
167
|
+
|
|
168
|
+
type ToggleButtonState = (typeof ToggleButtonStateEnum)[keyof typeof ToggleButtonStateEnum];
|
|
169
|
+
|
|
170
|
+
export class ToggleButton implements Button{
|
|
171
|
+
x: Int32;
|
|
172
|
+
y: Int32;
|
|
173
|
+
off_text: string;
|
|
174
|
+
on_text: string;
|
|
175
|
+
text: string;
|
|
176
|
+
width: Int32;
|
|
177
|
+
height: Int32;
|
|
178
|
+
text_size: Int32;
|
|
179
|
+
state: ToggleButtonState;
|
|
180
|
+
|
|
181
|
+
colours: Map<ToggleButtonState, WebGL.Colour.ColourRGB>;
|
|
182
|
+
|
|
183
|
+
onToggleOn: VoidFunction;
|
|
184
|
+
onToggleOff: VoidFunction;
|
|
185
|
+
|
|
186
|
+
text_colour: WebGL.Colour.ColourRGB;
|
|
187
|
+
|
|
188
|
+
constructor(x: Int32, y: Int32, w: Int32, h: Int32, ts: Int32=h){
|
|
189
|
+
this.off_text = "";
|
|
190
|
+
this.on_text = "";
|
|
191
|
+
this.text = "";
|
|
192
|
+
this.x = x;
|
|
193
|
+
this.y = y;
|
|
194
|
+
this.width = w;
|
|
195
|
+
this.height = h;
|
|
196
|
+
this.text_size = ts;
|
|
197
|
+
this.state = ToggleButtonStateEnum.Off;
|
|
198
|
+
|
|
199
|
+
this.colours = new Map();
|
|
200
|
+
this.colours.set(ToggleButtonStateEnum.Off, WebGL.Colour.ColourUtils.pink());
|
|
201
|
+
this.colours.set(ToggleButtonStateEnum.OffHovered, WebGL.Colour.ColourUtils.blue());
|
|
202
|
+
this.colours.set(ToggleButtonStateEnum.On, WebGL.Colour.ColourUtils.cyan());
|
|
203
|
+
this.colours.set(ToggleButtonStateEnum.OnHovered, WebGL.Colour.ColourUtils.green());
|
|
204
|
+
|
|
205
|
+
this.onToggleOn = () => {};
|
|
206
|
+
this.onToggleOff = () => {};
|
|
207
|
+
this.text_colour = WebGL.Colour.ColourUtils.white();
|
|
208
|
+
}
|
|
209
|
+
private isInside(x: Int32, y: Int32): boolean{
|
|
210
|
+
const sx = x - this.x;
|
|
211
|
+
const sy = y - this.y;
|
|
212
|
+
return 0 < sx && sx < this.width && 0 < sy && sy < this.height;
|
|
213
|
+
}
|
|
214
|
+
isOn(): boolean{
|
|
215
|
+
return this.state === ToggleButtonStateEnum.On || this.state === ToggleButtonStateEnum.OnHovered;
|
|
216
|
+
}
|
|
217
|
+
isOff(): boolean{
|
|
218
|
+
return this.state === ToggleButtonStateEnum.Off || this.state === ToggleButtonStateEnum.OffHovered;
|
|
219
|
+
}
|
|
220
|
+
toggleOff(){
|
|
221
|
+
if(this.state === ToggleButtonStateEnum.OnHovered){
|
|
222
|
+
this.state = ToggleButtonStateEnum.OffHovered;
|
|
223
|
+
}else if(this.state === ToggleButtonStateEnum.On){
|
|
224
|
+
this.state = ToggleButtonStateEnum.Off;
|
|
225
|
+
}
|
|
226
|
+
this.onToggleOff();
|
|
227
|
+
}
|
|
228
|
+
toggleOn(){
|
|
229
|
+
if(this.state === ToggleButtonStateEnum.Off){
|
|
230
|
+
this.state = ToggleButtonStateEnum.On;
|
|
231
|
+
}else if(this.state === ToggleButtonStateEnum.OffHovered){
|
|
232
|
+
this.state = ToggleButtonStateEnum.OnHovered;
|
|
233
|
+
}
|
|
234
|
+
this.onToggleOn();
|
|
235
|
+
}
|
|
236
|
+
updateMouse(point: Point){
|
|
237
|
+
//console.log(point);
|
|
238
|
+
if(this.isInside(point.x, point.y)){
|
|
239
|
+
if(this.state === ToggleButtonStateEnum.Off){
|
|
240
|
+
this.state = ToggleButtonStateEnum.OffHovered;
|
|
241
|
+
}else if(this.state == ToggleButtonStateEnum.On){
|
|
242
|
+
this.state = ToggleButtonStateEnum.OnHovered;
|
|
243
|
+
}
|
|
244
|
+
}else{
|
|
245
|
+
if(this.state === ToggleButtonStateEnum.OffHovered){
|
|
246
|
+
this.state = ToggleButtonStateEnum.Off;
|
|
247
|
+
}else if(this.state === ToggleButtonStateEnum.OnHovered){
|
|
248
|
+
this.state = ToggleButtonStateEnum.On;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
mouseDown(){
|
|
253
|
+
if(this.state === ToggleButtonStateEnum.OffHovered){
|
|
254
|
+
this.state = ToggleButtonStateEnum.OnHovered;
|
|
255
|
+
this.onToggleOn();
|
|
256
|
+
}else if(this.state === ToggleButtonStateEnum.OnHovered){
|
|
257
|
+
this.state = ToggleButtonStateEnum.OffHovered;
|
|
258
|
+
this.onToggleOff();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
mouseUp(){
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
draw(vp: WebGL.Matrix.TransformationMatrix3x3, colour_shader: WebGL.Shader.MVPColourProgram, text_drawer: WebGL.TextDrawer){
|
|
265
|
+
colour_shader.use();
|
|
266
|
+
const transformation = WebGL.WebGL.rectangleModel(this.x, this.y, this.width, this.height);
|
|
267
|
+
colour_shader.setMvp(vp.multiplyCopy(transformation));
|
|
268
|
+
if(this.colours.has(this.state)){
|
|
269
|
+
colour_shader.setColourFromColourRGB(this.colours.get(this.state)!);
|
|
270
|
+
}
|
|
271
|
+
WebGL.Shapes.Quad.draw();
|
|
272
|
+
const text = this.isOn() ? this.on_text : this.off_text;
|
|
273
|
+
if(text.length > 0){
|
|
274
|
+
const text_width = this.text_size*text.length;
|
|
275
|
+
const tx = this.x + (this.width/2) - (text_width/2);
|
|
276
|
+
const ty = this.y + (this.height/2) - (this.text_size/2);
|
|
277
|
+
text_drawer.drawTextColour(vp, tx, ty, text, this.text_size, this.text_colour);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export class ToggleButtonSet{
|
|
283
|
+
buttons: ToggleButton[];
|
|
284
|
+
constructor(){
|
|
285
|
+
this.buttons = [];
|
|
286
|
+
}
|
|
287
|
+
addButton(b: ToggleButton){
|
|
288
|
+
this.buttons.push(b);
|
|
289
|
+
}
|
|
290
|
+
updateMouse(pt: Point){
|
|
291
|
+
for(const button of this.buttons){
|
|
292
|
+
button.updateMouse(pt);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
mouseDown(){
|
|
296
|
+
for(const button of this.buttons){
|
|
297
|
+
button.mouseDown();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
mouseUp(){
|
|
301
|
+
for(const button of this.buttons){
|
|
302
|
+
button.mouseUp();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
draw(vp: WebGL.Matrix.TransformationMatrix3x3, colour_shader: WebGL.Shader.MVPColourProgram, text_drawer: WebGL.TextDrawer){
|
|
306
|
+
for(const button of this.buttons){
|
|
307
|
+
button.draw(vp, colour_shader, text_drawer);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export class SingleSelectToggleButtonSet extends ToggleButtonSet{
|
|
313
|
+
selected_button: Int32 | undefined;
|
|
314
|
+
//hovered_button: ToggleButton | undefined;
|
|
315
|
+
constructor(){
|
|
316
|
+
super();
|
|
317
|
+
this.selected_button = undefined;
|
|
318
|
+
}
|
|
319
|
+
mouseDown(){
|
|
320
|
+
for(let i = 0; i < this.buttons.length; i++){
|
|
321
|
+
const button = this.buttons[i];
|
|
322
|
+
button.mouseDown();
|
|
323
|
+
if(button.isOn()){
|
|
324
|
+
if(this.selected_button != undefined){
|
|
325
|
+
this.buttons[this.selected_button].toggleOff();
|
|
326
|
+
}
|
|
327
|
+
this.selected_button = i;
|
|
328
|
+
}else if(this.selected_button == i){
|
|
329
|
+
this.selected_button = undefined;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
export class GridButtonSet{
|
|
336
|
+
buttons: Button[];
|
|
337
|
+
rows: Int32;
|
|
338
|
+
cols: Int32;
|
|
339
|
+
constructor(){
|
|
340
|
+
this.buttons = [];
|
|
341
|
+
this.rows = 1;
|
|
342
|
+
this.cols = 1;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as WebGL from "./../WebGL/globals";
|
|
2
|
+
type Int32 = number;
|
|
3
|
+
|
|
4
|
+
export class InterfaceElement{
|
|
5
|
+
x: Int32;
|
|
6
|
+
y: Int32;
|
|
7
|
+
width: Int32;
|
|
8
|
+
height: Int32;
|
|
9
|
+
constructor(x: Int32, y: Int32, width: Int32, height: Int32){
|
|
10
|
+
this.x = x;
|
|
11
|
+
this.y = y;
|
|
12
|
+
this.width = width;
|
|
13
|
+
this.height = height;
|
|
14
|
+
}
|
|
15
|
+
isInside(point: WebGL.Matrix.Point2D){
|
|
16
|
+
const in_x = this.x < point.x && point.x < this.x+this.width;
|
|
17
|
+
const in_y = this.y < point.y && point.y < this.y+this.height;
|
|
18
|
+
return in_x && in_y;
|
|
19
|
+
}
|
|
20
|
+
drawBackground(vp: WebGL.Matrix.TransformationMatrix3x3,
|
|
21
|
+
colour_shader: WebGL.Shader.MVPColourProgram,
|
|
22
|
+
bg_colour: WebGL.Colour.ColourRGB){
|
|
23
|
+
colour_shader.use();
|
|
24
|
+
colour_shader.setColourFromColourRGB(bg_colour);
|
|
25
|
+
const bg_model = WebGL.WebGL.rectangleModel(this.x, this.y, this.width, this.height);
|
|
26
|
+
colour_shader.setMvp(vp.multiplyCopy(bg_model));
|
|
27
|
+
WebGL.Shapes.Quad.draw();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as WebGL from "./../WebGL/globals";
|
|
2
|
+
|
|
3
|
+
type Int32 = number;
|
|
4
|
+
type Float = number;
|
|
5
|
+
type VoidFunction = () => void;
|
|
6
|
+
const EmptyFunction = () => {};
|
|
7
|
+
|
|
8
|
+
export class InternalWindow{
|
|
9
|
+
x: Int32;
|
|
10
|
+
y: Int32;
|
|
11
|
+
header_height: Int32;
|
|
12
|
+
width: Int32;
|
|
13
|
+
height: Int32;
|
|
14
|
+
hover_header: boolean;
|
|
15
|
+
dragged_header: boolean;
|
|
16
|
+
header_offset_x: Int32;
|
|
17
|
+
header_offset_y: Int32;
|
|
18
|
+
|
|
19
|
+
can_close: boolean;
|
|
20
|
+
visible: boolean;
|
|
21
|
+
|
|
22
|
+
onClose: VoidFunction;
|
|
23
|
+
constructor(x: Int32, y: Int32, width: Int32, height: Int32){
|
|
24
|
+
this.x = x;
|
|
25
|
+
this.y = y;
|
|
26
|
+
this.width = width;
|
|
27
|
+
this.height = height;
|
|
28
|
+
this.header_height = 15;
|
|
29
|
+
this.hover_header = false;
|
|
30
|
+
this.dragged_header = false;
|
|
31
|
+
this.header_offset_x = 0;
|
|
32
|
+
this.header_offset_y = 0;
|
|
33
|
+
this.can_close = true;
|
|
34
|
+
this.visible = true;
|
|
35
|
+
this.onClose = EmptyFunction;
|
|
36
|
+
}
|
|
37
|
+
getInternalY(): Int32{ // where the internal window starts
|
|
38
|
+
return this.y+this.header_height;
|
|
39
|
+
}
|
|
40
|
+
isInsideHeader(pos: WebGL.Matrix.Point2D): boolean{
|
|
41
|
+
const inside_x = this.x < pos.x && pos.x < this.x + this.width;
|
|
42
|
+
const inside_y = this.y < pos.y && pos.y < this.y + this.header_height;
|
|
43
|
+
return inside_x && inside_y;
|
|
44
|
+
}
|
|
45
|
+
isInsideClose(pos: WebGL.Matrix.Point2D): boolean{
|
|
46
|
+
const inside_x = this.x+this.width-this.header_height < pos.x && pos.x < this.x+this.width;
|
|
47
|
+
const inside_y = this.y < pos.y && pos.y < this.y + this.header_height;
|
|
48
|
+
return inside_x && inside_y;
|
|
49
|
+
}
|
|
50
|
+
getWindowPosition(): WebGL.Matrix.Point2D{
|
|
51
|
+
return new WebGL.Matrix.Point2D(this.x, this.y+this.header_height);
|
|
52
|
+
}
|
|
53
|
+
mouseMove(global_position: WebGL.Matrix.Point2D){
|
|
54
|
+
if(!this.visible) return;
|
|
55
|
+
this.hover_header = this.isInsideHeader(global_position);
|
|
56
|
+
if(this.dragged_header){
|
|
57
|
+
this.x = global_position.x + this.header_offset_x;
|
|
58
|
+
this.y = global_position.y + this.header_offset_y;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
mouseDown(global_position: WebGL.Matrix.Point2D){
|
|
62
|
+
if(this.isInsideClose(global_position)){
|
|
63
|
+
this.visible = false;
|
|
64
|
+
this.onClose();
|
|
65
|
+
}
|
|
66
|
+
if(this.hover_header){
|
|
67
|
+
this.dragged_header = true;
|
|
68
|
+
this.header_offset_x = this.x - global_position.x;
|
|
69
|
+
this.header_offset_y = this.y - global_position.y;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
mouseUp(){
|
|
73
|
+
this.dragged_header = false;
|
|
74
|
+
}
|
|
75
|
+
draw(vp: WebGL.Matrix.TransformationMatrix3x3, solid_shader: WebGL.Shader.MVPColourProgram){
|
|
76
|
+
if(this.visible){
|
|
77
|
+
//draw header
|
|
78
|
+
solid_shader.use();
|
|
79
|
+
const header_model = WebGL.WebGL.rectangleModel(this.x, this.y, this.width, this.header_height);
|
|
80
|
+
solid_shader.setColourFromColourRGB(WebGL.Colour.ColourUtils.grey());
|
|
81
|
+
solid_shader.setMvp(vp.multiplyCopy(header_model));
|
|
82
|
+
WebGL.Shapes.Quad.draw();
|
|
83
|
+
|
|
84
|
+
//window background
|
|
85
|
+
const back_model = WebGL.WebGL.rectangleModel(this.x, this.y+this.header_height, this.width, this.height);
|
|
86
|
+
solid_shader.setColourFromColourRGB(WebGL.Colour.ColourUtils.white());
|
|
87
|
+
solid_shader.setMvp(vp.multiplyCopy(back_model));
|
|
88
|
+
WebGL.Shapes.Quad.draw();
|
|
89
|
+
|
|
90
|
+
//close header
|
|
91
|
+
if(this.can_close){
|
|
92
|
+
const close_model = WebGL.WebGL.rectangleModel(this.x+this.width-this.header_height, this.y, this.header_height, this.header_height);
|
|
93
|
+
solid_shader.setColourFromColourRGB(WebGL.Colour.ColourUtils.grey(0.75));
|
|
94
|
+
solid_shader.setMvp(vp.multiplyCopy(close_model));
|
|
95
|
+
WebGL.Shapes.Quad.draw();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
}
|