Skip to content

Commit

Permalink
Implement settings dialog for examples (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
DrA1ex committed Sep 30, 2023
1 parent ba0f4eb commit 418c5bb
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 60 deletions.
5 changes: 5 additions & 0 deletions examples/collision/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
<head>
<meta charset="UTF-8">
<title>physics.js: Collision Demo</title>
<link href="../common/styles/common.css" rel="stylesheet">
<link href="../common/styles/themes/white.css" rel="stylesheet">
<link href="./style.css" rel="stylesheet">
</head>
<body>
<canvas id="canvas"></canvas>

<button id="settings-button" class="settings-button icon-btn"><div></div></button>
<div id="settings" class="settings-dialog"><div id="settings-content"></div></div>
</body>
<script type="module" src="index.js"></script>
</html>
19 changes: 11 additions & 8 deletions examples/collision/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import {InsetConstraint} from "../../lib/physics/constraint.js";
import {CanvasRenderer} from "../../lib/render/renderer/canvas/renderer.js";
import {Vector2} from "../../lib/utils/vector.js";
import {Bootstrap, State} from "../common/bootstrap.js";
import * as Params from "../common/params.js";
import * as Utils from "../common/utils.js";
import {CommonBootstrapSettings, CommonSettings} from "../common/settings/default.js";
import {SettingsController} from "../common/ui/controllers/settings.js";

delete CommonSettings.Properties.resistance;
delete CommonSettings.Properties.gravity;
const Settings = CommonBootstrapSettings.fromQueryParams({bias: 0.1});
const settingsCtrl = SettingsController.defaultCtrl(Settings);

const options = Params.parse()
const BootstrapInstance = new Bootstrap(
new CanvasRenderer(document.getElementById("canvas"), options),
Object.assign({solverBias: 0.1}, options)
);
new CanvasRenderer(document.getElementById("canvas"), Settings.renderer), Settings);
settingsCtrl.subscribe(this, SettingsController.RECONFIGURE_EVENT, SettingsController.defaultReconfigure(BootstrapInstance));

const WorldRect = new BoundaryBox(0, BootstrapInstance.canvasWidth, 0, BootstrapInstance.canvasHeight);
BootstrapInstance.addConstraint(new InsetConstraint(WorldRect, 0.3));
Expand All @@ -35,7 +39,7 @@ for (let i = 0; i < count; i++) {
}

BootstrapInstance.addRigidBody(
body.setFriction(options.friction)
body.setFriction(Settings.common.friction)
.setRestitution(Math.random())
.setMass(1 + Math.random() * 5)
);
Expand All @@ -49,13 +53,12 @@ BootstrapInstance.enableHotKeys();
BootstrapInstance.run();

const timeout = 1000 / 60;
const delta = timeout / 1000 * options.slowMotion;
const delta = timeout / 1000 * Settings.solver.slowMotion;
setInterval(() => {
if (BootstrapInstance.state !== State.play) {
return;
}

const count = BootstrapInstance.rigidBodies.length;
if (rotatingBody._angle === undefined) {
rotatingBody._angle = 0;
rotatingBody._position = rotatingBody.position.copy();
Expand Down
5 changes: 5 additions & 0 deletions examples/collision2/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
<head>
<meta charset="UTF-8">
<title>physics.js: Collision 2 Demo</title>
<link href="../common/styles/common.css" rel="stylesheet">
<link href="../common/styles/themes/white.css" rel="stylesheet">
<link href="./style.css" rel="stylesheet">
</head>
<body>
<canvas id="canvas"></canvas>

<button id="settings-button" class="settings-button icon-btn"><div></div></button>
<div id="settings" class="settings-dialog"><div id="settings-content"></div></div>
</body>
<script type="module" src="index.js"></script>
</html>
18 changes: 12 additions & 6 deletions examples/collision2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ import {InsetConstraint} from "../../lib/physics/constraint.js";
import {CanvasRenderer} from "../../lib/render/renderer/canvas/renderer.js";
import {Vector2} from "../../lib/utils/vector.js";
import {Bootstrap} from "../common/bootstrap.js";
import * as Params from "../common/params.js";
import {CommonBootstrapSettings, CommonSettings} from "../common/settings/default.js";
import {SettingsController} from "../common/ui/controllers/settings.js";

delete CommonSettings.Properties.resistance;
delete CommonSettings.Properties.gravity;
const Settings = CommonBootstrapSettings.fromQueryParams({restitution: 1, bias: 0.1});
const settingsCtrl = SettingsController.defaultCtrl(Settings);

const options = Params.parse({restitution: 1});
const BootstrapInstance = new Bootstrap(
new CanvasRenderer(document.getElementById("canvas"), options),
Object.assign({solverBias: 0.01}, options)
new CanvasRenderer(document.getElementById("canvas"), Settings.renderer),
Settings,
);
settingsCtrl.subscribe(this, SettingsController.RECONFIGURE_EVENT, SettingsController.defaultReconfigure(BootstrapInstance));

const WorldRect = new BoundaryBox(0, BootstrapInstance.canvasWidth, 0, BootstrapInstance.canvasHeight);
BootstrapInstance.addConstraint(new InsetConstraint(WorldRect, 0.3));
Expand All @@ -37,8 +43,8 @@ BootstrapInstance.addRigidBody(new CircleBody(center.x + distance * 2, center.y
BootstrapInstance.addRigidBody(new CircleBody(center.x - distance * 2, center.y - distance + 1, size / 2).setVelocity(new Vector2(speed, 0)));

for (const body of BootstrapInstance.rigidBodies) {
body.setFriction(options.friction);
body.setRestitution(options.restitution);
body.setFriction(Settings.common.friction);
body.setRestitution(Settings.common.restitution);
}

BootstrapInstance.enableHotKeys();
Expand Down
3 changes: 2 additions & 1 deletion examples/common/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class Bootstrap {
constructor(renderer, options = {}) {
this.#renderer = renderer;

this.#slowMotion = Math.max(0.01, Math.min(2, options.slowMotion ?? 1));
this.#slowMotion = 1;

this.#particleSystem = new ParticleSystem();
this.#particleSystem.onParticleCreated.subscribe(this, this.#addParticle.bind(this));
Expand All @@ -122,6 +122,7 @@ export class Bootstrap {
if (Number.isFinite(options.solver?.overlap)) this.#solver.allowedOverlap = options.solver.overlap;
if (Number.isFinite(options.solver?.treeDivider)) this.#solver.treeDivider = options.solver.treeDivider;
if (Number.isFinite(options.solver?.treeMaxCount)) this.#solver.treeMaxCount = options.solver.treeMaxCount;
if (Number.isFinite(options.solver?.slowMotion)) this.#slowMotion = options.solver.slowMotion;
if (options.solver?.warming !== undefined) this.#solver.warming = options.solver.warming;

this.#debug = options.debug?.debug ?? false;
Expand Down
38 changes: 38 additions & 0 deletions examples/common/settings/default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {AppSettingsBase, Property, SettingsBase, SettingsGroup} from "./base.js";
import {RenderConfigGroup} from "./renderer.js";
import {SolverConfigGroup} from "./solver.js";
import {DebugConfigGroup} from "./debug.js";

export class DefaultBootstrapSettings extends AppSettingsBase {
static Types = {
...RenderConfigGroup,
...SolverConfigGroup,
...DebugConfigGroup,
}
}

export class CommonSettings extends SettingsBase {
static Properties = {
gravity: Property.float("resistance", 100)
.setName("Gravity")
.setConstraints(-10000, 10000),
resistance: Property.float("resistance", 1)
.setName("Resistance")
.setConstraints(0, 1),
friction: Property.float("friction", 0.5)
.setName("Friction")
.setConstraints(0, 1),
restitution: Property.float("restitution", 0.2)
.setName("Restitution")
.setConstraints(0, 1),
}
}

export class CommonBootstrapSettings extends AppSettingsBase {
static Types = {
common: SettingsGroup.of(CommonSettings).setName("Common"),
...RenderConfigGroup,
...SolverConfigGroup,
...DebugConfigGroup,
}
}
3 changes: 3 additions & 0 deletions examples/common/settings/solver.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export class SolverSettings extends SettingsBase {
steps: Property.int("steps", 6)
.setName("Steps")
.setConstraints(1, 20),
slowMotion: Property.float("slow_motion", 1)
.setName("Slow motion")
.setConstraints(0.01, 1),
bias: Property.float("bias", 0.2)
.setName("Velocity bias")
.setConstraints(0, 1),
Expand Down
File renamed without changes.
83 changes: 83 additions & 0 deletions examples/common/styles/themes/white.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
body {
color: #555;
background: #ece9e9 linear-gradient(180deg, #fff, #ece9e9) no-repeat;
}

button {
border: 0.1em solid black;
color: black;
}

button:hover {
background: rgba(155, 155, 155, 0.1);
}

button:active {
background: rgba(110, 110, 110, 0.2);
}

input[type=text] {
color: black;
border-bottom: 0.1em solid #606060;
}

input[type=text]:disabled {
color: #606060;
}

input[type=checkbox] {
border: 0.1em solid #606060;
}

input[type=checkbox]::before {
background: #606060;
}

.dialog {
background: white;
border: 0.1rem solid rgba(90, 90, 90, 0.5);
}

.dialog .dialog-caption {
border-bottom: 0.1rem solid #606060;
}

[data-tooltip]:before {
background: #f3f3f3;
}

.dialog button.dialog-close {
border: 0.1em solid #606060;
}

.settings-button {
position: absolute;
right: 1em;
bottom: 1em;
}

.settings-dialog .dialog {
padding: 0 1em 1em 1em;
box-sizing: border-box;
max-height: calc(100vh - 1em);
max-width: max(40vw, 400px);
}

.settings-dialog .dialog-close.settings-close {
position: absolute;
right: 0;
border: none;
}

.settings-close > img {
width: 1.5em;
height: 1.5em;
}

.settings-dialog .settings-dialog-caption {
position: sticky;
top: 0;
background: white;
z-index: 1;
padding-top: 0.5em;
}
44 changes: 44 additions & 0 deletions examples/common/ui/controllers/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,57 @@ import {Checkbox} from "../controls/checkbox.js";
import {Label} from "../controls/label.js";

import view from "./views/settings.js";
import {Dialog, DialogPositionEnum, DialogTypeEnum} from "../controls/dialog.js";
import {Button} from "../controls/button.js";
import * as Utils from "../../utils.js";

/**
* @template {AppSettingsBase} SettingsT
*/
export class SettingsController extends ControllerBase {
static RECONFIGURE_EVENT = "start_recording";

/**
* @param {SettingsT} settings
* @param contentId
* @param buttonId
* @param type
* @param position
* @return {SettingsController}
*/
static defaultCtrl(settings, {
contentId = "settings-content", buttonId = "settings-button",
type = DialogTypeEnum.popover,
position = DialogPositionEnum.right
} = {}) {
const settingsCtrl = new SettingsController(document.getElementById(contentId), this);
const settingsDialog = Dialog.byId("settings", settingsCtrl.root);

settingsDialog.type = type;
settingsDialog.position = position;

settingsCtrl.configure(settings);

const bSettings = Button.byId(buttonId);
bSettings.setOnClick(() => {
bSettings.setEnabled(false);
settingsDialog.show();
})

settingsDialog.setOnDismissed(() => {
bSettings.setEnabled(true);
});

return settingsCtrl;
}

static defaultReconfigure(bootstrap) {
return function (_, newSettings) {
Utils.updateUrl(newSettings);
bootstrap.configure(newSettings);
}
}

/** @type {SettingsT} */
settings;
/** @type {{[string]: {[string]: InputControl}}} */
Expand Down
5 changes: 5 additions & 0 deletions examples/crusher/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
<head>
<meta charset="UTF-8">
<title>physics.js: Crusher Demo</title>
<link href="../common/styles/common.css" rel="stylesheet">
<link href="../common/styles/themes/white.css" rel="stylesheet">
<link href="./style.css" rel="stylesheet">
</head>
<body>
<canvas id="canvas"></canvas>

<button id="settings-button" class="settings-button icon-btn"><div></div></button>
<div id="settings" class="settings-dialog"><div id="settings-content"></div></div>
</body>
<script type="module" src="index.js"></script>
</html>
23 changes: 13 additions & 10 deletions examples/crusher/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import {CanvasRenderer} from "../../lib/render/renderer/canvas/renderer.js";
import * as GeomUtils from "../../lib/utils/geom.js";
import {Vector2} from "../../lib/utils/vector.js";
import {Bootstrap, State} from "../common/bootstrap.js";
import * as Params from "../common/params.js";
import * as Utils from "../common/utils.js";
import {CommonBootstrapSettings} from "../common/settings/default.js";
import {SettingsController} from "../common/ui/controllers/settings.js";


const options = Params.parse({g: 500, steps: 20, bias: 0.1, beta: 0.8});
const BootstrapInstance = new Bootstrap(new CanvasRenderer(document.getElementById("canvas"), options), options);
const Settings = CommonBootstrapSettings.fromQueryParams({gravity: 500, steps: 20, bias: 0.1, beta: 0.8});
const settingsCtrl = SettingsController.defaultCtrl(Settings);
const BootstrapInstance = new Bootstrap(new CanvasRenderer(document.getElementById("canvas"), Settings.renderer), Settings);
settingsCtrl.subscribe(this, SettingsController.RECONFIGURE_EVENT, SettingsController.defaultReconfigure(BootstrapInstance));

const {canvasWidth, canvasHeight} = BootstrapInstance;
const {canvasWidth, canvasHeight} = BootstrapInstance.renderer;
const yOffset = 20;

const crusherWidth = 100;
Expand All @@ -33,8 +36,8 @@ const WorldRect = new BoundaryBox(0, BootstrapInstance.canvasWidth, 0, Bootstrap
BootstrapInstance.addConstraint(new InsetConstraint(WorldRect, 0.3));
BootstrapInstance.addRect(WorldRect)

BootstrapInstance.addForce(new GravityForce(options.gravity));
BootstrapInstance.addForce(new ResistanceForce(options.resistance));
BootstrapInstance.addForce(new GravityForce(Settings.common.gravity));
BootstrapInstance.addForce(new ResistanceForce(Settings.common.resistance));

const floor = BootstrapInstance.addRigidBody(new RectBody(canvasWidth / 2, yOffset + canvasHeight - crusherWidth / 2, canvasWidth, crusherWidth).setActive(false))
floor.renderer.fill = true;
Expand All @@ -61,8 +64,8 @@ for (const crusher of crushers) {
}

for (const body of BootstrapInstance.rigidBodies) {
body.setFriction(options.friction);
body.setRestitution(options.restitution);
body.setFriction(Settings.common.friction);
body.setRestitution(Settings.common.restitution);
}


Expand All @@ -86,8 +89,8 @@ for (let i = 0; i < trashCount; i++) {
const size = trashMinSize + Math.random() * (trashMaxSize - trashMinSize);
const vertexCount = Math.floor(3 + Math.random() * 5);
const body = Utils.createRegularPoly(new Vector2(canvasWidth / 2, canvasHeight / 2), vertexCount, size)
.setFriction(options.friction)
.setRestitution(options.restitution);
.setFriction(Settings.common.friction)
.setRestitution(Settings.common.restitution);

setTimeout(() => BootstrapInstance.addRigidBody(body), delta * i);
}
Loading

0 comments on commit 418c5bb

Please sign in to comment.