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