2023-01-17 18:32:15 +00:00
|
|
|
<template>
|
|
|
|
<PlannerSidebar title="Properties">
|
|
|
|
<div
|
2023-01-18 17:00:51 +00:00
|
|
|
class="bg-white-50 flex h-full flex-col overflow-auto"
|
2023-01-17 18:32:15 +00:00
|
|
|
v-if="selectedObject && applicableProperties"
|
|
|
|
>
|
2023-01-18 17:00:51 +00:00
|
|
|
<PropertyFormItem
|
2023-01-17 18:32:15 +00:00
|
|
|
v-for="prop of applicableProperties.properties"
|
2023-01-18 17:00:51 +00:00
|
|
|
:id="selectedObject.id"
|
|
|
|
:prop="prop"
|
|
|
|
:value="selectedObject[prop.key as keyof typeof selectedObject]"
|
|
|
|
@update="(newValue) => updateProp(prop, newValue)"
|
|
|
|
/>
|
2023-01-17 18:32:15 +00:00
|
|
|
</div>
|
|
|
|
</PlannerSidebar>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
import PlannerSidebar from './PlannerSidebar.vue';
|
|
|
|
import { Layer } from '../../modules/house-planner/interfaces';
|
|
|
|
import {
|
|
|
|
ObjectProperties,
|
|
|
|
ObjectProperty,
|
|
|
|
} from './interfaces/properties.interfaces';
|
|
|
|
import { computed } from 'vue';
|
2023-01-18 17:00:51 +00:00
|
|
|
import PropertyFormItem from './PropertyFormItem.vue';
|
2023-01-17 18:32:15 +00:00
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
layers: Layer[];
|
|
|
|
}>();
|
|
|
|
|
|
|
|
const emit = defineEmits<{
|
|
|
|
(
|
|
|
|
e: 'update',
|
|
|
|
layerId: number,
|
|
|
|
objectId: number,
|
|
|
|
key: string,
|
|
|
|
value: unknown
|
|
|
|
): void;
|
|
|
|
}>();
|
|
|
|
|
|
|
|
const commonProps: ObjectProperty[] = [
|
|
|
|
{ key: 'name', title: 'Name', type: 'string' },
|
|
|
|
{ key: 'visible', title: 'Visible', type: 'boolean', groupable: true },
|
|
|
|
];
|
|
|
|
|
|
|
|
const lineProps: ObjectProperty[] = [
|
|
|
|
...commonProps,
|
|
|
|
{ key: 'width', title: 'Line Width', type: 'number', groupable: true },
|
|
|
|
{ key: 'color', title: 'Color', type: 'color', groupable: true },
|
|
|
|
{
|
|
|
|
key: 'lineCap',
|
|
|
|
title: 'Line Cap',
|
|
|
|
type: 'select',
|
|
|
|
groupable: true,
|
|
|
|
options: [
|
|
|
|
{ value: undefined, title: '' },
|
|
|
|
{ value: 'butt', title: 'Butt' },
|
|
|
|
{ value: 'round', title: 'Round' },
|
|
|
|
{ value: 'square', title: 'Square' },
|
|
|
|
],
|
|
|
|
},
|
2023-01-18 17:00:51 +00:00
|
|
|
{
|
|
|
|
key: 'lineJoin',
|
|
|
|
title: 'Line Join',
|
|
|
|
type: 'select',
|
|
|
|
groupable: true,
|
|
|
|
options: [
|
|
|
|
{ value: undefined, title: '' },
|
|
|
|
{ value: 'miter', title: 'Miter' },
|
|
|
|
{ value: 'bevel', title: 'Bevel' },
|
|
|
|
{ value: 'round', title: 'Round' },
|
|
|
|
],
|
|
|
|
},
|
2023-01-17 18:32:15 +00:00
|
|
|
{ key: 'closed', title: 'Closed', type: 'boolean', groupable: true },
|
|
|
|
];
|
|
|
|
|
|
|
|
const objectTypeProperties: ObjectProperties[] = [
|
|
|
|
{
|
|
|
|
type: 'line',
|
|
|
|
properties: lineProps,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'curve',
|
|
|
|
properties: lineProps,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'room',
|
|
|
|
properties: lineProps,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'object',
|
|
|
|
properties: commonProps,
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
const currentLayer = computed(() =>
|
|
|
|
props.layers.find((layer) => layer.active && layer.visible)
|
|
|
|
);
|
|
|
|
|
|
|
|
// TODO multi edit
|
|
|
|
const selectedObject = computed(
|
|
|
|
() => currentLayer.value?.contents?.filter((obj) => obj.selected)[0]
|
|
|
|
);
|
|
|
|
|
|
|
|
const applicableProperties = computed(
|
|
|
|
() =>
|
|
|
|
selectedObject.value &&
|
|
|
|
objectTypeProperties.find(
|
|
|
|
(prop) => prop.type === selectedObject.value?.type
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
const updateProp = (prop: ObjectProperty, value: unknown) => {
|
|
|
|
if (!currentLayer.value || !selectedObject.value) return;
|
|
|
|
if (prop.type === 'number') value = parseFloat(value as string);
|
|
|
|
emit(
|
|
|
|
'update',
|
|
|
|
currentLayer.value!.id,
|
|
|
|
selectedObject.value!.id,
|
|
|
|
prop.key,
|
|
|
|
value
|
|
|
|
);
|
|
|
|
};
|
|
|
|
</script>
|