Browse Source
- 新增 TransformEditor 组件,用于编辑物体的变换属性(位置、旋转、缩放) - 在 PropertyPanel 中集成 TransformEditor,实现对 tf 属性的编辑 - 优化 DataForm 项的样式,增加无标签项的样式处理 - 调整 PropertyPanel 的样式,优化属性编辑界面布局master
4 changed files with 238 additions and 8 deletions
@ -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> |
||||
Loading…
Reference in new issue