diff --git a/src/editor/configs/voidstrike.ts b/src/editor/configs/voidstrike.ts
index fcb75de3..2bc5f367 100644
--- a/src/editor/configs/voidstrike.ts
+++ b/src/editor/configs/voidstrike.ts
@@ -644,13 +644,14 @@ export const VOIDSTRIKE_THEME: UIThemeConfig = {
// ============================================
export const VOIDSTRIKE_PANELS: PanelConfig[] = [
- { id: 'ai', name: 'AI', icon: '🪄', type: 'ai' },
- { id: 'paint', name: 'Paint', icon: '🖌', type: 'paint' },
+ { id: 'paint', name: 'Paint', icon: '🎨', type: 'paint' },
{ id: 'bases', name: 'Bases', icon: '🏠', type: 'objects' },
- { id: 'objects', name: 'Objects', icon: '🪨', type: 'objects' },
+ { id: 'objects', name: 'Obj', icon: '📦', type: 'objects' },
{ id: 'decorations', name: 'Decor', icon: '🌲', type: 'objects' },
- { id: 'settings', name: 'Settings', icon: '⚙', type: 'settings' },
- { id: 'validate', name: 'Validate', icon: '✓', type: 'validate' },
+ { id: 'selected', name: 'Edit', icon: '✎', type: 'selected' },
+ { id: 'settings', name: 'Set', icon: '⚙', type: 'settings' },
+ { id: 'ai', name: 'AI', icon: '✨', type: 'ai' },
+ { id: 'validate', name: 'Val', icon: '✓', type: 'validate' },
];
// ============================================
diff --git a/src/editor/core/EditorPanels.tsx b/src/editor/core/EditorPanels.tsx
index 25e83d14..4c2a1e04 100644
--- a/src/editor/core/EditorPanels.tsx
+++ b/src/editor/core/EditorPanels.tsx
@@ -155,36 +155,40 @@ function Section({
);
}
-// Modern panel tab with animated indicator
+// Modern panel tab with animated indicator - compact design
function PanelTab({
active,
onClick,
icon,
name,
theme,
+ hasContent,
}: {
active: boolean;
onClick: () => void;
icon?: string;
name: string;
theme: EditorConfig['theme'];
+ hasContent?: boolean;
}) {
return (
);
}
@@ -1530,8 +1533,51 @@ function ScaleControl({
);
}
+// Selected panel - wrapper with empty state
+function SelectedPanel({
+ config,
+ state,
+ onPropertyUpdate,
+ onRemove,
+}: {
+ config: EditorConfig;
+ state: EditorState;
+ onPropertyUpdate: (id: string, key: string, value: unknown) => void;
+ onRemove: (id: string) => void;
+}) {
+ const theme = config.theme;
+
+ if (state.selectedObjects.length === 0 || !state.mapData) {
+ return (
+
+
+ ✎
+
+
+ No Object Selected
+
+
+ Click on an object in the map to select it and edit its properties here
+
+
+ );
+ }
+
+ return (
+
+ );
+}
+
// Selected object properties panel with enhanced UI
-function SelectedObjectPanel({
+function SelectedObjectPanelContent({
config,
state,
onPropertyUpdate,
@@ -1564,10 +1610,7 @@ function SelectedObjectPanel({
const currentScale = (selectedObj.properties?.scale as number) ?? scaleProp?.defaultValue ?? 1;
return (
-
+
{/* Header */}
@@ -1848,6 +1891,7 @@ export function EditorPanels({
icon={panel.icon}
name={panel.name}
theme={theme}
+ hasContent={panel.id === 'selected' ? state.selectedObjects.length > 0 : undefined}
/>
))}
@@ -1900,6 +1944,14 @@ export function EditorPanels({
onObjectRemove={onObjectRemove}
/>
+
+
+
- {/* Selected object properties */}
-
-
{/* Keyboard shortcuts footer */}
diff --git a/src/editor/rendering3d/EditorModelLoader.ts b/src/editor/rendering3d/EditorModelLoader.ts
index 02cff4c9..9127c750 100644
--- a/src/editor/rendering3d/EditorModelLoader.ts
+++ b/src/editor/rendering3d/EditorModelLoader.ts
@@ -103,8 +103,9 @@ let initPromise: Promise
| null = null;
/**
* Normalize a model: scale to target height and ground to y=0
+ * This matches how the game's AssetManager handles model scaling.
*/
-function normalizeModel(root: THREE.Object3D, scale: number, rotationY: number = 0): void {
+function normalizeModel(root: THREE.Object3D, targetScale: number, rotationY: number = 0): void {
root.updateMatrixWorld(true);
const box = new THREE.Box3().setFromObject(root);
@@ -112,9 +113,11 @@ function normalizeModel(root: THREE.Object3D, scale: number, rotationY: number =
const size = box.getSize(new THREE.Vector3());
- // Apply scale
+ // Normalize to unit height first, then multiply by target scale
+ // This ensures model height equals targetScale in world units
if (size.y > 0.001) {
- root.scale.setScalar(scale);
+ const normalizeScale = targetScale / size.y;
+ root.scale.setScalar(normalizeScale);
}
// Apply base rotation