Browse Source

feat(editor): 添加 TransformEditor 组件并优化 DataForm 样式

- 新增 TransformEditor 组件,用于编辑物体的变换属性(位置、旋转、缩放)
- 在 PropertyPanel 中集成 TransformEditor,实现对 tf 属性的编辑
- 优化 DataForm 项的样式,增加无标签项的样式处理
- 调整 PropertyPanel 的样式,优化属性编辑界面布局
master
lizw-2015 6 months ago
parent
commit
c87c1eac07
  1. 7
      src/components/data-form/DataForm.vue
  2. 216
      src/editor/propEditors/TransformEditor.vue
  3. 9
      src/editor/widgets/property/PropertyPanel.vue
  4. 14
      src/editor/widgets/property/PropertyPanelConstant.ts

7
src/components/data-form/DataForm.vue

@ -410,8 +410,10 @@ export type {
'data-form-item',
`data-form-item-flex-${Math.min(dataFormItem.widthCount, state.columnCount)}`,
{
'data-form-item-no-label': !dataFormItem.formItemProps.label,
'multiple-width-count': Math.min(dataFormItem.widthCount, state.columnCount) > 1,
'data-form-item-has-ext-input': dataFormItem.extInputs && dataFormItem.extInputs.length > 0,
},
]"
>
@ -483,6 +485,11 @@ export type {
flex-shrink: 0;
}
.data-form-item-no-label :deep(> .el-form-item__content),
.data-form-item-ext-input :deep(> .el-form-item__content){
margin-left: 0 !important;
}
.data-form-item.data-form-item-flex-1 {
flex: 1 1 0;
}

216
src/editor/propEditors/TransformEditor.vue

@ -0,0 +1,216 @@
<script setup lang="ts">
import { reactive } from "vue";
import { ElInputNumber, useFormItem } from "element-plus";
import { Typeof } from "@ease-forge/shared";
import { renderIcon } from "@/utils/webutils.js";
defineOptions({
name: 'TransformEditor',
});
//
const emit = defineEmits<{
/** 更新内联表格数据 */
"update:modelValue": [value: ItemJson["tf"]];
}>();
// //
// const slots = defineSlots<{
// /** */
// slots01?: (props?: any) => Array<VueNode>;
// }>();
// //
// const attrs = useAttrs();
// //
// const slots = useSlots();
//
// const instance = getCurrentInstance();
// // value
// const value = defineModel<string>();
// Props
interface TransformEditorProps {
modelValue: ItemJson["tf"];
}
// props
const props = withDefaults(defineProps<TransformEditorProps>(), {});
// State
interface TransformEditorState {
}
// state
const state = reactive<TransformEditorState>({});
// Data
interface TransformEditorData {
}
//
const data: TransformEditorData = {};
const { formItem } = useFormItem();
function updateValue(value: number | undefined, prs: 0 | 1 | 2, xyz: 0 | 1 | 2) {
const rawValue: any = props.modelValue;
if (!rawValue[prs]) rawValue[prs] = [];
if (prs === 1) value = calcRotation(value);
rawValue[prs][xyz] = value;
emit("update:modelValue", rawValue);
console.log("updateValue", rawValue);
// formItem?.validate('change', (valid) => console.log(valid));
}
function getPosition(idx: 0 | 1 | 2) {
return props.modelValue?.[0]?.[idx];
}
function getRotation(idx: 0 | 1 | 2) {
const radian = props.modelValue?.[1]?.[idx];
if (Typeof.noValue(radian)) return;
return Math.round(radian * 180 / Math.PI);
}
function getScale(idx: 0 | 1 | 2) {
return props.modelValue?.[2]?.[idx];
}
function calcRotation(rotation?: number) {
if (Typeof.noValue(rotation)) return;
return rotation * Math.PI / 180;
}
interface TransformEditorExpose {
state: TransformEditorState;
data: TransformEditorData;
}
const expose: TransformEditorExpose = {
state,
data,
};
//
defineExpose(expose);
export type {
TransformEditorProps,
TransformEditorState,
}
</script>
<template>
<div class="transform-editor gui-toolbar">
<div class="gui-row">
<div class="gui-item-name"></div>
<div class="gui-item">X</div>
<div class="gui-item">Y</div>
<div class="gui-item">Z</div>
</div>
<div class="gui-row">
<div class="gui-item-name">
<component :is="renderIcon('element Rank')"></component>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getPosition(0)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 0, 0)"
/>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getPosition(1)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 0, 1)"
/>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getPosition(2)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 0, 2)"
/>
</div>
</div>
<div class="gui-row">
<div class="gui-item-name">
<component :is="renderIcon('element RefreshLeft')"></component>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getRotation(0)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 1, 0)"
/>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getRotation(1)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 1, 1)"
/>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getRotation(2)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 1, 2)"
/>
</div>
</div>
<div class="gui-row">
<div class="gui-item-name">
<component :is="renderIcon('element ScaleToOriginal')"></component>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getScale(0)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 2, 0)"
/>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getScale(1)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 2, 1)"
/>
</div>
<div class="gui-item">
<ElInputNumber
:modelValue="getScale(2)"
size="small"
:precision="3"
:controls="false"
@change="(currentValue: number) => updateValue(currentValue, 2, 2)"
/>
</div>
</div>
</div>
</template>
<style scoped>
div.transform-editor.gui-toolbar {
border: none;
margin: 0;
}
</style>

9
src/editor/widgets/property/PropertyPanel.vue

@ -75,10 +75,13 @@ function getCollapseItemId(group: PropertySetterGroup, idx: number) {
function onDataChange(newData: any) {
const viewport = props.viewport;
if (!viewport) return;
const data = _.find(viewport.stateManager.vdata.items, item => item.id === props.data.id);
viewport.stateManager.beginStateUpdate();
lodash.merge(props.data, newData);
console.log("onDataChange", props.data === newData);
lodash.merge(data, newData);
console.log("onDataChange@1", JSON.stringify(data.tf));
viewport.stateManager.endStateUpdate();
// data = _.find(viewport.stateManager.vdata.items, item => item.id === props.data.id);
// console.log("onDataChange#2", JSON.stringify(data.tf));
}
interface PropertyPanelExpose {
@ -130,6 +133,6 @@ export type {
<style scoped>
.property-panel {
padding: 8px 12px 16px 0;
padding: 8px 12px 16px 4px;
}
</style>

14
src/editor/widgets/property/PropertyPanelConstant.ts

@ -1,5 +1,8 @@
import { markRaw } from "vue";
import type { DataFormProps } from "@/components/data-form/DataFormTypes.ts";
import type { PropertyFieldSetter } from "@/core/base/PropertyTypes.ts";
import { dataFormInputComponents } from "@/components/data-form/DataFormConstant.ts";
import TransformEditor from "@/editor/propEditors/TransformEditor.vue";
const defDataFormProps: DataFormProps = {
columnCount: 1,
@ -8,6 +11,8 @@ const defDataFormProps: DataFormProps = {
size: "small",
};
dataFormInputComponents.TransformEditor = markRaw<any>(TransformEditor);
const basicFieldsSetter: Array<PropertyFieldSetter> = [
{
dataPath: 'id', label: '唯一ID', input: 'Input',
@ -39,11 +44,10 @@ const basicFieldsSetter: Array<PropertyFieldSetter> = [
dataPath: 'dt.color', label: '颜色', input: 'ColorPicker',
inputProps: {},
},
// {
// dataPath: 'tf', input: 'TransformEditor',
// inputProps: {
// },
// },
{
dataPath: 'tf', input: 'TransformEditor',
inputProps: {},
},
// {
// dataPath: 'dt', input: 'InOutCenterEditor',
// inputProps: {

Loading…
Cancel
Save