Chairs have no rotation controls (rotatable flag on configs)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ Layout and editing UI. No optimizer yet.
|
|||||||
|
|
||||||
**Editing (Phase 2)**
|
**Editing (Phase 2)**
|
||||||
- Click an item to select it (blue outline); click empty floor to deselect (Escape/Done too). Dragging still moves. Selecting opens the item panel in the sidebar (replaces tiles / type menu).
|
- Click an item to select it (blue outline); click empty floor to deselect (Escape/Done too). Dragging still moves. Selecting opens the item panel in the sidebar (replaces tiles / type menu).
|
||||||
- Item panel: Rotate 90 button + free angle wheel (0-359, wraps); Lock/Unlock; Delete (also Delete/Backspace key, ignored while typing in an input); "Seats at this table" wheel for tables (per-item override, "Reset to default" link when overridden); Size wheels (0.3-6 m, 0.1 steps; screens show only Length).
|
- Item panel (chairs have no rotation controls; every other type does): Rotate 90 button + free angle wheel (0-359, wraps); Lock/Unlock; Delete (also Delete/Backspace key, ignored while typing in an input); "Seats at this table" wheel for tables (per-item override, "Reset to default" link when overridden); Size wheels (0.3-6 m, 0.1 steps; screens show only Length).
|
||||||
- Rotation turns around the item's center and collision/wall clamping use the rotated bounding box (`boundsOf`). A rotate/size change is pushed back inside the walls, then rejected if it would overlap (`tryUpdate`).
|
- Rotation turns around the item's center and collision/wall clamping use the rotated bounding box (`boundsOf`). A rotate/size change is pushed back inside the walls, then rejected if it would overlap (`tryUpdate`).
|
||||||
- Locked items can't be dragged or rotated and show a padlock. (Size, seats and delete are still allowed on locked items.)
|
- Locked items can't be dragged or rotated and show a padlock. (Size, seats and delete are still allowed on locked items.)
|
||||||
- Delete frees inventory automatically (remaining is derived from `items`).
|
- Delete frees inventory automatically (remaining is derived from `items`).
|
||||||
@@ -54,6 +54,7 @@ interface FurnitureTypeConfig {
|
|||||||
id: FurnitureType; name: string; shape: Shape;
|
id: FurnitureType; name: string; shape: Shape;
|
||||||
defaultWidth: number; defaultHeight: number; // meters
|
defaultWidth: number; defaultHeight: number; // meters
|
||||||
isTable: boolean;
|
isTable: boolean;
|
||||||
|
rotatable: boolean; // chairs: false (no rotation controls)
|
||||||
available: number; // inventory count
|
available: number; // inventory count
|
||||||
seatsPerUnit?: number; // type-level seats
|
seatsPerUnit?: number; // type-level seats
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ export default function App() {
|
|||||||
defaultWidth: d.width,
|
defaultWidth: d.width,
|
||||||
defaultHeight: d.height,
|
defaultHeight: d.height,
|
||||||
isTable: d.isTable,
|
isTable: d.isTable,
|
||||||
|
rotatable: true,
|
||||||
available: d.available,
|
available: d.available,
|
||||||
seatsPerUnit: d.seats,
|
seatsPerUnit: d.seats,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export function ItemPanel({ item, config, onPatch, onDelete, onClose }: Props) {
|
|||||||
{item.locked ? " 🔒" : ""}
|
{item.locked ? " 🔒" : ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{config.rotatable && (
|
||||||
<div>
|
<div>
|
||||||
<div style={label}>Rotation</div>
|
<div style={label}>Rotation</div>
|
||||||
<Wheel
|
<Wheel
|
||||||
@@ -66,6 +67,7 @@ export function ItemPanel({ item, config, onPatch, onDelete, onClose }: Props) {
|
|||||||
Rotate 90°
|
Rotate 90°
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{config.isTable && (
|
{config.isTable && (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
+3
-3
@@ -19,9 +19,9 @@ export type Action =
|
|||||||
| { kind: "addConfig"; config: FurnitureTypeConfig };
|
| { kind: "addConfig"; config: FurnitureTypeConfig };
|
||||||
|
|
||||||
const BUILT_IN: FurnitureTypeConfig[] = [
|
const BUILT_IN: FurnitureTypeConfig[] = [
|
||||||
{ id: "chair", name: "Chair", shape: "chair", defaultWidth: 0.5, defaultHeight: 0.5, isTable: false, available: 20 },
|
{ id: "chair", name: "Chair", shape: "chair", defaultWidth: 0.5, defaultHeight: 0.5, isTable: false, rotatable: false, available: 20 },
|
||||||
{ id: "table", name: "Table", shape: "table", defaultWidth: 1.8, defaultHeight: 0.8, isTable: true, available: 6, seatsPerUnit: 8 },
|
{ id: "table", name: "Table", shape: "table", defaultWidth: 1.8, defaultHeight: 0.8, isTable: true, rotatable: true, available: 6, seatsPerUnit: 8 },
|
||||||
{ id: "screen", name: "Screen", shape: "screen", defaultWidth: 2, defaultHeight: 0.2, isTable: false, available: 2 },
|
{ id: "screen", name: "Screen", shape: "screen", defaultWidth: 2, defaultHeight: 0.2, isTable: false, rotatable: true, available: 2 },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const initialState: LayoutState = {
|
export const initialState: LayoutState = {
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export interface FurnitureTypeConfig {
|
|||||||
defaultWidth: number; // meters
|
defaultWidth: number; // meters
|
||||||
defaultHeight: number;
|
defaultHeight: number;
|
||||||
isTable: boolean;
|
isTable: boolean;
|
||||||
|
rotatable: boolean; // false = no rotation controls (chairs)
|
||||||
available: number; // inventory count
|
available: number; // inventory count
|
||||||
seatsPerUnit?: number; // type-level seats (tables, couches...)
|
seatsPerUnit?: number; // type-level seats (tables, couches...)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user