-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.js
174 lines (140 loc) · 4.77 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
* @module Spatiality.Main
* @description Entry point for the Spatiality app.
* @author William Martin
* @version 0.1.0
*/
import './style.css';
import './src/dropdown-menu.js';
import './src/projects-list.js';
import * as Interface from './src/interface.js';
import * as Helpers from './src/helpers.js';
// The global state object. Instantiated as a singleton.
import { State } from './src/state.js';
// The hosted LLM AI we want to use.
import * as OpenAI from './src/openai.js';
// The global State singleton.
let state
// TODO Consider making p5.js part of the Simulation.
const sketch = p => {
// Put any sketch-specific state here.
const darkModeColors = {
backgroundColor: p.color('#222'),
objectFillColor: p.color('#222'),
objectStrokeColor: p.color('gray'),
pointCloudColor: p.color(255, 255, 255, 128),
highlightColor: p.color('#eac451'),
};
const lightModeColors = {
backgroundColor: p.color('white'),
objectFillColor: p.color('white'),
objectStrokeColor: p.color('gray'),
pointCloudColor: p.color(0, 0, 0, 128),
highlightColor: p.color('#eac451'),
};
const interfaceState = {
renderObjects: true,
renderOutlines: true,
darkMode: false,
drawAxes: true,
colorScheme: lightModeColors,
cam: null,
};
p.setup = async function () {
const canvasSize = getCanvasSize();
p.createCanvas(canvasSize.width, canvasSize.height, p.WEBGL);
initializeCamera();
// Create the LLM context.
const openai = new OpenAI.OpenAIInterface();
// Create the global state singleton, which also creates the default Project,
// populates the project list, and manages the list of Projects.
state = new State(openai);
await state.initialize(interfaceState);
} // end setup
p.draw = function () {
p.background(interfaceState.colorScheme.backgroundColor);
p.scale(20);
p.strokeWeight(0.5);
if (interfaceState.renderObjects) {
p.fill(interfaceState.colorScheme.objectFillColor);
} else {
p.noFill();
}
if (interfaceState.renderOutlines) {
p.stroke(interfaceState.colorScheme.objectStrokeColor);
} else {
p.noStroke();
}
// Render the ground plane.
p.push();
p.translate(0, -0.1, 0);
p.box(20.0, 0.2, 20.0);
p.pop();
if (state.currentSimulation) {
state.currentSimulation.draw(p, interfaceState);
}
if (interfaceState.drawAxes) {
Interface.drawAxes(p);
}
} // end draw
function initializeCamera () {
interfaceState.cam = p.createEasyCam({ rotation: [ 0, 0, 0.4794255, 0.8775826 ] });
// Disable right click for the benefit of EasyCam.
const sim = document.querySelector('#simulation');
sim.oncontextmenu = function() { return false; };
}
Interface.initializeCheckbox('#toggle-axes', (value, event) => {
interfaceState.drawAxes = value;
});
Interface.initializeCheckbox('#toggle-objects', (value, event) => {
interfaceState.renderObjects = value;
});
Interface.initializeCheckbox('#toggle-outlines', (value, event) => {
interfaceState.renderOutlines = value;
});
Interface.initializeCheckbox('#toggle-darkmode', (value, event) => {
interfaceState.darkMode = value;
if (interfaceState.darkMode) {
interfaceState.colorScheme = darkModeColors;
} else {
interfaceState.colorScheme = lightModeColors;
}
});
// Resize the sketch if the window changes size.
p.windowResized = () => {
const eltSize = getCanvasSize();
p.resizeCanvas(eltSize.width, eltSize.height);
interfaceState.cam.update();
}
p.mouseClicked = event => {
// We only want click events that originated on the canvas itself,
// otherwise we get events for the entire page, because p5.js is weird.
if (event.target.className !== 'p5Canvas') { return; }
const mousePosition = Helpers.screenToWorld(p, p.mouseX, p.mouseY);
const cameraPosition = Helpers.getCameraPosition(p);
const dir = p5.Vector.sub(mousePosition, cameraPosition);
// console.debug(mousePosition, cameraPosition, dir);
state.currentSimulation.mouseClicked(event, p, interfaceState, mousePosition, dir);
}
} // end sketch function
function getHostElement () {
return document.querySelector('#sketch');
}
function getCanvasSize () {
const host = getHostElement();
if (!host) {
return { width: 800, height: 400 };
};
const rect = host.getBoundingClientRect();
return { width: rect.width, height: rect.height };
}
async function onReady () {
const sketchElt = getHostElement();
// Note: P5.js is loaded in a <link> tag in the HTML because it's weird.
new p5(sketch, sketchElt);
} // end onReady
if (document.readyState === 'complete') {
onReady();
} else {
document.addEventListener("DOMContentLoaded", onReady);
}