mock: スイッチ・スタビの十字をトグルで出し、スタビ候補を選べるようにする(T-30 単位8)
スタビ候補はキーの長辺の長さで引き、キーごとに複数選べる。選択は ProjectFile.ui.phy.stabilizers に持つ。 プロパティ欄に switchOffset の入力欄を置く。異形キーは候補なし。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017yoUu9Xd8dhwyQdCfKfaXG
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
import type { Node, Transform } from "../../domain/phy";
|
||||
import type { StabilizerCandidate } from "../../domain/stabilizers";
|
||||
const props = defineProps<{
|
||||
selectedCount: number;
|
||||
selectedId: string | null;
|
||||
item: Node | null;
|
||||
mismatch: boolean;
|
||||
stabilizers: { candidates: StabilizerCandidate[]; selected: string[] } | null;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
update: [id: string, change: (node: Node) => void, label?: string];
|
||||
@@ -14,7 +16,24 @@ const emit = defineEmits<{
|
||||
changeVariant: [group: Node, variantId: string];
|
||||
deleteNode: [id: string];
|
||||
addVariant: [groupId: string, name: string];
|
||||
stabilizers: [keyId: string, ids: string[]];
|
||||
}>();
|
||||
function setSwitchOffset(axis: "x" | "y", value: number) {
|
||||
emit("update", props.item!.id, (n) => {
|
||||
if (n.type !== "key") return;
|
||||
const offset = { x: n.switchOffset?.x ?? 0, y: n.switchOffset?.y ?? 0, [axis]: value };
|
||||
if (offset.x === 0 && offset.y === 0) delete n.switchOffset;
|
||||
else n.switchOffset = offset;
|
||||
});
|
||||
}
|
||||
function toggleStabilizer(id: string, on: boolean) {
|
||||
const current = props.stabilizers?.selected ?? [];
|
||||
emit(
|
||||
"stabilizers",
|
||||
props.item!.id,
|
||||
on ? [...current.filter((x) => x !== id), id] : current.filter((x) => x !== id),
|
||||
);
|
||||
}
|
||||
const group = computed(() => (props.item?.type === "variantGroup" ? props.item : null));
|
||||
const frameX = ref(0);
|
||||
const frameY = ref(0);
|
||||
@@ -94,6 +113,33 @@ const frameR = ref(0);
|
||||
})
|
||||
"
|
||||
/></label>
|
||||
<label
|
||||
>switchOffset X
|
||||
<input
|
||||
type="number"
|
||||
step="any"
|
||||
:value="item.switchOffset?.x ?? 0"
|
||||
@change="setSwitchOffset('x', Number(($event.target as HTMLInputElement).value))"
|
||||
/></label>
|
||||
<label
|
||||
>switchOffset Y
|
||||
<input
|
||||
type="number"
|
||||
step="any"
|
||||
:value="item.switchOffset?.y ?? 0"
|
||||
@change="setSwitchOffset('y', Number(($event.target as HTMLInputElement).value))"
|
||||
/></label>
|
||||
<div class="stabilizers">
|
||||
スタビ
|
||||
<span v-if="!stabilizers?.candidates.length" class="none">候補なし</span>
|
||||
<label v-for="c in stabilizers?.candidates ?? []" :key="c.id" class="check"
|
||||
><input
|
||||
type="checkbox"
|
||||
:checked="stabilizers!.selected.includes(c.id)"
|
||||
@change="toggleStabilizer(c.id, ($event.target as HTMLInputElement).checked)"
|
||||
/>{{ c.label }}</label
|
||||
>
|
||||
</div>
|
||||
<label
|
||||
>Label
|
||||
<input
|
||||
@@ -174,4 +220,15 @@ const frameR = ref(0);
|
||||
width: 110px;
|
||||
margin-left: auto;
|
||||
}
|
||||
.properties label.check {
|
||||
margin: 4px 0 4px 12px;
|
||||
}
|
||||
.properties label.check input {
|
||||
width: auto;
|
||||
margin-left: 0;
|
||||
}
|
||||
.stabilizers .none {
|
||||
margin-left: 8px;
|
||||
color: #6b7380;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user