freeblox/packages/editor/src/components/sidebar/SidebarForm.vue

124 lines
3.3 KiB
Vue

<template>
<div class="sidebar-form">
<template v-for="form of formFields">
<component
:is="form.component"
:name="form.name"
:label="form.label"
:value="form.value"
:type="form.type"
@update="(value: string) => propertyChanged(form.name, value)"
></component>
</template>
</div>
</template>
<script setup lang="ts">
import { GameObject } from '@freeblox/engine';
import type { Component } from 'vue';
import { computed } from 'vue';
import Field from '../form/Field.vue';
import { Color, Euler, Vector3 } from 'three';
import Vector3Field from '../form/Vector3Field.vue';
import Checkbox from '../form/Checkbox.vue';
import ColorPicker from '../form/ColorPicker.vue';
interface FormItem {
name: string;
label: string;
value: unknown;
type?: unknown;
component: Component;
}
const props = defineProps<{
selection: GameObject[];
}>();
const emit = defineEmits<{
(e: 'update', item: GameObject, property: string, value: string): void;
}>();
const propertyChanged = (property: string, value: string) => {
const object = props.selection[0];
emit('update', object, property, value);
};
function toCapitalizedWords(name: string) {
const words = name.match(/[A-Za-z][a-z]*/g) || [];
return words.map(capitalize).join(' ');
}
function capitalize(word: string) {
return word.charAt(0).toUpperCase() + word.substring(1);
}
const formFields = computed(() => {
// TODO: multi-edit
const object = props.selection[0];
if (!object) return [];
const fields: FormItem[] = [];
object.properties
.filter((item) => item.definition.exposed && item.definition.name)
.forEach((property) => {
if (
property.definition.type === String ||
property.definition.type === Number
) {
fields.push({
name: property.definition.name!,
label: toCapitalizedWords(property.definition.name!),
value: (object as unknown as Record<string, unknown>)[
property.definition.name!
],
type: property.definition.type === String ? 'string' : 'number',
component: Field,
});
}
if (
property.definition.type === Vector3 ||
property.definition.type === Euler
) {
fields.push({
name: property.definition.name!,
label: toCapitalizedWords(property.definition.name!),
value: (object as unknown as Record<string, unknown>)[
property.definition.name!
],
type: property.definition.type === Vector3 ? 'vector' : 'euler',
component: Vector3Field,
});
}
if (property.definition.type === Color) {
fields.push({
name: property.definition.name!,
label: toCapitalizedWords(property.definition.name!),
value: (object as unknown as Record<string, unknown>)[
property.definition.name!
],
component: ColorPicker,
});
}
if (property.definition.type === Boolean) {
fields.push({
name: property.definition.name!,
label: toCapitalizedWords(property.definition.name!),
value: (object as unknown as Record<string, unknown>)[
property.definition.name!
],
component: Checkbox,
});
}
});
return fields;
});
</script>
<style lang="scss"></style>