Skip to content

Commit

Permalink
Menu bar done
Browse files Browse the repository at this point in the history
  • Loading branch information
siddharthroy12 committed Jul 12, 2022
1 parent ee9a4d8 commit f2ce50d
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 61 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
## 1.3.0

- Added menu bar
- * Added saving and loading simulations
- * Added select and delete body tool
- * Added help and about
- Added saving and loading simulations
- Added select and delete body tool
- Added about
- Added few more shortcut keys
- Improved Performance

## 1.2.0

Expand Down
47 changes: 39 additions & 8 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@
File
<ul class="menu__list">
<li id="new">New<span class="shortcut">CTRL+M</span></li>
<li id="open">Open</li>
<li id="open">
Open
<ul class="sub-menu__list">
<li class="disabled">Empty</li>
</ul>
</li>
<li id="save">Save<span class="shortcut">CTRL+S</span></li>
</ul>
</div>
Expand All @@ -30,15 +35,12 @@
<ul class="menu__list">
<li id="undo">Undo<span class="shortcut">CTRL+Z</span></li>
<li id="redo">Redo<span class="shortcut">CTRL+Y</span></li>
<li id="redo">Delete Selected<span class="shortcut">Delete</span></li>
<li id="delete">Delete Selected<span class="shortcut">Delete</span></li>
</ul>
</div>
<div class="menu">
<div class="menu" id="about">
About
</div>
<div class="menu">
Help
</div>
<input type="text" id="filename" oninput="this.size = this.value.length" value="Untitled" size="8">
</div>
<canvas id="canvas" oncontextmenu="return false;"></canvas>
Expand Down Expand Up @@ -69,7 +71,6 @@
</div>
</div>
</div>

<div class="sliders-container">
<div class="sliders">
<div class="slider">
Expand All @@ -92,12 +93,42 @@
</div>
</div>
</div>
<div class="window hidden" id="about-window">
<span class="close-btn">Close</span>
<h2 style="text-align: center;">Gravity Sandbox</h2>
<p>
Gravity Sandbox is a fun toy/game where you can play with Newtonian Gravity
by placing heavy objects in patterns and see intersting results.
</p>
<h3>Controls</h3>
<p>
On the left side there are 5 buttons for Play/Pause, Place Mode, Pan Mode, Selection Mode,
Clear All, and Load Presets.
</p>
<p>
On the right side the <code>Mass</code> and <code>Color</code> properties are for
new bodies and <code>Speed</code> and <code>Gravity</code> are for simulation.
</p>
<h3>Shortcuts</h3>
<ul>
<li>Pause/Play: <code>space</code></li>
<li>Place Mode: <code>p</code></li>
<li>Pan Mode: <code>h</code></li>
<li>Selection Mode: <code>s</code></li>
<li>Clear All: <code>c</code></li>
<li>Undo: <code>CTRL + Z</code></li>
<li>Redo: <code>CTRL + Y</code></li>
<li>Delete Selection: <code>delete</code></li>
<li>New File: <code>CTRL + M</code></li>
<li>Save File: <code>CTRL + S</code></li>
</ul>
</div>
<div class="info-bar" id="info-bar"></div>
<div class="links">
<a href="https://github.com/siddharthroy12/Gravity-Sandbox" target="_blank">Source Code</a> |
<a href="https://twitter.com/reactoverflow" target="_blank">Author</a> |
<a href="https://github.com/siddharthroy12/Gravity-Sandbox/issues" target="_blank">Report a bug</a> |
<span>Version 1.3.1</span>
<span>Version 1.3.0</span>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
Expand Down
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
"preview": "vite preview"
},
"devDependencies": {
"vite": "^2.9.2"
"vite": "^2.9.2",
"typescript": "^4.7.4"
},
"author": "Siddharth Roy",
"license": "MIT",
"dependencies": {
"typescript": "^4.7.4"
}
"license": "MIT"
}
2 changes: 1 addition & 1 deletion public/service-worker.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const version = '1.3.1';
const version = '1.3.0';

const contentToCache = [
'/',
Expand Down
16 changes: 13 additions & 3 deletions src/Universe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ type History = {
export default class Universe {
bodies: Body[] = [];
previousPlacedCoords = {};
lastAddedBody = [];
lastRemovedBody = [];
undoHistory: History[] = [];
redoHistory: History[] = [];
selectedBodies = new WeakMap<Body, boolean>();
Expand Down Expand Up @@ -162,7 +160,19 @@ export default class Universe {

loadStateFromJSON(json: string) {
const state = JSON.parse(json);
this.bodies = state.bodies;
this.bodies = [];

state.bodies.forEach((body:Body) => {
const newBody = new Body(body.mass, body.color);
newBody.velocity.x = body.velocity.x;
newBody.velocity.y = body.velocity.y;
newBody.previousStates = body.previousStates;
this.addBody(newBody, body.position.x, body.position.y);
})

this.redoHistory = [];
this.undoHistory = [];

this.G = state.G;
}
}
136 changes: 96 additions & 40 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// Warning: spaghetti code
// TODO:
// finish menu bar
// Add save and load function
// add about
// add help
// Fix this spaghetti code

import './style.css'

Expand All @@ -15,17 +12,18 @@ import {
orbit, grid, infinity, circle, square, sinewave
} from './patterns';

type ModeType = "pan" | "selection" | "add" | "pan"

let autoPause = false;
let simulationRunning = false;
let startTime: number;
let simulationSpeed = 44;
let mode: "pan" | "selection" | "add" = "pan"
let mode: ModeType = "pan";
let nextColor = "random";
let nextMass = 10;
let bodyToFollow = null;
let isTouchDevice = false;
let filename = "Untitled";
let moveSvgString = new Blob(["hals"],{type: 'image/svg+xml'});

let U = new Universe();

Expand Down Expand Up @@ -72,7 +70,8 @@ function updateInfoBar() {
infoBar.innerText =
`Looking at : ${(cameraOffset.x+'').slice(0, 7)} ${(cameraOffset.y+'').slice(0, 7)} | ` +
`Zoom : ${(cameraZoom+'').slice(0, 4)} | ` +
`Bodies: ${U.bodies.length}`
`Bodies: ${U.bodies.length} | ` +
`Mode: ${mode.toUpperCase()}`
;
}

Expand Down Expand Up @@ -331,6 +330,43 @@ window.addEventListener('load', () => {
}

// Menu
const newFileMenu = document.getElementById('new');
const saveFileMenu = document.getElementById('save');
const openFileMenu = document.getElementById('open');
const undoMenu = document.getElementById('undo');
const redoMenu = document.getElementById('redo');
const deleteMenu = document.getElementById('delete');
const aboutMenu = document.getElementById('about');

// Update saved files list in menu
function updateSavedFilesList() {
const savedFiles = Object.keys(JSON.parse(localStorage.getItem("files")));

if (savedFiles.length) {
openFileMenu.getElementsByTagName("ul")[0].innerHTML = "";
savedFiles.forEach(file => {
const newLi = document.createElement("li")
newLi.innerHTML = file;
const deleteButton = document.createElement("span");
deleteButton.addEventListener('click', (e) => {
e.stopPropagation();
const files:any = JSON.parse(localStorage.getItem('files'));
delete files[file];
localStorage.setItem('files', JSON.stringify(files));
updateSavedFilesList();
})
deleteButton.innerHTML = "Delete";
newLi.appendChild(deleteButton);
newLi.addEventListener('click', () => load(file));
openFileMenu.getElementsByTagName("ul")[0].appendChild(newLi);
})
} else {
openFileMenu.getElementsByTagName("ul")[0].innerHTML = "<li class='disabled'>Empty</li>";
}
}

updateSavedFilesList();

function newFile() {
filename = "Untitled"
U.clear();
Expand All @@ -353,19 +389,24 @@ window.addEventListener('load', () => {
files[filename] = JSON.parse(U.getStateJSON());
files[filename].speed = simulationSpeed;
localStorage.setItem('files', JSON.stringify(files));
updateSavedFilesList();
}

function load(filename: string) {
function load(file: string) {
const files:any = JSON.parse(localStorage.getItem('files'));

if (files[filename] !== null) {
filename = filename;
simulationSpeed = files[filename].speed;
U.loadStateFromJSON(JSON.stringify(files[filename]));
if (files[file] !== null) {
console.log(file);
simulationSpeed = files[file].speed;
U.loadStateFromJSON(JSON.stringify(files[file]));
(gravityInput as HTMLInputElement).value = U.G+'';
(speedSlider as HTMLInputElement).value = simulationSpeed + '';
}

updateInfoBar();
filename = file;
(filenameInput as HTMLInputElement).value = filename
simulationRunning = false;
}

function undo() {
Expand All @@ -378,14 +419,19 @@ window.addEventListener('load', () => {
updateInfoBar();
}

const newFileMenu = document.getElementById('new');
const saveFileMenu = document.getElementById('save');
const undoMenu = document.getElementById('undo');
const redoMenu = document.getElementById('redo');
const aboutMenu = document.getElementById('about');
const helpMenu = document.getElementById('help');

newFileMenu.addEventListener('click', newFile);
saveFileMenu.addEventListener('click', save);
undoMenu.addEventListener('click', undo);
redoMenu.addEventListener('click', redo);
deleteMenu.addEventListener('click', () => U.deleteSelectedBodies());
function toggleAboutWindow() {
document.getElementById("about-window").classList.toggle("hidden");
}
aboutMenu.addEventListener('click', toggleAboutWindow);

document.getElementById("about-window")
.getElementsByClassName("close-btn")[0]
.addEventListener('click', toggleAboutWindow);

// Simulations
setOrbit.addEventListener('click',setPattern(orbit));
Expand Down Expand Up @@ -421,7 +467,7 @@ window.addEventListener('load', () => {
U.G = parseInt((e.target as HTMLInputElement).value)
})

filenameInput.addEventListener('filename', (e) => {
filenameInput.addEventListener('input', (e) => {
filename = (e.target as HTMLInputElement).value;
})

Expand All @@ -436,21 +482,44 @@ window.addEventListener('load', () => {
}
}

function switchMode(nextMode: ModeType) {
mode = nextMode;
switch (mode) {
case "pan":
document.getElementById("canvas")
.style.cursor = 'url("data:image/svg+xml;base64,' +
window.btoa(panBtn.innerHTML.trim()) + '") 12 12,auto';
break;
case "add":
document.getElementById('canvas').style.cursor = "none";
break;
case "selection":
document.getElementById('canvas').style.cursor = "default";
break;
}
updateInfoBar();
}

window.addEventListener('keydown', (e) => {
console.log(e)
if (e.key === " " || e.code === "Space") {
pausePlay();
} else if (e.key === "h" || e.code === "H") {
mode = "pan"
switchMode("pan")
} else if (e.key === "p" || e.code === "P") {
mode = "add"
switchMode("add");
} else if (e.key === "c" || e.code === "C") {
U.clear();
} else if (e.ctrlKey && (e.key === "z" || e.code === "Z")) {
e.preventDefault();
undo();
} else if (e.ctrlKey && (e.key === "y" || e.code === "Y")) {
e.preventDefault();
redo();
} else if (e.ctrlKey && (e.key === "s" || e.code === "S")) {
e.preventDefault();
save();
} else if (e.key === "s" || e.code === "S") {
switchMode("selection");
} else if (e.ctrlKey && (e.key === "m" || e.code === "M")) {
e.preventDefault();
newFile();
Expand All @@ -459,26 +528,13 @@ window.addEventListener('load', () => {
}
});

function changeCursorToSVG(svg: string) {
document.getElementById("canvas").style.cursor = 'url("data:image/svg+xml;base64,' + window.btoa(svg.trim()) + '"),auto'
}

playPauseBtn.addEventListener('click', pausePlay);
addBtn.addEventListener('click', () => {
mode = "add"
document.getElementById('canvas').style.cursor = "none";
});
panBtn.addEventListener('click', () => {
mode = "pan"
changeCursorToSVG(panBtn.innerHTML);
});
changeCursorToSVG(panBtn.innerHTML);
addBtn.addEventListener('click', () => switchMode("add"));
panBtn.addEventListener('click', () => switchMode("pan"));
clearBtn.addEventListener('click', () => { U.clear(); updateInfoBar(); bodyToFollow = null });
selectBtn.addEventListener('click', () => {
mode = "selection"
document.getElementById('canvas').style.cursor = "default";
});
selectBtn.addEventListener('click', () => switchMode("selection"));

switchMode("pan");

// Canvas zoon and pan
canvas.addEventListener('mousedown', (e) => { if (!isTouchDevice) { onPointerDown(e) }});
Expand Down
Loading

0 comments on commit f2ce50d

Please sign in to comment.