no message

This commit is contained in:
hawk86104 2024-09-04 10:19:50 +08:00
parent 1d25c797d4
commit c56314e8b1
37 changed files with 1679 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

View File

@ -0,0 +1,147 @@
<template>
<Suspense>
<template v-if="envSetup.isLightFormer">
<Environment :blur="envSetup.blur" :background="!backgroundSetup.useBackImg" :far="100000">
<TresGroup
:position="[envSetup.pos.x, envSetup.pos.y, envSetup.pos.z]"
:rotation="[envSetup.rotate.x, envSetup.rotate.y, envSetup.rotate.z]"
:scale="[envSetup.scale.x, envSetup.scale.y, envSetup.scale.z]"
>
<Lightformer :intensity="0.75" :rotation-x="Math.PI / 2" :position="[0, 5, -9]" :scale="[10, 10, 1]" />
<Lightformer :intensity="4" :rotation-y="Math.PI / 2" :position="[-5, 1, -1]" :scale="[20, 0.1, 1]" />
<Lightformer :rotation-y="Math.PI / 2" :position="[-5, -1, -1]" :scale="[20, 0.5, 1]" />
<Lightformer :rotation-y="-Math.PI / 2" :position="[10, 1, 0]" :scale="[20, 11, 1]" />
<Levioso :speed="5" :floatFactor="2" :rotationFactor="2">
<Lightformer form="ring" :color="envSetup.colorA" :intensity="1" :scale="10" :position="[-15, 4, -18]" />
</Levioso>
<TresGroup :rotation="[0, 0.5, 0]">
<TresGroup ref="group">
<Lightformer
v-for="(i, x) in lightFormerPositions"
:key="i"
form="circle"
:intensity="2"
:rotation="[Math.PI / 2, 0, 0]"
:position="[x, 4, i * 4]"
:scale="[3, 1, 1]"
/>
</TresGroup>
</TresGroup>
<TresMesh :scale="[100, 100, 100]">
<TresSphereGeometry :args="[1, 64, 64]" />
<LayerMaterial :side="THREE.BackSide">
<Color color="#444" :alpha="1.0" mode="normal" />
<Depth
:colorA="envSetup.colorB"
colorB="black"
:alpha="0.5"
mode="normal"
:near="0"
:far="300"
:origin="new THREE.Vector3(100, 100, 100)"
/>
</LayerMaterial>
</TresMesh>
</TresGroup>
</Environment>
</template>
</Suspense>
</template>
<script setup lang="ts">
import { watch, ref } from 'vue'
import * as THREE from 'three'
import { useTresContext, useTexture, useRenderLoop } from '@tresjs/core'
import { LayerMaterial, Color, Depth } from 'PLS/basic/components/forCientos/LayerMaterial'
import { Environment, Lightformer } from 'PLS/basic'
import { Levioso } from '@tresjs/cientos'
import { useBackgroundSetupStore } from 'PLS/tvtSceneCreator/stores/backgroundSetup'
import { useEnvSetupStore } from 'PLS/tvtSceneCreator/stores/envSetup'
const lightFormerPositions = [2, 0, 2, 0, 2, 0, 2, 0]
const { scene } = useTresContext()
const backgroundSetup = useBackgroundSetupStore()
const envSetup = useEnvSetupStore()
const setupEnvBackground = async () => {
//
if (envSetup.isLightFormer) {
//
} else {
scene.value.environment = envSetup.envHDR.src
}
//
if (backgroundSetup.useBackImg) {
if (backgroundSetup.img.name === '') {
scene.value.background = new THREE.Color(backgroundSetup.color)
} else {
const pTexture = await useTexture([backgroundSetup.img.src])
scene.value.background = pTexture
}
} else {
scene.value.background = scene.value.environment
}
scene.value.backgroundBlurriness = envSetup.blur
}
// @ts-ignore
backgroundSetup.setupEnvBackground = setupEnvBackground
watch(
() => backgroundSetup.color,
() => {
backgroundSetup.img = {
name: '',
src: '',
}
setupEnvBackground()
},
{ immediate: true },
)
watch(
() => backgroundSetup.img,
async (img) => {
if (img.name) {
setupEnvBackground()
}
},
{ immediate: true, deep: true },
)
watch(
() => envSetup.envHDR,
() => {
setupEnvBackground()
},
{ immediate: true, deep: true },
)
watch(
() => envSetup.isLightFormer,
() => {
setupEnvBackground()
},
)
watch(
() => backgroundSetup.useBackImg,
() => {
setupEnvBackground()
},
)
watch(
() => envSetup.blur,
() => {
setupEnvBackground()
},
)
const group = ref(null)
const { onBeforeLoop } = useRenderLoop()
onBeforeLoop(({ delta }) => {
if (group.value) {
// @ts-ignore
;(group.value.position.z += delta * 10) > 20 && (group.value.position.z = -60)
}
})
</script>

View File

@ -0,0 +1,151 @@
<template>
<TresPerspectiveCamera :position="[20, 15, -20]" :fov="45" :near="0.1" :far="10000" :look-at="[0, 0, 0]" />
<OrbitControls enableDamping makeDefault />
<TresGroup ref="tresGroupRef">
<primitive :object="toRaw(mesh)" :meshListIndex="index" v-for="(mesh, index) in primitiveList" @click="pClick" />
</TresGroup>
<TransformControls
@dragging="draggingEvent"
v-if="transformRef && curMeshList.controlState !== 'sel' && curMeshList.controlState !== null && curMeshList.selectedMeshIndex !== null"
:object="transformRef"
:mode="curMeshList.controlState"
/>
</template>
<script setup lang="ts">
// @ts-nocheck
import * as THREE from 'three'
import { ref, onMounted, toRaw, watch } from 'vue'
import { useTresContext, useSeek } from '@tresjs/core'
import { OrbitControls, TransformControls, useGLTF } from '@tresjs/cientos'
import { useCurMeshListStore } from 'PLS/tvtSceneCreator/stores/curMeshList'
const curMeshList = useCurMeshListStore()
const transformRef = ref()
const tresMeshRef = ref()
onMounted(() => {})
const getOneMesh = async (m) => {
const mesh = m as any
let onePrimitive = null as any
if (mesh.type === 'AmbientLight') {
onePrimitive = new THREE[mesh.type](mesh.color, mesh.intensity)
onePrimitive.name = mesh.type
} else if (mesh.type === 'DirectionalLight') {
onePrimitive = new THREE[mesh.type](mesh.color, mesh.intensity)
onePrimitive.position.set(...toRaw(mesh.position))
onePrimitive.name = mesh.type
} else if (mesh.type === 'Mesh') {
const geometry = new THREE[mesh.geometry](...toRaw(mesh.args))
const material = new THREE[mesh.material]()
material.metalness = mesh.metalness
material.roughness = mesh.roughness
material.color = new THREE.Color(mesh.color)
onePrimitive = new THREE[mesh.type](geometry, material)
onePrimitive.name = mesh.name
onePrimitive.position.set(...toRaw(mesh.position))
onePrimitive.rotation.set(...toRaw(mesh.rotation))
onePrimitive.scale.set(...toRaw(mesh.scale))
} else {
const { scene: modelScene } = await useGLTF(mesh.url, { draco: true, decoderPath: './draco/' })
modelScene.name = mesh.name
onePrimitive = modelScene
onePrimitive.position.set(...toRaw(mesh.position))
onePrimitive.rotation.set(...toRaw(mesh.rotation))
onePrimitive.scale.set(...toRaw(mesh.scale))
}
onePrimitive.visible = mesh.visible
return onePrimitive
}
const primitiveList = ref([])
watch(
() => curMeshList.mlist,
async (mlist) => {
const list = []
for (const mesh of curMeshList.mlist) {
list.push(await getOneMesh(mesh))
}
primitiveList.value = list
console.log('primitiveList', list)
},
{ immediate: true, deep: true },
)
const pClick = (event) => {
// event.stopPropagation()
if (!curMeshList.controlState) {
return
}
if (event.eventObject.meshListIndex) {
curMeshList.selectedMeshIndex = event.eventObject.meshListIndex
}
}
const { scene } = useTresContext()
const { seek } = useSeek()
const tresGroupRef = ref()
let directionalLightHelper = null as any
watch(
() => curMeshList.selectedMeshIndex,
(index) => {
if (directionalLightHelper) {
directionalLightHelper.parent.remove(directionalLightHelper)
directionalLightHelper.dispose()
directionalLightHelper = null
}
scene.value.children.forEach((child) => {
if (child.type === 'AmbientLight') {
} else if (child.type === 'DirectionalLight') {
if (child.meshListIndex === index) {
directionalLightHelper = new THREE.DirectionalLightHelper(child, 10)
scene.value.add(directionalLightHelper)
}
} else {
if (child.material) {
child.material.wireframe = child.meshListIndex === index
}
}
})
if (index !== null) {
// const mesh = seek(tresGroupRef.value, 'meshListIndex', index) as any
const mesh = seek(scene.value, 'meshListIndex', index) as any
if (mesh) {
transformRef.value = toRaw(mesh)
}
}
},
)
watch(
() => curMeshList.controlState,
(controlState) => {
if (controlState) {
//
} else {
curMeshList.selectedMeshIndex = null
}
},
)
watch(
() => tresGroupRef.value,
(value) => {
// curMeshList.tresGroup = value
curMeshList.tresGroup = scene.value
// curMeshList.addMesh({ name: 'AmbientLight', type: 'AmbientLight', intensity: 10 })
// curMeshList.addMesh({ name: 'DirectionalLight', type: 'DirectionalLight', intensity: 5, position: [5, 3, 5] })
// curMeshList.addMesh({ name: 'm1', position: [3, -3, 6], args: [6, 6, 6], metalness: 1, roughness: 0.14 })
// curMeshList.addMesh({ name: 'm2', position: [0, 2, -4], material: 'MeshNormalMaterial', args: [2, 2, 2] })
// curMeshList.addMesh({ name: 'm3', position: [0, 8, -4], material: 'MeshNormalMaterial', args: [2, 2, 2] })
},
)
const draggingEvent = (e: any) => {
if (!e && window['TvTSCinForPane']) {
window['TvTSCinForPane']()
}
}
</script>

View File

@ -0,0 +1,52 @@
<template></template>
<script setup lang="ts">
import { useTresContext, useRenderLoop } from '@tresjs/core'
// @ts-ignore
import { ViewHelper } from 'three/addons/helpers/ViewHelper.js'
import { onMounted } from 'vue'
const { camera, renderer } = useTresContext()
let panel = null as any
const createDiv = () => {
panel = document.createElement('div')
panel.id = 'viewHelper'
panel.style.position = 'absolute'
// panel.style.right = '0px'
panel.style.bottom = '0px'
panel.style.height = '128px'
panel.style.width = '128px'
panel.style.pointerEvents = 'all'
document.getElementById('app')?.appendChild(panel)
}
let viewHelper = null as any
onMounted(() => {
createDiv()
viewHelper = new ViewHelper(camera.value, panel)
panel.addEventListener('pointerup', (event: any) => {
event.stopPropagation()
event.preventDefault()
viewHelper.handleClick(event)
})
panel.addEventListener('pointerdown', function (event: any) {
event.stopPropagation()
})
})
const { onBeforeLoop } = useRenderLoop()
onBeforeLoop(({ delta }) => {
if (!viewHelper)
return
if (viewHelper.animating === true) {
viewHelper.update(delta)
}
renderer.value.autoClear = false
viewHelper?.render(renderer.value)
renderer.value.autoClear = true
})
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,25 @@
<template>
<TresCanvas v-bind="tcConfig">
<backgroundEnv />
<defaultMesh />
<viewHelper />
</TresCanvas>
</template>
<script setup lang="ts">
import * as THREE from "three"
import backgroundEnv from './default/backgroundEnv.vue'
import defaultMesh from './default/deMesh.vue'
import viewHelper from './default/viewHelper.vue'
const tcConfig = {
clearColor: "#201919",
windowSize: true,
shadows: true,
toneMapping: THREE.ACESFilmicToneMapping,
toneMappingExposure: 0.8,
}
</script>

View File

@ -0,0 +1,60 @@
<template>
<div class="bt-con-div">
<FRadioGroup v-model="curMeshList.controlState" size="small">
<FRadioButton value="sel">
<template #icon>
<MinusCircleOutlined />
</template>
选择
</FRadioButton>
<FRadioButton value="translate">
<template #icon>
<DragOutlined />
</template>
移动
</FRadioButton>
<FRadioButton value="scale">
<template #icon>
<PlusCircleOutlined />
</template>
缩放
</FRadioButton>
<FRadioButton value="rotate">
<template #icon>
<ReloadOutlined />
</template>
旋转
</FRadioButton>
</FRadioGroup>
</div>
</template>
<script lang="ts" setup>
import { FRadioGroup, FRadioButton } from '@fesjs/fes-design'
import { MinusCircleOutlined, DragOutlined, PlusCircleOutlined, ReloadOutlined } from '@fesjs/fes-design/icon'
import { useCurMeshListStore } from 'PLS/tvtSceneCreator/stores/curMeshList'
const curMeshList = useCurMeshListStore()
</script>
<style lang="scss" scoped>
.bt-con-div {
position: absolute;
bottom: 6px;
width: 100%;
color: white;
}
</style>
<style lang="scss">
.bt-con-div {
.fes-radio-group {
margin: 0 auto;
display: block;
width: 270px;
pointer-events: all;
.fes-radio-button {
background: #0f1222;
}
}
}
</style>

View File

@ -0,0 +1,80 @@
<template>
<div class="is-fixed" style="width: 280px; height: 700px; margin-top: 16px;pointer-events: all;">
<FTabs type="card" v-model="otherConfig.activeModel">
<FTabPane name="加入场景" value="modelList" displayDirective="show">
<div class="tab-content">
<modelList />
</div>
</FTabPane>
<FTabPane name="现有物体" value="nowin" displayDirective="show">
<div class="tab-content">
<curList />
</div>
</FTabPane>
<FTabPane name="独立效果" value="effect" displayDirective="show">
<div class="tab-content" style="color: #fff;">
导入TvT.js生态中封装好独立的效果组件敬请期待
</div>
</FTabPane>
</FTabs>
</div>
</template>
<script lang="ts" setup>
import { FTabs, FTabPane } from '@fesjs/fes-design'
import modelList from './small/modelList.vue'
import curList from './small/curList.vue'
import { useotherConfigStore } from 'PLS/tvtSceneCreator/stores/otherConfig'
const otherConfig = useotherConfigStore() as any
</script>
<style lang="scss" scoped>
.fes-scrollbar::-webkit-scrollbar {
width: 4px;
}
.fes-scrollbar::-webkit-scrollbar-track {
background-color: #f1f1f1;
opacity: 0.2;
}
.fes-scrollbar::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 5px;
}
.fes-scrollbar::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
.fes-layout-aside.is-fixed.is-placement-left {
top: 60px;
}
.fes-tabs-tab-pane {
height: 100%;
.tab-content {
height: 100%;
line-height: 60px;
text-align: center;
background: #0f1222;
padding: 10px;
}
}
.fes-tabs {
background: #0f1222;
padding-top: 10px;
}
</style>
<style lang="scss">
.fes-tabs-card .fes-tabs-tab-card.fes-tabs-tab-active{
background: #0f1222;
}
.fes-tabs-card .fes-tabs-tab-card{
background:#0e0e0e;
}
.fes-tabs-tab {
color: #bcbcbc;
}
.fes-tabs-tab-active {
color: #ffffff;
}
</style>

View File

@ -0,0 +1,100 @@
<template>
<div class="right-env-setup">
<FTabs v-model="reseletTab" type="card">
<FTabPane name="场景设置" value="modelList" displayDirective="show">
<div class="tab-content">
<backgroundMap />
<FDivider />
<envMap />
</div>
</FTabPane>
<FTabPane name="选中物体" value="selMesh" displayDirective="show">
<div class="tab-content" style="color: #fff">
<selMeshInfo />
</div>
</FTabPane>
</FTabs>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { FDivider, FTabs, FTabPane } from '@fesjs/fes-design'
import { useCurMeshListStore } from 'PLS/tvtSceneCreator/stores/curMeshList'
import backgroundMap from './small/backgroundMap.vue'
import envMap from './small/envMap.vue'
import selMeshInfo from './small/selMeshInfo.vue'
const curMeshList = useCurMeshListStore()
const reseletTab = ref('modelList')
watch(
() => curMeshList.selectedMeshIndex,
(index) => {
if (index !== null) {
reseletTab.value = 'selMesh'
}
},
)
</script>
<style lang="scss" scoped>
.right-env-setup {
position: absolute;
top: 70px;
width: 260px;
pointer-events: all;
background-color: var(--f-font-color-base);
color: var(--f-text-color-caption);
right: 0;
padding: 10px;
}
.fes-scrollbar::-webkit-scrollbar {
width: 4px;
}
.fes-scrollbar::-webkit-scrollbar-track {
background-color: #f1f1f1;
opacity: 0.2;
}
.fes-scrollbar::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 5px;
}
.fes-scrollbar::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
.fes-layout-aside.is-fixed.is-placement-left {
top: 60px;
}
.fes-tabs-tab-pane {
height: 100%;
.tab-content {
height: 100%;
margin-top: 10px;
text-align: center;
}
}
.fes-tabs {
background: #0f1222;
color: var(--f-text-color-caption);
}
</style>
<style lang="scss">
.fes-tabs-card .fes-tabs-tab-card.fes-tabs-tab-active {
background: #0f1222;
}
.fes-tabs-card .fes-tabs-tab-card {
background: #0e0e0e;
}
.fes-tabs-tab {
color: #bcbcbc;
}
.fes-tabs-tab-active {
color: #ffffff;
}
.right-env-setup {
.fes-tabs-tab-pane-wrapper {
overflow: visible;
}
}
</style>

View File

@ -0,0 +1,155 @@
<template>
<div class="backgroundMapDiv">
<input type="file" id="fileBackground" accept="image/*" style="display: none" />
<FText size="large" class="title">背景管理</FText>
<div style="text-align: center; margin: 10px 0px">
<FSwitch v-model="backgroundSetup.useBackImg">
<template #active> 使用背景色 </template>
<template #inactive> 使用环境贴图 </template>
</FSwitch>
</div>
<div v-show="backgroundSetup.useBackImg">
<div class="color-div"></div>
<FGrid style="margin-top: 10px" :gutter="10">
<FGridItem :span="6">
<div class="col-title">默认颜色</div>
</FGridItem>
<FGridItem :span="18">
<FRadioGroup v-model="selectedColor" @change="changeColor">
<FRadioButton value="b"> 黑色 </FRadioButton>
<FRadioButton value="w"> 白色 </FRadioButton>
<FRadioButton value="g"> 灰色 </FRadioButton>
</FRadioGroup>
</FGridItem>
</FGrid>
<FGrid style="margin-top: 10px" :gutter="10">
<FGridItem :span="6">
<div class="col-title">选择图片</div>
</FGridItem>
<FGridItem :span="20">
<FButton size="small" style="margin-top: 5px" @click="uploadImg()">
<template #icon> <ProductOutlined /> </template>上传
</FButton>
</FGridItem>
</FGrid>
<FGrid style="margin-top: 10px" :gutter="10" wrap>
<FGridItem v-for="ione in imgList" :span="8">
<FImage
style="width: 66px; height: 48px; margin-bottom: 8px; cursor: pointer"
class="background-image"
:class="{ 'sel-background-image': ione.name === backgroundSetup.img.name }"
:src="ione.src"
fit="contain"
@click="imgclick(ione)"
/>
</FGridItem>
</FGrid>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { FText, FRadioButton, FRadioGroup, FGrid, FGridItem, FButton, FImage, FSwitch, FMessage } from '@fesjs/fes-design'
import { ProductOutlined } from '@fesjs/fes-design/icon'
import { Pane } from 'tweakpane'
import { useBackgroundSetupStore } from 'PLS/tvtSceneCreator/stores/backgroundSetup'
const backgroundSetup = useBackgroundSetupStore()
const selectedColor = ref('')
let pane = null as any
let fileInput = null as any
const changeColor = (color: string) => {
if (color === 'b') {
backgroundSetup.color = '#000'
pane.children[0].refresh()
}
if (color === 'w') {
backgroundSetup.color = '#fff'
pane.children[0].refresh()
}
if (color === 'g') {
backgroundSetup.color = '#888'
pane.children[0].refresh()
}
}
const imgList = [
{ name: 'upload', src: './plugins/tvtSceneCreator/image/backGround/upload.png' },
{ name: 'b-blue', src: './plugins/tvtSceneCreator/image/backGround/b-blue.jpeg' },
{ name: 'b-black', src: './plugins/tvtSceneCreator/image/backGround/b-black.jpeg' },
{ name: 'b-green', src: './plugins/tvtSceneCreator/image/backGround/b-green.jpeg' },
{ name: 'b-red', src: './plugins/tvtSceneCreator/image/backGround/b-red.jpeg' },
{ name: 'b-cyan', src: './plugins/tvtSceneCreator/image/backGround/b-cyan.jpeg' },
]
const imgclick = (ione: any) => {
if (ione.name === 'upload' && ione.src === './plugins/tvtSceneCreator/image/backGround/upload.png') {
FMessage.error({
content: `请先上传背景图片!`,
colorful: false,
})
return
}
backgroundSetup.img = { name: ione.name, src: ione.src }
}
const uploadImg = () => {
fileInput.click()
}
onMounted(() => {
const domcolor = document.querySelector('.backgroundMapDiv .color-div') as any
pane = new Pane({ container: domcolor })
pane.addBinding(backgroundSetup, 'color', { label: '纯色' })
fileInput = document.getElementById('fileBackground') as any
fileInput.onchange = () => {
const file = fileInput.files[0]
if (file) {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => {
const imgSrc = reader.result as string
imgList[0].src = imgSrc
backgroundSetup.img = imgList[0]
}
}
}
})
</script>
<style lang="scss" scoped>
.backgroundMapDiv {
.title {
color: var(--f-text-color-caption);
text-align: center;
display: block;
}
.color-div {
margin: 6px 0px;
}
.fes-radio-button {
background: #0f1222;
}
.col-title {
font-size: 13px;
line-height: 2.5em;
font-weight: 500;
}
.background-image {
border: 1px solid #ffffff30;
}
.sel-background-image {
border: 1px solid #ffffff;
}
}
</style>
<style lang="scss">
:root {
--tp-base-background-color: #0f1222;
--tp-label-foreground-color: #cfd0d3;
}
.tp-rotv {
font-size: 13px !important;
}
</style>

View File

@ -0,0 +1,84 @@
<template>
<div class="container">
<FDraggable v-model="curMeshList.mlist" disabled>
<template #default="{ item, index }">
<div class="sort-item" :class="{ 'active': index === curMeshList.selectedMeshIndex }" @click="selListOne(index)">
{{ item.name }}
<template v-if="item.type!=='AmbientLight'&&item.type!=='DirectionalLight'">
<{{item.type}}>
</template>
<CloseCircleFilled color="rgb(212 0 78)" class="del-i" @click="delItem(index)" />
</div>
</template>
</FDraggable>
<div style="color: white;" v-show="curMeshList.mlist.length === 0"> 暂无任何物体 </div>
</div>
</template>
<script lang="ts" setup>
// <DragOutlined :size="18" :color="item.color" /> DragOutlined
import { FDraggable, FModal } from '@fesjs/fes-design'
import { CloseCircleFilled } from '@fesjs/fes-design/icon'
import { useCurMeshListStore } from 'PLS/tvtSceneCreator/stores/curMeshList'
const curMeshList = useCurMeshListStore() as any
// const getRandomBrightColor = () => {
// const r = Math.floor(Math.random() * 128) + 128
// const g = Math.floor(Math.random() * 128) + 128
// const b = Math.floor(Math.random() * 128) + 128
// const color = `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
// return color
// }
const delItem = (index: number) => {
FModal.confirm({
title: '删除选中项',
content: `是否删除当前项:${curMeshList.mlist[index].name} `,
okText: '确认删除',
onOk() {
if (curMeshList.selectedMeshIndex === index) {
curMeshList.selectedMeshIndex = null
}
curMeshList.removeMesh(index)
// curMeshList.selectedMeshIndex = curMeshList.mlist.length - 2
},
onCancel() {},
})
}
const selListOne = (index: number) => {
if (!curMeshList.controlState) {
curMeshList.controlState = 'sel'
}
curMeshList.selectedMeshIndex = index
}
</script>
<style lang="scss" scoped>
.sort-item {
line-height: 22px;
background: #000;
margin: 2px 0;
padding-left: 23px;
color: #cbcbcb;
text-align: left;
cursor: pointer;
position: relative;
.fes-design-icon {
position: absolute;
top: 2px;
left: 2px;
}
.del-i {
right: 6px;
top: 4px;
left: auto;
}
}
.active{
border: 1px solid #fff;
}
</style>
<style lang="scss"></style>

View File

@ -0,0 +1,185 @@
<template>
<div class="envMapDiv">
<input type="file" id="fileEnv" accept=".hdr,.HDR" style="display: none" />
<FText size="large" class="title">环境管理</FText>
<div style="text-align: center; margin: 10px 0px">
<FSwitch v-model="envSetup.isLightFormer">
<template #active> lightFormer </template>
<template #inactive> HDR 贴图 </template>
</FSwitch>
</div>
<div v-show="!envSetup.isLightFormer">
<FGrid style="margin-top: 10px" :gutter="10">
<FGridItem :span="6">
<div class="col-title">选择HDR</div>
</FGridItem>
<FGridItem :span="20">
<FButton size="small" style="margin-top: 5px" @click="uploadImg()">
<template #icon> <ProductOutlined /> </template>上传
</FButton>
</FGridItem>
</FGrid>
<FGrid style="margin-top: 10px" :gutter="10" wrap>
<FGridItem v-for="ione in imgList" :span="8">
<FImage
style="width: 66px; height: 48px; margin-bottom: 8px; cursor: pointer"
:src="ione.img"
fit="contain"
class="background-image"
:class="{ 'sel-background-image': ione.name === envSetup.envHDR.name }"
@click="imgclick(ione)"
/>
</FGridItem>
</FGrid>
</div>
<div class="lightFormer-div"></div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, watch } from 'vue'
import { FText, FGrid, FGridItem, FButton, FImage, FSwitch, FMessage } from '@fesjs/fes-design'
import { ProductOutlined } from '@fesjs/fes-design/icon'
import { Pane } from 'tweakpane'
import { useEnvSetupStore } from 'PLS/tvtSceneCreator/stores/envSetup'
import { loadHDR } from 'PLS/skyBox/common/utils'
const envSetup = useEnvSetupStore()
let pane = null as any
let fileInput = null as any
const imgList = ref([
{ name: 'upload', img: './plugins/tvtSceneCreator/image/backGround/upload.png', src: null },
{
name: 'desert',
img: './plugins/tvtSceneCreator/image/envHDR/desert.jpeg',
src: await loadHDR('https://opensource-1314935952.cos.ap-nanjing.myqcloud.com/images/skyBox/desert_1k.hdr'),
},
{
name: 'belfast_sunset_puresky_1k',
img: './plugins/tvtSceneCreator/image/envHDR/belfast_sunset_puresky_1k.jpeg',
src: await loadHDR('./plugins/tvtSceneCreator/image/envHDR/belfast_sunset_puresky_1k.hdr'),
},
{
name: 'metro_noord_1k',
img: './plugins/tvtSceneCreator/image/envHDR/metro_noord_1k.jpeg',
src: await loadHDR('./plugins/tvtSceneCreator/image/envHDR/metro_noord_1k.hdr'),
},
{
name: 'pretville_cinema_1k',
img: './plugins/tvtSceneCreator/image/envHDR/pretville_cinema_1k.jpeg',
src: await loadHDR('./plugins/tvtSceneCreator/image/envHDR/pretville_cinema_1k.hdr'),
},
{
name: 'shanghai_bund_1k',
img: './plugins/tvtSceneCreator/image/envHDR/shanghai_bund_1k.jpeg',
src: await loadHDR('./plugins/tvtSceneCreator/image/envHDR/shanghai_bund_1k.hdr'),
},
])
const uploadImg = () => {
fileInput.click()
}
const imgclick = async (ione: any) => {
if (ione.name === 'upload' && !ione.src) {
FMessage.error({
content: `请先上传HDR图片`,
colorful: false,
})
return
}
envSetup.envHDR.name = ione.name
envSetup.envHDR.src = ione.src
}
const setEnvHDR = (name: string) => {
imgList.value.forEach((item) => {
if (item.name === name) {
envSetup.envHDR.name = name
envSetup.envHDR.src = item.src
}
})
}
envSetup.setEnvHDR = setEnvHDR
let fcc = null as any
onMounted(() => {
const domcolor = document.querySelector('.envMapDiv .lightFormer-div') as any
pane = new Pane({ container: domcolor })
pane.addBinding(envSetup, 'blur', { label: '背景模糊', min: 0, max: 1.0, step: 0.01 })
fcc = pane.addFolder({ title: '属性' })
fcc.addBinding(envSetup, 'colorA', { label: '颜色1' })
fcc.addBinding(envSetup, 'colorB', { label: '颜色2' })
fcc.addBinding(envSetup, 'pos', { label: '位置' })
fcc.addBinding(envSetup, 'rotate', { label: '旋转' })
fcc.addBinding(envSetup, 'scale', { label: '缩放', min: 0.1, max: 2.0, step: 0.01 })
fcc.hidden = true
fileInput = document.getElementById('fileEnv') as any
fileInput.onchange = () => {
const file = fileInput.files[0]
if (file) {
const reader = new FileReader()
reader.readAsArrayBuffer(file)
reader.onload = async (e) => {
if (e.target) {
const arrayBuffer = e.target.result as ArrayBuffer
const blob = new Blob([arrayBuffer], { type: 'application/octet-stream' })
const url = URL.createObjectURL(blob)
const texture = await loadHDR(url)
// texture.mapping = THREE.EquirectangularReflectionMapping
// texture.minFilter = THREE.LinearFilter
// texture.magFilter = THREE.LinearFilter
imgList.value[0].img = './plugins/tvtSceneCreator/image/envHDR/finishHDR.png'
imgList.value[0].src = texture
envSetup.envHDR.name = 'upload'
envSetup.envHDR.src = texture
}
}
}
}
})
watch(
() => envSetup.isLightFormer,
(v) => {
fcc.hidden = !v
},
)
</script>
<style lang="scss" scoped>
.envMapDiv {
margin-top: -10px;
.title {
color: var(--f-text-color-caption);
text-align: center;
display: block;
}
.color-div {
margin: 6px 0px;
}
.fes-radio-button {
background: #0f1222;
}
.col-title {
font-size: 13px;
line-height: 2.5em;
font-weight: 500;
}
.background-image {
border: 1px solid #ffffff30;
}
.sel-background-image {
border: 1px solid #ffffff;
}
}
</style>
<style lang="scss">
:root {
--tp-base-background-color: #0f1222;
--tp-label-foreground-color: #cfd0d3;
}
.tp-rotv {
font-size: 13px !important;
}
</style>

View File

@ -0,0 +1,145 @@
<template>
<div class="fit-demo">
<FCollapse v-model="activeNames">
<FCollapseItem title="模型列表" name="1">
<div class="list-div">
<div v-for="(item, index) in modelFileList" :key="index" class="block" @click="addMesh(item)">
<FEllipsis class="demonstration" :content="item.name" :tooltip="{ popperClass: 'a', showAfter: 500 }" style="max-width: 100px" />
<FImage style="width: 100px; height: 100px" :src="item.img" fit="contain" />
</div>
</div>
</FCollapseItem>
<FCollapseItem title="常用灯光" name="2">
<div class="one-light" @click="addMesh('ambientLight')"><PlusCircleFilled :size="13" /> 环境光</div>
<div class="one-light" @click="addMesh('directionalLight')"><PlusCircleFilled :size="13" /> 平行光</div>
</FCollapseItem>
<FCollapseItem title="常用物体" name="3">
<div class="one-light" @click="addMesh('Sphere')"><PlusCircleFilled :size="13" /> 圆球</div>
<div class="one-light" @click="addMesh('Box')"><PlusCircleFilled :size="13" /> 立方体</div>
</FCollapseItem>
</FCollapse>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { FImage, FEllipsis, FCollapse, FCollapseItem, FMessage } from '@fesjs/fes-design'
import { PlusCircleFilled } from '@fesjs/fes-design/icon'
import { useCurMeshListStore } from 'PLS/tvtSceneCreator/stores/curMeshList'
import { useotherConfigStore } from 'PLS/tvtSceneCreator/stores/otherConfig'
import { modelFileList } from 'PLS/tvtSceneCreator/modelList.config.js'
const otherConfig = useotherConfigStore() as any
const curMeshList = useCurMeshListStore() as any
const addMesh = (type: any) => {
if (type === 'ambientLight') {
if (curMeshList.hasAmbientLight()) {
FMessage.error({
content: `场景内已存在环境光,不能再添加!`,
colorful: false,
})
return
} else {
curMeshList.addMesh({ name: 'AmbientLight', type: 'AmbientLight', intensity: 10 })
}
} else if (type === 'directionalLight') {
curMeshList.addMesh({ name: 'DirectionalLight', type: 'DirectionalLight', intensity: 5, position: [5, 3, 5] })
} else if (type === 'Box') {
curMeshList.addMesh({ name: 'Box-add', type: 'Mesh', position: [0, 0, 0], args: [10, 10, 10], metalness: 1, roughness: 0.14 })
} else if (type === 'Sphere') {
curMeshList.addMesh({
name: 'Sphere-add',
type: 'Mesh',
position: [0, 0, 0],
args: [2, 32, 16],
geometry: 'SphereGeometry',
material: 'MeshStandardMaterial',
})
} else {
curMeshList.addMesh({
name: type.name,
type: type.type,
position: [0, 0, 0],
url: type.url,
})
}
curMeshList.selectedMeshIndex = null
otherConfig.activeModel = 'nowin'
}
const activeNames = ref(['1'])
</script>
<style lang="scss" scoped>
.fit-demo {
overflow-y: auto;
overflow-x: hidden;
max-height: 600px;
.list-div {
display: flex;
flex-wrap: wrap;
.block {
width: 100px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 10px;
padding-right: 0px;
cursor: pointer;
}
}
.one-light {
text-align: left;
padding: 10px 0px 10px 40px;
color: #fff;
cursor: pointer;
line-height: 14px;
position: relative;
.fes-design-icon {
display: block;
position: absolute;
left: 16px;
}
}
}
.fit-demo::-webkit-scrollbar {
width: 4px;
}
.fit-demo::-webkit-scrollbar-track {
background-color: #f1f1f1;
opacity: 0.2;
}
.fit-demo::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 5px;
}
.fit-demo::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
</style>
<style lang="scss">
.fit-demo {
.block {
.demonstration {
font-size: 12px;
color: #eee;
line-height: 28px;
margin-top: -10px;
margin-bottom: -10px;
}
}
.fes-collapse-item__header {
background: #0f1222;
color: var(--f-text-color-caption);
}
.fes-collapse-item__wrap.is-embedded {
background: #0f1222;
}
.fes-collapse-item__content {
padding: 5px;
}
}
</style>

View File

@ -0,0 +1,124 @@
<template>
<div class="selMeshInfo-div" v-show="curMeshList.selectedMeshIndex !== null">
<FText size="large" class="title">详情信息</FText>
<div class="info-div" />
</div>
<div v-show="curMeshList.selectedMeshIndex === null">暂未选择物体</div>
</template>
<script lang="ts" setup>
import { onMounted, watch, toRaw } from 'vue'
import { useSeek } from '@tresjs/core'
import { FText } from '@fesjs/fes-design'
import { Pane } from 'tweakpane'
import { useCurMeshListStore } from 'PLS/tvtSceneCreator/stores/curMeshList'
const curMeshList = useCurMeshListStore()
const PARAMS = {
meshType: 'Mesh',
meshName: '自行车',
uuid: '1234567890',
position: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
scale: { x: 1, y: 1, z: 1 },
renderOrder: 0,
visible: true,
castShadow: true,
receiveShadow: true,
}
let pane = null as any
const { seek } = useSeek()
let selMesh = null as any
watch(
() => curMeshList.selectedMeshIndex,
(index) => {
bingPARAMS()
},
)
const bingPARAMS = () => {
const index = curMeshList.selectedMeshIndex
if (index !== null) {
const mesh = seek(curMeshList.tresGroup as any, 'meshListIndex', index) as any
if (mesh) {
selMesh = toRaw(mesh)
PARAMS.meshType = selMesh.type
PARAMS.meshName = selMesh.name
PARAMS.uuid = selMesh.uuid
PARAMS.position = selMesh.position
PARAMS.rotation = selMesh.rotation
PARAMS.scale = selMesh.scale
PARAMS.renderOrder = selMesh.renderOrder
PARAMS.visible = selMesh.visible
PARAMS.castShadow = selMesh.castShadow
PARAMS.receiveShadow = selMesh.receiveShadow
pane.refresh()
}
}
}
// @ts-ignore
window['TvTSCinForPane'] = bingPARAMS
onMounted(() => {
const domcolor = document.querySelector('.selMeshInfo-div .info-div') as any
pane = new Pane({ container: domcolor })
pane.addBinding(PARAMS, 'meshType', { label: '物体类型', disabled: true })
pane.addBinding(PARAMS, 'meshName', { label: '物体名称', disabled: true })
pane.addBinding(PARAMS, 'uuid', { label: '识别码', disabled: true })
pane.addBinding(PARAMS, 'position', { label: '位置' })
pane.addBinding(PARAMS, 'rotation', { label: '旋转' })
pane.addBinding(PARAMS, 'scale', { label: '缩放' })
pane.addBinding(PARAMS, 'renderOrder', { label: '渲染顺序', step: 1, min: 0 })
pane.addBinding(PARAMS, 'visible', { label: '是否可见' })
pane.addBinding(PARAMS, 'castShadow', { label: '产生阴影' })
pane.addBinding(PARAMS, 'receiveShadow', { label: '接受阴影' })
pane.on('change', (ev: any) => {
if (ev.target.key === 'visible') {
selMesh.visible = ev.value
}
if (ev.target.key === 'renderOrder') {
selMesh.renderOrder = ev.value
}
if (ev.target.key === 'castShadow') {
selMesh.castShadow = ev.value
}
if (ev.target.key === 'receiveShadow') {
selMesh.receiveShadow = ev.value
}
const index = curMeshList.selectedMeshIndex
if (index !== null) {
const mesh = toRaw(seek(curMeshList.tresGroup as any, 'meshListIndex', index)) as any
const mObject = toRaw(curMeshList.mlist[index]) as any
if (mesh && ev.target.key !== 'uuid') {
console.log(ev.target.key, index, mesh, mObject)
if (mesh[ev.target.key] && mObject[ev.target.key]) {
if (ev.target.key === 'position' || ev.target.key === 'rotation' || ev.target.key === 'scale') {
mObject[ev.target.key][0] = mesh[ev.target.key].x
mObject[ev.target.key][1] = mesh[ev.target.key].y
mObject[ev.target.key][2] = mesh[ev.target.key].z
} else {
mObject[ev.target.key] = mesh[ev.target.key]
}
}
}
}
})
})
</script>
<style lang="scss" scoped>
.selMeshInfo-div {
.title {
color: var(--f-text-color-caption);
text-align: center;
display: block;
margin-bottom: 10px;
}
}
</style>
<style lang="scss"></style>

View File

@ -0,0 +1,172 @@
<template>
<f-menu inverted @select="handleSelect">
<f-sub-menu value="1">
<template #icon>
<FolderOutlined />
</template>
<template #label>文件</template>
<f-menu-item value="1.1">
<template #label>新建 - 场景</template>
</f-menu-item>
<f-menu-item value="1.2">
<template #label>导入 - 场景配置</template>
</f-menu-item>
<f-menu-item value="1.3">
<template #label>导出 - 场景配置</template>
</f-menu-item>
<f-menu-item value="1.4">
<template #label>生成 - 项目插件包</template>
</f-menu-item>
</f-sub-menu>
<!-- <f-sub-menu value="2">
<template #icon>
<SettingOutlined />
</template>
<template #label>场景设置</template>
<f-menu-item value="2.1" label="环境设置" />
<f-menu-item value="2.2" label="全屏" />
</f-sub-menu>
<f-sub-menu value="3">
<template #icon>
<ShareOutlined />
</template>
<template #label>助手</template>
<f-menu-item value="3.1" label="网格助手" />
<f-menu-item value="3.2" label="灯光助手" />
<f-menu-item value="3.3" label="场景属性" />
<f-menu-item value="3.4" label="陀螺仪" />
</f-sub-menu>
<f-menu-item value="4" label="当前预览">
<template #icon>
<EyeOutlined />
</template>
</f-menu-item> -->
<f-sub-menu value="5">
<template #icon>
<ShareOutlined />
</template>
<template #label>关于</template>
<f-menu-item value="5.1" label="功能介绍" />
<f-menu-item value="5.2" label="视频说明" />
<f-menu-item value="5.3" label="免费源码包" />
</f-sub-menu>
</f-menu>
</template>
<script setup lang="ts">
import { FMenu, FSubMenu, FMenuItem, FMessage } from '@fesjs/fes-design'
import { FolderOutlined, ShareOutlined } from '@fesjs/fes-design/icon' // SettingOutlined EyeOutlined
import { useCurMeshListStore } from 'PLS/tvtSceneCreator/stores/curMeshList'
import { useBackgroundSetupStore } from 'PLS/tvtSceneCreator/stores/backgroundSetup'
import { useEnvSetupStore } from 'PLS/tvtSceneCreator/stores/envSetup'
const envSetup = useEnvSetupStore()
const backgroundSetup = useBackgroundSetupStore()
const curMeshList = useCurMeshListStore()
const exportSceneConfig = () => {
const configAll = {
mlist: curMeshList.mlist,
envSetup: envSetup,
backgroundSetup: backgroundSetup,
}
debugger
const fileContent = JSON.stringify(configAll, null, 2)
const blob = new Blob([fileContent], { type: 'application/javascript' })
const a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = 'tvtSceneCreator.config.js'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
const inputSceneConfig = () => {
if (curMeshList.mlist.length > 0) {
FMessage.error({
content: `当前场景存在物体,请新建空场景再导入配置!`,
colorful: true,
})
return
}
const input = document.createElement('input')
input.type = 'file'
input.accept = '.js'
input.onchange = async (event: any) => {
const file = event.target.files[0]
if (file) {
const text = await file.text()
try {
const config = JSON.parse(text) as any
curMeshList.mlist = config.mlist
envSetup.isLightFormer = config.envSetup.isLightFormer
envSetup.colorA = config.envSetup.colorA
envSetup.colorB = config.envSetup.colorB
envSetup.blur = config.envSetup.blur
envSetup.pos = config.envSetup.pos
envSetup.rotate = config.envSetup.rotate
envSetup.scale = config.envSetup.scale
if (config.envSetup.envHDR.name !== 'upload') {
envSetup.setEnvHDR(config.envSetup.envHDR.name)
}
backgroundSetup.color = config.backgroundSetup.color
backgroundSetup.img = config.backgroundSetup.img
backgroundSetup.useBackImg = config.backgroundSetup.useBackImg
FMessage.info({
content: `配置导入成功!`,
colorful: true,
})
} catch (error: any) {
FMessage.error({
content: `读取文件时发生错误: ${error.message}`,
colorful: true,
})
}
}
}
input.click()
}
const handleSelect = ({ value }: { value: string }) => {
if (value === '5.1') {
window.open('https://www.icegl.cn/tvtstore/tvtSceneCreator')
}
if (value === '5.3') {
window.open('https://www.icegl.cn/tvtstore/tvtSceneCreator')
}
if (value === '5.2' || value === '1.4') {
FMessage.info({
content: `功能更新中,敬请期待!`,
colorful: true,
})
}
if (value === '1.1') {
curMeshList.clearMesh()
FMessage.info({
content: `场景已清空!`,
colorful: true,
})
}
if (value === '1.3') {
exportSceneConfig()
FMessage.info({
content: `配置导出成功!`,
colorful: true,
})
}
if (value === '1.2') {
inputSceneConfig()
}
}
</script>
<style lang="less" scoped>
.fes-sub-menu {
min-width: 120px;
pointer-events: all;
}
</style>

View File

@ -0,0 +1,22 @@
export default {
"name": "tvtSceneCreator",
"title": "TvT.js场景生成器",
"intro": `根据模型列表,设置光源、背景、环境等,生成场景, 导入导出配置,生成插件包,持续更新中...
整体文档教程和免费插件下载详见<a style="color: #5384ff;" href="https://www.icegl.cn/tvtstore/tvtSceneCreator" target="_blank">TvT.js场景生成器</a>`,
"version": "1.0.0",
"author": '地虎降天龙',
"website": 'https://gitee.com/hawk86104',
"state": "active",
"creatTime": "2024-08-20",
"updateTime": "2024-08-20",
"require": [],
"tvtstore": 'FREE',
"preview": [{
"src": "/plugins/tvtSceneCreator/preview/index.png",
"type": "img",
"name": "index",
"title": "场景生成器预览",
disableFPSGraph: false,
disableSrcBtn: true
}, ]
}

View File

@ -0,0 +1,9 @@
export const modelFileList = [
{ name: '笔记本', url: './plugins/basic/htmls/model/model.gltf', type: 'gltf', img: './plugins/basic/htmls/preview/websiteReflector.png' },
{
name: '飞机',
url: 'https://opensource-1314935952.cos.ap-nanjing.myqcloud.com/model/industry4/plane/scene.gltf',
type: 'gltf',
img: './plugins/UIdemo/preview/sizeMark.png',
},
]

View File

@ -0,0 +1,76 @@
<template>
<threeDcom />
<FConfigProvider :themeOverrides="themeOverrides">
<div
id="UIDIV"
style="
position: absolute;
width: 100%;
height: 100%;
pointer-events: none;
-webkit-user-select: none; /* Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+/Edge */
user-select: none; /* Standard syntax */
"
>
<topMenu />
<leftLayout />
<rightEnvSetup />
<bottomContr />
</div>
</FConfigProvider>
</template>
<script setup lang="ts">
import { FConfigProvider } from '@fesjs/fes-design'
import topMenu from '../components/UI/topMenu.vue'
import leftLayout from '../components/UI/leftLayout.vue'
import rightEnvSetup from '../components/UI/rightEnvSetup.vue'
import bottomContr from '../components/UI/bottomContr.vue'
import threeDcom from '../components/Tres/index.vue'
const themeOverrides = {
common: {
primaryColor: '#8f98ff',
successColor: '#00cb91',
dangerColor: '#ff4d4f',
warningColor: '#f29360',
tipColor: '#8f98ff',
white: '#fff',
black: '#000',
bodyBgColor: '#fff',
fontColorBase: '#0f1222',
fontSizeBase: '14px',
borderRadiusBase: '4px',
borderRadiusSm: '2px',
borderWidthBase: '1px',
borderStyleBase: 'solid',
borderColorBase: '#cfd0d3',
shadowColor: 'rgba(18, 18, 18, 0.1)',
shadowColorSm: 'rgba(18, 18, 18, 0.2)',
shadowRadius: '12px',
shadowRadiusSm: '4px',
maskColor: 'rgba(18, 18, 18, 0.45)',
},
}
</script>
<style lang="scss">
:root {
.fpsStats {
top: 7px;
right: 8px;
left: auto;
}
}
</style>

View File

@ -0,0 +1,14 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useBackgroundSetupStore = defineStore('backgroundSetup', () => {
const color = ref('#333333')
const img = ref({
name: '',
src: '',
})
const useBackImg = ref(true)
const setupEnvBackground = ref(null)
return { color, img, useBackImg, setupEnvBackground }
})

View File

@ -0,0 +1,49 @@
/* eslint-disable no-undefined */
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useCurMeshListStore = defineStore('curMeshList', () => {
const controlState = ref('sel') // rotate scale translate
const mlist = ref([])
const addMesh = (mesh) => {
const one = {
name: mesh.name !== undefined ? mesh.name : 'deMesh',
type: mesh.type ? mesh.type : 'Mesh',
position: mesh.position ? mesh.position : [0, 0, 0],
rotation: mesh.rotation ? mesh.rotation : [0, 0, 0],
scale: mesh.scale ? mesh.scale : [1, 1, 1],
visible: mesh.visible !== undefined ? mesh.visible : true,
renderOrder: mesh.renderOrder ? mesh.renderOrder : 0,
receiveShadow: mesh.receiveShadow !== undefined ? mesh.receiveShadow : false,
castShadow: mesh.castShadow !== undefined ? mesh.castShadow : false,
geometry: mesh.geometry ? mesh.geometry : 'BoxGeometry',
args: mesh.args ? mesh.args : [1, 1, 1],
material: mesh.material ? mesh.material : 'MeshStandardMaterial',
metalness: mesh.metalness ? mesh.metalness : 0,
roughness: mesh.roughness ? mesh.roughness : 0.5,
color: mesh.color ? mesh.color : '#ffffff',
intensity: mesh.intensity ? mesh.intensity : 1,
url: mesh.url ? mesh.url : '',
}
mlist.value.push(one)
}
const removeMesh = (index) => {
mlist.value.splice(index, 1)
}
const hasAmbientLight = () => mlist.value.some((mesh) => mesh.type === 'AmbientLight')
const selectedMeshIndex = ref(null)
const clearMesh = () => {
mlist.value = []
selectedMeshIndex.value = null
}
const tresGroup = ref(null)
return { controlState, mlist, addMesh, removeMesh, selectedMeshIndex, tresGroup, hasAmbientLight,clearMesh }
})

View File

@ -0,0 +1,21 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useEnvSetupStore = defineStore('envSetup', () => {
const isLightFormer = ref(false)
const colorA = ref('#ff0000')
const colorB = ref('#0000ff')
const blur = ref(1)
const pos = ref({ x: 0, y: 0, z: 0 })
const rotate = ref({ x: 0, y: 0, z: 0 })
const scale = ref({ x: 1, y: 1, z: 1 })
const envHDR = ref({
name: '',
src: null,
})
const setEnvHDR = ref()
return { isLightFormer, colorA, colorB, blur, pos, rotate, scale, envHDR, setEnvHDR }
})

View File

@ -0,0 +1,8 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useotherConfigStore = defineStore('otherConfig', () => {
const activeModel = ref('modelList')
return { activeModel }
})