Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #59 Collisions #175

Merged
merged 50 commits into from
Sep 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
301f6fc
Initial integration of Matter JS.
amyjko Sep 10, 2023
d10a0e7
Removed unused type.
amyjko Sep 10, 2023
d55e9b1
Moved gravity to stage.
amyjko Sep 10, 2023
1c9907b
Moved mass, bouciness to Matter.
amyjko Sep 11, 2023
f4b43b5
Added optional rotation to Place.
amyjko Sep 11, 2023
754baf1
Default to place rotation if provided.
amyjko Sep 11, 2023
beb062d
Handle initial and future velocities.
amyjko Sep 11, 2023
6555ec7
Reactions only depend on condition value.
amyjko Sep 11, 2023
ebacbb4
Fixed tutorial references to motion.
amyjko Sep 11, 2023
d3e44f8
Set position when updated.
amyjko Sep 12, 2023
0b24dad
Matter-free = collision free, motion-free = static.
amyjko Sep 12, 2023
7666cdd
Cleaned up examples.
amyjko Sep 12, 2023
4fdb019
Encapsulated physics engine.
amyjko Sep 12, 2023
35be74a
Watch wordplay extensions.
amyjko Sep 12, 2023
8285270
Fixed move defect.
amyjko Sep 12, 2023
166625c
Removed extensions change, didn't work.
amyjko Sep 12, 2023
d7b0b91
Reflect size changes on bodies.
amyjko Sep 13, 2023
2df469b
Redesigned Motion API for common cases.
amyjko Sep 13, 2023
7da656f
Fine grained control over collisions with text, ground, and barriers.
amyjko Sep 13, 2023
2b437f7
Fixed several tutorial programs.
amyjko Sep 13, 2023
226b3bb
Position body on output move.
amyjko Sep 13, 2023
6ed7f7b
Wrap around list access index.
amyjko Sep 13, 2023
abd3f81
Wrap list access.
amyjko Sep 13, 2023
9c83c9b
Only include stage level outputs in physics.
amyjko Sep 13, 2023
6d8f233
Cleaned up Pounce.
amyjko Sep 13, 2023
fc49c9b
One engine for each z-layer.
amyjko Sep 14, 2023
d62ba69
Darker dark grey in dark mode.
amyjko Sep 14, 2023
acdaccc
Basic collision stream.
amyjko Sep 15, 2023
cdf16e8
Pounce tweaks.
amyjko Sep 15, 2023
4f5608e
Created Shape
amyjko Sep 16, 2023
872683b
Only one physics step per animation frame.
amyjko Sep 16, 2023
4466341
Pounce tweaks.
amyjko Sep 16, 2023
55c93d1
Apply color of shape to border.
amyjko Sep 16, 2023
2e959c2
Removed log.
amyjko Sep 16, 2023
8f3b8dd
Documentation for collisions.
amyjko Sep 16, 2023
0b20637
Clamp velocity.
amyjko Sep 16, 2023
45fe789
Fixed direction of fitting.
amyjko Sep 16, 2023
fe0bcf4
Collision tutorial, improved collision end.
amyjko Sep 16, 2023
b386212
Added roundedness to Matter.
amyjko Sep 16, 2023
f416dba
Fixed tooltip on full screen button, due to SVG.
amyjko Sep 16, 2023
6ef2ef0
Editable gravity.
amyjko Sep 16, 2023
f7f8f8a
Fixed Unit's denominator construction.
amyjko Sep 16, 2023
4cbe7d6
Shape editing on palette.
amyjko Sep 16, 2023
461cb51
Fixed defect in number value conversion.
amyjko Sep 16, 2023
501de4e
Add shape to content.
amyjko Sep 16, 2023
9c8292e
Add ground by default.
amyjko Sep 16, 2023
16ae6d0
Increase precision of size slider.
amyjko Sep 16, 2023
feffdc9
Fixed sign on pan.
amyjko Sep 16, 2023
339e5cd
Velocity editor.
amyjko Sep 16, 2023
43445e8
Basic placement editor.
amyjko Sep 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@sveltejs/kit": "^1",
"@testing-library/jest-dom": "^5",
"@testing-library/svelte": "^4",
"@types/matter-js": "^0.19.0",
"@types/uuid": "^9",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
Expand Down Expand Up @@ -83,6 +84,7 @@
"firebase": "^9",
"firebase-functions": "^4.4.1",
"graphemer": "^1.4.0",
"matter-js": "^0.19.0",
"pitchy": "^4.0.7",
"recoverable-random": "^1.0.3",
"uuid": "^9"
Expand Down
6 changes: 4 additions & 2 deletions src/components/concepts/ExampleUI.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import type Value from '../../values/Value';
import CodeView from './CodeView.svelte';
import { DB, locales } from '../../db/Database';
import Stage, { toStage } from '../../output/Stage';
import Stage, { NameGenerator, toStage } from '../../output/Stage';
import OutputView from '../output/OutputView.svelte';

export let example: Example;
Expand Down Expand Up @@ -44,7 +44,9 @@
function update() {
if (evaluator) {
value = evaluator.getLatestSourceValue(project.main);
stage = value ? toStage(project, value) : undefined;
stage = value
? toStage(project, value, new NameGenerator())
: undefined;
}
}

Expand Down
24 changes: 19 additions & 5 deletions src/components/output/GroupView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@
import Group from '@output/Group';
import Evaluate from '@nodes/Evaluate';
import { getSelectedOutput } from '../project/Contexts';
import type { Shape } from '../../output/Shapes';
import type Stage from '../../output/Stage';
import { locale, locales } from '../../db/Database';
import type { Form } from '../../output/Form';
import Shape from '../../output/Shape';
import ShapeView from './ShapeView.svelte';

export let group: Group | Stage;
export let place: Place;
export let focus: Place;
export let viewport: { width: number; height: number } | undefined =
undefined;
export let clip: Shape | undefined = undefined;
export let clip: Form | undefined = undefined;
export let interactive: boolean;
export let parentAscent: number;
export let context: RenderContext;
Expand Down Expand Up @@ -108,6 +110,17 @@
{editing}
{still}
/>
{:else if child instanceof Shape}
<ShapeView
shape={child}
place={childPlace}
focus={offsetFocus}
{interactive}
parentAscent={root ? 0 : layout.height}
{context}
{editing}
{still}
/>
{:else}
<svelte:self
group={child}
Expand All @@ -125,10 +138,11 @@
<svg
class="frame"
role="presentation"
width={clip.getWidth()}
height={clip.getHeight()}
width={clip.getWidth() * PX_PER_METER}
height={clip.getHeight() * PX_PER_METER}
xmlns="http://www.w3.org/2000/svg"
style="transform: translate({clip.getLeft()}px, {clip.getTop()}px)"
style="transform: translate({clip.getLeft() *
PX_PER_METER}px, {-clip.getTop() * PX_PER_METER}px)"
>
<path class="border" d={clip.toSVGPath()} />
</svg>
Expand Down
8 changes: 7 additions & 1 deletion src/components/output/OutputView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,17 @@
let startGesturePlace: Place | undefined = undefined;

$: exception = value instanceof ExceptionValue ? value : undefined;

/** Everyt ime the value changes, try to parse a Stage from it. */
$: stageValue = value === undefined ? undefined : toStage(project, value);

/** Keep track of whether the creator is typing, so we can blur output until the next change. */
$: typing =
!mini &&
$evaluation?.playing === true &&
$keyboardEditIdle === IdleKind.Typing;

/** Keep a background color up to date. */
$: background =
value instanceof ExceptionValue
? 'var(--wordplay-error)'
Expand Down Expand Up @@ -581,7 +587,7 @@
// Scale down the mouse delta and offset by the drag starting point.
stage.setFocus(
renderedDeltaX / scale + drag.startPlace.x,
-renderedDeltaY / scale + drag.startPlace.y,
renderedDeltaY / scale + drag.startPlace.y,
drag.startPlace.z
);
event.stopPropagation();
Expand Down
88 changes: 88 additions & 0 deletions src/components/output/ShapeView.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<script lang="ts">
import type Place from '@output/Place';
import {
getColorCSS,
getFaceCSS as getFaceCSS,
getSizeCSS as getSizeCSS,
getOpacityCSS,
toOutputTransform,
PX_PER_METER,
} from '@output/outputToCSS';
import type RenderContext from '@output/RenderContext';
import { locale, locales } from '../../db/Database';
import type Shape from '../../output/Shape';
import { Rectangle } from '../../output/Form';

export let shape: Shape;
export let place: Place;
export let focus: Place;
export let interactive: boolean;
export let parentAscent: number;
export let context: RenderContext;
export let editing: boolean;
export let still: boolean;

// Visible if z is ahead of focus and font size is greater than 0.
$: visible = place.z > focus.z;

$: selectable = shape.selectable;

$: width = shape.form.getWidth() * PX_PER_METER;
$: height = shape.form.getHeight() * PX_PER_METER;
</script>

{#if visible}
<div
role={selectable ? 'button' : 'presentation'}
aria-disabled={!selectable}
aria-label={still ? shape.getDescription($locales) : null}
aria-roledescription={!selectable ? $locale.term.phrase : null}
class="output shape {shape.form instanceof Rectangle
? 'rectangle'
: ''}"
tabIndex={interactive && (selectable || editing) ? 0 : null}
data-id={shape.getHTMLID()}
data-node-id={shape.value.creator.id}
data-name={shape.getName()}
data-selectable={selectable}
style:font-family={getFaceCSS(context.face)}
style:font-size={getSizeCSS(context.size)}
style:border-color={shape.getDefaultPose()?.color?.toCSS()}
style:background={shape.background?.toCSS() ?? null}
style:color={getColorCSS(shape.getFirstRestPose(), shape.pose)}
style:opacity={getOpacityCSS(shape.getFirstRestPose(), shape.pose)}
style:width="{width}px"
style:height="{height}px"
style:transform={toOutputTransform(
shape.getFirstRestPose(),
shape.pose,
place,
focus,
parentAscent,
{
width,
height,
ascent: height,
descent: 0,
}
)}
/>
{/if}

<style>
.shape {
position: absolute;
left: 0;
top: 0;
/* This disables translation around the center; we want to translate around the focus.*/
transform-origin: 0 0;
}

.shape.rectangle {
background: var(--wordplay-inactive-color);
border-radius: calc(2 * var(--wordplay-border-radius));
border-width: calc(2 * var(--wordplay-border-width));
border-style: solid;
border-color: transparent;
}
</style>
20 changes: 14 additions & 6 deletions src/components/output/StageView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
getEvaluation,
} from '../project/Contexts';
import type Evaluator from '@runtime/Evaluator';
import type TypeOutput from '../../output/TypeOutput';
import type Output from '../../output/Output';
import { animationFactor, locale, locales } from '../../db/Database';
import {
describeEnteredOutput,
Expand Down Expand Up @@ -91,10 +91,10 @@
}

let exiting: OutputInfoSet = new Map();
let entered: Map<string, TypeOutput> = new Map();
let present: Map<string, TypeOutput> = new Map();
let entered: Map<string, Output> = new Map();
let present: Map<string, Output> = new Map();
let moved: Moved = new Map();
let previouslyPresent: Map<string, TypeOutput> | undefined = undefined;
let previouslyPresent: Map<string, Output> | undefined = undefined;

const announcer = getAnnounce();

Expand Down Expand Up @@ -127,7 +127,9 @@
/** A stage to manage entries, exits, animations. A new one each time the for each project. */
let scene: Scene;
$: {
// Previous scene? Stop it.
if (scene !== undefined) scene.stop();
// Make a new one.
scene = new Scene(
evaluator,
// When output exits, remove it from the map and triggering a render.
Expand All @@ -154,7 +156,7 @@
$: editableStore.set(editable);
setContext('project', project);

/** Whenever the verse, languages, fonts, or rendered focus changes, update the rendered scene accordingly. */
/** Whenever the stage, languages, fonts, or rendered focus changes, update the rendered scene accordingly. */
$: {
const results = scene.update(
stage,
Expand Down Expand Up @@ -256,7 +258,7 @@
fitFocus = createPlace(
evaluator,
-(contentBounds.left + contentBounds.width / 2),
-contentBounds.top + contentBounds.height / 2,
contentBounds.top - contentBounds.height / 2,
z
);
// If we're currently fitting to content, just make the adjusted focus the same in case the setting is inactive.
Expand Down Expand Up @@ -458,4 +460,10 @@
background-color: var(--grid-color);
opacity: 0.4;
}

.rectangle-barrier {
position: absolute;
background: var(--wordplay-inactive-color);
border-radius: calc(var(--wordplay-border-radius) * 2);
}
</style>
23 changes: 21 additions & 2 deletions src/components/palette/ContentEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
value.is(
project.shares.output.Group,
project.getNodeContext(value)
) ||
value.is(
project.shares.output.Shape,
project.getNodeContext(value)
))
);

Expand Down Expand Up @@ -92,7 +96,7 @@
project,
list,
list?.values.length ?? 1 - 1,
true
'phrase'
)
: undefined}
>+{project.shares.output.Phrase.getNames()[0]}</Button
Expand All @@ -107,10 +111,25 @@
project,
list,
list?.values.length ?? 1 - 1,
false
'group'
)
: undefined}
>+{project.shares.output.Group.getNames()[0]}</Button
>
<Button
tip={$locale.ui.palette.button.addShape}
active={editable}
action={() =>
list
? addContent(
DB,
project,
list,
list?.values.length ?? 1 - 1,
'shape'
)
: undefined}
>+{project.shares.output.Shape.getNames()[0]}</Button
></div
>
{:else}
Expand Down
Loading