Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions .changeset/ui-button-pressed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@jolly-pixel/ui": minor
---

Add `pressed` to `jolly-button`, `count` to `jolly-tool-button` and `floating` to `jolly-rail`.
Export `FolderReorder`, the folder grip controller panes use. `jolly-folder` no longer toggles its own grab: its handler sets the new `grabbed` property.
1 change: 1 addition & 0 deletions packages/editors/scene/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ The `SceneDocument` of the target lease is the only state that is saved. Everyth
- `SelectionStore` follows the document: an actor that a command or a reset removes leaves the selection.
- Reparenting rewrites the moved actor's transform from the file data, so it keeps its world pose whatever the binding has drawn.
- The inspector forms are row descriptors in `components/componentForms.ts`, `Script` included. A row edit becomes a `component-changed` patch of one top-level field, unset when set back to its default. A nested field rewrites its whole object, as the room requires.
- Dragging a component folder by its grip, or moving it with the keyboard, commits one `component-moved` command on drop. The order lives in the document, never in pane storage. A gesture is cancelled when the component list changes under it.

## Collaboration

Expand Down
8 changes: 4 additions & 4 deletions packages/editors/scene/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
<jolly-editor-toolbar></jolly-editor-toolbar>
<section id="scene-viewport">
<canvas tabindex="-1"></canvas>
<div class="viewport-top-left">
<jolly-scene-view-toolbar></jolly-scene-view-toolbar>
<jolly-log></jolly-log>
</div>
<jolly-log></jolly-log>
<jolly-presence-stack selectable max="6" hidden></jolly-presence-stack>
<div class="viewport-toolbars">
<jolly-scene-toolbar></jolly-scene-toolbar>
</div>
</section>
</div>
<jolly-dock
Expand Down
15 changes: 10 additions & 5 deletions packages/editors/scene/public/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,24 @@ jolly-dock {
outline: none;
}

#scene-viewport .viewport-top-left {
#scene-viewport jolly-log {
position: absolute;
inset-block-start: 12px;
inset-inline-start: 16px;
z-index: 5;
}

#scene-viewport .viewport-toolbars {
position: absolute;
inset-block-end: 16px;
inset-inline: 16px;
z-index: 5;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 8px;
justify-content: center;
pointer-events: none;
}

#scene-viewport .viewport-top-left > * {
#scene-viewport .viewport-toolbars > * {
pointer-events: auto;
}

Expand Down
43 changes: 35 additions & 8 deletions packages/editors/scene/src/app/sceneIcons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,24 +248,51 @@ registerIcon("gizmo-scale", svg`
/>
`, { tone: "coral" });

registerIcon("move-up", svg`
registerIcon("gizmo-space-local", svg`
<path
d="M12 19V5M6 11l6-6 6 6"
class="tone-fill"
d="M12 3l8 4.5L12 12 4 7.5z"
/>
<path
d="M12 3l8 4.5v9L12 21l-8-4.5v-9zM4 7.5l8 4.5 8-4.5M12 12v9"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
/>
`, { tone: "sky" });
`, { tone: "amber" });

registerIcon("move-down", svg`
registerIcon("gizmo-space-world", svg`
<circle
class="tone-fill"
cx="12"
cy="12"
r="9"
/>
<path
d="M12 5v14M6 13l6 6 6-6"
d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0ZM3 12h18M12 3c2.5 2.4 3.8 5.4 3.8 9s-1.3 6.6-3.8 9M12 3c-2.5 2.4-3.8 5.4-3.8 9s1.3 6.6 3.8 9"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
/>
`, { tone: "sky" });
`, { tone: "teal" });

registerIcon("view-frame", svg`
<circle
class="tone-fill"
cx="12"
cy="12"
r="3.5"
/>
<path
d="M4 9V5a1 1 0 0 1 1-1h4M15 4h4a1 1 0 0 1 1 1v4M20 15v4a1 1 0 0 1-1 1h-4M9 20H5a1 1 0 0 1-1-1v-4M15.5 12a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
/>
`, { tone: "violet" });
2 changes: 1 addition & 1 deletion packages/editors/scene/src/boot/EditorShell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const kAttachedTags = [
"jolly-scene-hierarchy",
"jolly-scene-inspector",
"jolly-scene-environment",
"jolly-scene-view-toolbar"
"jolly-scene-toolbar"
] as const satisfies readonly (keyof HTMLElementTagNameMap)[];

export interface EditorShellOptions {
Expand Down
3 changes: 2 additions & 1 deletion packages/editors/scene/src/boot/SceneEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ export class SceneEditor {
context.preferences,
SCENE_KEYBINDINGS,
(message) => console.warn(message)
)
),
keyboardLayout: context.keyboardLayout
});
const { sceneManager } = editorRuntime.runtime.world;
teardown.defer(() => sceneManager.unloadScene(scene));
Expand Down
26 changes: 17 additions & 9 deletions packages/editors/scene/src/components/scriptProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,30 +95,38 @@ export function parseList(
}
}

export function freePropertyKey(
export function addProperty(
properties: Readonly<JSONObject>,
base = "property"
): string {
let key = base;
for (let suffix = 2; Object.hasOwn(properties, key); suffix++) {
key = `${base}${suffix}`;
key: string,
value: JSONValue
): JSONObject {
const trimmed = key.trim();
if (trimmed === "" || Object.hasOwn(properties, trimmed)) {
return { ...properties };
}

return key;
return {
...properties,
[trimmed]: value
};
}

export function renameProperty(
properties: Readonly<JSONObject>,
from: string,
to: string
): JSONObject {
if (from === to || Object.hasOwn(properties, to)) {
const trimmed = to.trim();
if (trimmed === "") {
return removeProperty(properties, from);
}
if (from === trimmed || Object.hasOwn(properties, trimmed)) {
return { ...properties };
}

return Object.fromEntries(
Object.entries(properties).map(
([key, value]) => [key === from ? to : key, value]
([key, value]) => [key === from ? trimmed : key, value]
)
);
}
Expand Down
3 changes: 3 additions & 0 deletions packages/editors/scene/src/editing/SceneEditing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import type {
SceneDocument,
SceneEnvironmentPatch
} from "@jolly-pixel/asset.scene/client";
import type { ShortcutLabels } from "@jolly-pixel/controls";

// Import Internal Dependencies
import type { SceneActions } from "./SceneActions.ts";
import type { SceneHistory } from "../features/history/sceneHistory.ts";
import type { GizmoSettings } from "../features/viewport/GizmoSettings.ts";
import type { SceneAction } from "../keybindings/sceneActions.ts";
import type { PresenceStore } from "../state/PresenceStore.ts";
import type { SelectionStore } from "../state/SelectionStore.ts";

Expand Down Expand Up @@ -39,6 +41,7 @@ export interface SceneEditing {
presence: PresenceStore;
gizmo: GizmoSettings;
assetSlots: SceneAssetSlots;
shortcuts: ShortcutLabels<SceneAction>;
frameSelection(): void;
previewEnvironment(
patch: SceneEnvironmentPatch
Expand Down
Loading
Loading