18 changed files with 559 additions and 126 deletions
@ -0,0 +1,34 @@ |
|||||
|
<template> |
||||
|
<el-form-item> |
||||
|
<template #label> |
||||
|
<div :title="prop.label + ' - ' + prop.field"> |
||||
|
{{ prop.label }} |
||||
|
</div> |
||||
|
</template> |
||||
|
<el-color-picker v-model="value" class="prop-editor" type="text" clearable size="small" /> |
||||
|
</el-form-item> |
||||
|
</template> |
||||
|
<script> |
||||
|
import IMetaProp from './IMetaProp.ts' |
||||
|
import { getColorFromCode, getColorFromString } from '@/utils/webutils.js' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [IMetaProp], |
||||
|
data() { |
||||
|
// 从字符串 '#409EFF' 变换为 0x409EFF |
||||
|
return { |
||||
|
value: getColorFromCode(_.get(this.object3D, this.prop.field)) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
refreshValue() { |
||||
|
this.value = getColorFromCode(_.get(this.object3D, this.prop.field)) |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
value(newValue) { |
||||
|
_.set(this.object3D, this.prop.field, getColorFromString(newValue)) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,26 @@ |
|||||
|
import * as THREE from 'three' |
||||
|
import { type ItemTypeMetaItem } from '@/model/itemType/ItemTypeDefine.ts' |
||||
|
import { defineComponent, type PropType } from 'vue' |
||||
|
import type Viewport from '@/designer/Viewport.ts' |
||||
|
import EventBus from '@/runtime/EventBus' |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
props: { |
||||
|
prop: Object as PropType<ItemTypeMetaItem>, |
||||
|
viewport: Object as PropType<Viewport> |
||||
|
}, |
||||
|
mounted() { |
||||
|
EventBus.$on('objectChanged', (data) => { |
||||
|
//@ts-ignore
|
||||
|
if (typeof this.refreshValue === 'function') { |
||||
|
//@ts-ignore
|
||||
|
this.refreshValue() |
||||
|
} |
||||
|
}) |
||||
|
}, |
||||
|
computed: { |
||||
|
object3D(): THREE.Object3D { |
||||
|
return this.viewport.state.selectedObject |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
@ -0,0 +1,32 @@ |
|||||
|
<template> |
||||
|
<el-form-item> |
||||
|
<template #label> |
||||
|
<div :title="prop.label + ' - ' + prop.field"> |
||||
|
{{ prop.label }} |
||||
|
</div> |
||||
|
</template> |
||||
|
<el-input v-model="value" class="prop-editor" type="number" clearable size="small" /> |
||||
|
</el-form-item> |
||||
|
</template> |
||||
|
<script> |
||||
|
import IMetaProp from './IMetaProp.ts' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [IMetaProp], |
||||
|
data() { |
||||
|
return { |
||||
|
value: _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
refreshValue() { |
||||
|
this.value = _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
value(newValue) { |
||||
|
_.set(this.object3D, this.prop.field, newValue) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,32 @@ |
|||||
|
<template> |
||||
|
<el-form-item> |
||||
|
<template #label> |
||||
|
<div :title="prop.label + ' - ' + prop.field"> |
||||
|
{{ prop.label }} |
||||
|
</div> |
||||
|
</template> |
||||
|
<el-switch v-model="value" class="prop-editor" clearable size="small" /> |
||||
|
</el-form-item> |
||||
|
</template> |
||||
|
<script> |
||||
|
import IMetaProp from './IMetaProp.ts' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [IMetaProp], |
||||
|
data() { |
||||
|
return { |
||||
|
value: _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
refreshValue() { |
||||
|
this.value = _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
value(newValue) { |
||||
|
_.set(this.object3D, this.prop.field, newValue) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,32 @@ |
|||||
|
<template> |
||||
|
<el-form-item> |
||||
|
<template #label> |
||||
|
<div :title="prop.label + ' - ' + prop.field"> |
||||
|
{{ prop.label }} |
||||
|
</div> |
||||
|
</template> |
||||
|
<el-input v-model="value" class="prop-editor" type="text" clearable size="small" /> |
||||
|
</el-form-item> |
||||
|
</template> |
||||
|
<script> |
||||
|
import IMetaProp from './IMetaProp.ts' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [IMetaProp], |
||||
|
data() { |
||||
|
return { |
||||
|
value: _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
refreshValue() { |
||||
|
this.value = _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
value(newValue) { |
||||
|
_.set(this.object3D, this.prop.field, newValue) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,210 @@ |
|||||
|
<template> |
||||
|
<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> |
||||
|
<template v-if="!object3DIsNull"> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="position.x" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="position.y" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="position.z" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</div> |
||||
|
<div class="gui-row"> |
||||
|
<div class="gui-item-name"> |
||||
|
<component :is="renderIcon('element RefreshLeft')"></component> |
||||
|
</div> |
||||
|
<template v-if="!object3DIsNull"> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="radianX" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="radianY" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="radianZ" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</div> |
||||
|
<div class="gui-row"> |
||||
|
<div class="gui-item-name"> |
||||
|
<component :is="renderIcon('element ScaleToOriginal')"></component> |
||||
|
</div> |
||||
|
<template v-if="!object3DIsNull"> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="scale.x" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="scale.y" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
<div class="gui-item"> |
||||
|
<el-input-number v-model="scale.z" size="small" :precision="3" :controls="false" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script> |
||||
|
import _ from 'lodash' |
||||
|
import { renderIcon } from '@/utils/webutils.js' |
||||
|
import { markRaw } from 'vue' |
||||
|
import IMetaProp from './IMetaProp.js' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [IMetaProp], |
||||
|
data() { |
||||
|
return { |
||||
|
isBindable: true, |
||||
|
object3DIsNull: true, |
||||
|
position: { x: 0, y: 0, z: 0 }, |
||||
|
rotation: { x: 0, y: 0, z: 0 }, |
||||
|
scale: { x: 1, y: 1, z: 1 } |
||||
|
} |
||||
|
}, |
||||
|
mounted() { |
||||
|
}, |
||||
|
methods: { |
||||
|
renderIcon, |
||||
|
refreshValue() { |
||||
|
this.isBindable = false |
||||
|
this.$nextTick(() => { |
||||
|
this.isBindable = true |
||||
|
}) |
||||
|
|
||||
|
const object3D = this.object3D |
||||
|
if(!object3D) { |
||||
|
this.object3DIsNull = true |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
this.position.x = object3D.position.x |
||||
|
this.position.y = object3D.position.y |
||||
|
this.position.z = object3D.position.z |
||||
|
|
||||
|
this.rotation.x = object3D.rotation.x |
||||
|
this.rotation.y = object3D.rotation.y |
||||
|
this.rotation.z = object3D.rotation.z |
||||
|
|
||||
|
this.scale.x = object3D.scale.x |
||||
|
this.scale.y = object3D.scale.y |
||||
|
this.scale.z = object3D.scale.z |
||||
|
|
||||
|
this.object3DIsNull = false |
||||
|
}, |
||||
|
}, |
||||
|
watch: { |
||||
|
position: { |
||||
|
deep: true, |
||||
|
handler(newVal) { |
||||
|
if (this.object3D && this.isBindable) { |
||||
|
this.object3D.position.x = newVal.x |
||||
|
this.object3D.position.y = newVal.y |
||||
|
this.object3D.position.z = newVal.z |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
rotation: { |
||||
|
deep: true, |
||||
|
handler(newVal) { |
||||
|
if (this.object3D && this.isBindable) { |
||||
|
this.object3D.rotation.x = newVal.x |
||||
|
this.object3D.rotation.y = newVal.y |
||||
|
this.object3D.rotation.z = newVal.z |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
scale: { |
||||
|
deep: true, |
||||
|
handler(newVal) { |
||||
|
if (this.object3D && this.isBindable) { |
||||
|
this.object3D.scale.x = newVal.x |
||||
|
this.object3D.scale.y = newVal.y |
||||
|
this.object3D.scale.z = newVal.z |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
computed: { |
||||
|
// 弧度转角度 |
||||
|
radianX: { |
||||
|
get() { |
||||
|
return Math.round(this.rotation.x * 180 / Math.PI) |
||||
|
}, |
||||
|
set(newVal) { |
||||
|
this.rotation.x = newVal * Math.PI / 180 |
||||
|
} |
||||
|
}, |
||||
|
radianY: { |
||||
|
get() { |
||||
|
return Math.round(this.rotation.y * 180 / Math.PI) |
||||
|
}, |
||||
|
set(newVal) { |
||||
|
this.rotation.y = newVal * Math.PI / 180 |
||||
|
} |
||||
|
}, |
||||
|
radianZ: { |
||||
|
get() { |
||||
|
return Math.round(this.rotation.z * 180 / Math.PI) |
||||
|
}, |
||||
|
set(newVal) { |
||||
|
this.rotation.z = newVal * Math.PI / 180 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
|
<style lang="less"> |
||||
|
.gui-toolbar { |
||||
|
color: #fff; |
||||
|
|
||||
|
.el-input-number.is-without-controls .el-input__wrapper { |
||||
|
padding-left: 2px; |
||||
|
padding-right: 2px; |
||||
|
} |
||||
|
|
||||
|
.gui-row { |
||||
|
display: flex; |
||||
|
flex-direction: row; |
||||
|
gap: 3px; |
||||
|
padding: 3px 0; |
||||
|
|
||||
|
.gui-item-name { |
||||
|
width: 26px; |
||||
|
align-self: stretch; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
|
||||
|
.el-icon { |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.gui-item { |
||||
|
flex: 1; |
||||
|
text-align: center; |
||||
|
font-size: 12px; |
||||
|
|
||||
|
.el-input-number { |
||||
|
width: 100%; |
||||
|
|
||||
|
.el-input__wrapper { |
||||
|
background-color: #424242; |
||||
|
box-shadow: none |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,32 @@ |
|||||
|
<template> |
||||
|
<el-form-item> |
||||
|
<template #label> |
||||
|
<div :title="prop.label + ' - ' + prop.field"> |
||||
|
{{ prop.label }} |
||||
|
</div> |
||||
|
</template> |
||||
|
<el-input v-model="value" class="prop-editor" type="text" clearable size="small" /> |
||||
|
</el-form-item> |
||||
|
</template> |
||||
|
<script> |
||||
|
import IMetaProp from './IMetaProp.ts' |
||||
|
|
||||
|
export default { |
||||
|
mixins: [IMetaProp], |
||||
|
data() { |
||||
|
return { |
||||
|
value: _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
refreshValue() { |
||||
|
this.value = _.get(this.object3D, this.prop.field) |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
value(newValue) { |
||||
|
_.set(this.object3D, this.prop.field, newValue) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
@ -1,28 +0,0 @@ |
|||||
import _ from 'lodash' |
|
||||
import type { ItemTypeDefineOption } from '@/model/itemType/ItemTypeDefine.ts' |
|
||||
|
|
||||
const itemTypes: Record<string, ItemTypeDefineOption> = {} |
|
||||
window['itemTypes'] = itemTypes |
|
||||
|
|
||||
/** |
|
||||
* 定义一个 物流单元 |
|
||||
*/ |
|
||||
export function defineItemType(option: ItemTypeDefineOption) { |
|
||||
itemTypes[option.name] = option |
|
||||
option.clazz.name = option.name |
|
||||
option.clazz.option = option |
|
||||
return option |
|
||||
} |
|
||||
|
|
||||
export function getItemTypeByName(type: string): ItemTypeDefineOption { |
|
||||
const itemType = _.get(itemTypes, type) |
|
||||
if (!itemType) { |
|
||||
console.warn(`未找到物流单元类型定义: ${type}`) |
|
||||
return |
|
||||
} |
|
||||
return itemType |
|
||||
} |
|
||||
|
|
||||
export function getAllItemTypes(): ItemTypeDefineOption[] { |
|
||||
return Object.values(itemTypes) |
|
||||
} |
|
||||
@ -0,0 +1,9 @@ |
|||||
|
import mitt from 'mitt' |
||||
|
|
||||
|
const instance = mitt() |
||||
|
|
||||
|
export default { |
||||
|
$emit: instance.emit, |
||||
|
$on: instance.on, |
||||
|
$off: instance.off |
||||
|
} |
||||
Loading…
Reference in new issue