Browse Source

解决循环依赖问题、世界模型初始化时机问题

master
修宁 6 months ago
parent
commit
c19f6d6fbc
  1. 3
      src/core/ModelUtils.ts
  2. 2
      src/core/base/BaseRenderer.ts
  3. 6
      src/core/manager/CodeDropper.ts
  4. 44
      src/core/manager/ModuleManager.ts
  5. 41
      src/core/manager/WorldModel.ts
  6. 2
      src/editor/CatalogDefine.vue
  7. 1
      src/editor/Model2DEditor.vue
  8. 33
      src/editor/ModelMain.vue
  9. 5
      src/editor/ModelMainInit.ts
  10. 181
      src/editor/menus/FileMenu.ts
  11. 1
      src/editor/widgets/modeltree/ModeltreeViewJs.js
  12. 2
      src/main.ts
  13. 7
      src/modules/agv1/index.ts
  14. 13
      src/modules/carton/index.ts
  15. 13
      src/modules/charger/index.ts
  16. 13
      src/modules/cl2/index.ts
  17. 14
      src/modules/clx/index.ts
  18. 13
      src/modules/gstore/index.ts
  19. 3
      src/modules/measure/MeasureRenderer.ts
  20. 15
      src/modules/measure/index.ts
  21. 13
      src/modules/pallet/index.ts
  22. 760
      src/modules/rack/RackRenderer.ts_back
  23. 13
      src/modules/rack/index.ts
  24. 13
      src/modules/shuttle_rack/index.ts
  25. 7
      src/modules/tote/index.ts
  26. 13
      src/modules/way/index.ts
  27. 1
      src/types/global.d.ts

3
src/core/ModelUtils.ts

@ -1,7 +1,6 @@
import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport'
import { Vector2 } from 'three/src/math/Vector2'
import EventBus from '@/runtime/EventBus.ts'
import Decimal from 'decimal.js'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import axios from 'axios'
@ -9,7 +8,7 @@ import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { TDSLoader } from 'three/examples/jsm/loaders/TDSLoader'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2'
import { worldModel } from '@/core/manager/WorldModel.ts'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { Line2 } from 'three/examples/jsm/lines/Line2'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'

2
src/core/base/BaseRenderer.ts

@ -7,6 +7,8 @@ import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts'
import { getRenderer } from '@/core/manager/ModuleManager.ts'
debugger
/**
*
* / 线 Three.js .

6
src/core/manager/CodeDropper.ts

@ -42,7 +42,7 @@ export default class CodeDropper extends BaseInteraction {
droppedItemCallback: (item: ItemJson, pos: THREE.Vector3, evt: MouseEvent) => boolean
}
defineModule({
name: 'CodeDropper',
const ITEM_NAME = 'CodeDropper'
defineModule(ITEM_NAME, () => ({
interaction: CodeDropper.INSTANCE
})
}))

44
src/core/manager/ModuleManager.ts

@ -1,17 +1,20 @@
import * as THREE from 'three'
import BaseRenderer from '@/core/base/BaseRenderer'
import BaseInteraction from '@/core/base/BaseInteraction'
import BaseEntity from '@/core/base/BaseItemEntity'
import type { PropertySetter } from "@/core/base/PropertyTypes.ts";
import type { PropertySetter } from '@/core/base/PropertyTypes.ts'
// Define the ModuleDefineOption interface
export interface ModuleDefineOption {
/**
*
*
*/
name: string;
renderer?: BaseRenderer;
/**
*
*/
interaction?: BaseInteraction;
/**
*
*/
setter?: PropertySetter;
}
@ -22,12 +25,19 @@ window['modules'] = modules
/**
*
*/
export function defineModule(option: ModuleDefineOption): Promise<any> {
if (modules.has(option.name)) {
throw new Error(`Module with name "${option.name}" is already defined.`)
export function defineModule(name: string, optionFn: () => ModuleDefineOption): Promise<any> {
if (modules.has(name)) {
throw new Error(`Module with name "${name}" is already defined.`)
}
modules.set(option.name, option)
return option.renderer?.init()
return new Promise((resolve) => {
if (typeof optionFn !== 'function') {
console.log(`Module "${name}" is not a function, using it directly.`)
debugger
}
const option = optionFn()
modules.set(name, option)
option.renderer?.init().then(resolve)
})
}
/**
@ -62,17 +72,5 @@ export function getInteraction<T extends BaseInteraction>(name: string): T {
export function getSetter(name: string) {
const module = getModuleOption(name)
return module.setter;
}
/**
* ,
*
*/
export function createEntity<T extends BaseEntity>(name: string, itemjson: ItemJson, objects: THREE.Object3D[]): T {
const module = getModuleOption(name)
const v = new module.entity() as T
v.setItem(itemjson)
v.setObjects(objects)
return v
return module.setter
}

41
src/core/manager/WorldModel.ts

@ -1,18 +1,6 @@
import _, { cloneDeep } from 'lodash'
import { reactive, watch } from 'vue'
import EventBus from '@/runtime/EventBus'
import Measure from '@/modules/measure'
import Way from '@/modules/way'
import Gstore from '@/modules/gstore'
import Rack from '@/modules/rack'
import ShuttleRack from '@/modules/shuttle_rack'
import Pallet from '@/modules/pallet'
import Tote from '@/modules/tote'
// import Agv1 from '@/modules/agv1'
import Carton from '@/modules/carton'
import Cl2 from '@/modules/cl2'
import Clx from '@/modules/clx'
import Charger from '@/modules/charger'
import StateManager from '@/core/manager/StateManager.ts'
import { getQueryParams, setQueryParam } from '@/utils/webutils.ts'
import localforage from 'localforage'
@ -68,7 +56,7 @@ export default class WorldModel {
isLoading: false,
isRunning: false,
isVirtual: false,
timeRate: 1,
timeRate: 1
}
})
@ -101,18 +89,17 @@ export default class WorldModel {
init() {
// 观察 this.state.catalogCode 的变化, 如果变化就调用 catalogCodeChange 方法
return Promise.all([
Measure,
Way,
Gstore,
Rack,
ShuttleRack,
Pallet,
Tote,
Carton,
Cl2,
Clx,
// Agv1,
Charger
import('../../modules/measure'),
import('../../modules/way'),
import('../../modules/gstore'),
import('../../modules/rack'),
import('../../modules/shuttle_rack'),
import('../../modules/pallet'),
import('../../modules/tote'),
import('../../modules/carton'),
import('../../modules/cl2'),
import('../../modules/clx'),
import('../../modules/charger')
]).then(() => {
console.log('世界模型初始化完成')
@ -241,3 +228,7 @@ export default class WorldModel {
})
}
}
const worldModel = new WorldModel()
debugger
export { worldModel }

2
src/editor/CatalogDefine.vue

@ -3,6 +3,7 @@ import { computed, createVNode, reactive, useTemplateRef } from "vue";
import { ElButton, ElSpace, ElTree } from "element-plus";
import YvSrcEditor from "@/components/YvSrcEditor.vue";
import DataForm from "@/components/data-form/DataForm.vue";
import {worldModel} from '@/core/manager/WorldModel.ts'
import lodash from "lodash";
defineOptions({
@ -39,7 +40,6 @@ interface CatalogDefineData {
//
const data: CatalogDefineData = {};
const tree = useTemplateRef<InstanceType<typeof ElTree>>("treeRef");
const worldModel = computed(() => window['worldModel']);
const catalog = computed<Array<any>>(() => {
// state.forceUpdateForCatalog;
return worldModel.value?.state?.catalog;

1
src/editor/Model2DEditor.vue

@ -104,6 +104,7 @@ import { renderIcon, setQueryParam } from '@/utils/webutils'
import { createVNode, defineComponent, markRaw } from 'vue'
import Viewport from '@/core/engine/Viewport'
import Constract from '@/core/Constract'
import { worldModel } from '@/core/manager/WorldModel.ts'
import EventBus from '@/runtime/EventBus'
import SceneHelp from '@/core/engine/SceneHelp'
import BulkCopy from './BulkCopy.vue'

33
src/editor/ModelMain.vue

@ -9,10 +9,10 @@
<component :is="renderIcon('element ArrowDown')"></component>
</div>
<div style="flex-grow: 1;"></div>
<div style="display: flex; flex-direction: row; align-items: center; margin-right: 10px;">
<div v-if="isModelOpen" style="display: flex; flex-direction: row; align-items: center; margin-right: 10px;">
<div class="field-block" style="margin-right: 5px;">
<el-select style="width:130px;" placeholder="运行环境"
v-model="worldModel.state.currentEnvId">
v-model="worldModelState.currentEnvId">
<template #footer>
<el-button size="small" type="primary" plain>创建运行环境</el-button>
<el-button size="small" :icon="renderIcon('Refresh')" @click="reloadEnvList" />
@ -21,20 +21,20 @@
</div>
<div class="field-block" style="margin-right: 5px;">
<el-select style="width:130px;" placeholder="时间速率"
v-model="worldModel.state.timeRate">
v-model="worldModelState.timeRate">
<el-option label="1x" :value="1"></el-option>
<el-option label="2x" :value="2"></el-option>
<el-option label="10x" :value="10"></el-option>
</el-select>
</div>
<el-button :icon="renderIcon('Play')" type="primary"
v-if="!worldModel.state.runState.isRunning"
:disabled="!worldModel.state.runState.currentEnvId"
:loading="worldModel.state.runState.isLoading">启动
v-if="!worldModelState.runState.isRunning"
:disabled="!worldModelState.runState.currentEnvId"
:loading="worldModelState.runState.isLoading">启动
</el-button>
<el-button :icon="renderIcon('Stop')" type="danger" plain
v-if="worldModel.state.runState.isRunning"
:loading="worldModel.state.runState.isLoading">停止
v-if="worldModelState.runState.isRunning"
:loading="worldModelState.runState.isLoading">停止
</el-button>
</div>
</div>
@ -47,7 +47,7 @@
</span>
</div>
</div>
<div class="app-section" v-if="worldModel.state.isOpened">
<div class="app-section" v-if="worldModelState.isOpened">
<div class="btns-toolbar btns-toolbar-left">
<div class="btns btns-top">
<template v-for="panel in getWidgetBySide('left')">
@ -150,6 +150,7 @@ import Logo from '@/assets/images/logo.png'
import './ModelMain.less'
import EventBus from '@/runtime/EventBus.js'
import { useRouter } from 'vue-router'
import { worldModel } from '@/core/manager/WorldModel.ts'
import runManager from '@/core/manager/RunManager.js'
export default {
@ -225,10 +226,10 @@ export default {
},
computed: {
isModelOpen() {
return this.worldModel.state.isOpened
return this.worldModelState.isOpened
},
worldModel() {
return window['worldModel']
worldModelState() {
return worldModel.state
},
calcLeftPanel() {
if (!this.sectionLeftName || this.hideLeft) {
@ -260,6 +261,12 @@ export default {
}
},
watch: {
'worldModel.state.project_uuid': {
handler() {
this.reloadEnvList()
},
immediate: true
},
hideBottom(value) {
if (value) {
this.$refs.mainSplit.refreshSize([100, 0])
@ -278,7 +285,7 @@ export default {
renderIcon,
getWidgetBySide,
reloadEnvList() {
runManager.getAllEnv(this.worldModel.state.project_uuid).then(res => {
runManager.getAllEnv(this.worldModelState.project_uuid).then(res => {
this.envList = res.data
})
},

5
src/editor/ModelMainInit.ts

@ -13,10 +13,10 @@ import FileMenu from './menus/FileMenu'
import EditMenu from './menus/EditMenu'
import ToolsMenu from './menus/Tools'
import Model3DView from './menus/Model3DView'
import { worldModel } from '@/core/manager/WorldModel.ts'
import { install as ThreeExtendInstall } from '@/core/ThreeExtend.ts'
import { forEachMenu } from '@/runtime/DefineMenu'
import { normalizeShortKey } from '@/utils/webutils'
import WorldModel from '@/core/manager/WorldModel'
/**
*
@ -36,9 +36,6 @@ export function ModelMainInit() {
ToolsMenu.install()
Model3DView.install()
const worldModel = new WorldModel()
window['worldModel'] = worldModel
ThreeExtendInstall()
}

181
src/editor/menus/FileMenu.ts

@ -6,49 +6,50 @@ import type Viewport from '@/core/engine/Viewport.ts'
import DataForm from '@/components/data-form/DataForm.vue'
import OpenProject from '../OpenProject.vue'
import { Request } from '@ease-forge/shared'
import { worldModel } from '@/core/manager/WorldModel.ts'
function addProject(successful?: Function) {
const data = {
server: window.location.origin,
};
system.showDialog(createVNode(DataForm, {
style: {
paddingRight: "12px",
},
data: data,
formFields: [
{
dataPath: 'projectUuid', label: '项目编号', input: 'Input',
inputProps: {
placeholder: '请输入项目唯一编号',
},
},
{
dataPath: 'projectLabel', label: '项目标题', input: 'Input',
inputProps: {
placeholder: '请输入项目标题',
},
},
],
columnCount: 1,
labelWidth: "80px",
}), {
title: '创建项目',
width: 480,
height: 200,
showClose: true,
showMax: false,
showCancelButton: true,
showOkButton: true,
okButtonText: "创建",
cancelButtonText: "取消",
const data = {
server: window.location.origin
}
system.showDialog(createVNode(DataForm, {
style: {
paddingRight: '12px'
},
data: data,
formFields: [
{
dataPath: 'projectUuid', label: '项目编号', input: 'Input',
inputProps: {
placeholder: '请输入项目唯一编号'
}
},
{
dataPath: 'projectLabel', label: '项目标题', input: 'Input',
inputProps: {
placeholder: '请输入项目标题'
}
}
],
columnCount: 1,
labelWidth: '80px'
}), {
title: '创建项目',
width: 480,
height: 200,
showClose: true,
showMax: false,
showCancelButton: true,
showOkButton: true,
okButtonText: '创建',
cancelButtonText: '取消'
}).then(() => {
Request.request.post("/api/workbench/LccModelManager@addProject", data).then(()=> {
system.msg("创建成功");
successful?.();
})
}).finally();
}).then(() => {
Request.request.post('/api/workbench/LccModelManager@addProject', data).then(() => {
system.msg('创建成功')
successful?.()
})
}).finally()
}
export default defineMenu((menus) => {
@ -59,65 +60,65 @@ export default defineMenu((menus) => {
[
{
name: 'open', label: '打开', icon: SvgCode.open, order: 1, tip: 'Ctrl+O',
click: async () => {
click: async () => {
worldModel.state.isOpened = false
worldModel.state.isDraft = false
worldModel.state.catalog = []
worldModel.state.catalogCode = ''
worldModel.state.stateManagerId = ''
setQueryParam('store', '')
system.showLoading()
try {
await nextTick()
const res = await import('@/example/example1')
worldModel.state.isDraft = false
await worldModel.loadWorldFromRemoting(res.default)
} finally {
system.clearLoading()
}
},
click2: async () => {
let dialog: any = null
system.showDialog(createVNode(OpenProject, {
onCancel: () => dialog?.onClose(),
onOpen: async row => {
dialog?.onClose()
const veryBigData = JSON.parse(row.otherData)
veryBigData.catalog = JSON.parse(row.directoryData)
veryBigData.items = []
worldModel.state.isOpened = false
worldModel.state.isDraft = false
worldModel.state.catalog = []
worldModel.state.catalogCode = ''
worldModel.state.stateManagerId = ''
setQueryParam('store', '')
system.showLoading()
try {
await nextTick()
const res = await import('@/example/example1')
worldModel.state.isDraft = false
await worldModel.loadWorldFromRemoting(res.default)
await nextTick()
worldModel.state.isDraft = false
await worldModel.loadWorldFromRemoting(veryBigData)
} finally {
system.clearLoading()
system.clearLoading()
}
},
click2: async () => {
let dialog: any = null;
system.showDialog(createVNode(OpenProject, {
onCancel: () => dialog?.onClose(),
onOpen: async row => {
dialog?.onClose();
const veryBigData = JSON.parse(row.otherData);
veryBigData.catalog = JSON.parse(row.directoryData);
veryBigData.items = [];
worldModel.state.isOpened = false
worldModel.state.isDraft = false
worldModel.state.catalog = []
worldModel.state.catalogCode = ''
worldModel.state.stateManagerId = ''
setQueryParam('store', '')
system.showLoading()
try {
await nextTick()
worldModel.state.isDraft = false
await worldModel.loadWorldFromRemoting(veryBigData)
} finally {
system.clearLoading()
}
},
onAdd: that => {
addProject(() => that.loadData());
},
}), {
title: '打开项目',
width: 1500,
height: 500,
showClose: true,
showMax: true,
showCancelButton: false,
showOkButton: false,
okButtonText: "创建",
cancelButtonText: "取消",
onMounted: d => dialog = d,
}).finally();
},
onAdd: that => {
addProject(() => that.loadData())
}
}), {
title: '打开项目',
width: 1500,
height: 500,
showClose: true,
showMax: true,
showCancelButton: false,
showOkButton: false,
okButtonText: '创建',
cancelButtonText: '取消',
onMounted: d => dialog = d
}).finally()
}
},
{
@ -131,7 +132,7 @@ export default defineMenu((menus) => {
{
name: 'saveAs', label: '新建项目', icon: renderIcon('ModelFile'), order: 3,
click: () => {
addProject();
addProject()
}
}
]

1
src/editor/widgets/modeltree/ModeltreeViewJs.js

@ -1,6 +1,7 @@
import { defineComponent, markRaw } from 'vue'
import YvTable from '@/components/yvTable/YvTable.vue'
import IWidgets from '../IWidgets.js'
import { worldModel } from '@/core/manager/WorldModel.ts'
export default defineComponent({
name: 'ModeltreeView',

2
src/main.ts

@ -25,7 +25,7 @@ async function main() {
app.use(webIndex)
app.mount('#app')
globalConfig()
await getCurrentUser()
// await getCurrentUser()
}
main().finally()

7
src/modules/agv1/index.ts

@ -5,9 +5,8 @@ import propertySetter from './Agv1PropertySetter.ts'
export const ITEM_TYPE_NAME = 'agv1'
export default defineModule({
name: ITEM_TYPE_NAME,
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new Agv1Renderer(ITEM_TYPE_NAME),
interaction: new Agv1Interaction(ITEM_TYPE_NAME),
setter: propertySetter,
})
setter: propertySetter
}))

13
src/modules/carton/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import CartonRenderer from './CartonRenderer.ts'
import CartonInteraction from './CartonInteraction.ts'
import propertySetter from "./CartonPropertySetter.ts";
import propertySetter from './CartonPropertySetter.ts'
export const ITEM_TYPE_NAME = 'carton'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new CartonRenderer(ITEM_TYPE_NAME),
interaction: new CartonInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new CartonRenderer(ITEM_TYPE_NAME),
interaction: new CartonInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

13
src/modules/charger/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import ChargerRenderer from './ChargerRenderer.ts'
import ChargerInteraction from './ChargerInteraction.ts'
import propertySetter from "@/modules/charger/ChargerPropertySetter.ts";
import propertySetter from '@/modules/charger/ChargerPropertySetter.ts'
export const ITEM_TYPE_NAME = 'charger'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new ChargerRenderer(ITEM_TYPE_NAME),
interaction: new ChargerInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new ChargerRenderer(ITEM_TYPE_NAME),
interaction: new ChargerInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

13
src/modules/cl2/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import Cl2Renderer from './Cl2Renderer.ts'
import Cl2Interaction from './Cl2Interaction.ts'
import propertySetter from "./Cl2PropertySetter.ts";
import propertySetter from './Cl2PropertySetter.ts'
export const ITEM_TYPE_NAME = 'cl2'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new Cl2Renderer(ITEM_TYPE_NAME),
interaction: new Cl2Interaction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new Cl2Renderer(ITEM_TYPE_NAME),
interaction: new Cl2Interaction(ITEM_TYPE_NAME),
setter: propertySetter
}))

14
src/modules/clx/index.ts

@ -1,13 +1,13 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import ClxRenderer from './ClxRenderer.ts'
import ClxInteraction from './ClxInteraction.ts'
import propertySetter from "@/modules/clx/ClxPropertySetter.ts";
import propertySetter from '@/modules/clx/ClxPropertySetter.ts'
export const ITEM_TYPE_NAME = 'clx'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new ClxRenderer(ITEM_TYPE_NAME),
interaction: new ClxInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME,
renderer: new ClxRenderer(ITEM_TYPE_NAME),
interaction: new ClxInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

13
src/modules/gstore/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import GstoreRenderer from './GstoreRenderer.ts'
import GstoreInteraction from './GstoreInteraction.ts'
import propertySetter from "@/modules/gstore/GstorePropertySetter.ts";
import propertySetter from '@/modules/gstore/GstorePropertySetter.ts'
export const ITEM_TYPE_NAME = 'gstore'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new GstoreRenderer(ITEM_TYPE_NAME),
interaction: new GstoreInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new GstoreRenderer(ITEM_TYPE_NAME),
interaction: new GstoreInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

3
src/modules/measure/MeasureRenderer.ts

@ -7,6 +7,9 @@ import LineSegmentManager, { LineWrap } from '@/core/manager/LineSegmentManager.
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
debugger
console.log('MeasureRenderer initialized at', performance.now());
/**
*
* InstanceMesh LineSegment

15
src/modules/measure/index.ts

@ -1,13 +1,14 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import MeasureRenderer from './MeasureRenderer.ts'
import MeasureInteraction from './MeasureInteraction.ts'
import propertySetter from "@/modules/measure/MeasurePropertySetter.ts";
import propertySetter from '@/modules/measure/MeasurePropertySetter.ts'
export const ITEM_TYPE_NAME = 'measure'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new MeasureRenderer(ITEM_TYPE_NAME),
interaction: new MeasureInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
console.log('MeasureRenderer initialized at', performance.now())
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new MeasureRenderer(ITEM_TYPE_NAME),
interaction: new MeasureInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

13
src/modules/pallet/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import PalletRenderer from './PalletRenderer.ts'
import PalletInteraction from './PalletInteraction.ts'
import propertySetter from "@/modules/pallet/PalletPropertySetter.ts";
import propertySetter from '@/modules/pallet/PalletPropertySetter.ts'
export const ITEM_TYPE_NAME = 'pallet'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new PalletRenderer(ITEM_TYPE_NAME),
interaction: new PalletInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new PalletRenderer(ITEM_TYPE_NAME),
interaction: new PalletInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

760
src/modules/rack/RackRenderer.ts_back

@ -1,760 +0,0 @@
import * as THREE from 'three'
import { BufferGeometry } from 'three'
import BaseRenderer from '@/core/base/BaseRenderer.ts'
import { decimalSumBy } from '@/core/ModelUtils'
import Constract from '@/core/Constract.ts'
import Plastic_Rough_JPG from '@/assets/Models/Plastic_Rough.jpg?inline'
import storageBar_PNG from '@/assets/Models/storageBar.png?inline'
import { Material } from 'three/src/materials/Material'
import { InstancedMesh } from 'three/src/objects/InstancedMesh'
//@ts-ignore
import { mergeGeometries } from 'three/addons/utils/BufferGeometryUtils.js'
import type Viewport from '@/core/engine/Viewport.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
/**
* 货架货位渲染器
*/
export default class RackRenderer extends BaseRenderer {
static POINT_NAME = 'rack'
pointMaterial: THREE.Material
/**
* 默认点的高度, 防止和地面重合
*/
readonly defulePositionY: number = Constract.HEIGHT_WAY
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(1, 1, 1)
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0)
readonly defaultLineWidth: number = 0.05
constructor(itemTypeName: string) {
super(itemTypeName)
}
/**
* 所有的点,必须使用 storeWidth/storeDepth, 改TF无效
*/
override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: THREE.Object3D) {
super.afterCreateOrUpdatePoint(item, option, object)
const point = object
point.position.y = this.defulePositionY
//point.scale.set(_.sumBy(item.dt.bays, b=>b.bayWidth), this.defaultScale.y, item.dt.rackDepth)
point.rotation.set(
THREE.MathUtils.degToRad(item.tf[1][0]),
THREE.MathUtils.degToRad(item.tf[1][1]),
THREE.MathUtils.degToRad(item.tf[1][2])
)
}
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D {
throw new Error('not allow store line.')
}
updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) {
throw new Error('not allow store line.')
}
/**
* 获取物品存放在货架后的位置和旋转角度
* item.dt.storeAt 必须存在, 比如 { item:'货架ID', bay:0, level:1, cell:0 }
*/
getStorePlacement(viewport: Viewport, item: ItemJson): { position: [number, number, number], rotation: [number, number, number] } {
if (!item.dt?.storeAt?.item) {
// 没有定义存储位置,返回空对象
//@ts-ignore
return {}
}
const bay = item.dt?.storeAt?.bay || 0
const level = item.dt?.storeAt?.level || 0
// 暂时不用算格子 const cell = item.dt?.storeAt?.cell || 0
// 目标货架
const rack = viewport.stateManager.findItemById(item.dt.storeAt.item)
const rackWidth = decimalSumBy(rack.dt.bays, (b: any) => b.bayWidth)
const bays = rack.dt.bays
const levelHeights = rack.dt.bays[bay]?.levelHeight
// 局部坐标系下的偏移量
let localX = 0
for (let i = 0; i < bay; i++) {
localX += bays[i]?.bayWidth || 0
}
localX += bays[bay].bayWidth / 2 // 居中
let localY = 0
for (let i = 0; i < level; i++) {
localY += levelHeights[i]
}
// 构建局部偏移向量
const rackPos = new THREE.Vector3(...rack.tf[0])
const offset = new THREE.Vector3(
localX - rackWidth / 2, // 相对坐标从最左边开始,
localY, 0)
// 应用货架的旋转
const q = new THREE.Quaternion()
q.setFromEuler(new THREE.Euler(
THREE.MathUtils.degToRad(rack.tf[1][0]),
THREE.MathUtils.degToRad(rack.tf[1][1]),
THREE.MathUtils.degToRad(rack.tf[1][2])
))
offset.applyQuaternion(q)
const worldPosition = rackPos.clone().add(offset)
return {
position: [
worldPosition.x,
worldPosition.y + this.bottomBarHeight + 0.1, // 加上横梁高度
worldPosition.z
],
rotation: [
// 托盘旋转90度才能放进货架
rack.tf[1][0],
rack.tf[1][1] + 90,
rack.tf[1][2]
]
}
}
updatePoint(item: ItemJson, group: THREE.Group, option?: RendererCudOption): THREE.Group {
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
group.rotation.set(
THREE.MathUtils.degToRad(item.tf[1][0]),
THREE.MathUtils.degToRad(item.tf[1][1]),
THREE.MathUtils.degToRad(item.tf[1][2])
)
// group.scale 不允许修改!!
// 禁止缩放,
item.tf[2][0] = item.dt.rackWidth
item.tf[2][1] = item.dt.rackHeight
// 更新放在内部的所有箱子
const subItems = this.tempViewport.runtimeManager.getItemsByRack(item.id)
const viewport = this.tempViewport
if (subItems) {
_.defer(() => {
viewport.stateManager.update(({ getEntity, putEntity, deleteEntity, addEntity }) => {
for (const subItemId of subItems) {
const subItem = getEntity(subItemId)
if (subItem) {
const { position, rotation } = this.getStorePlacement(viewport, subItem)
if (position) {
subItem.tf[0][0] = position[0]
subItem.tf[0][1] = position[1]
subItem.tf[0][2] = position[2]
subItem.tf[1][0] = rotation[0]
subItem.tf[1][1] = rotation[1]
subItem.tf[1][2] = rotation[2]
putEntity(subItem)
}
}
}
})
})
}
return group
}
createPoint(item: ItemJson, option?: RendererCudOption): THREE.Object3D {
// 创建平面几何体
if (!item.dt.bays || !item.dt.rackDepth) {
system.showErrorDialog('RackRenderer field bays / rackDepth is null!')
return null
}
const group = new THREE.Group()
group.name = RackRenderer.POINT_NAME
const rackWidth = decimalSumBy(item.dt.bays, (b: any) => b.bayWidth)
const heights = []
for (let i = 0; i < item.dt.bays.length; i++) {
const bay = item.dt.bays[i]
const bayHeight = decimalSumBy(bay.levelHeight)
heights.push(bayHeight)
}
const rackHeight = _.max(heights)
// // 绘制背景矩形框
// const planeGeometry = new THREE.PlaneGeometry(rackWidth, item.dt.rackDepth)
//
// planeGeometry.rotateX(Math.PI / 2)
//
// const planeMaterial = new THREE.MeshBasicMaterial({
// color: '#9a9090',
// transparent: true, // 启用透明
// opacity: 0.5, // 50%透明度
// depthWrite: false, // 防止深度冲突
// side: THREE.DoubleSide // 双面渲染:ml-citation{ref="5,8" data="citationList"}
// })
// const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial)
// group.add(planeMesh)
//
//
// // 绘制边框
// const lineXLen = rackWidth - this.defaultLineWidth
// const lineYLen = item.dt.rackDepth - this.defaultLineWidth
//
// const lineGeometry = new LineGeometry().setPositions([
// -(lineXLen / 2), 0, -(lineYLen / 2),
// lineXLen / 2, 0, -(lineYLen / 2),
// lineXLen / 2, 0, lineYLen / 2,
// -(lineXLen / 2), 0, lineYLen / 2,
// -(lineXLen / 2), 0, -(lineYLen / 2)
// ])
// const lineMaterial = new LineMaterial({
// color: '#0d89a5',
// linewidth: this.defaultLineWidth,
// worldUnits: true,
// resolution: new THREE.Vector2(window.innerWidth, window.innerHeight),
// side: THREE.DoubleSide
// })
// const line = new Line2(lineGeometry, lineMaterial)
// group.add(line as THREE.Object3D)
//
// let lineDistanceX = 0
//
// for (let i = 0; item.dt.bays.length > 1 && i < item.dt.bays.length - 1; i++) {
// const bay = item.dt.bays[i]
// lineDistanceX += bay.bayWidth
// const lineGeometryT = new LineGeometry().setPositions([
// -(lineDistanceX) + (lineXLen / 2), 0, lineYLen / 2,
// -(lineDistanceX) + (lineXLen / 2), 0, -(lineYLen / 2)
// ])
// const lineT = new Line2(lineGeometryT, lineMaterial)
// group.add(lineT as THREE.Object3D)
// }
const meshes = this.createRack(item, option)
meshes.forEach(mesh => {
group.add(mesh)
mesh.instanceMatrix.needsUpdate = true
})
// 设置位置
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
group.rotation.set(
THREE.MathUtils.degToRad(item.tf[1][0]),
THREE.MathUtils.degToRad(item.tf[1][1]),
THREE.MathUtils.degToRad(item.tf[1][2])
)
item.dt.rackWidth = rackWidth
item.dt.rackHeight = rackHeight
item.tf[2][0] = item.dt.rackWidth
item.tf[2][1] = item.dt.rackHeight
return group
}
dispose() {
super.dispose()
this.pointMaterial?.dispose()
}
rackVerticalBarWidth = 0.1
rackVerticalBarDepth = 0.08
rackVerticalBarColor = 0xFF35499C
rackVerticalBarGeometry: BufferGeometry = null
rackVerticalBarMaterial: Material = null
rackLinkBarColor = 0xFF35499C
rackLinkBarGeometry: BufferGeometry = null
rackLinkBarMaterial: Material = null
rackHorizontalBarWidth = 0.1
rackHorizontalBarDepth = 0.08
rackHorizontalBarColor = 0xFFF97F27
rackHorizontalBarGeometry: BufferGeometry = null
rackHorizontalBarMaterial: Material = null
bottomBarHeight = 0.2
bottomLinkHeight = 0.2
barSectionPoints = [
{ x: -0.05, y: -0.05 },
{ x: -0.025, y: -0.05 },
{ x: -0.01, y: -0.045 },
{ x: 0.01, y: -0.045 },
{ x: 0.025, y: -0.05 },
{ x: 0.05, y: -0.05 },
{ x: 0.05, y: 0.042 },
{ x: 0.042, y: 0.05 },
{ x: 0.025, y: 0.05 },
{ x: 0.025, y: 0.042 },
{ x: 0.042, y: 0.042 },
{ x: 0.042, y: -0.042 },
{ x: -0.042, y: -0.042 },
{ x: -0.042, y: 0.042 },
{ x: -0.025, y: 0.042 },
{ x: -0.025, y: 0.05 },
{ x: -0.042, y: 0.05 },
{ x: -0.05, y: 0.042 },
{ x: -0.05, y: -0.05 }
]
linkSectionPoints = [
{ x: -0.05, y: -0.05 },
{ x: -0.05, y: 0.05 },
{ x: 0, y: 0.05 },
{ x: 0, y: 0.06 },
{ x: -0.06, y: 0.06 },
{ x: -0.06, y: -0.05 },
{ x: -0.05, y: -0.05 }
]
linkBarSectionPoints = [
{ x: -0.025, y: -0.025 },
{ x: 0.025, y: -0.025 },
{ x: 0.025, y: 0.025 },
{ x: -0.025, y: 0.025 },
{ x: -0.025, y: -0.025 }
]
createVerticalBar(x, y, z, length): THREE.BufferGeometry {
// 创建一个形状 柱子的截面形状
const shape = new THREE.Shape()
shape.moveTo(this.barSectionPoints[0].x, this.barSectionPoints[0].y)
for (let i = 1; i < this.barSectionPoints.length; i++) {
shape.lineTo(this.barSectionPoints[i].x, this.barSectionPoints[i].y)
}
// 拉伸轨迹线
const curve = new THREE.CatmullRomCurve3(
[new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, length, 0)],
false, // 闭合曲线
'catmullrom',
0
)
// 挤出几何图形 参数
const options = {
steps: 1,
bevelEnabled: false,
extrudePath: curve // 设置挤出轨迹
}
// 创建挤出几何体
const geometry = new THREE.ExtrudeGeometry(shape, options)
// 调整uv方便正确贴图
this.resetUVs(geometry)
return geometry
}
createVerticalBarMaterial(): THREE.Material {
let textureLoader = new THREE.TextureLoader()
// 加载纹理
const textureHole = textureLoader.load(storageBar_PNG) // 孔洞
const textureMaterial = textureLoader.load(Plastic_Rough_JPG) // 表面材质
textureHole.repeat.set(10, 18) // X轴重复,Y轴重复
textureMaterial.repeat.set(2, 2) // X轴重复,Y轴重复
// textureHole.offset.set(0.5, 0)
// textureHole.center.set(0.5, 0)
// 必须设置包裹模式为重复
textureHole.wrapS = THREE.RepeatWrapping
textureHole.wrapT = THREE.RepeatWrapping
textureMaterial.wrapS = THREE.RepeatWrapping
textureMaterial.wrapT = THREE.RepeatWrapping
const material = new THREE.MeshPhongMaterial()
material.alphaMap = textureHole
material.normalMap = textureMaterial
material.color.setHex(this.rackVerticalBarColor, 'srgb')
material.specular.setHex(0xff6d6d6d, 'srgb')
material.transparent = true
material.needsUpdate = true
return material
}
createLinkBar(x, y, z, vBarLength, depth, bottomDistance, topDistance): THREE.BufferGeometry {
const bgs: BufferGeometry[] = []
const top = vBarLength - topDistance
// 创建一个形状 柱子的截面形状
const shape = new THREE.Shape()
shape.moveTo(this.linkBarSectionPoints[0].x, this.linkBarSectionPoints[0].y)
for (let i = 1; i < this.linkBarSectionPoints.length; i++) {
shape.lineTo(this.linkBarSectionPoints[i].x, this.linkBarSectionPoints[i].y)
}
// 拉伸轨迹线 横向 底部
const curveHBottom = new THREE.CatmullRomCurve3(
[new THREE.Vector3(0, bottomDistance, 0), new THREE.Vector3(0, bottomDistance, depth)],
false, // 闭合曲线
'catmullrom',
0
)
// 挤出几何图形 参数
const optionsHBottom = {
steps: 1,
bevelEnabled: false,
extrudePath: curveHBottom // 设置挤出轨迹
}
// 拉伸轨迹线 横向 底部
const curveHTop = new THREE.CatmullRomCurve3(
[new THREE.Vector3(0, top, 0), new THREE.Vector3(0, top, depth)],
false, // 闭合曲线
'catmullrom',
0
)
// 挤出几何图形 参数
const optionsHTop = {
steps: 1,
bevelEnabled: false,
extrudePath: curveHTop // 设置挤出轨迹
}
// 创建挤出几何体
const geometryHBottom = new THREE.ExtrudeGeometry(shape, optionsHBottom)
const geometryHTop = new THREE.ExtrudeGeometry(shape, optionsHTop)
bgs.push(geometryHBottom, geometryHTop)
let remainingHeight = vBarLength - bottomDistance - topDistance
// 需要创建斜杆
for (let i = 0; i < Math.floor(remainingHeight / depth); i++) {
// 拉伸轨迹线 斜向
const curveD = new THREE.CatmullRomCurve3(
(i % 2 == 0) ? [new THREE.Vector3(0, bottomDistance + depth * i, 0), new THREE.Vector3(0, bottomDistance + depth * (i + 1), depth)]
: [new THREE.Vector3(0, bottomDistance + depth * (i + 1), 0), new THREE.Vector3(0, bottomDistance + depth * (i), depth)],
false, // 闭合曲线
'catmullrom',
0
)
const optionsD = {
steps: 1,
bevelEnabled: false,
extrudePath: curveD // 设置挤出轨迹
}
const geometryD = new THREE.ExtrudeGeometry(shape, optionsD)
bgs.push(geometryD)
}
if (vBarLength - bottomDistance - topDistance > depth) {
}
// 调整uv方便正确贴图
// this.resetUVs(geometry);
return mergeGeometries(bgs)
}
createLinkBarMaterial(): THREE.Material {
const material = new THREE.MeshPhongMaterial()
material.color.setHex(this.rackLinkBarColor, 'srgb')
material.specular.setHex(0xff6d6d6d, 'srgb')
material.transparent = true
material.needsUpdate = true
return material
}
createHorizontalBar(x, y, z, length): THREE.BufferGeometry {
// 创建一个形状 柱子的截面形状
const shape = new THREE.Shape()
shape.moveTo(this.barSectionPoints[0].x, this.barSectionPoints[0].y)
for (let i = 1; i < this.barSectionPoints.length; i++) {
shape.lineTo(this.barSectionPoints[i].x, this.barSectionPoints[i].y)
}
// 拉伸轨迹线
const curve = new THREE.CatmullRomCurve3(
[new THREE.Vector3(0.05, 0, 0), new THREE.Vector3(length - 0.05, 0, 0)],
false, // 闭合曲线
'catmullrom',
0
)
// 挤出几何图形 参数
const options = {
steps: 1,
bevelEnabled: false,
extrudePath: curve // 设置挤出轨迹
}
// 创建挤出几何体
const geometry = new THREE.ExtrudeGeometry(shape, options)
const linkShapeL = new THREE.Shape()
const linkShapeR = new THREE.Shape()
linkShapeL.moveTo(this.linkSectionPoints[0].x, this.linkSectionPoints[0].y)
linkShapeR.moveTo(this.linkSectionPoints[0].x + (length), this.linkSectionPoints[0].y)
for (let i = 1; i < this.linkSectionPoints.length; i++) {
linkShapeL.lineTo(this.linkSectionPoints[i].x, this.linkSectionPoints[i].y)
linkShapeR.lineTo(this.linkSectionPoints[i].x + (length), this.linkSectionPoints[i].y)
}
// 拉伸轨迹线
const linkCurve = new THREE.CatmullRomCurve3(
[new THREE.Vector3(0, 0, -0.08), new THREE.Vector3(0, 0, 0.08)],
false, // 闭合曲线
'catmullrom',
0
)
// 挤出几何图形 参数
const linkOptions = {
steps: 1,
bevelEnabled: false,
extrudePath: linkCurve // 设置挤出轨迹
}
// 创建挤出几何体
const linkGeometryL = new THREE.ExtrudeGeometry(linkShapeL, linkOptions)
linkGeometryL.rotateZ(-Math.PI / 2)
const linkGeometryR = new THREE.ExtrudeGeometry(linkShapeR, linkOptions)
linkGeometryR.rotateX(-Math.PI)
linkGeometryR.rotateZ(-Math.PI / 2)
// 调整uv方便正确贴图
// this.resetUVs(geometry);
return mergeGeometries([geometry, linkGeometryL, linkGeometryR])
}
createHorizontalBarMaterial(): THREE.Material {
const material = new THREE.MeshPhongMaterial()
material.color.setHex(this.rackHorizontalBarColor, 'srgb')
material.specular.setHex(0xff6d6d6d, 'srgb')
material.transparent = true
material.needsUpdate = true
return material
}
createRack(item: ItemJson, option?: RendererCudOption): InstancedMesh[] {
if (!item.dt.bays || !item.dt.rackDepth) {
system.showErrorDialog('RackRenderer field bays / rackDepth is null!')
return null
}
const rackPoint = {
x: item.tf[0][0],
y: item.tf[0][1],
z: item.tf[0][2]
}
const rackWidth = decimalSumBy(item.dt.bays, (b: any) => b.bayWidth)
const rackDepth = item.dt.rackDepth
const heights = []
for (let i = 0; i < item.dt.bays.length; i++) {
const bay = item.dt.bays[i]
const bayHeight = decimalSumBy(bay.levelHeight)
heights.push(bayHeight)
}
const rackHeight = _.max(heights)
// 计算立住坐标点和长度
const vBarMatrix: { x: number, y: number, z: number, sx: number, sy: number, sz: number, rx: number, ry: number, rz: number, l: number }[] = []
// 计算
const linkBarMatrix: { x: number, y: number, z: number, sx: number, sy: number, sz: number, rx: number, ry: number, rz: number, l: number }[] = []
let distanceX = 0, distanceY = 0
for (let i = -1; i < item.dt.bays.length; i++) {
if (i >= 0) {
const bay = item.dt.bays[i]
distanceX += bay.bayWidth
}
vBarMatrix.push({
x: distanceX - rackWidth / 2,
y: 0,
z: -rackDepth / 2,
sx: 0.8,
sy: 1,
sz: 1,
rx: 0,
ry: Math.PI / 2,
rz: 0,
l: rackHeight
})
vBarMatrix.push({
x: distanceX - rackWidth / 2,
y: 0,
z: item.dt.rackDepth - rackDepth / 2,
sx: 0.8,
sy: 1,
sz: 1,
rx: 0,
ry: -Math.PI / 2,
rz: 0,
l: rackHeight
})
linkBarMatrix.push({
x: distanceX - rackWidth / 2,
y: 0,
z: i % 2 == 0 ? (item.dt.rackDepth - rackDepth / 2) : -rackDepth / 2,
sx: 1,
sy: 1,
sz: 1,
rx: 0,
ry: i % 2 == 0 ? Math.PI : 0,
rz: 0,
l: rackHeight
})
}
// 计算横梁数量
const hBarMatrix: { x: number, y: number, z: number, sx: number, sy: number, sz: number, rx: number, ry: number, rz: number, l: number }[] = []
distanceX = 0
for (let i = 0; i < item.dt.bays.length; i++) {
distanceY = this.bottomBarHeight
const bay = item.dt.bays[i]
for (let j = 0; j < bay.levelHeight.length; j++) {
const levelHeight = bay.levelHeight[j]
if (distanceY <= 0) {
continue
}
hBarMatrix.push({
x: distanceX - rackWidth / 2,
y: distanceY,
z: -rackDepth / 2,
sx: 1,
sy: 0.8,
sz: 1,
rx: Math.PI / 2,
ry: 0,
rz: 0,
l: bay.bayWidth
})
hBarMatrix.push({
x: distanceX - rackWidth / 2,
y: distanceY,
z: item.dt.rackDepth - rackDepth / 2,
sx: 1,
sy: 0.8,
sz: 1,
rx: -Math.PI / 2,
ry: 0,
rz: 0,
l: bay.bayWidth
})
distanceY += levelHeight
}
distanceX += bay.bayWidth
}
const meshes: InstancedMesh[] = []
if (vBarMatrix.length > 0) {
if (!this.rackVerticalBarGeometry) {
this.rackVerticalBarGeometry = this.createVerticalBar(vBarMatrix[0].x, vBarMatrix[0].y, vBarMatrix[0].z, vBarMatrix[0].l)
}
if (!this.rackVerticalBarMaterial) {
this.rackVerticalBarMaterial = this.createVerticalBarMaterial()
}
const dummy = new THREE.Object3D()
const vBarMesh = new THREE.InstancedMesh(this.rackVerticalBarGeometry, this.rackVerticalBarMaterial, vBarMatrix.length)
for (let i = 0; i < vBarMatrix.length; i++) {
const vp = vBarMatrix[i]
dummy.position.set(vp.x, vp.y, vp.z)
dummy.rotation.set(vp.rx, vp.ry, vp.rz)
dummy.scale.set(vp.sx, vp.sy, vp.sz)
dummy.updateMatrix()
vBarMesh.setMatrixAt(i, dummy.matrix)
}
meshes.push(vBarMesh)
}
if (linkBarMatrix.length > 0) {
if (!this.rackLinkBarGeometry) {
this.rackLinkBarGeometry = this.createLinkBar(linkBarMatrix[0].x, linkBarMatrix[0].y, linkBarMatrix[0].z, rackHeight, item.dt.rackDepth, this.bottomLinkHeight, 0.2)
}
if (!this.rackLinkBarMaterial) {
this.rackLinkBarMaterial = this.createLinkBarMaterial()
}
const dummy = new THREE.Object3D()
const linkBarMesh = new THREE.InstancedMesh(this.rackLinkBarGeometry, this.rackLinkBarMaterial, linkBarMatrix.length)
for (let i = 0; i < linkBarMatrix.length; i++) {
const lp = linkBarMatrix[i]
dummy.position.set(lp.x, lp.y, lp.z)
dummy.rotation.set(lp.rx, lp.ry, lp.rz)
dummy.scale.set(lp.sx, lp.sy, lp.sz)
dummy.updateMatrix()
linkBarMesh.setMatrixAt(i, dummy.matrix)
}
meshes.push(linkBarMesh)
}
if (hBarMatrix.length > 0) {
if (!this.rackHorizontalBarGeometry) {
this.rackHorizontalBarGeometry = this.createHorizontalBar(hBarMatrix[0].x, hBarMatrix[0].y, hBarMatrix[0].z, hBarMatrix[0].l)
}
if (!this.rackHorizontalBarMaterial) {
this.rackHorizontalBarMaterial = this.createHorizontalBarMaterial()
}
const dummy = new THREE.Object3D()
const hBarMesh = new THREE.InstancedMesh(this.rackHorizontalBarGeometry, this.rackHorizontalBarMaterial, hBarMatrix.length)
for (let i = 0; i < hBarMatrix.length; i++) {
const hp = hBarMatrix[i]
dummy.position.set(hp.x, hp.y, hp.z)
dummy.rotation.set(hp.rx, hp.ry, hp.rz)
dummy.scale.set(hp.sx, hp.sy, hp.sz)
dummy.updateMatrix()
hBarMesh.setMatrixAt(i, dummy.matrix)
}
meshes.push(hBarMesh)
}
return meshes
}
resetUVs(geometry: THREE.ExtrudeGeometry) {
if (geometry == undefined) return
const pos = geometry.getAttribute('position'),
nor = geometry.getAttribute('normal'),
uvs = geometry.getAttribute('uv')
for (let i = 0; i < pos.count; i++) {
let x = 0, y = 0
const nx = Math.abs(nor.getX(i)), ny = Math.abs(nor.getY(i)), nz = Math.abs(nor.getZ(i))
// if facing X
if (nx >= ny && nx >= nz) {
x = pos.getZ(i)
y = pos.getY(i)
}
// if facing Y
if (ny >= nx && ny >= nz) {
x = pos.getX(i)
y = pos.getZ(i)
}
// if facing Z
if (nz >= nx && nz >= ny) {
x = pos.getX(i)
y = pos.getY(i)
}
uvs.setXY(i, x, y)
}
}
}

13
src/modules/rack/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import RackRenderer from './RackRenderer.ts'
import RackInteraction from './RackInteraction.ts'
import propertySetter from "@/modules/rack/RackPropertySetter.ts";
import propertySetter from '@/modules/rack/RackPropertySetter.ts'
export const ITEM_TYPE_NAME = 'rack'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new RackRenderer(ITEM_TYPE_NAME),
interaction: new RackInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new RackRenderer(ITEM_TYPE_NAME),
interaction: new RackInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

13
src/modules/shuttle_rack/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import ShuttleRackRenderer from './ShuttleRackRenderer.ts'
import ShuttleRackInteraction from './ShuttleRackInteraction.ts'
import propertySetter from "./ShuttleRackPropertySetter.ts";
import propertySetter from './ShuttleRackPropertySetter.ts'
export const ITEM_TYPE_NAME = 'shuttle_rack'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new ShuttleRackRenderer(ITEM_TYPE_NAME),
interaction: new ShuttleRackInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new ShuttleRackRenderer(ITEM_TYPE_NAME),
interaction: new ShuttleRackInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

7
src/modules/tote/index.ts

@ -5,9 +5,8 @@ import propertySetter from './TotePropertySetter.ts'
export const ITEM_TYPE_NAME = 'tote'
export default defineModule({
name: ITEM_TYPE_NAME,
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new ToteRenderer(ITEM_TYPE_NAME),
interaction: new ToteInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
setter: propertySetter
}))

13
src/modules/way/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts'
import WayRenderer from './WayRenderer.ts'
import WayInteraction from './WayInteraction.ts'
import propertySetter from "@/modules/way/WayPropertySetter.ts";
import propertySetter from '@/modules/way/WayPropertySetter.ts'
export const ITEM_TYPE_NAME = 'way'
export default defineModule({
name: ITEM_TYPE_NAME,
renderer: new WayRenderer(ITEM_TYPE_NAME),
interaction: new WayInteraction(ITEM_TYPE_NAME),
setter: propertySetter,
})
export default defineModule(ITEM_TYPE_NAME, () => ({
renderer: new WayRenderer(ITEM_TYPE_NAME),
interaction: new WayInteraction(ITEM_TYPE_NAME),
setter: propertySetter
}))

1
src/types/global.d.ts

@ -9,6 +9,5 @@ declare global {
const _: _
const system: System
const worldModel: WorldModel
const CurrentMouseInfo: CurrentMouseInfo
}
Loading…
Cancel
Save