Browse Source

Merge remote-tracking branch 'origin/master'

master
yuliang 6 months ago
parent
commit
c46c165807
  1. 3
      doc/RCS3任务拆解.md
  2. 24
      doc/RCS数据库结构.md
  3. 3
      src/core/ModelUtils.ts
  4. 6
      src/core/manager/CodeDropper.ts
  5. 4
      src/core/manager/EntityManager.ts
  6. 44
      src/core/manager/ModuleManager.ts
  7. 67
      src/core/manager/RunManager.ts
  8. 56
      src/core/manager/WorldModel.ts
  9. 2
      src/editor/CatalogDefine.vue
  10. 1
      src/editor/Model2DEditor.vue
  11. 47
      src/editor/ModelMain.vue
  12. 5
      src/editor/ModelMainInit.ts
  13. 181
      src/editor/menus/FileMenu.ts
  14. 1
      src/editor/widgets/modeltree/ModeltreeViewJs.js
  15. 48
      src/example/example1.js
  16. 2
      src/main.ts
  17. 7
      src/modules/agv1/index.ts
  18. 13
      src/modules/carton/index.ts
  19. 13
      src/modules/charger/index.ts
  20. 13
      src/modules/cl2/index.ts
  21. 14
      src/modules/clx/index.ts
  22. 13
      src/modules/gstore/index.ts
  23. 15
      src/modules/measure/index.ts
  24. 13
      src/modules/pallet/index.ts
  25. 760
      src/modules/rack/RackRenderer.ts_back
  26. 13
      src/modules/rack/index.ts
  27. 13
      src/modules/shuttle_rack/index.ts
  28. 7
      src/modules/tote/index.ts
  29. 49
      src/modules/way/WayRenderer.ts
  30. 13
      src/modules/way/index.ts
  31. 3
      src/types/global.d.ts
  32. 17
      src/types/model.d.ts

3
doc/RCS3任务拆解.md

@ -111,8 +111,7 @@ CL2 和 CLX 使用的是货叉朝向和方向正负系。比如: 凯乐士CL2使
{ {
type: 'robotRotation', type: 'robotRotation',
executorId: '机器人编号', executorId: '机器人编号',
worldRotation: 90 worldRotation: 90 // 转动身体到世界角度 90 度, 世界角度为:上=0°,左=90°,右=270°,下=180°
// 转动身体到世界角度 90 度
} }
``` ```

24
doc/RCS数据库结构.md

@ -3,6 +3,7 @@ drop table if exists rcs_task_biz;
create table rcs_task_biz create table rcs_task_biz
( (
biz_task_id bigint not null, biz_task_id bigint not null,
env_id bigint not null comment '环境ID',
biz_type varchar(10) not null comment '任务类型' default 'carry', biz_type varchar(10) not null comment '任务类型' default 'carry',
lpn varchar(50) not null comment '托盘ID', lpn varchar(50) not null comment '托盘ID',
priority integer not null comment '任务优先级', priority integer not null comment '任务优先级',
@ -13,9 +14,9 @@ create table rcs_task_biz
biz_task_error_info varchar(500) default 'N/A' comment '异常提示信息', biz_task_error_info varchar(500) default 'N/A' comment '异常提示信息',
biz_task_description varchar(500) default 'N/A' comment '任务描述', biz_task_description varchar(500) default 'N/A' comment '任务描述',
biz_task_status varchar(10) default 'pending' comment '任务状态', biz_task_status varchar(10) default 'pending' comment '任务状态',
create_at timestamp not null comment '创建时间', create_at timestamp not null comment '创建时间',
create_by varchar(50) not null comment '创建人', create_by varchar(50) not null comment '创建人',
update_at timestamp not null comment '更新时间', update_at timestamp not null comment '更新时间',
update_by varchar(50) not null comment '更新人', update_by varchar(50) not null comment '更新人',
primary key (biz_task_id) primary key (biz_task_id)
); );
@ -25,6 +26,7 @@ create table rcs_task_plan
( (
plan_task_id bigint not null comment '规划ID', plan_task_id bigint not null comment '规划ID',
biz_task_id bigint not null comment '业务任务ID', biz_task_id bigint not null comment '业务任务ID',
env_id bigint not null comment '环境ID',
plan_type varchar(10) not null comment '规划类型' default 'carry', plan_type varchar(10) not null comment '规划类型' default 'carry',
executor_id varchar(50) not null comment '执行器ID', executor_id varchar(50) not null comment '执行器ID',
seq integer not null comment '规划序号', seq integer not null comment '规划序号',
@ -46,6 +48,7 @@ create table rcs_task_device
device_task_id bigint not null comment '设备任务ID', device_task_id bigint not null comment '设备任务ID',
plan_task_id bigint not null comment '规划ID', plan_task_id bigint not null comment '规划ID',
biz_task_id bigint not null comment '业务任务ID', biz_task_id bigint not null comment '业务任务ID',
env_id bigint not null comment '环境ID',
device_type varchar(50) not null comment '设备类型', device_type varchar(50) not null comment '设备类型',
device_item_id varchar(50) not null comment '执行器ID', device_item_id varchar(50) not null comment '执行器ID',
seq integer not null comment '执行序号', seq integer not null comment '执行序号',
@ -65,4 +68,21 @@ create table rcs_task_device
create index idx_rcs_task_device1 on rcs_task_device (biz_task_id); create index idx_rcs_task_device1 on rcs_task_device (biz_task_id);
create index idx_rcs_task_device2 on rcs_task_device (plan_task_id); create index idx_rcs_task_device2 on rcs_task_device (plan_task_id);
drop table if exists lcc_env_info;
create table lcc_env_info
(
env_id bigint not null comment '环境ID',
world_id varchar(50) not null comment '世界地图ID',
env_name varchar(50) not null comment '环境名称',
is_virtual boolean not null default false comment '是否虚拟环境',
env_payload varchar(3000) not null default 'N/A' comment '环境负载信息',
create_at timestamp not null comment '创建时间',
create_by varchar(50) not null comment '创建人',
update_at timestamp not null comment '更新时间',
update_by varchar(50) not null comment '更新人',
primary key (env_id)
);
create index idx_lcc_env_info_1 on lcc_env_info (world_id);
``` ```

3
src/core/ModelUtils.ts

@ -1,7 +1,6 @@
import * as THREE from 'three' import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport' import type Viewport from '@/core/engine/Viewport'
import { Vector2 } from 'three/src/math/Vector2' import { Vector2 } from 'three/src/math/Vector2'
import EventBus from '@/runtime/EventBus.ts'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts' import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import axios from 'axios' 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 { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { TDSLoader } from 'three/examples/jsm/loaders/TDSLoader' import { TDSLoader } from 'three/examples/jsm/loaders/TDSLoader'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' 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 { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { Line2 } from 'three/examples/jsm/lines/Line2' import { Line2 } from 'three/examples/jsm/lines/Line2'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry' import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'

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 droppedItemCallback: (item: ItemJson, pos: THREE.Vector3, evt: MouseEvent) => boolean
} }
defineModule({ const ITEM_NAME = 'CodeDropper'
name: 'CodeDropper', defineModule(ITEM_NAME, () => ({
interaction: CodeDropper.INSTANCE interaction: CodeDropper.INSTANCE
}) }))

4
src/core/manager/EntityManager.ts

@ -473,11 +473,11 @@ export default class EntityManager {
} }
} }
appendLineObject(id: string, lines: LineLike) { appendLineObject(id: string, lines: any) {
this.__lineMap.set(id, lines) this.__lineMap.set(id, lines)
} }
findLineObjectById(lineId: string): LineLike | undefined { findLineObjectById(lineId: string): any | undefined {
return this.__lineMap.get(lineId) return this.__lineMap.get(lineId)
} }

44
src/core/manager/ModuleManager.ts

@ -1,17 +1,20 @@
import * as THREE from 'three'
import BaseRenderer from '@/core/base/BaseRenderer' import BaseRenderer from '@/core/base/BaseRenderer'
import BaseInteraction from '@/core/base/BaseInteraction' 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 // Define the ModuleDefineOption interface
export interface ModuleDefineOption { export interface ModuleDefineOption {
/** /**
* *
*/ */
name: string;
renderer?: BaseRenderer; renderer?: BaseRenderer;
/**
*
*/
interaction?: BaseInteraction; interaction?: BaseInteraction;
/**
*
*/
setter?: PropertySetter; setter?: PropertySetter;
} }
@ -22,12 +25,19 @@ window['modules'] = modules
/** /**
* *
*/ */
export function defineModule(option: ModuleDefineOption): Promise<any> { export function defineModule(name: string, optionFn: () => ModuleDefineOption): Promise<any> {
if (modules.has(option.name)) { if (modules.has(name)) {
throw new Error(`Module with name "${option.name}" is already defined.`) throw new Error(`Module with name "${name}" is already defined.`)
} }
modules.set(option.name, option) return new Promise((resolve) => {
return option.renderer?.init() 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) { export function getSetter(name: string) {
const module = getModuleOption(name) const module = getModuleOption(name)
return module.setter; 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
} }

67
src/core/manager/RunManager.ts

@ -0,0 +1,67 @@
import { Request } from '@ease-forge/shared'
/**
*
*/
class RunManager {
// 是否正在运行
isRunning: boolean = false
/**
*
*/
async getAllEnv(worldId: string): Promise<ServerResponse<EnvInfo[]>> {
// system.invokeServer('')
if (!worldId) {
return Promise.resolve({ success: true, data: [], msg: '' })
}
const res = await Request.request.post('/api/workbench/EnvController@getAllEnv', {
worldId: worldId
})
for (const env of res.data) {
// payload 转换为 json 数据
if (env.env_payload) {
try {
env.env_payload = JSON.parse(env.env_payload)
} catch (e) {
console.error('解析环境负载失败:', e)
env.env_payload = {}
}
}
}
return res
}
/**
*
* @param worldId ID
* @param envName
* @param isVirtual
*/
async createEnv(worldId: string, envName: string, isVirtual: boolean) {
throw new Error('Method not implemented.')
}
/**
*
*/
async run(timeRate: number, envId: number) {
if (this.isRunning) {
await this.stop()
}
// 启动 websocket 监听等等
}
/**
*
*/
async stop() {
// 停止 websocket 监听等等
}
}
const runManager = new RunManager()
export default runManager

56
src/core/manager/WorldModel.ts

@ -1,18 +1,6 @@
import _, { cloneDeep } from 'lodash' import _, { cloneDeep } from 'lodash'
import { reactive, watch } from 'vue' import { reactive, watch } from 'vue'
import EventBus from '@/runtime/EventBus' 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 StateManager from '@/core/manager/StateManager.ts'
import { getQueryParams, setQueryParam } from '@/utils/webutils.ts' import { getQueryParams, setQueryParam } from '@/utils/webutils.ts'
import localforage from 'localforage' import localforage from 'localforage'
@ -30,6 +18,14 @@ export interface WorldModelState {
stateManagerId: string // 当前楼层的状态管理器id stateManagerId: string // 当前楼层的状态管理器id
isDraft: boolean // 是否是草稿数据 isDraft: boolean // 是否是草稿数据
runState: {
currentEnvId: number,
isLoading: boolean,
isRunning: boolean,
isVirtual: boolean,
timeRate: number,
}
} }
/** /**
@ -53,7 +49,15 @@ export default class WorldModel {
catalogCode: '', // 当前楼层的目录代码 catalogCode: '', // 当前楼层的目录代码
stateManagerId: '', // 当前楼层的状态管理器id, 一般是 项目ID+目录项ID stateManagerId: '', // 当前楼层的状态管理器id, 一般是 项目ID+目录项ID
isDraft: false // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据 isDraft: false, // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据
runState: {
currentEnvId: 0,
isLoading: false,
isRunning: false,
isVirtual: false,
timeRate: 1
}
}) })
get gridOption(): IGridHelper { get gridOption(): IGridHelper {
@ -85,18 +89,17 @@ export default class WorldModel {
init() { init() {
// 观察 this.state.catalogCode 的变化, 如果变化就调用 catalogCodeChange 方法 // 观察 this.state.catalogCode 的变化, 如果变化就调用 catalogCodeChange 方法
return Promise.all([ return Promise.all([
Measure, import('../../modules/measure'),
Way, import('../../modules/way'),
Gstore, import('../../modules/gstore'),
Rack, import('../../modules/rack'),
ShuttleRack, import('../../modules/shuttle_rack'),
Pallet, import('../../modules/pallet'),
Tote, import('../../modules/tote'),
Carton, import('../../modules/carton'),
Cl2, import('../../modules/cl2'),
Clx, import('../../modules/clx'),
// Agv1, import('../../modules/charger')
Charger
]).then(() => { ]).then(() => {
console.log('世界模型初始化完成') console.log('世界模型初始化完成')
@ -225,3 +228,6 @@ export default class WorldModel {
}) })
} }
} }
const worldModel = new WorldModel()
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 { ElButton, ElSpace, ElTree } from "element-plus";
import YvSrcEditor from "@/components/YvSrcEditor.vue"; import YvSrcEditor from "@/components/YvSrcEditor.vue";
import DataForm from "@/components/data-form/DataForm.vue"; import DataForm from "@/components/data-form/DataForm.vue";
import {worldModel} from '@/core/manager/WorldModel.ts'
import lodash from "lodash"; import lodash from "lodash";
defineOptions({ defineOptions({
@ -39,7 +40,6 @@ interface CatalogDefineData {
// //
const data: CatalogDefineData = {}; const data: CatalogDefineData = {};
const tree = useTemplateRef<InstanceType<typeof ElTree>>("treeRef"); const tree = useTemplateRef<InstanceType<typeof ElTree>>("treeRef");
const worldModel = computed(() => window['worldModel']);
const catalog = computed<Array<any>>(() => { const catalog = computed<Array<any>>(() => {
// state.forceUpdateForCatalog; // state.forceUpdateForCatalog;
return worldModel.value?.state?.catalog; 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 { createVNode, defineComponent, markRaw } from 'vue'
import Viewport from '@/core/engine/Viewport' import Viewport from '@/core/engine/Viewport'
import Constract from '@/core/Constract' import Constract from '@/core/Constract'
import { worldModel } from '@/core/manager/WorldModel.ts'
import EventBus from '@/runtime/EventBus' import EventBus from '@/runtime/EventBus'
import SceneHelp from '@/core/engine/SceneHelp' import SceneHelp from '@/core/engine/SceneHelp'
import BulkCopy from './BulkCopy.vue' import BulkCopy from './BulkCopy.vue'

47
src/editor/ModelMain.vue

@ -8,6 +8,36 @@
>{{ rootMenu.label }} >{{ rootMenu.label }}
<component :is="renderIcon('element ArrowDown')"></component> <component :is="renderIcon('element ArrowDown')"></component>
</div> </div>
<div style="flex-grow: 1;"></div>
<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="worldModelState.runState.currentEnvId">
<el-option v-for="env in envList" :key="env.env_id" :label="env.env_name" :value="env.env_id"></el-option>
<template #footer>
<el-button size="small" type="primary" plain>创建运行环境</el-button>
<el-button size="small" :icon="renderIcon('Refresh')" @click="reloadEnvList" />
</template>
</el-select>
</div>
<div class="field-block" style="margin-right: 5px;">
<el-select style="width:130px;" placeholder="时间速率"
v-model="worldModelState.runState.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="!worldModelState.runState.isRunning"
:disabled="!worldModelState.runState.currentEnvId"
:loading="worldModelState.runState.isLoading">启动
</el-button>
<el-button :icon="renderIcon('Stop')" type="danger" plain
v-if="worldModelState.runState.isRunning"
:loading="worldModelState.runState.isLoading">停止
</el-button>
</div>
</div> </div>
<div class="user"> <div class="user">
<span style="margin-right: 10px;"> <span style="margin-right: 10px;">
@ -18,7 +48,7 @@
</span> </span>
</div> </div>
</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-toolbar btns-toolbar-left">
<div class="btns btns-top"> <div class="btns btns-top">
<template v-for="panel in getWidgetBySide('left')"> <template v-for="panel in getWidgetBySide('left')">
@ -121,6 +151,8 @@ import Logo from '@/assets/images/logo.png'
import './ModelMain.less' import './ModelMain.less'
import EventBus from '@/runtime/EventBus.js' import EventBus from '@/runtime/EventBus.js'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { worldModel } from '@/core/manager/WorldModel.ts'
import runManager from '@/core/manager/RunManager.js'
export default { export default {
components: { Model2DEditor, Model3DViewer, Split, SplitArea, CatalogDefine }, components: { Model2DEditor, Model3DViewer, Split, SplitArea, CatalogDefine },
@ -158,6 +190,7 @@ export default {
} }
}) })
}) })
this.reloadEnvList()
EventBus.on('dataLoadComplete', (data) => { EventBus.on('dataLoadComplete', (data) => {
const { stateManager } = data const { stateManager } = data
if (stateManager) { if (stateManager) {
@ -174,6 +207,7 @@ export default {
data() { data() {
return { return {
Logo, Logo,
envList: [],
isShowEditor: false, isShowEditor: false,
editorHash: 0, editorHash: 0,
currentViewport: null, currentViewport: null,
@ -193,10 +227,10 @@ export default {
}, },
computed: { computed: {
isModelOpen() { isModelOpen() {
return this.worldModel.state.isOpened return this.worldModelState.isOpened
}, },
worldModel() { worldModelState() {
return window['worldModel'] return worldModel.state
}, },
calcLeftPanel() { calcLeftPanel() {
if (!this.sectionLeftName || this.hideLeft) { if (!this.sectionLeftName || this.hideLeft) {
@ -245,6 +279,11 @@ export default {
methods: { methods: {
renderIcon, renderIcon,
getWidgetBySide, getWidgetBySide,
reloadEnvList() {
runManager.getAllEnv(this.worldModelState.project_uuid).then(res => {
this.envList = res.data
})
},
toHome() { toHome() {
system.router.push({ name: 'home' }) system.router.push({ name: 'home' })
}, },

5
src/editor/ModelMainInit.ts

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

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

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

48
src/example/example1.js

@ -155,6 +155,26 @@ export default {
catalogCode: 'f2', t: 'floor', catalogCode: 'f2', t: 'floor',
items: [ items: [
{ {
id: 'm1', t: 'measure', v: true,
tf: [[0, 0, 0], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m2', 'm4'] }
},
{
id: 'm2', t: 'measure', v: true,
tf: [[8.4, 0, 0], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m1', 'm3'] }
},
{
id: 'm3', t: 'measure', v: true,
tf: [[8.4, 0, 9], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m2', 'm4'] }
},
{
id: 'm4', t: 'measure', v: true,
tf: [[0, 0, 9], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m3', 'm1'] }
},
{
id: 'rack1', id: 'rack1',
t: 'rack', t: 'rack',
v: true, v: true,
@ -182,26 +202,6 @@ export default {
} }
}, },
{ {
id: 'm1', t: 'measure', v: true,
tf: [[0, 0, 0], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m2', 'm4'] }
},
{
id: 'm2', t: 'measure', v: true,
tf: [[8.4, 0, 0], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m1', 'm3'] }
},
{
id: 'm3', t: 'measure', v: true,
tf: [[8.4, 0, 9], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m2', 'm4'] }
},
{
id: 'm4', t: 'measure', v: true,
tf: [[0, 0, 9], [90, 0, 0], [0.1, 0.1, 0.1]],
dt: { in: [], out: [], center: ['m3', 'm1'] }
},
{
id: '1', t: 'way', v: true, id: '1', t: 'way', v: true,
logicX: 11, logicX: 11,
logicY: 10, logicY: 10,
@ -433,14 +433,14 @@ export default {
dt: { in: [], out: [], center: [], clxWidth: 1.65, clxDepth: 1.65, clxHeight: 3.393 } dt: { in: [], out: [], center: [], clxWidth: 1.65, clxDepth: 1.65, clxHeight: 3.393 }
}, },
{ {
id: 'charger1', t: 'charger', v: true, id: 'charger1', t: 'way', v: true,
tf: [[2.696, 0, 8.75], [0, 0, 0], [1, 1, 1]], tf: [[2.696, 0, 8.75], [0, 0, 0], [1, 1, 1]],
dt: { in: ['8'], out: ['8'], center: [], chargerWidth: 0.53, chargerDepth: 0.275, clxHeight: 0.3 } dt: { in: ['8'], out: ['8'], center: [], isCharger: true }
}, },
{ {
id: 'charger2', t: 'charger', v: true, id: 'charger2', t: 'way', v: true,
tf: [[5.655, 0, 8.75], [0, 0, 0], [1, 1, 1]], tf: [[5.655, 0, 8.75], [0, 0, 0], [1, 1, 1]],
dt: { in: ['27'], out: ['27'], center: [], chargerWidth: 0.53, chargerDepth: 0.275, clxHeight: 0.3 } dt: { in: ['27'], out: ['27'], center: [], isCharger: true }
}, },
{ {
id: 'pallet1122', // 托盘唯一编码 id: 'pallet1122', // 托盘唯一编码

2
src/main.ts

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

7
src/modules/agv1/index.ts

@ -5,9 +5,8 @@ import propertySetter from './Agv1PropertySetter.ts'
export const ITEM_TYPE_NAME = 'agv1' export const ITEM_TYPE_NAME = 'agv1'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME,
renderer: new Agv1Renderer(ITEM_TYPE_NAME), renderer: new Agv1Renderer(ITEM_TYPE_NAME),
interaction: new Agv1Interaction(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 { defineModule } from '@/core/manager/ModuleManager.ts'
import CartonRenderer from './CartonRenderer.ts' import CartonRenderer from './CartonRenderer.ts'
import CartonInteraction from './CartonInteraction.ts' import CartonInteraction from './CartonInteraction.ts'
import propertySetter from "./CartonPropertySetter.ts"; import propertySetter from './CartonPropertySetter.ts'
export const ITEM_TYPE_NAME = 'carton' export const ITEM_TYPE_NAME = 'carton'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME, renderer: new CartonRenderer(ITEM_TYPE_NAME),
renderer: new CartonRenderer(ITEM_TYPE_NAME), interaction: new CartonInteraction(ITEM_TYPE_NAME),
interaction: new CartonInteraction(ITEM_TYPE_NAME), setter: propertySetter
setter: propertySetter, }))
})

13
src/modules/charger/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts' import { defineModule } from '@/core/manager/ModuleManager.ts'
import ChargerRenderer from './ChargerRenderer.ts' import ChargerRenderer from './ChargerRenderer.ts'
import ChargerInteraction from './ChargerInteraction.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 const ITEM_TYPE_NAME = 'charger'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME, renderer: new ChargerRenderer(ITEM_TYPE_NAME),
renderer: new ChargerRenderer(ITEM_TYPE_NAME), interaction: new ChargerInteraction(ITEM_TYPE_NAME),
interaction: new ChargerInteraction(ITEM_TYPE_NAME), setter: propertySetter
setter: propertySetter, }))
})

13
src/modules/cl2/index.ts

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

14
src/modules/clx/index.ts

@ -1,13 +1,13 @@
import { defineModule } from '@/core/manager/ModuleManager.ts' import { defineModule } from '@/core/manager/ModuleManager.ts'
import ClxRenderer from './ClxRenderer.ts' import ClxRenderer from './ClxRenderer.ts'
import ClxInteraction from './ClxInteraction.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 const ITEM_TYPE_NAME = 'clx'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME, name: ITEM_TYPE_NAME,
renderer: new ClxRenderer(ITEM_TYPE_NAME), renderer: new ClxRenderer(ITEM_TYPE_NAME),
interaction: new ClxInteraction(ITEM_TYPE_NAME), interaction: new ClxInteraction(ITEM_TYPE_NAME),
setter: propertySetter, setter: propertySetter
}) }))

13
src/modules/gstore/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts' import { defineModule } from '@/core/manager/ModuleManager.ts'
import GstoreRenderer from './GstoreRenderer.ts' import GstoreRenderer from './GstoreRenderer.ts'
import GstoreInteraction from './GstoreInteraction.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 const ITEM_TYPE_NAME = 'gstore'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME, renderer: new GstoreRenderer(ITEM_TYPE_NAME),
renderer: new GstoreRenderer(ITEM_TYPE_NAME), interaction: new GstoreInteraction(ITEM_TYPE_NAME),
interaction: new GstoreInteraction(ITEM_TYPE_NAME), setter: propertySetter
setter: propertySetter, }))
})

15
src/modules/measure/index.ts

@ -1,13 +1,14 @@
import { defineModule } from '@/core/manager/ModuleManager.ts' import { defineModule } from '@/core/manager/ModuleManager.ts'
import MeasureRenderer from './MeasureRenderer.ts' import MeasureRenderer from './MeasureRenderer.ts'
import MeasureInteraction from './MeasureInteraction.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 const ITEM_TYPE_NAME = 'measure'
export default defineModule({ console.log('MeasureRenderer initialized at', performance.now())
name: ITEM_TYPE_NAME,
renderer: new MeasureRenderer(ITEM_TYPE_NAME), export default defineModule(ITEM_TYPE_NAME, () => ({
interaction: new MeasureInteraction(ITEM_TYPE_NAME), renderer: new MeasureRenderer(ITEM_TYPE_NAME),
setter: propertySetter, 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 { defineModule } from '@/core/manager/ModuleManager.ts'
import PalletRenderer from './PalletRenderer.ts' import PalletRenderer from './PalletRenderer.ts'
import PalletInteraction from './PalletInteraction.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 const ITEM_TYPE_NAME = 'pallet'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME, renderer: new PalletRenderer(ITEM_TYPE_NAME),
renderer: new PalletRenderer(ITEM_TYPE_NAME), interaction: new PalletInteraction(ITEM_TYPE_NAME),
interaction: new PalletInteraction(ITEM_TYPE_NAME), setter: propertySetter
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 { defineModule } from '@/core/manager/ModuleManager.ts'
import RackRenderer from './RackRenderer.ts' import RackRenderer from './RackRenderer.ts'
import RackInteraction from './RackInteraction.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 const ITEM_TYPE_NAME = 'rack'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME, renderer: new RackRenderer(ITEM_TYPE_NAME),
renderer: new RackRenderer(ITEM_TYPE_NAME), interaction: new RackInteraction(ITEM_TYPE_NAME),
interaction: new RackInteraction(ITEM_TYPE_NAME), setter: propertySetter
setter: propertySetter, }))
})

13
src/modules/shuttle_rack/index.ts

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

7
src/modules/tote/index.ts

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

49
src/modules/way/WayRenderer.ts

@ -10,6 +10,7 @@ import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' import LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { getRenderer } from '@/core/manager/ModuleManager.ts' import { getRenderer } from '@/core/manager/ModuleManager.ts'
import chargerUrl from '@/assets/images/ptr/charger.png'
/** /**
* AGV行走路线渲染器 point * AGV行走路线渲染器 point
@ -17,7 +18,7 @@ import { getRenderer } from '@/core/manager/ModuleManager.ts'
export default class WayRenderer extends BaseRenderer { export default class WayRenderer extends BaseRenderer {
static LABEL_NAME = 'way_label' static LABEL_NAME = 'way_label'
static POINT_NAME = 'way_point' static POINT_NAME = 'way_point'
static LINE_NAME = 'way_line' static CHARGER_POINT_NAME = 'charger'
static GUIDEWAY_LINE_NAME = 'guideway' static GUIDEWAY_LINE_NAME = 'guideway'
static RED_LINE_NAME = 'red_line' static RED_LINE_NAME = 'red_line'
@ -42,6 +43,7 @@ export default class WayRenderer extends BaseRenderer {
dirGeometry: THREE.PlaneGeometry dirGeometry: THREE.PlaneGeometry
dirMaterial: THREE.Material dirMaterial: THREE.Material
dir2Material: THREE.Material dir2Material: THREE.Material
chargerMaterial: THREE.Material
/** /**
* , * ,
@ -58,13 +60,18 @@ export default class WayRenderer extends BaseRenderer {
super.init(), super.init(),
new THREE.TextureLoader().loadAsync(MoveLinePointPng), new THREE.TextureLoader().loadAsync(MoveLinePointPng),
new THREE.TextureLoader().loadAsync(TriangleUrl), new THREE.TextureLoader().loadAsync(TriangleUrl),
new THREE.TextureLoader().loadAsync(Triangle2Url) new THREE.TextureLoader().loadAsync(Triangle2Url),
new THREE.TextureLoader().loadAsync(chargerUrl)
]).then(([_, texture, dirTexture, dir2Texture]) => { ]).then(([_, texture, dirTexture, dir2Texture, chargerTexture]) => {
texture.flipY = false texture.flipY = false
this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2) this.pointGeometry = new THREE.PlaneGeometry(1, 1).rotateX(-Math.PI / 2)
this.pointGeometry.center() this.pointGeometry.center()
this.chargerMaterial = new THREE.MeshLambertMaterial({
map: chargerTexture, // 颜色贴图
transparent: true // 允许透明纹理
})
this.pointMaterial = new THREE.MeshBasicMaterial({ this.pointMaterial = new THREE.MeshBasicMaterial({
map: texture, map: texture,
@ -98,16 +105,35 @@ export default class WayRenderer extends BaseRenderer {
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike { createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
// 不允许改变高度/角度/大小 // 不允许改变高度/角度/大小
item.tf = [ if (item.dt.isCharger) {
[item.tf[0][0], this.defulePositionY, item.tf[0][2]], return this.createCharger(item)
[this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z],
[this.defaultScale.x, this.defaultScale.y, this.defaultScale.z] } else {
] item.tf = [
return this.pointManager.createByItem(item) [item.tf[0][0], this.defulePositionY, item.tf[0][2]],
[this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z],
[this.defaultScale.x, this.defaultScale.y, this.defaultScale.z]
]
return this.pointManager.createByItem(item)
}
}
private createCharger(item: ItemJson) {
// 创建平面几何体
const group = new THREE.Group()
group.name = WayRenderer.CHARGER_POINT_NAME
// 绘制背景矩形框
const planeGeometry = new THREE.PlaneGeometry(item.dt.chargerWidth, item.dt.chargerDepth)
planeGeometry.rotateX(-Math.PI / 2)
const planeMesh = new THREE.Mesh(planeGeometry, this.chargerMaterial)
group.add(planeMesh)
return group
} }
createLine(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike { createLine(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
if (start.t === this.itemTypeName && end.t === this.itemTypeName) { if ((start.t === this.itemTypeName) && end.t === this.itemTypeName) {
return this._createOrUpdateGuideway(start, end, type) return this._createOrUpdateGuideway(start, end, type)
} else { } else {
// throw new Error('目前只支持二维码站点之间的连接') // throw new Error('目前只支持二维码站点之间的连接')
@ -260,6 +286,9 @@ export default class WayRenderer extends BaseRenderer {
*/ */
afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: Object3DLike) { afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: Object3DLike) {
super.afterCreateOrUpdatePoint(item, option, object) super.afterCreateOrUpdatePoint(item, option, object)
if (item.dt.isCharger) {
return
}
// 创建一个 id 标签 // 创建一个 id 标签
this.tempViewport.labelManager.createOrUpdateMeshLabel(object, '' + item.id, { this.tempViewport.labelManager.createOrUpdateMeshLabel(object, '' + item.id, {

13
src/modules/way/index.ts

@ -1,13 +1,12 @@
import { defineModule } from '@/core/manager/ModuleManager.ts' import { defineModule } from '@/core/manager/ModuleManager.ts'
import WayRenderer from './WayRenderer.ts' import WayRenderer from './WayRenderer.ts'
import WayInteraction from './WayInteraction.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 const ITEM_TYPE_NAME = 'way'
export default defineModule({ export default defineModule(ITEM_TYPE_NAME, () => ({
name: ITEM_TYPE_NAME, renderer: new WayRenderer(ITEM_TYPE_NAME),
renderer: new WayRenderer(ITEM_TYPE_NAME), interaction: new WayInteraction(ITEM_TYPE_NAME),
interaction: new WayInteraction(ITEM_TYPE_NAME), setter: propertySetter
setter: propertySetter, }))
})

3
src/types/global.d.ts

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

17
src/types/model.d.ts

@ -460,3 +460,20 @@ interface Cl2If extends EntityIf, Carry, Walk, ForkArm, LiftingArm {
*/ */
interface ClxIf extends EntityIf, Carry, Walk, ForkArm, LiftingArm { interface ClxIf extends EntityIf, Carry, Walk, ForkArm, LiftingArm {
} }
interface ServerResponse<T> {
success: boolean,
msg: string,
data: T
}
/**
*
*/
interface EnvInfo {
env_id: string
world_id: string
env_name: string
is_virtual: boolean
env_payload: any
}

Loading…
Cancel
Save