auto-git:

[change] src/app/App.tsx
 [change] src/app/editor-store.ts
 [change] src/document/migrate-scene-document.ts
 [change] src/document/scene-document.ts
 [change] src/viewport-three/ViewportCanvas.tsx
 [change] src/viewport-three/viewport-host.ts
This commit is contained in:
2026-03-31 01:30:33 +02:00
parent 3af579c6bb
commit efb706a0f3
6 changed files with 20 additions and 8 deletions

View File

@@ -1,6 +1,7 @@
import { useEffect, useRef, useState } from "react";
import { useEffect, useRef, useState, type ChangeEvent } from "react";
import { createSetSceneNameCommand } from "../commands/set-scene-name-command";
import type { EditorSelection } from "../core/selection";
import { Panel } from "../shared-ui/Panel";
import { ViewportCanvas } from "../viewport-three/ViewportCanvas";
import type { EditorStore } from "./editor-store";
@@ -10,7 +11,7 @@ interface AppProps {
store: EditorStore;
}
function describeSelection(selectionKind: string): string {
function describeSelection(selectionKind: EditorSelection["kind"]): string {
switch (selectionKind) {
case "none":
return "No authored selection yet";
@@ -87,7 +88,7 @@ export function App({ store }: AppProps) {
importInputRef.current?.click();
};
const handleImportChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
const handleImportChange = async (event: ChangeEvent<HTMLInputElement>) => {
const file = event.currentTarget.files?.[0];
if (file === undefined) {

View File

@@ -123,6 +123,7 @@ export class EditorStore {
replaceDocument(document: SceneDocument, resetHistory = true) {
this.document = document;
this.selection = { kind: "none" };
this.toolMode = "select";
if (resetHistory) {
this.history.clear();

View File

@@ -30,6 +30,14 @@ function expectHexColor(value: unknown, label: string): string {
return normalizedValue;
}
function expectLiteralString<T extends string>(value: unknown, expectedValue: T, label: string): T {
if (value !== expectedValue) {
throw new Error(`${label} must be ${expectedValue}.`);
}
return expectedValue;
}
function expectEmptyCollection(value: unknown, label: string): Record<string, never> {
if (!isRecord(value)) {
throw new Error(`${label} must be a record.`);
@@ -71,7 +79,7 @@ function readWorldSettings(value: unknown): WorldSettings {
return {
background: {
mode: "solid",
mode: expectLiteralString(background.mode, "solid", "world.background.mode"),
colorHex: expectHexColor(background.colorHex, "world.background.colorHex")
},
ambientLight: {

View File

@@ -50,7 +50,9 @@ export function createDefaultWorldSettings(): WorldSettings {
sunLight: {
colorHex: "#fff1d5",
intensity: 1.75,
direction: DEFAULT_SUN_DIRECTION
direction: {
...DEFAULT_SUN_DIRECTION
}
}
};
}

View File

@@ -21,7 +21,8 @@ export function ViewportCanvas({ world }: ViewportCanvasProps) {
const viewportHost = new ViewportHost();
hostRef.current = viewportHost;
viewportHost.mount(container, world);
viewportHost.mount(container);
viewportHost.updateWorld(world);
return () => {
viewportHost.dispose();

View File

@@ -36,10 +36,9 @@ export class ViewportHost {
this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
}
mount(container: HTMLElement, world: WorldSettings) {
mount(container: HTMLElement) {
this.container = container;
container.appendChild(this.renderer.domElement);
this.updateWorld(world);
this.resize();
this.resizeObserver = new ResizeObserver(() => {