Spaces:
Running
Running
Update index.html
Browse files- index.html +694 -18
index.html
CHANGED
@@ -1,19 +1,695 @@
|
|
1 |
-
<!
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
</html>
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="hi">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<title>Responsive Physics Simulator with Menus on Top</title>
|
6 |
+
<style>
|
7 |
+
body { margin: 0; overflow: hidden; font-family: Arial, sans-serif; }
|
8 |
+
/* Full-page canvas */
|
9 |
+
canvas { display: block; }
|
10 |
+
/* Controls Panel (Menus) – z-index high to always appear on top */
|
11 |
+
#controls {
|
12 |
+
position: absolute;
|
13 |
+
top: 10px;
|
14 |
+
left: 10px;
|
15 |
+
z-index: 1000;
|
16 |
+
background: rgba(255,255,255,0.95);
|
17 |
+
padding: 10px;
|
18 |
+
border-radius: 5px;
|
19 |
+
max-width: 320px;
|
20 |
+
max-height: 90vh;
|
21 |
+
overflow-y: auto;
|
22 |
+
}
|
23 |
+
#controls label { display: block; margin-top: 8px; }
|
24 |
+
#controls input, #controls select, #controls button {
|
25 |
+
width: 100%; padding: 6px; margin-top: 4px; box-sizing: border-box;
|
26 |
+
}
|
27 |
+
#buttonContainer { display: flex; justify-content: space-between; }
|
28 |
+
/* Edit Panel – Always on top */
|
29 |
+
#editPanel {
|
30 |
+
position: absolute;
|
31 |
+
top: 10px;
|
32 |
+
right: 10px;
|
33 |
+
z-index: 1000;
|
34 |
+
background: rgba(255,255,255,0.95);
|
35 |
+
padding: 10px;
|
36 |
+
border-radius: 5px;
|
37 |
+
max-width: 300px;
|
38 |
+
max-height: 90vh;
|
39 |
+
overflow-y: auto;
|
40 |
+
display: none;
|
41 |
+
}
|
42 |
+
#editPanel h3 { margin: 0 0 5px 0; }
|
43 |
+
#editPanel label { display: block; margin-top: 8px; }
|
44 |
+
#editPanel input, #editPanel select, #editPanel button {
|
45 |
+
width: 100%; padding: 6px; margin-top: 4px; box-sizing: border-box;
|
46 |
+
}
|
47 |
+
/* Connection Options Panel */
|
48 |
+
#connectionPanel {
|
49 |
+
position: absolute;
|
50 |
+
top: 150px;
|
51 |
+
right: 10px;
|
52 |
+
z-index: 1000;
|
53 |
+
background: rgba(255,255,255,0.95);
|
54 |
+
padding: 10px;
|
55 |
+
border-radius: 5px;
|
56 |
+
max-width: 250px;
|
57 |
+
display: none;
|
58 |
+
}
|
59 |
+
#connectionPanel h3 { margin: 0 0 5px 0; }
|
60 |
+
#connectionPanel label { display: block; margin-top: 8px; }
|
61 |
+
#connectionPanel input, #connectionPanel select, #connectionPanel button {
|
62 |
+
width: 100%; padding: 6px; margin-top: 4px; box-sizing: border-box;
|
63 |
+
}
|
64 |
+
/* Constraint Edit Panel */
|
65 |
+
#constraintEditPanel {
|
66 |
+
position: absolute;
|
67 |
+
bottom: 10px;
|
68 |
+
right: 10px;
|
69 |
+
z-index: 1000;
|
70 |
+
background: rgba(255,255,255,0.95);
|
71 |
+
padding: 10px;
|
72 |
+
border-radius: 5px;
|
73 |
+
max-width: 250px;
|
74 |
+
display: none;
|
75 |
+
}
|
76 |
+
#constraintEditPanel h3 { margin: 0 0 5px 0; }
|
77 |
+
#constraintEditPanel label { display: block; margin-top: 8px; }
|
78 |
+
#constraintEditPanel input, #constraintEditPanel select, #constraintEditPanel button {
|
79 |
+
width: 100%; padding: 6px; margin-top: 4px; box-sizing: border-box;
|
80 |
+
}
|
81 |
+
</style>
|
82 |
+
</head>
|
83 |
+
<body>
|
84 |
+
<!-- Controls Panel (Menus) -->
|
85 |
+
<div id="controls">
|
86 |
+
<label for="simulationSelect">Simulation Element Chunein:</label>
|
87 |
+
<select id="simulationSelect">
|
88 |
+
<option value="bouncingBall">Bouncing Ball</option>
|
89 |
+
<option value="pendulum">Pendulum</option>
|
90 |
+
<option value="projectile">Projectile Motion</option>
|
91 |
+
<option value="inclinedPlane">Inclined Plane</option>
|
92 |
+
<option value="springMass">Spring–Mass System</option>
|
93 |
+
</select>
|
94 |
+
<!-- Dynamic Suboptions Container -->
|
95 |
+
<div id="subOptionsContainer"></div>
|
96 |
+
<div id="buttonContainer">
|
97 |
+
<button id="addElement">Add Element</button>
|
98 |
+
<button id="reset">Reset Simulation</button>
|
99 |
+
</div>
|
100 |
+
</div>
|
101 |
+
|
102 |
+
<!-- Edit Panel (Opens on Double–Click on an Element) -->
|
103 |
+
<div id="editPanel"></div>
|
104 |
+
|
105 |
+
<!-- Connection Options Panel -->
|
106 |
+
<div id="connectionPanel">
|
107 |
+
<h3>Connection Options</h3>
|
108 |
+
<label for="connType">Connection Type:</label>
|
109 |
+
<select id="connType">
|
110 |
+
<option value="string">String</option>
|
111 |
+
<option value="spring">Spring</option>
|
112 |
+
<option value="stick">Stick</option>
|
113 |
+
</select>
|
114 |
+
<div id="sourceEndpointDiv">
|
115 |
+
<label for="sourceEndpoint">Source Endpoint:</label>
|
116 |
+
<select id="sourceEndpoint">
|
117 |
+
<option value="mass">Mass</option>
|
118 |
+
<option value="fixed">Fixed</option>
|
119 |
+
</select>
|
120 |
+
</div>
|
121 |
+
<button id="cancelConn">Cancel</button>
|
122 |
+
<p style="font-size: 12px; color: #555;">Ab target element par click karein jisse attach karna hai.</p>
|
123 |
+
</div>
|
124 |
+
|
125 |
+
<!-- Constraint Edit Panel -->
|
126 |
+
<div id="constraintEditPanel">
|
127 |
+
<h3>Edit Constraint</h3>
|
128 |
+
<label for="consA_X">Endpoint A X:</label>
|
129 |
+
<input type="number" id="consA_X" step="1">
|
130 |
+
<label for="consA_Y">Endpoint A Y:</label>
|
131 |
+
<input type="number" id="consA_Y" step="1">
|
132 |
+
<label for="consB_X">Endpoint B X:</label>
|
133 |
+
<input type="number" id="consB_X" step="1">
|
134 |
+
<label for="consB_Y">Endpoint B Y:</label>
|
135 |
+
<input type="number" id="consB_Y" step="1">
|
136 |
+
<label for="consType">Connection Type:</label>
|
137 |
+
<select id="consType">
|
138 |
+
<option value="string">String</option>
|
139 |
+
<option value="spring">Spring</option>
|
140 |
+
<option value="stick">Stick</option>
|
141 |
+
</select>
|
142 |
+
<button id="updateConstraint">Update Constraint</button>
|
143 |
+
<button id="deleteConstraint">Delete Constraint</button>
|
144 |
+
</div>
|
145 |
+
|
146 |
+
<!-- Matter.js Library and Script -->
|
147 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
|
148 |
+
<script>
|
149 |
+
// Module aliases and Engine Setup
|
150 |
+
const Engine = Matter.Engine,
|
151 |
+
Render = Matter.Render,
|
152 |
+
Runner = Matter.Runner,
|
153 |
+
World = Matter.World,
|
154 |
+
Bodies = Matter.Bodies,
|
155 |
+
Body = Matter.Body,
|
156 |
+
Constraint = Matter.Constraint,
|
157 |
+
Mouse = Matter.Mouse,
|
158 |
+
MouseConstraint = Matter.MouseConstraint,
|
159 |
+
Events = Matter.Events;
|
160 |
+
|
161 |
+
const engine = Engine.create();
|
162 |
+
const world = engine.world;
|
163 |
+
const render = Render.create({
|
164 |
+
element: document.body,
|
165 |
+
engine: engine,
|
166 |
+
options: {
|
167 |
+
width: window.innerWidth,
|
168 |
+
height: window.innerHeight,
|
169 |
+
wireframes: false,
|
170 |
+
background: '#f0f0f0'
|
171 |
+
}
|
172 |
+
});
|
173 |
+
Render.run(render);
|
174 |
+
const runner = Runner.create();
|
175 |
+
Runner.run(runner, engine);
|
176 |
+
|
177 |
+
// Global variables for boundaries (declare as let so we can update them)
|
178 |
+
let floor, wallLeft, wallRight;
|
179 |
+
|
180 |
+
// Function to create/update boundaries based on current window dimensions
|
181 |
+
function updateBoundaries() {
|
182 |
+
// Agar boundaries already exist, remove unhein
|
183 |
+
if(floor && wallLeft && wallRight) {
|
184 |
+
World.remove(world, [floor, wallLeft, wallRight]);
|
185 |
+
}
|
186 |
+
floor = Bodies.rectangle(window.innerWidth/2, window.innerHeight - 50, window.innerWidth, 100, {
|
187 |
+
isStatic: true,
|
188 |
+
render: { fillStyle: '#060a19' }
|
189 |
+
});
|
190 |
+
wallLeft = Bodies.rectangle(-50, window.innerHeight/2, 100, window.innerHeight, { isStatic: true });
|
191 |
+
wallRight = Bodies.rectangle(window.innerWidth+50, window.innerHeight/2, 100, window.innerHeight, { isStatic: true });
|
192 |
+
World.add(world, [floor, wallLeft, wallRight]);
|
193 |
+
}
|
194 |
+
// Initial boundaries creation
|
195 |
+
updateBoundaries();
|
196 |
+
|
197 |
+
// Mouse control for drag & drop
|
198 |
+
let mouse = Mouse.create(render.canvas);
|
199 |
+
let mouseConstraint = MouseConstraint.create(engine, {
|
200 |
+
mouse: mouse,
|
201 |
+
constraint: { stiffness: 0.2, render: { visible: false } }
|
202 |
+
});
|
203 |
+
World.add(world, mouseConstraint);
|
204 |
+
render.mouse = mouse;
|
205 |
+
|
206 |
+
// Global Variables for Editing & Attachment
|
207 |
+
let selectedBody = null;
|
208 |
+
let selectedConstraint = null;
|
209 |
+
let attachMode = false;
|
210 |
+
let attachFrom = null;
|
211 |
+
const connectionPanel = document.getElementById('connectionPanel');
|
212 |
+
const editPanel = document.getElementById('editPanel');
|
213 |
+
|
214 |
+
// Helper function for random color
|
215 |
+
function getRandomColor() {
|
216 |
+
return '#' + Math.floor(Math.random()*16777215).toString(16);
|
217 |
+
}
|
218 |
+
|
219 |
+
/* ---------- Dynamic Suboptions for Adding Elements ---------- */
|
220 |
+
function updateSubOptions() {
|
221 |
+
const simulationSelect = document.getElementById('simulationSelect');
|
222 |
+
const subOptionsContainer = document.getElementById('subOptionsContainer');
|
223 |
+
let selected = simulationSelect.value;
|
224 |
+
let html = '';
|
225 |
+
if(selected === 'bouncingBall'){
|
226 |
+
html += `
|
227 |
+
<label for="ballInitialX">Initial X:</label>
|
228 |
+
<input type="number" id="ballInitialX" value="100">
|
229 |
+
<label for="ballInitialY">Initial Y:</label>
|
230 |
+
<input type="number" id="ballInitialY" value="50">
|
231 |
+
<label for="ballRadius">Radius:</label>
|
232 |
+
<input type="number" id="ballRadius" value="30">
|
233 |
+
<label for="ballRestitution">Restitution:</label>
|
234 |
+
<input type="number" id="ballRestitution" value="0.9" step="0.1" min="0" max="1">
|
235 |
+
<label for="ballFriction">Friction:</label>
|
236 |
+
<input type="number" id="ballFriction" value="0.005" step="0.001" min="0" max="1">
|
237 |
+
<label for="ballColor">Color:</label>
|
238 |
+
<input type="color" id="ballColor" value="#3498db">
|
239 |
+
`;
|
240 |
+
} else if(selected === 'pendulum'){
|
241 |
+
html += `
|
242 |
+
<label for="pendulumPivotX">Pivot X:</label>
|
243 |
+
<input type="number" id="pendulumPivotX" value="${window.innerWidth-200}">
|
244 |
+
<label for="pendulumPivotY">Pivot Y:</label>
|
245 |
+
<input type="number" id="pendulumPivotY" value="50">
|
246 |
+
<label for="pendulumBobRadius">Bob Radius:</label>
|
247 |
+
<input type="number" id="pendulumBobRadius" value="40">
|
248 |
+
<label for="pendulumLength">Length:</label>
|
249 |
+
<input type="number" id="pendulumLength" value="250">
|
250 |
+
<label for="pendulumStiffness">Stiffness:</label>
|
251 |
+
<input type="number" id="pendulumStiffness" value="1" step="0.1" min="0" max="1">
|
252 |
+
<label for="pendulumBobColor">Color:</label>
|
253 |
+
<input type="color" id="pendulumBobColor" value="#ff0000">
|
254 |
+
`;
|
255 |
+
} else if(selected === 'projectile'){
|
256 |
+
html += `
|
257 |
+
<label for="projectileInitialX">Initial X:</label>
|
258 |
+
<input type="number" id="projectileInitialX" value="100">
|
259 |
+
<label for="projectileInitialY">Initial Y:</label>
|
260 |
+
<input type="number" id="projectileInitialY" value="300">
|
261 |
+
<label for="projectileRadius">Radius:</label>
|
262 |
+
<input type="number" id="projectileRadius" value="20">
|
263 |
+
<label for="projectileVelX">Velocity X:</label>
|
264 |
+
<input type="number" id="projectileVelX" value="15">
|
265 |
+
<label for="projectileVelY">Velocity Y:</label>
|
266 |
+
<input type="number" id="projectileVelY" value="-15">
|
267 |
+
<label for="projectileColor">Color:</label>
|
268 |
+
<input type="color" id="projectileColor" value="#e67e22">
|
269 |
+
`;
|
270 |
+
} else if(selected === 'inclinedPlane'){
|
271 |
+
html += `
|
272 |
+
<label for="rampWidth">Ramp Width:</label>
|
273 |
+
<input type="number" id="rampWidth" value="300">
|
274 |
+
<label for="rampHeight">Ramp Height:</label>
|
275 |
+
<input type="number" id="rampHeight" value="20">
|
276 |
+
<label for="rampAngle">Ramp Angle (°):</label>
|
277 |
+
<input type="number" id="rampAngle" value="30">
|
278 |
+
<label for="rampX">Ramp X:</label>
|
279 |
+
<input type="number" id="rampX" value="400">
|
280 |
+
<label for="rampY">Ramp Y:</label>
|
281 |
+
<input type="number" id="rampY" value="${window.innerHeight-150}">
|
282 |
+
<label for="rampColor">Ramp Color:</label>
|
283 |
+
<input type="color" id="rampColor" value="#8e44ad">
|
284 |
+
<hr>
|
285 |
+
<label for="blockWidth">Block Width:</label>
|
286 |
+
<input type="number" id="blockWidth" value="40">
|
287 |
+
<label for="blockHeight">Block Height:</label>
|
288 |
+
<input type="number" id="blockHeight" value="40">
|
289 |
+
<label for="blockFriction">Block Friction:</label>
|
290 |
+
<input type="number" id="blockFriction" value="0.05" step="0.01" min="0" max="1">
|
291 |
+
<label for="blockColor">Block Color:</label>
|
292 |
+
<input type="color" id="blockColor" value="#1abc9c">
|
293 |
+
`;
|
294 |
+
} else if(selected === 'springMass'){
|
295 |
+
html += `
|
296 |
+
<label for="springMassRadius">Mass Radius:</label>
|
297 |
+
<input type="number" id="springMassRadius" value="25">
|
298 |
+
<label for="springMassRestitution">Restitution:</label>
|
299 |
+
<input type="number" id="springMassRestitution" value="0.8" step="0.1" min="0" max="1">
|
300 |
+
<label for="fixedPointX">Fixed X:</label>
|
301 |
+
<input type="number" id="fixedPointX" value="${Math.floor(window.innerWidth/2)}">
|
302 |
+
<label for="fixedPointY">Fixed Y:</label>
|
303 |
+
<input type="number" id="fixedPointY" value="100">
|
304 |
+
<label for="springLength">Spring Length:</label>
|
305 |
+
<input type="number" id="springLength" value="200">
|
306 |
+
<label for="springStiffness">Stiffness:</label>
|
307 |
+
<input type="number" id="springStiffness" value="0.02" step="0.01" min="0" max="1">
|
308 |
+
<label for="springMassColor">Color:</label>
|
309 |
+
<input type="color" id="springMassColor" value="#f39c12">
|
310 |
+
`;
|
311 |
+
}
|
312 |
+
subOptionsContainer.innerHTML = html;
|
313 |
+
}
|
314 |
+
updateSubOptions();
|
315 |
+
document.getElementById('simulationSelect').addEventListener('change', updateSubOptions);
|
316 |
+
|
317 |
+
/* ---------- Functions to Add Simulation Elements ---------- */
|
318 |
+
function addBouncingBall(){
|
319 |
+
const x = parseFloat(document.getElementById("ballInitialX").value);
|
320 |
+
const y = parseFloat(document.getElementById("ballInitialY").value);
|
321 |
+
const radius = parseFloat(document.getElementById("ballRadius").value);
|
322 |
+
const restitution = parseFloat(document.getElementById("ballRestitution").value);
|
323 |
+
const friction = parseFloat(document.getElementById("ballFriction").value);
|
324 |
+
const color = document.getElementById("ballColor").value || getRandomColor();
|
325 |
+
const ball = Bodies.circle(x, y, radius, { restitution, friction, render: { fillStyle: color } });
|
326 |
+
ball.elementType = "bouncingBall";
|
327 |
+
ball.customOptions = { x, y, radius, restitution, friction, color };
|
328 |
+
World.add(world, ball);
|
329 |
+
}
|
330 |
+
function addPendulum(){
|
331 |
+
const pivotX = parseFloat(document.getElementById("pendulumPivotX").value);
|
332 |
+
const pivotY = parseFloat(document.getElementById("pendulumPivotY").value);
|
333 |
+
const bobRadius = parseFloat(document.getElementById("pendulumBobRadius").value);
|
334 |
+
const pendulumLength = parseFloat(document.getElementById("pendulumLength").value);
|
335 |
+
const stiffness = parseFloat(document.getElementById("pendulumStiffness").value);
|
336 |
+
const bobColor = document.getElementById("pendulumBobColor").value || "#ff0000";
|
337 |
+
const bob = Bodies.circle(pivotX, pivotY+pendulumLength, bobRadius, { restitution: 1, density: 0.005, render: { fillStyle: bobColor } });
|
338 |
+
bob.elementType = "pendulum";
|
339 |
+
bob.customOptions = { pivotX, pivotY, bobRadius, pendulumLength, stiffness, bobColor };
|
340 |
+
const pendulumConstraint = Constraint.create({
|
341 |
+
pointA: { x: pivotX, y: pivotY },
|
342 |
+
bodyB: bob,
|
343 |
+
length: pendulumLength,
|
344 |
+
stiffness: stiffness,
|
345 |
+
render: { strokeStyle: '#000', lineWidth: 2 }
|
346 |
+
});
|
347 |
+
World.add(world, [bob, pendulumConstraint]);
|
348 |
+
}
|
349 |
+
function addProjectile(){
|
350 |
+
const x = parseFloat(document.getElementById("projectileInitialX").value);
|
351 |
+
const y = parseFloat(document.getElementById("projectileInitialY").value);
|
352 |
+
const radius = parseFloat(document.getElementById("projectileRadius").value);
|
353 |
+
const velX = parseFloat(document.getElementById("projectileVelX").value);
|
354 |
+
const velY = parseFloat(document.getElementById("projectileVelY").value);
|
355 |
+
const color = document.getElementById("projectileColor").value || getRandomColor();
|
356 |
+
const proj = Bodies.circle(x, y, radius, { restitution: 0.8, frictionAir: 0.001, render: { fillStyle: color } });
|
357 |
+
proj.elementType = "projectile";
|
358 |
+
proj.customOptions = { x, y, radius, velX, velY, color };
|
359 |
+
Body.setVelocity(proj, { x: velX, y: velY });
|
360 |
+
World.add(world, proj);
|
361 |
+
}
|
362 |
+
function addInclinedPlane(){
|
363 |
+
// Do bodies: ek ramp (static) aur ek block.
|
364 |
+
const rampWidth = parseFloat(document.getElementById("rampWidth").value);
|
365 |
+
const rampHeight = parseFloat(document.getElementById("rampHeight").value);
|
366 |
+
const angleDeg = parseFloat(document.getElementById("rampAngle").value);
|
367 |
+
const angle = angleDeg * Math.PI/180;
|
368 |
+
const rampX = parseFloat(document.getElementById("rampX").value);
|
369 |
+
const rampY = parseFloat(document.getElementById("rampY").value);
|
370 |
+
const rampColor = document.getElementById("rampColor").value || "#8e44ad";
|
371 |
+
const ramp = Bodies.rectangle(rampX, rampY, rampWidth, rampHeight, {
|
372 |
+
isStatic: true,
|
373 |
+
angle: angle,
|
374 |
+
render: { fillStyle: rampColor }
|
375 |
+
});
|
376 |
+
ramp.elementType = "inclinedPlane_ramp";
|
377 |
+
ramp.customOptions = { rampWidth, rampHeight, angleDeg, rampX, rampY, rampColor };
|
378 |
+
const blockWidth = parseFloat(document.getElementById("blockWidth").value);
|
379 |
+
const blockHeight = parseFloat(document.getElementById("blockHeight").value);
|
380 |
+
const blockFriction = parseFloat(document.getElementById("blockFriction").value);
|
381 |
+
const blockColor = document.getElementById("blockColor").value || "#1abc9c";
|
382 |
+
const block = Bodies.rectangle(rampX - rampWidth/4, rampY - 50, blockWidth, blockHeight, {
|
383 |
+
friction: blockFriction,
|
384 |
+
render: { fillStyle: blockColor }
|
385 |
+
});
|
386 |
+
block.elementType = "inclinedPlane_block";
|
387 |
+
block.customOptions = { blockWidth, blockHeight, blockFriction, blockColor };
|
388 |
+
World.add(world, [ramp, block]);
|
389 |
+
}
|
390 |
+
function addSpringMass(){
|
391 |
+
const massRadius = parseFloat(document.getElementById("springMassRadius").value);
|
392 |
+
const massRestitution = parseFloat(document.getElementById("springMassRestitution").value);
|
393 |
+
const fixedPointX = parseFloat(document.getElementById("fixedPointX").value);
|
394 |
+
const fixedPointY = parseFloat(document.getElementById("fixedPointY").value);
|
395 |
+
const springLength = parseFloat(document.getElementById("springLength").value);
|
396 |
+
const springStiffness = parseFloat(document.getElementById("springStiffness").value);
|
397 |
+
const massColor = document.getElementById("springMassColor").value || getRandomColor();
|
398 |
+
const mass = Bodies.circle(fixedPointX, fixedPointY+springLength, massRadius, {
|
399 |
+
restitution: massRestitution,
|
400 |
+
density: 0.004,
|
401 |
+
render: { fillStyle: massColor }
|
402 |
+
});
|
403 |
+
mass.elementType = "springMass";
|
404 |
+
mass.customOptions = { massRadius, massRestitution, fixedPointX, fixedPointY, springLength, springStiffness, massColor };
|
405 |
+
mass.fixedPoint = { x: fixedPointX, y: fixedPointY };
|
406 |
+
const spring = Constraint.create({
|
407 |
+
pointA: { x: fixedPointX, y: fixedPointY },
|
408 |
+
bodyB: mass,
|
409 |
+
length: springLength,
|
410 |
+
stiffness: springStiffness,
|
411 |
+
damping: 0.05,
|
412 |
+
render: { strokeStyle: '#000', lineWidth: 2 }
|
413 |
+
});
|
414 |
+
World.add(world, [mass, spring]);
|
415 |
+
}
|
416 |
+
document.getElementById('addElement').addEventListener('click', function(){
|
417 |
+
const selected = document.getElementById('simulationSelect').value;
|
418 |
+
if(selected === 'bouncingBall') addBouncingBall();
|
419 |
+
else if(selected === 'pendulum') addPendulum();
|
420 |
+
else if(selected === 'projectile') addProjectile();
|
421 |
+
else if(selected === 'inclinedPlane') addInclinedPlane();
|
422 |
+
else if(selected === 'springMass') addSpringMass();
|
423 |
+
});
|
424 |
+
document.getElementById('reset').addEventListener('click', function(){
|
425 |
+
World.clear(world);
|
426 |
+
Engine.clear(engine);
|
427 |
+
// Re-create boundaries on reset
|
428 |
+
updateBoundaries();
|
429 |
+
mouse = Mouse.create(render.canvas);
|
430 |
+
mouseConstraint = MouseConstraint.create(engine, { mouse: mouse, constraint: { stiffness: 0.2, render: { visible: false } } });
|
431 |
+
World.add(world, mouseConstraint);
|
432 |
+
render.mouse = mouse;
|
433 |
+
hideEditPanel();
|
434 |
+
hideConnectionPanel();
|
435 |
+
hideConstraintEditPanel();
|
436 |
+
});
|
437 |
+
|
438 |
+
/* ---------- Edit Panel Functions (Double–Click to Open) ---------- */
|
439 |
+
function openEditPanel(body) {
|
440 |
+
selectedBody = body;
|
441 |
+
let html = `<h3>Edit Element</h3>
|
442 |
+
<label for="editPosX">Position X:</label>
|
443 |
+
<input type="number" id="editPosX" value="${body.position.x.toFixed(2)}">
|
444 |
+
<label for="editPosY">Position Y:</label>
|
445 |
+
<input type="number" id="editPosY" value="${body.position.y.toFixed(2)}">
|
446 |
+
<label for="editAngle">Angle (radians):</label>
|
447 |
+
<input type="number" id="editAngle" value="${body.angle.toFixed(2)}">
|
448 |
+
<label for="editColor">Color:</label>
|
449 |
+
<input type="color" id="editColor" value="${body.render.fillStyle || '#ffffff'}">`;
|
450 |
+
if(body.elementType === "bouncingBall"){
|
451 |
+
const opts = body.customOptions;
|
452 |
+
html += `<label for="editBallRadius">Radius:</label>
|
453 |
+
<input type="number" id="editBallRadius" value="${opts.radius}">
|
454 |
+
<label for="editBallRestitution">Restitution:</label>
|
455 |
+
<input type="number" id="editBallRestitution" value="${opts.restitution}" step="0.1" min="0" max="1">
|
456 |
+
<label for="editBallFriction">Friction:</label>
|
457 |
+
<input type="number" id="editBallFriction" value="${opts.friction}" step="0.001" min="0" max="1">`;
|
458 |
+
} else if(body.elementType === "pendulum"){
|
459 |
+
const opts = body.customOptions;
|
460 |
+
html += `<label for="editPendulumPivotX">Pivot X:</label>
|
461 |
+
<input type="number" id="editPendulumPivotX" value="${opts.pivotX}">
|
462 |
+
<label for="editPendulumPivotY">Pivot Y:</label>
|
463 |
+
<input type="number" id="editPendulumPivotY" value="${opts.pivotY}">
|
464 |
+
<label for="editPendulumBobRadius">Bob Radius:</label>
|
465 |
+
<input type="number" id="editPendulumBobRadius" value="${opts.bobRadius}">
|
466 |
+
<label for="editPendulumLength">Length:</label>
|
467 |
+
<input type="number" id="editPendulumLength" value="${opts.pendulumLength}">
|
468 |
+
<label for="editPendulumStiffness">Stiffness:</label>
|
469 |
+
<input type="number" id="editPendulumStiffness" value="${opts.stiffness}" step="0.1" min="0" max="1">
|
470 |
+
<label for="editPendulumBobColor">Bob Color:</label>
|
471 |
+
<input type="color" id="editPendulumBobColor" value="${opts.bobColor}">`;
|
472 |
+
} else if(body.elementType === "projectile"){
|
473 |
+
const opts = body.customOptions;
|
474 |
+
html += `<label for="editProjectileRadius">Radius:</label>
|
475 |
+
<input type="number" id="editProjectileRadius" value="${opts.radius}">
|
476 |
+
<label for="editProjectileVelX">Velocity X:</label>
|
477 |
+
<input type="number" id="editProjectileVelX" value="${opts.velX}">
|
478 |
+
<label for="editProjectileVelY">Velocity Y:</label>
|
479 |
+
<input type="number" id="editProjectileVelY" value="${opts.velY}">`;
|
480 |
+
} else if(body.elementType === "inclinedPlane_ramp"){
|
481 |
+
const opts = body.customOptions;
|
482 |
+
html += `<label for="editRampWidth">Ramp Width:</label>
|
483 |
+
<input type="number" id="editRampWidth" value="${opts.rampWidth}">
|
484 |
+
<label for="editRampHeight">Ramp Height:</label>
|
485 |
+
<input type="number" id="editRampHeight" value="${opts.rampHeight}">
|
486 |
+
<label for="editRampAngle">Ramp Angle (°):</label>
|
487 |
+
<input type="number" id="editRampAngle" value="${opts.angleDeg}">
|
488 |
+
<label for="editRampX">Ramp X:</label>
|
489 |
+
<input type="number" id="editRampX" value="${opts.rampX}">
|
490 |
+
<label for="editRampY">Ramp Y:</label>
|
491 |
+
<input type="number" id="editRampY" value="${opts.rampY}">
|
492 |
+
<label for="editRampColor">Ramp Color:</label>
|
493 |
+
<input type="color" id="editRampColor" value="${opts.rampColor}">`;
|
494 |
+
} else if(body.elementType === "inclinedPlane_block"){
|
495 |
+
const opts = body.customOptions;
|
496 |
+
html += `<label for="editBlockWidth">Block Width:</label>
|
497 |
+
<input type="number" id="editBlockWidth" value="${opts.blockWidth}">
|
498 |
+
<label for="editBlockHeight">Block Height:</label>
|
499 |
+
<input type="number" id="editBlockHeight" value="${opts.blockHeight}">
|
500 |
+
<label for="editBlockFriction">Block Friction:</label>
|
501 |
+
<input type="number" id="editBlockFriction" value="${opts.blockFriction}" step="0.01" min="0" max="1">
|
502 |
+
<label for="editBlockColor">Block Color:</label>
|
503 |
+
<input type="color" id="editBlockColor" value="${opts.blockColor}">`;
|
504 |
+
} else if(body.elementType === "springMass"){
|
505 |
+
const opts = body.customOptions;
|
506 |
+
html += `<label for="editSpringMassRadius">Mass Radius:</label>
|
507 |
+
<input type="number" id="editSpringMassRadius" value="${opts.massRadius}">
|
508 |
+
<label for="editSpringMassRestitution">Restitution:</label>
|
509 |
+
<input type="number" id="editSpringMassRestitution" value="${opts.massRestitution}" step="0.1" min="0" max="1">
|
510 |
+
<label for="editFixedPointX">Fixed X:</label>
|
511 |
+
<input type="number" id="editFixedPointX" value="${opts.fixedPointX}">
|
512 |
+
<label for="editFixedPointY">Fixed Y:</label>
|
513 |
+
<input type="number" id="editFixedPointY" value="${opts.fixedPointY}">
|
514 |
+
<label for="editSpringLength">Spring Length:</label>
|
515 |
+
<input type="number" id="editSpringLength" value="${opts.springLength}">
|
516 |
+
<label for="editSpringStiffness">Spring Stiffness:</label>
|
517 |
+
<input type="number" id="editSpringStiffness" value="${opts.springStiffness}" step="0.01" min="0" max="1">
|
518 |
+
<label for="editSpringMassColor">Mass Color:</label>
|
519 |
+
<input type="color" id="editSpringMassColor" value="${opts.massColor}">`;
|
520 |
+
}
|
521 |
+
html += `<div style="margin-top:10px;">
|
522 |
+
<button id="updateElement">Update</button>
|
523 |
+
<button id="deleteElement">Delete</button>
|
524 |
+
</div>`;
|
525 |
+
editPanel.innerHTML = html;
|
526 |
+
editPanel.style.display = "block";
|
527 |
+
document.getElementById("updateElement").addEventListener("click", updateElementFromEditPanel);
|
528 |
+
document.getElementById("deleteElement").addEventListener("click", function(){
|
529 |
+
World.remove(world, selectedBody);
|
530 |
+
hideEditPanel();
|
531 |
+
});
|
532 |
+
}
|
533 |
+
function hideEditPanel() {
|
534 |
+
editPanel.style.display = "none";
|
535 |
+
selectedBody = null;
|
536 |
+
}
|
537 |
+
function updateElementFromEditPanel(){
|
538 |
+
if(!selectedBody) return;
|
539 |
+
const newX = parseFloat(document.getElementById("editPosX").value);
|
540 |
+
const newY = parseFloat(document.getElementById("editPosY").value);
|
541 |
+
const newAngle = parseFloat(document.getElementById("editAngle").value);
|
542 |
+
const newColor = document.getElementById("editColor").value;
|
543 |
+
Body.setPosition(selectedBody, { x: newX, y: newY });
|
544 |
+
Body.setAngle(selectedBody, newAngle);
|
545 |
+
selectedBody.render.fillStyle = newColor;
|
546 |
+
if(selectedBody.elementType === "bouncingBall"){
|
547 |
+
const oldRadius = selectedBody.circleRadius;
|
548 |
+
const newRadius = parseFloat(document.getElementById("editBallRadius").value);
|
549 |
+
const newRestitution = parseFloat(document.getElementById("editBallRestitution").value);
|
550 |
+
const newFriction = parseFloat(document.getElementById("editBallFriction").value);
|
551 |
+
if(newRadius && oldRadius && newRadius !== oldRadius){
|
552 |
+
const scaleFactor = newRadius / oldRadius;
|
553 |
+
Body.scale(selectedBody, scaleFactor, scaleFactor);
|
554 |
+
}
|
555 |
+
selectedBody.restitution = newRestitution;
|
556 |
+
selectedBody.friction = newFriction;
|
557 |
+
selectedBody.customOptions = { x: newX, y: newY, radius: newRadius, restitution: newRestitution, friction: newFriction, color: newColor };
|
558 |
+
}
|
559 |
+
// (Update code for other types as needed...)
|
560 |
+
hideEditPanel();
|
561 |
+
}
|
562 |
+
|
563 |
+
// Open edit panel on double–click on an element
|
564 |
+
render.canvas.addEventListener("dblclick", function(event){
|
565 |
+
const rect = render.canvas.getBoundingClientRect();
|
566 |
+
const mousePos = { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
567 |
+
const bodies = Matter.Composite.allBodies(world);
|
568 |
+
const clicked = Matter.Query.point(bodies, mousePos);
|
569 |
+
if(clicked.length > 0){
|
570 |
+
openEditPanel(clicked[0]);
|
571 |
+
} else {
|
572 |
+
hideEditPanel();
|
573 |
+
}
|
574 |
+
});
|
575 |
+
|
576 |
+
/* ---------- Constraint & Connection Panels (Same as previous example) ---------- */
|
577 |
+
document.getElementById('cancelConn').addEventListener('click', function(){
|
578 |
+
connectionPanel.style.display = "none";
|
579 |
+
attachMode = false;
|
580 |
+
attachFrom = null;
|
581 |
+
});
|
582 |
+
Events.on(mouseConstraint, 'mouseup', function(event){
|
583 |
+
const mousePos = event.mouse.position;
|
584 |
+
const bodies = Matter.Composite.allBodies(world);
|
585 |
+
const clickedBodies = Matter.Query.point(bodies, mousePos);
|
586 |
+
if(clickedBodies.length > 0){
|
587 |
+
const clickedBody = clickedBodies[0];
|
588 |
+
if(attachMode && attachFrom && clickedBody !== attachFrom){
|
589 |
+
const connType = document.getElementById('connType').value;
|
590 |
+
let sourceEndpoint = "mass";
|
591 |
+
if(attachFrom.elementType === "springMass"){
|
592 |
+
sourceEndpoint = document.getElementById('sourceEndpoint').value;
|
593 |
+
}
|
594 |
+
let targetEndpoint = "mass";
|
595 |
+
if(clickedBody.elementType === "springMass"){
|
596 |
+
targetEndpoint = prompt("Target springMass: 'fixed' ya 'mass' (default mass):", "mass") || "mass";
|
597 |
+
if(targetEndpoint !== "fixed") { targetEndpoint = "mass"; }
|
598 |
+
}
|
599 |
+
let pointA = { x: 0, y: 0 }, bodyA = attachFrom;
|
600 |
+
if(attachFrom.elementType === "springMass" && sourceEndpoint === "fixed"){
|
601 |
+
bodyA = null;
|
602 |
+
pointA = attachFrom.fixedPoint;
|
603 |
+
}
|
604 |
+
let pointB = { x: 0, y: 0 }, bodyB = clickedBody;
|
605 |
+
if(clickedBody.elementType === "springMass" && targetEndpoint === "fixed"){
|
606 |
+
bodyB = null;
|
607 |
+
pointB = clickedBody.fixedPoint || { x: clickedBody.position.x, y: clickedBody.position.y };
|
608 |
+
}
|
609 |
+
let posA = bodyA ? attachFrom.position : pointA;
|
610 |
+
let posB = bodyB ? clickedBody.position : pointB;
|
611 |
+
let dx = posB.x - posA.x, dy = posB.y - posA.y;
|
612 |
+
let length = Math.sqrt(dx*dx+dy*dy);
|
613 |
+
let stiffness = (connType === "spring") ? 0.05 : 1;
|
614 |
+
const newConstraint = Constraint.create({
|
615 |
+
bodyA: bodyA,
|
616 |
+
pointA: pointA,
|
617 |
+
bodyB: bodyB,
|
618 |
+
pointB: pointB,
|
619 |
+
length: length,
|
620 |
+
stiffness: stiffness,
|
621 |
+
render: { strokeStyle: '#000', lineWidth: 2 }
|
622 |
+
});
|
623 |
+
World.add(world, newConstraint);
|
624 |
+
attachMode = false;
|
625 |
+
attachFrom = null;
|
626 |
+
connectionPanel.style.display = "none";
|
627 |
+
alert("Attachment created using " + connType + " connection.");
|
628 |
+
}
|
629 |
+
} else {
|
630 |
+
const constraints = Matter.Composite.allConstraints(world);
|
631 |
+
for(let cons of constraints){
|
632 |
+
let posA = cons.bodyA ? { x: cons.bodyA.position.x + cons.pointA.x, y: cons.bodyA.position.y + cons.pointA.y } : cons.pointA;
|
633 |
+
let posB = cons.bodyB ? { x: cons.bodyB.position.x + cons.pointB.x, y: cons.bodyB.position.y + cons.pointB.y } : cons.pointB;
|
634 |
+
let dist = distanceToSegment(mousePos, posA, posB);
|
635 |
+
if(dist < 5){
|
636 |
+
showConstraintEditPanel(cons);
|
637 |
+
return;
|
638 |
+
}
|
639 |
+
}
|
640 |
+
hideConstraintEditPanel();
|
641 |
+
}
|
642 |
+
});
|
643 |
+
function distanceToSegment(p, v, w){
|
644 |
+
let l2 = (w.x-v.x)**2 + (w.y-v.y)**2;
|
645 |
+
if(l2 === 0) return Math.hypot(p.x-v.x, p.y-v.y);
|
646 |
+
let t = ((p.x-v.x)*(w.x-v.x) + (p.y-v.y)*(w.y-v.y)) / l2;
|
647 |
+
t = Math.max(0, Math.min(1, t));
|
648 |
+
let proj = { x: v.x + t*(w.x-v.x), y: v.y + t*(w.y-v.y) };
|
649 |
+
return Math.hypot(p.x-proj.x, p.y-proj.y);
|
650 |
+
}
|
651 |
+
const constraintEditPanel = document.getElementById('constraintEditPanel');
|
652 |
+
function showConstraintEditPanel(cons){
|
653 |
+
selectedConstraint = cons;
|
654 |
+
let posA = cons.bodyA ? { x: cons.bodyA.position.x + cons.pointA.x, y: cons.bodyA.position.y + cons.pointA.y } : cons.pointA;
|
655 |
+
let posB = cons.bodyB ? { x: cons.bodyB.position.x + cons.pointB.x, y: cons.bodyB.position.y + cons.pointB.y } : cons.pointB;
|
656 |
+
document.getElementById('consA_X').value = posA.x.toFixed(2);
|
657 |
+
document.getElementById('consA_Y').value = posA.y.toFixed(2);
|
658 |
+
document.getElementById('consB_X').value = posB.x.toFixed(2);
|
659 |
+
document.getElementById('consB_Y').value = posB.y.toFixed(2);
|
660 |
+
let connType = (cons.stiffness < 0.1) ? "spring" : "string";
|
661 |
+
document.getElementById('consType').value = connType;
|
662 |
+
constraintEditPanel.style.display = "block";
|
663 |
+
}
|
664 |
+
function hideConstraintEditPanel(){
|
665 |
+
constraintEditPanel.style.display = "none";
|
666 |
+
selectedConstraint = null;
|
667 |
+
}
|
668 |
+
document.getElementById('updateConstraint').addEventListener('click', function(){
|
669 |
+
if(selectedConstraint){
|
670 |
+
let aX = parseFloat(document.getElementById('consA_X').value);
|
671 |
+
let aY = parseFloat(document.getElementById('consA_Y').value);
|
672 |
+
let bX = parseFloat(document.getElementById('consB_X').value);
|
673 |
+
let bY = parseFloat(document.getElementById('consB_Y').value);
|
674 |
+
if(!selectedConstraint.bodyA) { selectedConstraint.pointA = { x: aX, y: aY }; }
|
675 |
+
if(!selectedConstraint.bodyB) { selectedConstraint.pointB = { x: bX, y: bY }; }
|
676 |
+
let connType = document.getElementById('consType').value;
|
677 |
+
selectedConstraint.stiffness = (connType === "spring") ? 0.05 : 1;
|
678 |
+
hideConstraintEditPanel();
|
679 |
+
}
|
680 |
+
});
|
681 |
+
document.getElementById('deleteConstraint').addEventListener('click', function(){
|
682 |
+
if(selectedConstraint){
|
683 |
+
World.remove(world, selectedConstraint);
|
684 |
+
hideConstraintEditPanel();
|
685 |
+
}
|
686 |
+
});
|
687 |
+
|
688 |
+
// Window resize event: update renderer and boundaries
|
689 |
+
window.addEventListener('resize', function(){
|
690 |
+
Render.lookAt(render, { min: { x: 0, y: 0 }, max: { x: window.innerWidth, y: window.innerHeight } });
|
691 |
+
updateBoundaries();
|
692 |
+
});
|
693 |
+
</script>
|
694 |
+
</body>
|
695 |
</html>
|