mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-05 14:19:04 +00:00
+65
-1
@@ -28,7 +28,7 @@
|
||||
* colour, so a plan stays a drawing (owner: «символы рисуются линейно»).
|
||||
*/
|
||||
|
||||
import { NORM_W, GRID_PITCH, CANVAS_LIMIT } from './space-geometry';
|
||||
import { NORM_W, GRID_PITCH, CANVAS_LIMIT, clampCanvasN } from './space-geometry';
|
||||
import { GENERATED_FURNITURE_PLAN } from './furniture-plan-art.generated';
|
||||
|
||||
/** Groups the palette shows, in the order it shows them. */
|
||||
@@ -395,6 +395,33 @@ export interface FurnitureSnap {
|
||||
/** Wall segments (`[x1,y1,x2,y2]`) in whatever units the caller works in. */
|
||||
export type WallSeg = number[];
|
||||
|
||||
/** Final normalised box shared by the placement ghost and the saved decor
|
||||
* record. Keeping this result pure prevents a preview/commit jump when wall
|
||||
* magnetism or the canvas guard participates (#359). */
|
||||
export interface FurniturePlacement {
|
||||
symbol: string;
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
angle: number;
|
||||
}
|
||||
|
||||
export interface FurniturePlacementInput {
|
||||
symbol: string;
|
||||
widthCm: number;
|
||||
depthCm: number;
|
||||
/** Already resolved decor/grid snap point, in render units. */
|
||||
point: readonly [number, number];
|
||||
canvasW: number;
|
||||
canvasH: number;
|
||||
cellCm: number;
|
||||
gridPitch: number;
|
||||
walls: WallSeg[];
|
||||
wallReach: number;
|
||||
free?: boolean;
|
||||
}
|
||||
|
||||
const norm180 = (a: number): number => {
|
||||
let x = ((a % 360) + 360) % 360;
|
||||
if (x > 180) x -= 360;
|
||||
@@ -458,6 +485,43 @@ export function snapFurnitureToWall(
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the exact geometry one furniture stamp will own.
|
||||
*
|
||||
* The caller owns the higher-level decor/room/grid snap because that geometry
|
||||
* is editor state. Everything after that point is pure and therefore shared
|
||||
* byte-for-byte by hover preview and commit. Unknown symbols fail dark: a
|
||||
* newer config or a stale palette cannot create invisible furniture.
|
||||
*/
|
||||
export function resolveFurniturePlacement(input: FurniturePlacementInput): FurniturePlacement | null {
|
||||
const {
|
||||
symbol, widthCm, depthCm, point, canvasW, canvasH, cellCm, gridPitch,
|
||||
walls, wallReach, free = false,
|
||||
} = input;
|
||||
if (!furnitureGraphic(symbol) || !(canvasW > 0) || !(canvasH > 0)
|
||||
|| !Number.isFinite(point[0]) || !Number.isFinite(point[1])) return null;
|
||||
const w = clampFurnSize(cmToNorm(widthCm, cellCm, gridPitch, canvasW));
|
||||
const h = clampFurnSize(cmToNorm(depthCm, cellCm, gridPitch, canvasW));
|
||||
let cx = point[0], cy = point[1];
|
||||
let angle = 0;
|
||||
const snap = free ? null : snapFurnitureToWall(
|
||||
cx, cy, h * canvasH, walls, wallReach, gridPitch,
|
||||
);
|
||||
if (snap) {
|
||||
cx = snap.cx;
|
||||
cy = snap.cy;
|
||||
angle = snap.angle;
|
||||
}
|
||||
return {
|
||||
symbol,
|
||||
x: clampCanvasN(cx / canvasW - w / 2),
|
||||
y: clampCanvasN(cy / canvasH - h / 2),
|
||||
w,
|
||||
h,
|
||||
angle: Number(angle.toFixed(2)),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The four corners of a rotated box, world units, in the order the frame
|
||||
* draws them: NW, NE, SE, SW. Pure, so the frame, the gestures and the tests
|
||||
|
||||
+53
-3
@@ -63,7 +63,8 @@ import { dayCycleStageVars, renderDayCycleEnvironment } from './day-cycle-render
|
||||
import {
|
||||
FURNITURE_GROUPS, furnitureOfGroup, furnitureSymbol, furnitureDefaultCm,
|
||||
furnitureGraphic, furnitureCorners, snapFurnitureToWall,
|
||||
cmToNorm, clampFurnSize, clampFurnCm, FURN_WALL_CELLS, type FurnitureGroup,
|
||||
cmToNorm, clampFurnSize, clampFurnCm, FURN_WALL_CELLS,
|
||||
type FurnitureGroup, type FurniturePlacement,
|
||||
} from './furniture';
|
||||
import {
|
||||
degradeWalls, rekeyWallsAfterMoveChecked, wallRecordCarrierViolations,
|
||||
@@ -1037,6 +1038,15 @@ export class HouseplanCard extends LitElement {
|
||||
private _furnPalette: { symbol: string; w: number; h: number } | null = null;
|
||||
/** Category currently open in the two-level furniture palette. */
|
||||
private _furnCategory: string | null = null;
|
||||
/** Last fine-pointer location while one furniture stamp is armed. The final
|
||||
* geometry is deliberately resolved on render from the live palette so a
|
||||
* Width/Depth edit updates the ghost without another mouse move (#359). */
|
||||
private _furnPreviewInput: { raw: [number, number]; free: boolean } | null = null;
|
||||
/** Touch/pen has no hover. Delay its one-shot stamp until a clean pointerup
|
||||
* so pointercancel or a second contact cannot save accidental geometry. */
|
||||
private _furnTouchPending: {
|
||||
pid: number; sx: number; sy: number; pointerType: string; cancelled: boolean;
|
||||
} | null = null;
|
||||
/** The selected shape's own unrotated frame (text is measured from SVG). */
|
||||
private _dtBox: { id: string; x: number; y: number; w: number; h: number } | null = null;
|
||||
/**
|
||||
@@ -1437,6 +1447,7 @@ export class HouseplanCard extends LitElement {
|
||||
if (id !== this._space) {
|
||||
this._clearTransientHover(true);
|
||||
this._cancelDevicePressFeedback();
|
||||
this._editorRuntime?._clearFurniturePreview();
|
||||
}
|
||||
this._space = id;
|
||||
return true;
|
||||
@@ -2431,6 +2442,7 @@ export class HouseplanCard extends LitElement {
|
||||
_backdropDialog: { state: true },
|
||||
_furnPalette: { state: true },
|
||||
_furnCategory: { state: true },
|
||||
_furnPreviewInput: { state: true },
|
||||
_bdDrag: { state: true },
|
||||
_dtBox: { state: true },
|
||||
_dtDrag: { state: true },
|
||||
@@ -2676,6 +2688,7 @@ export class HouseplanCard extends LitElement {
|
||||
this._warmRelease();
|
||||
this._clearPlanSnapHover();
|
||||
this._clearOpeningPlacement(true);
|
||||
this._editorRuntime?._clearFurniturePreview();
|
||||
this._touchContacts.clear();
|
||||
this._touchSequenceMultitouch = false;
|
||||
this._touchClickBlockUntil = 0;
|
||||
@@ -2781,6 +2794,7 @@ export class HouseplanCard extends LitElement {
|
||||
// The palette is one explicit surface: Escape closes it and returns
|
||||
// to Select in one step, regardless of whether a symbol was armed.
|
||||
else if (this._decorTool === 'furniture') {
|
||||
this._editorRuntime?._clearFurniturePreview();
|
||||
this._furnPalette = null;
|
||||
this._furnCategory = null;
|
||||
this._decorTool = 'select';
|
||||
@@ -6156,6 +6170,10 @@ export class HouseplanCard extends LitElement {
|
||||
this._decorMoveUpdate(ev);
|
||||
return;
|
||||
}
|
||||
if (this._mode === 'decor' && this._decorTool === 'furniture' && this._editorRuntime) {
|
||||
this._notePointer(ev);
|
||||
if (this._editorRuntime._furnPointerMove(ev, this._pointerModality.hoverEnabled)) return;
|
||||
}
|
||||
if (!this._pointers.has(ev.pointerId)) {
|
||||
this._markupMove(ev);
|
||||
return;
|
||||
@@ -6220,7 +6238,8 @@ export class HouseplanCard extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _stagePointerLeave(_ev: PointerEvent): void {
|
||||
private _stagePointerLeave(ev: PointerEvent): void {
|
||||
if (this._mode === 'decor') this._editorRuntime?._furnPointerLeave(ev);
|
||||
if (!this._markup) return;
|
||||
if (this._tool === 'opening') {
|
||||
this._cursorPt = null;
|
||||
@@ -6297,6 +6316,7 @@ export class HouseplanCard extends LitElement {
|
||||
this._decorMove = null;
|
||||
return;
|
||||
}
|
||||
if (this._editorRuntime?._furnPointerUp(ev)) return;
|
||||
const viewportGestureEnded = !!this._pinchStart || !!this._panStart;
|
||||
this._pointers.delete(ev.pointerId);
|
||||
if (this._pointers.size < 2) this._pinchStart = null;
|
||||
@@ -8018,6 +8038,36 @@ export class HouseplanCard extends LitElement {
|
||||
</g>` as unknown as TemplateResult;
|
||||
}
|
||||
|
||||
private get _furniturePreviewPlacement(): FurniturePlacement | null {
|
||||
const input = this._furnPreviewInput;
|
||||
if (!input || !this._editorRuntime || this._mode !== 'decor'
|
||||
|| this._decorTool !== 'furniture' || !this._furnPalette
|
||||
|| !this._pointerModality.hoverEnabled) return null;
|
||||
return this._editorRuntime._resolveFurniturePlacement(input.raw, input.free, 'mouse');
|
||||
}
|
||||
|
||||
/** One real furniture path, in the same decor composition group as saved
|
||||
* shapes. It paints after them (so it is visible) and the whole decor layer
|
||||
* still paints below physical walls (#359). */
|
||||
private _renderFurniturePlacementPreview(): TemplateResult | typeof nothing {
|
||||
const placement = this._furniturePreviewPlacement;
|
||||
if (!placement) return nothing;
|
||||
const art = furnitureGraphic(placement.symbol);
|
||||
if (!art) return nothing;
|
||||
const W = NORM_W, H = this._decorH;
|
||||
const W2 = placement.w * W, H2 = placement.h * H;
|
||||
const cx = placement.x * W + W2 / 2, cy = placement.y * H + H2 / 2;
|
||||
const transform = `${placement.angle ? `rotate(${placement.angle} ${cx} ${cy}) ` : ''}`
|
||||
+ `translate(${placement.x * W} ${placement.y * H}) scale(${W2 / art.viewW} ${H2 / art.viewH})`;
|
||||
const style = this._decorStyle;
|
||||
return svg`<path class="furniture-placement-preview dfurn"
|
||||
data-symbol=${placement.symbol} d=${art.d} transform=${transform}
|
||||
stroke=${style.color} stroke-opacity=${style.opacity}
|
||||
stroke-width=${decorCmToUnits(style.widthCm, this._cellCm, this._gridPitch)}
|
||||
fill="none" stroke-linecap="round" stroke-linejoin="round"
|
||||
vector-effect="non-scaling-stroke" aria-hidden="true" pointer-events="none"></path>`;
|
||||
}
|
||||
|
||||
private _renderDecorLayer(): TemplateResult {
|
||||
const W = NORM_W, H = this._decorH;
|
||||
const editing = this._mode === 'decor';
|
||||
@@ -8137,7 +8187,7 @@ export class HouseplanCard extends LitElement {
|
||||
stroke="${st.color}" stroke-opacity="${st.opacity}" stroke-width="${sw}" fill="${st.fill ? st.fillColor : 'none'}" fill-opacity="${st.fill ? st.fillOpacity : 0}"></ellipse>`;
|
||||
}
|
||||
}
|
||||
return svg`<g class="decorlayer">${shapes}${draft}</g>` as unknown as TemplateResult;
|
||||
return svg`<g class="decorlayer">${shapes}${draft}${this._renderFurniturePlacementPreview()}</g>` as unknown as TemplateResult;
|
||||
}
|
||||
|
||||
// ================= shared editor secondary surface =================
|
||||
|
||||
+122
-16
@@ -65,7 +65,9 @@ import { dayCycleStageVars, renderDayCycleEnvironment } from './day-cycle-render
|
||||
import {
|
||||
FURNITURE_GROUPS, furnitureOfGroup, furnitureDefaultCm,
|
||||
furnitureGraphic, furnitureCorners, snapFurnitureToWall,
|
||||
cmToNorm, clampFurnSize, clampFurnCm, FURN_WALL_CELLS, type FurnitureGroup,
|
||||
resolveFurniturePlacement,
|
||||
clampFurnCm, FURN_WALL_CELLS,
|
||||
type FurnitureGroup, type FurniturePlacement,
|
||||
} from './furniture';
|
||||
import { GENERATED_FURNITURE_MENU } from './furniture-menu-art.generated';
|
||||
import {
|
||||
@@ -917,6 +919,10 @@ export interface HouseplanEditorHostPort {
|
||||
_fullRegistryHass: any;
|
||||
_furnPalette: { symbol: string; w: number; h: number; } | null;
|
||||
_furnCategory: string | null;
|
||||
_furnPreviewInput: { raw: [number, number]; free: boolean; } | null;
|
||||
_furnTouchPending: {
|
||||
pid: number; sx: number; sy: number; pointerType: string; cancelled: boolean;
|
||||
} | null;
|
||||
_furnWallReach: number;
|
||||
_furnWalls: number[][];
|
||||
_gearPtCache: WeakMap<number[][], number[]>;
|
||||
@@ -1169,6 +1175,7 @@ public _help(key: Extract<I18nKey, `${string}.help`>): TemplateResult | typeof n
|
||||
|
||||
public _setMode(mode: 'view' | 'plan' | 'devices' | 'decor', animate = true): void {
|
||||
this.host._endTabDrag();
|
||||
this._clearFurniturePreview();
|
||||
// A mode command is newer than the editor remembered by a same-route warm
|
||||
// remount. Clear it before the same-mode early return: while can_write is
|
||||
// pending, Lit may still be presenting the previous editor DOM even though
|
||||
@@ -2197,6 +2204,7 @@ public _commitPhysicalGeometry(
|
||||
}
|
||||
|
||||
public _clearGeometryGesture(): void {
|
||||
this._clearFurniturePreview();
|
||||
this.host._path = [];
|
||||
this._clearPlanSnapHover();
|
||||
this._clearOpeningPlacement(false);
|
||||
@@ -2226,6 +2234,12 @@ public _clearGeometryGesture(): void {
|
||||
public _stagePointerCancel(ev: PointerEvent): void {
|
||||
clearTimeout(this.host._kioskHoldTimer);
|
||||
if (this.host._swipeStart?.id === ev.pointerId) this.host._swipeStart = null;
|
||||
if (this.host._furnTouchPending?.pid === ev.pointerId) {
|
||||
this._clearFurniturePreview();
|
||||
this.host._pointers.delete(ev.pointerId);
|
||||
this.host.requestUpdate();
|
||||
return;
|
||||
}
|
||||
if (this.host._physicalDrag?.pid === ev.pointerId || this.host._physicalRotate?.pid === ev.pointerId) {
|
||||
this._cancelPhysicalGesture();
|
||||
return;
|
||||
@@ -4095,7 +4109,29 @@ public _decorPointerDown(ev: PointerEvent): boolean {
|
||||
// must not silently place whatever was chosen last week.
|
||||
if (!this.host._furnPalette) return false;
|
||||
ev.preventDefault();
|
||||
this._furnPlace(this._svgPoint(ev), ev.shiftKey);
|
||||
// A mouse has already shown the exact result and keeps the traditional
|
||||
// one-press stamp. Touch/pen has no hover, so commit only after a clean
|
||||
// pointerup; pointercancel, movement and a second contact stay fail-dark.
|
||||
const pointerType = ev.pointerType || 'mouse';
|
||||
if (pointerType === 'mouse') {
|
||||
this._furnPlace(this._svgPoint(ev), ev.shiftKey, pointerType);
|
||||
return true;
|
||||
}
|
||||
const pending = this.host._furnTouchPending;
|
||||
if (pending && pending.pid !== ev.pointerId) {
|
||||
pending.cancelled = true;
|
||||
this.host._furnPreviewInput = null;
|
||||
return true;
|
||||
}
|
||||
this.host._furnTouchPending = {
|
||||
pid: ev.pointerId,
|
||||
sx: ev.clientX,
|
||||
sy: ev.clientY,
|
||||
pointerType,
|
||||
cancelled: false,
|
||||
};
|
||||
this.host._furnPreviewInput = null;
|
||||
capturePointer(ev);
|
||||
return true;
|
||||
}
|
||||
// Empty-space selection belongs only to Select. Erase is an object
|
||||
@@ -4639,41 +4675,104 @@ public _furnPick(symbol: string): void {
|
||||
this.host._furnPalette = { symbol, w: d.w, h: d.h };
|
||||
}
|
||||
|
||||
public _furnPlace(raw: number[], free = false): void {
|
||||
public _resolveFurniturePlacement(
|
||||
raw: number[], free = false, pointerType = 'mouse',
|
||||
): FurniturePlacement | null {
|
||||
const pal = this.host._furnPalette;
|
||||
const sp = this.host._curSpaceCfg;
|
||||
if (!pal || !sp) return;
|
||||
if (!pal || !sp) return null;
|
||||
const W = NORM_W, H = this.host._decorH;
|
||||
const wN = clampFurnSize(cmToNorm(pal.w, this.host._cellCm, this.host._gridPitch, W));
|
||||
const hN = clampFurnSize(cmToNorm(pal.h, this.host._cellCm, this.host._gridPitch, W));
|
||||
const snapped = this._decorSnap(raw, pointerType);
|
||||
return resolveFurniturePlacement({
|
||||
symbol: pal.symbol,
|
||||
widthCm: pal.w,
|
||||
depthCm: pal.h,
|
||||
point: [snapped[0], snapped[1]],
|
||||
canvasW: W,
|
||||
canvasH: H,
|
||||
cellCm: this.host._cellCm,
|
||||
gridPitch: this.host._gridPitch,
|
||||
walls: this.host._furnWalls,
|
||||
wallReach: this.host._furnWallReach,
|
||||
free,
|
||||
});
|
||||
}
|
||||
|
||||
public _furnPlace(raw: number[], free = false, pointerType = 'mouse'): void {
|
||||
const placement = this._resolveFurniturePlacement(raw, free, pointerType);
|
||||
if (!placement) return;
|
||||
const sp = this.host._curSpaceCfg;
|
||||
if (!sp) return;
|
||||
const before = this._geometrySnapshot();
|
||||
const c = this._decorSnap(raw);
|
||||
let cx = c[0], cy = c[1];
|
||||
let angle = 0;
|
||||
const snap = free ? null : snapFurnitureToWall(cx, cy, hN * H, this.host._furnWalls,
|
||||
this.host._furnWallReach, this.host._gridPitch);
|
||||
if (snap) { cx = snap.cx; cy = snap.cy; angle = snap.angle; }
|
||||
const id = 'df' + Date.now().toString(36) + Math.random().toString(36).slice(2, 5);
|
||||
const shape: any = {
|
||||
id, kind: 'furniture', symbol: pal.symbol,
|
||||
x: clampCanvasN(cx / W - wN / 2), y: clampCanvasN(cy / H - hN / 2),
|
||||
w: wN, h: hN,
|
||||
id, kind: 'furniture', symbol: placement.symbol,
|
||||
x: placement.x, y: placement.y, w: placement.w, h: placement.h,
|
||||
...decorStylePatch(this.host._decorStyle, false),
|
||||
};
|
||||
// a straight piece stores no angle at all, exactly as a straight label
|
||||
// stores none (docs/LIVE-TEXT.md §3)
|
||||
if (angle) shape.angle = Number(angle.toFixed(2));
|
||||
if (placement.angle) shape.angle = placement.angle;
|
||||
sp.decor = [...this.host._decorList, shape];
|
||||
this.host._decorSel = id;
|
||||
// …and the editor goes back to the tool that can move what was just placed
|
||||
this.host._decorTool = 'select';
|
||||
this.host._furnPalette = null;
|
||||
this.host._furnCategory = null;
|
||||
this._clearFurniturePreview();
|
||||
this._recordGeometry(this.host._t('history.decor_add'), before);
|
||||
this._saveConfig();
|
||||
this.host.requestUpdate();
|
||||
}
|
||||
|
||||
public _clearFurniturePreview(): void {
|
||||
this.host._furnPreviewInput = null;
|
||||
this.host._furnTouchPending = null;
|
||||
}
|
||||
|
||||
/** Track only real fine-pointer hover. Touch/pen own a delayed one-tap
|
||||
* transaction below and must never resurrect a compatibility mouse ghost. */
|
||||
public _furnPointerMove(ev: PointerEvent, hoverAllowed: boolean): boolean {
|
||||
const pending = this.host._furnTouchPending;
|
||||
if (pending?.pid === ev.pointerId) {
|
||||
if (Math.abs(ev.clientX - pending.sx) + Math.abs(ev.clientY - pending.sy) > 8) {
|
||||
pending.cancelled = true;
|
||||
}
|
||||
this.host._furnPreviewInput = null;
|
||||
return true;
|
||||
}
|
||||
if (this.host._mode !== 'decor' || this.host._decorTool !== 'furniture'
|
||||
|| !this.host._furnPalette) {
|
||||
this._clearFurniturePreview();
|
||||
return false;
|
||||
}
|
||||
if (ev.pointerType !== 'mouse' || !hoverAllowed) {
|
||||
this.host._furnPreviewInput = null;
|
||||
return false;
|
||||
}
|
||||
const raw = this._svgPoint(ev);
|
||||
this.host._furnPreviewInput = { raw: [raw[0], raw[1]], free: ev.shiftKey };
|
||||
return true;
|
||||
}
|
||||
|
||||
public _furnPointerLeave(ev: PointerEvent): void {
|
||||
if (this.host._furnTouchPending?.pid === ev.pointerId) {
|
||||
this.host._furnTouchPending.cancelled = true;
|
||||
}
|
||||
this.host._furnPreviewInput = null;
|
||||
}
|
||||
|
||||
public _furnPointerUp(ev: PointerEvent): boolean {
|
||||
const pending = this.host._furnTouchPending;
|
||||
if (!pending || pending.pid !== ev.pointerId) return false;
|
||||
this.host._furnTouchPending = null;
|
||||
if (!pending.cancelled && this.host._mode === 'decor'
|
||||
&& this.host._decorTool === 'furniture' && this.host._furnPalette) {
|
||||
this._furnPlace(this._svgPoint(ev), ev.shiftKey, pending.pointerType);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public _furnMoveUpdate(ev: PointerEvent): void {
|
||||
const m = this.host._decorMove!;
|
||||
if (m.orig.kind !== 'furniture') return;
|
||||
@@ -4765,6 +4864,7 @@ public _renderFurnPalette(): TemplateResult {
|
||||
<span class="spacer"></span>
|
||||
<button class="btn furnclose" title=${this.host._t('btn.close')}
|
||||
@click=${() => {
|
||||
this._clearFurniturePreview();
|
||||
this.host._furnPalette = null;
|
||||
this.host._furnCategory = null;
|
||||
this.host._decorTool = 'select';
|
||||
@@ -4775,6 +4875,7 @@ public _renderFurnPalette(): TemplateResult {
|
||||
<div class="furnbody">
|
||||
${category ? html`
|
||||
<button class="btn ghost furnback" @click=${() => {
|
||||
this._clearFurniturePreview();
|
||||
this.host._furnPalette = null;
|
||||
this.host._furnCategory = null;
|
||||
}}>
|
||||
@@ -4798,6 +4899,7 @@ public _renderFurnPalette(): TemplateResult {
|
||||
class="furnitem furncategory" data-category=${item.id}
|
||||
title=${this.host._t(`furn.cat_${item.id}` as I18nKey)}
|
||||
@click=${() => {
|
||||
this._clearFurniturePreview();
|
||||
this.host._furnPalette = null;
|
||||
this.host._furnCategory = item.id;
|
||||
}}>
|
||||
@@ -5117,6 +5219,7 @@ public _renderDecorSecondary(): EditorSecondaryModel | null {
|
||||
dismissPolicy: this.host._furnPalette ? 'stay-open-on-canvas' : 'outside',
|
||||
dismiss: () => {
|
||||
if (this.host._decorTool !== 'furniture') return;
|
||||
this._clearFurniturePreview();
|
||||
this.host._furnPalette = null;
|
||||
this.host._furnCategory = null;
|
||||
this.host._decorTool = 'select';
|
||||
@@ -5239,6 +5342,7 @@ public _renderDecorBar(): TemplateResult {
|
||||
data-editor-palette=${t === 'furniture' ? 'furniture' : nothing}
|
||||
@click=${() => {
|
||||
if (t === 'furniture' && this.host._decorTool === 'furniture') {
|
||||
this._clearFurniturePreview();
|
||||
this.host._furnPalette = null;
|
||||
this.host._furnCategory = null;
|
||||
this.host._decorTool = 'select';
|
||||
@@ -5250,9 +5354,11 @@ public _renderDecorBar(): TemplateResult {
|
||||
// the palette belongs to its tool and to nothing else: leaving the
|
||||
// tool disarms whatever was chosen, so no later click can stamp it
|
||||
if (t !== 'furniture') {
|
||||
this._clearFurniturePreview();
|
||||
this.host._furnPalette = null;
|
||||
this.host._furnCategory = null;
|
||||
} else {
|
||||
this._clearFurniturePreview();
|
||||
this.host._furnCategory = null;
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -737,6 +737,10 @@ export const planStyles = css`
|
||||
calc(5px * var(--hp-cell-visual-scale, 1));
|
||||
pointer-events: none;
|
||||
}
|
||||
.decorlayer .furniture-placement-preview {
|
||||
opacity: 0.55;
|
||||
pointer-events: none;
|
||||
}
|
||||
.decorlayer text {
|
||||
font-weight: 600;
|
||||
user-select: none;
|
||||
|
||||
Reference in New Issue
Block a user