更新打包配置,完善组件入参模式,新增事件总线
This commit is contained in:
parent
cfbfda520d
commit
4a648c2f97
26520
package-lock.json
generated
26520
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
19
package.json
19
package.json
@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "material-editor",
|
"name": "material-editor",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc -b && vite build",
|
"build": "vue-tsc -b && vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
@ -15,13 +16,15 @@
|
|||||||
"index.html",
|
"index.html",
|
||||||
"README.md"
|
"README.md"
|
||||||
],
|
],
|
||||||
"module": "./dist/material-editor.js",
|
"module": "dist/material-editor.es.js",
|
||||||
"main": "./dist/material-editor.umd.js",
|
"main": "dist/material-editor.umd.js",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": {
|
".": {
|
||||||
"import": "./dist/index.js",
|
"import": "./dist/material-editor.es.js",
|
||||||
"require": "./dist/index.cjs"
|
"require": "./dist/material-editor.umd.cjs"
|
||||||
}
|
},
|
||||||
|
"./style.css": "./dist/material-editor.css",
|
||||||
|
"./iife": "./dist/material-editor.iife.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jscad/modeling": "^2.11.0",
|
"@jscad/modeling": "^2.11.0",
|
||||||
@ -40,8 +43,10 @@
|
|||||||
"@types/node": "^22.14.1",
|
"@types/node": "^22.14.1",
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"@vue/tsconfig": "^0.7.0",
|
"@vue/tsconfig": "^0.7.0",
|
||||||
|
"sass-embedded": "^1.87.0",
|
||||||
"typescript": "~5.7.2",
|
"typescript": "~5.7.2",
|
||||||
"vite": "^6.2.6",
|
"vite": "^6.2.6",
|
||||||
|
"vite-plugin-dts": "^4.5.3",
|
||||||
"vue-tsc": "^2.2.4"
|
"vue-tsc": "^2.2.4"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.1.1+sha1.09ada6cd05003e0ced25fb716f9fda4063ec2e3b"
|
"packageManager": "pnpm@9.1.1+sha1.09ada6cd05003e0ced25fb716f9fda4063ec2e3b"
|
||||||
|
829
pnpm-lock.yaml
829
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@ import { Viewer } from './Viewer';
|
|||||||
import { PMREMGenerator3 } from './PMREMGenerator2';
|
import { PMREMGenerator3 } from './PMREMGenerator2';
|
||||||
import type { PhysicalMaterialRecord, TextureTableRecord } from 'webcad_ue4_api';
|
import type { PhysicalMaterialRecord, TextureTableRecord } from 'webcad_ue4_api';
|
||||||
import { MaterialEditorCameraControl } from './MaterialMouseControl';
|
import { MaterialEditorCameraControl } from './MaterialMouseControl';
|
||||||
|
import { GetConfig } from '../lib/libOutputConfig';
|
||||||
|
|
||||||
async function textureRenderUpdate(textureRecord:TextureTableRecord){
|
async function textureRenderUpdate(textureRecord:TextureTableRecord){
|
||||||
const texture = textureRecord['texture'] as Texture;
|
const texture = textureRecord['texture'] as Texture;
|
||||||
@ -81,11 +82,6 @@ export class MaterialEditor extends Singleton
|
|||||||
this.Viewer.UpdateRender();
|
this.Viewer.UpdateRender();
|
||||||
this.Viewer.Fov = 90;
|
this.Viewer.Fov = 90;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
this.Canvas.appendChild(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
SetViewer(canvas: HTMLElement)
|
SetViewer(canvas: HTMLElement)
|
||||||
{
|
{
|
||||||
@ -119,8 +115,8 @@ export class MaterialEditor extends Singleton
|
|||||||
|
|
||||||
return new Promise(async (res, rej) =>
|
return new Promise(async (res, rej) =>
|
||||||
{
|
{
|
||||||
let urls = ['right.webp', 'left.webp', 'top.webp', 'bottom.webp', 'front.webp', 'back.webp'];
|
let urls = [...GetConfig().envTextureSrc];
|
||||||
new CubeTextureLoader().setPath('./')
|
new CubeTextureLoader()
|
||||||
.load(urls, (t) =>
|
.load(urls, (t) =>
|
||||||
{
|
{
|
||||||
t.encoding = sRGBEncoding;
|
t.encoding = sRGBEncoding;
|
||||||
@ -148,8 +144,8 @@ export class MaterialEditor extends Singleton
|
|||||||
|
|
||||||
this.exrPromise = new Promise<Texture>((res, rej) =>
|
this.exrPromise = new Promise<Texture>((res, rej) =>
|
||||||
{
|
{
|
||||||
let urls = ['right-gray.webp', 'left-gray.webp', 'top-gray.webp', 'bottom-gray.webp', 'front-gray.webp', 'back-gray.webp'];
|
let urls = [...GetConfig().grayEnvTextureSrc];
|
||||||
new CubeTextureLoader().setPath('./')
|
new CubeTextureLoader()
|
||||||
.load(urls, (t) =>
|
.load(urls, (t) =>
|
||||||
{
|
{
|
||||||
t.encoding = sRGBEncoding;
|
t.encoding = sRGBEncoding;
|
||||||
|
@ -1,5 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<div vertical class="material-adjuster">
|
<div vertical class="material-adjuster">
|
||||||
|
<div class="adjust-section">
|
||||||
|
<h3>操作</h3>
|
||||||
|
<fieldset v-if="debugMode" style="margin: 1em 0;">
|
||||||
|
<legend>DEBUG</legend>
|
||||||
|
<label>上传路径ID</label>
|
||||||
|
<input v-model="materialInfo.dirId" type="text" placeholder="材质路径ID" />
|
||||||
|
</fieldset>
|
||||||
|
<label>材质名</label>
|
||||||
|
<input v-model.trim="materialInfo.materialName" type="text" placeholder="材质名" />
|
||||||
|
|
||||||
|
<!-- <CfFlex gap="1em">
|
||||||
|
<button class="btn-success" style="min-width: 110px;" @click="HandleUpload">上传</button>
|
||||||
|
<button class="btn-danger" style="min-width: 110px;" @click="HandleCancel">取消</button>
|
||||||
|
</CfFlex> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="adjust-section">
|
<div class="adjust-section">
|
||||||
<h3>模型预览</h3>
|
<h3>模型预览</h3>
|
||||||
<label>选择模型样式</label>
|
<label>选择模型样式</label>
|
||||||
@ -10,8 +26,8 @@
|
|||||||
<div class="adjust-section" v-if="debugMode">
|
<div class="adjust-section" v-if="debugMode">
|
||||||
<h3>纹理选择(DEBUG)</h3>
|
<h3>纹理选择(DEBUG)</h3>
|
||||||
<label>纹理链接</label>
|
<label>纹理链接</label>
|
||||||
<input v-model.trim="textureLink" type="text" placeholder="在此键入纹理图像的URL..." />
|
<input v-model.trim="_textureSrc" type="text" placeholder="在此键入纹理图像的URL..." />
|
||||||
<button class="btn-primary" @click="scene.ChangeTextureAsync(textureLink)"
|
<button class="btn-primary" @click="scene.ChangeTextureAsync(_textureSrc)"
|
||||||
style="margin-left: 1em;">应用</button>
|
style="margin-left: 1em;">应用</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="adjust-section">
|
<div class="adjust-section">
|
||||||
@ -85,39 +101,41 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="adjust-section">
|
|
||||||
<h3>操作</h3>
|
|
||||||
<fieldset v-if="debugMode" style="margin: 1em 0;">
|
|
||||||
<legend>DEBUG</legend>
|
|
||||||
<label>上传路径ID</label>
|
|
||||||
<input v-model="materialRequest.dirId" type="text" placeholder="材质路径ID" />
|
|
||||||
</fieldset>
|
|
||||||
<label>材质名</label>
|
|
||||||
<input v-model="materialRequest.materialName" type="text" placeholder="材质名" />
|
|
||||||
|
|
||||||
<CfFlex gap="1em">
|
|
||||||
<button class="btn-success" style="min-width: 110px;" @click="HandleUpload">上传</button>
|
|
||||||
<button class="btn-danger" style="min-width: 110px;" @click="HandleCancel">取消</button>
|
|
||||||
</CfFlex>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts'>
|
<script setup lang='ts'>
|
||||||
import { ref, reactive, watch } from "vue"
|
import { ref, reactive, watch, onMounted } from "vue"
|
||||||
import { useScene, type TextureAdjustment } from "../stores/sceneStore";
|
import { useScene, type TextureAdjustment } from "../stores/sceneStore";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import CfFlex from "./CfFlex.vue";
|
import CfFlex from "./CfFlex.vue";
|
||||||
import { DirectoryId } from "../api/Request";
|
import { DirectoryId } from "../api/Request";
|
||||||
import { IsNullOrWhitespace } from "../helpers/helper.string";
|
import { IsNullOrWhitespace } from "../helpers/helper.string";
|
||||||
|
import { DeflateAsync } from "../helpers/helper.compression";
|
||||||
|
|
||||||
|
export interface MaterialRequest {
|
||||||
|
/** 材质名 */
|
||||||
|
name: string;
|
||||||
|
/** 材质logo文件 */
|
||||||
|
logo: Blob;
|
||||||
|
/** 序列化并Deflate压缩后的材质文件的Base64编码 */
|
||||||
|
file: string;
|
||||||
|
}
|
||||||
|
|
||||||
const scene = useScene();
|
const scene = useScene();
|
||||||
|
|
||||||
const debugMode = ref(true);
|
const props = defineProps<{
|
||||||
|
textureSrc?: string;
|
||||||
|
}>();
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'cancel'): void;
|
||||||
|
(e: 'submit', data: MaterialRequest): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const debugMode = ref(false);
|
||||||
const { CurrGeometry, Geometries, Material } = storeToRefs(scene);
|
const { CurrGeometry, Geometries, Material } = storeToRefs(scene);
|
||||||
const enableTexture = ref(Material.value.useMap);
|
const enableTexture = ref(Material.value.useMap);
|
||||||
const textureLink = ref('');
|
const _textureSrc = ref(props.textureSrc);
|
||||||
const textureAdjustment = reactive<TextureAdjustment>({
|
const textureAdjustment = reactive<TextureAdjustment>({
|
||||||
wrapS: 0,
|
wrapS: 0,
|
||||||
wrapT: 0,
|
wrapT: 0,
|
||||||
@ -134,9 +152,18 @@ const model = reactive({
|
|||||||
normalScale: Material.value.bumpScale,
|
normalScale: Material.value.bumpScale,
|
||||||
emissiveIntensity: Material.value.specular
|
emissiveIntensity: Material.value.specular
|
||||||
});
|
});
|
||||||
const materialRequest = reactive({
|
const materialInfo = reactive({
|
||||||
dirId: DirectoryId.MaterialDir, // 正常来说是2
|
dirId: DirectoryId.MaterialDir, // 正常来说是2
|
||||||
materialName: ''
|
materialName: '材质1'
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
scene.ChangeTextureAsync(_textureSrc.value);
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => props.textureSrc, async (val) => {
|
||||||
|
_textureSrc.value = val;
|
||||||
|
await scene.ChangeTextureAsync(_textureSrc.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(model, async (val) => {
|
watch(model, async (val) => {
|
||||||
@ -171,25 +198,34 @@ async function EnableTexture(enable: boolean) {
|
|||||||
|
|
||||||
async function HandleUpload() {
|
async function HandleUpload() {
|
||||||
try {
|
try {
|
||||||
if (IsNullOrWhitespace(materialRequest.materialName)) {
|
if (IsNullOrWhitespace(materialInfo.materialName)) {
|
||||||
alert('材质名称不可为空');
|
alert('材质名称不可为空');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploading.value = true;
|
uploading.value = true;
|
||||||
await scene.UploadMaterialAsync(materialRequest);
|
const data = {
|
||||||
|
name: materialInfo.materialName,
|
||||||
|
logo: await scene.GenerateMaterialLogoAsync(),
|
||||||
|
// jsonString -> Deflate -> BinaryString -> Base64
|
||||||
|
file: btoa(String.fromCharCode(...await DeflateAsync(await scene.SerializeMaterialAsync())))
|
||||||
|
};
|
||||||
|
emits('submit', data);
|
||||||
|
return data;
|
||||||
|
} finally {
|
||||||
uploading.value = false;
|
uploading.value = false;
|
||||||
alert("上传成功");
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
alert("上传材质出错,请检查网络连接或联系管理员");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function HandleCancel() {
|
function HandleCancel() {
|
||||||
// TODO: 触发取消事件
|
emits('cancel');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
Upload: HandleUpload,
|
||||||
|
Cancel: HandleCancel
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -1,35 +1,59 @@
|
|||||||
<template>
|
<template>
|
||||||
<CfFlex class="material-view">
|
<CfFlex class="material-view">
|
||||||
<div ref="container" style="width: 100%; height: 100%; flex: 3; box-sizing: border-box;" />
|
<div ref="container" class="material-view-container" />
|
||||||
<MaterialAdjuster style="flex: 1;overflow-y: auto; width: 100%; height: 100%; box-sizing: border-box;" />
|
<MaterialAdjuster ref="adjuster" class="material-view-sider" :texture-src="textureSrc" @cancel="config.cancelCallback" @submit="config.submitCallback" />
|
||||||
</CfFlex>
|
</CfFlex>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, useTemplateRef } from 'vue';
|
import { onMounted, ref, useTemplateRef } from 'vue';
|
||||||
import MaterialAdjuster from './MaterialAdjuster.vue';
|
import MaterialAdjuster from './MaterialAdjuster.vue';
|
||||||
import { useScene } from '../stores/sceneStore';
|
import { useScene } from '../stores/sceneStore';
|
||||||
import CfFlex from './CfFlex.vue';
|
import CfFlex from './CfFlex.vue';
|
||||||
|
import { GetConfig } from '../lib/libOutputConfig';
|
||||||
|
import { useEvent } from '../stores/eventStore';
|
||||||
|
|
||||||
const scene = useScene();
|
const scene = useScene();
|
||||||
const container = useTemplateRef<HTMLElement>('container');
|
const eventbus = useEvent();
|
||||||
|
const container = useTemplateRef('container');
|
||||||
|
const adjusterRef = useTemplateRef('adjuster');
|
||||||
|
const config = GetConfig();
|
||||||
|
const textureSrc = ref(config.textureSrc);
|
||||||
|
|
||||||
// 禁用右键菜单
|
// 禁用右键菜单
|
||||||
document.addEventListener('contextmenu', (e) => e.preventDefault());
|
document.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
scene.Initial(container.value);
|
scene.Initial(container.value);
|
||||||
|
eventbus.Subscribe('submit', () => adjusterRef.value.Upload());
|
||||||
|
eventbus.Subscribe('update-texture', () => {
|
||||||
|
textureSrc.value = config.textureSrc
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped lang="scss">
|
||||||
.material-view
|
.material-view
|
||||||
{
|
{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
&-container {
|
||||||
|
flex: 3 1;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-sider {
|
||||||
|
flex: 1 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
43
src/lib/entry.ts
Normal file
43
src/lib/entry.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { createApp, type App as VueApp } from 'vue'
|
||||||
|
|
||||||
|
import App from '../App.vue'
|
||||||
|
import '../assets/main.css'
|
||||||
|
import { createPinia } from 'pinia';
|
||||||
|
import { ConfigureLibOutput, type LibOutputConfig } from './libOutputConfig';
|
||||||
|
import { useEvent } from '../stores/eventStore';
|
||||||
|
|
||||||
|
let app: VueApp<Element> = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 挂载材质编辑器到指定元素
|
||||||
|
* @param element 要挂载的HTML元素
|
||||||
|
* @param options 程序配置
|
||||||
|
*/
|
||||||
|
export function Mount(element: Element, options: Partial<LibOutputConfig>) {
|
||||||
|
ConfigureLibOutput(options);
|
||||||
|
|
||||||
|
const pinia = createPinia();
|
||||||
|
app = createApp(App);
|
||||||
|
app.use(pinia)
|
||||||
|
.mount(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 对程序配置进行更改 */
|
||||||
|
export function Configure(options: Partial<LibOutputConfig>) {
|
||||||
|
ConfigureLibOutput(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 卸载已经挂载的DOM */
|
||||||
|
export function Unmount() {
|
||||||
|
app.unmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 手动进行材质提交 */
|
||||||
|
export function Submit() {
|
||||||
|
useEvent().Publish('submit');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新材质贴图 */
|
||||||
|
export function UpdateTexture() {
|
||||||
|
useEvent().Publish('update-texture');
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
import MaterialView from "../components/MaterialView.vue";
|
import { Mount, Unmount, Submit, UpdateTexture, Configure } from "./entry";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
MaterialView
|
Mount,
|
||||||
|
Unmount,
|
||||||
|
Submit,
|
||||||
|
UpdateTexture,
|
||||||
|
Configure
|
||||||
}
|
}
|
38
src/lib/libOutputConfig.ts
Normal file
38
src/lib/libOutputConfig.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import type { DeepReadonly } from "vue"
|
||||||
|
import type { MaterialRequest } from "../components/MaterialAdjuster.vue"
|
||||||
|
|
||||||
|
let _libOutputConfig = {
|
||||||
|
textureSrc: "",
|
||||||
|
submitCallback: undefined,
|
||||||
|
cancelCallback: undefined,
|
||||||
|
envTextureSrc: ['./right.webp', './left.webp', './top.webp', './bottom.webp', './front.webp', './back.webp'],
|
||||||
|
grayEnvTextureSrc: ['./right-gray.webp', './left-gray.webp', './top-gray.webp', './bottom-gray.webp', './front-gray.webp', './back-gray.webp'],
|
||||||
|
} as LibOutputConfig
|
||||||
|
|
||||||
|
export function ConfigureLibOutput(config: Partial<LibOutputConfig>) {
|
||||||
|
Object.assign(_libOutputConfig, {
|
||||||
|
...config
|
||||||
|
});
|
||||||
|
// _libOutputConfig = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LibOutputConfig = {
|
||||||
|
/** 材质贴图链接 */
|
||||||
|
textureSrc: string,
|
||||||
|
/** 环境贴图链接(立方体贴图,按照顺序输入[右左上下前后]) */
|
||||||
|
envTextureSrc: string[],
|
||||||
|
/** 灰度环境贴图链接,输入格式与环境贴图一致 */
|
||||||
|
grayEnvTextureSrc: string[],
|
||||||
|
/** 提交材质时的回调 */
|
||||||
|
submitCallback?: (data: MaterialRequest) => void,
|
||||||
|
/**
|
||||||
|
* 取消材质编辑时的回调
|
||||||
|
* @deprecated 不需要使用
|
||||||
|
*/
|
||||||
|
cancelCallback?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function GetConfig(): DeepReadonly<typeof _libOutputConfig>
|
||||||
|
{
|
||||||
|
return _libOutputConfig;
|
||||||
|
}
|
18
src/stores/eventStore.ts
Normal file
18
src/stores/eventStore.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
export const useEvent = defineStore('event', () => {
|
||||||
|
const events: Partial<Record<EventNames, Function[]>> = {};
|
||||||
|
|
||||||
|
function Subscribe(name: EventNames, callback: Function) {
|
||||||
|
events[name] = events[name] || [];
|
||||||
|
events[name].push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Publish(name: EventNames, ...args: any[]) {
|
||||||
|
events[name]?.forEach(e => e(...args));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { Subscribe, Publish };
|
||||||
|
});
|
||||||
|
|
||||||
|
export type EventNames = 'submit' | 'update-texture'
|
@ -1,14 +1,11 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { computed, ref, watch } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import { MaterialEditor } from "../common/MaterialEditor";
|
import { MaterialEditor } from "../common/MaterialEditor";
|
||||||
import { Database, ObjectId, PhysicalMaterialRecord, TextureTableRecord } from "webcad_ue4_api";
|
import { ObjectId, PhysicalMaterialRecord, TextureTableRecord } from "webcad_ue4_api";
|
||||||
import { LoadImageFromUrl } from "../helpers/helper.imageLoader";
|
import { LoadImageFromUrl } from "../helpers/helper.imageLoader";
|
||||||
import { Texture } from "three";
|
import { Texture } from "three";
|
||||||
import { materialRenderer } from "../common/MaterialRenderer";
|
import { materialRenderer } from "../common/MaterialRenderer";
|
||||||
import { ImgsUrl, MaterialUrls } from "../api/Api";
|
|
||||||
import { Post, PostJson, RequestStatus } from "../api/Request";
|
|
||||||
import { MaterialOut } from "../common/MaterialSerializer";
|
import { MaterialOut } from "../common/MaterialSerializer";
|
||||||
import { DeflateAsync } from "../helpers/helper.compression";
|
|
||||||
|
|
||||||
export const useScene = defineStore('scene', () => {
|
export const useScene = defineStore('scene', () => {
|
||||||
let _editor: MaterialEditor;
|
let _editor: MaterialEditor;
|
||||||
@ -72,7 +69,7 @@ export const useScene = defineStore('scene', () => {
|
|||||||
|
|
||||||
_currTexture.value = record['texture'] as Texture;
|
_currTexture.value = record['texture'] as Texture;
|
||||||
_currTexture.value.image = img;
|
_currTexture.value.image = img;
|
||||||
Material.value.map = record.Id;
|
Material.value.map = img ? record.Id : undefined;
|
||||||
_currTexture.value.needsUpdate = true;
|
_currTexture.value.needsUpdate = true;
|
||||||
await UpdateMaterialAsync();
|
await UpdateMaterialAsync();
|
||||||
}
|
}
|
||||||
@ -90,31 +87,28 @@ export const useScene = defineStore('scene', () => {
|
|||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UploadMaterialRequest {
|
async function SerializeMaterialAsync() {
|
||||||
dirId: string;
|
|
||||||
materialName: string;
|
|
||||||
}
|
|
||||||
async function UploadMaterialAsync(request: UploadMaterialRequest) {
|
|
||||||
// TODO: Warn: 是否要生成logo路径?
|
// TODO: Warn: 是否要生成logo路径?
|
||||||
// const logoPath = await HandleUpdateLogo();
|
// const logoPath = await HandleUpdateLogo();
|
||||||
const matJson = MaterialOut(Material.value as PhysicalMaterialRecord);
|
const matJson = MaterialOut(Material.value as PhysicalMaterialRecord);
|
||||||
console.log(matJson);
|
return matJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function HandleUpdateLogo() {
|
async function GenerateMaterialLogoAsync() {
|
||||||
const blob = await materialRenderer.getBlob(Material.value.Material);
|
const blob = await materialRenderer.getBlob(Material.value.Material);
|
||||||
const file = new File([blob], "blob.png", { type: blob.type });
|
return blob;
|
||||||
|
// const file = new File([blob], "blob.png", { type: blob.type });
|
||||||
|
|
||||||
const formData = new FormData();
|
// const formData = new FormData();
|
||||||
formData.append("file", file);
|
// formData.append("file", file);
|
||||||
|
|
||||||
let data = await Post(ImgsUrl.logo, formData);
|
// let data = await Post(ImgsUrl.logo, formData);
|
||||||
|
|
||||||
let logoPath = "";
|
// let logoPath = "";
|
||||||
if (data.err_code === RequestStatus.Ok) {
|
// if (data.err_code === RequestStatus.Ok) {
|
||||||
logoPath = data.images.path;
|
// logoPath = data.images.path;
|
||||||
}
|
// }
|
||||||
return logoPath;
|
// return logoPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -126,7 +120,8 @@ export const useScene = defineStore('scene', () => {
|
|||||||
UpdateMaterialAsync,
|
UpdateMaterialAsync,
|
||||||
ChangeTextureAsync,
|
ChangeTextureAsync,
|
||||||
UpdateTexture,
|
UpdateTexture,
|
||||||
UploadMaterialAsync,
|
SerializeMaterialAsync,
|
||||||
|
GenerateMaterialLogoAsync
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -139,3 +134,7 @@ export type TextureAdjustment = {
|
|||||||
moveX: number,
|
moveX: number,
|
||||||
moveY: number
|
moveY: number
|
||||||
}
|
}
|
||||||
|
export interface UploadMaterialRequest {
|
||||||
|
dirId: string;
|
||||||
|
materialName: string;
|
||||||
|
}
|
@ -10,5 +10,5 @@
|
|||||||
// "noFallthroughCasesInSwitch": true,
|
// "noFallthroughCasesInSwitch": true,
|
||||||
// "noUncheckedSideEffectImports": true
|
// "noUncheckedSideEffectImports": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/lib/index.ts"]
|
||||||
}
|
}
|
||||||
|
10
tsconfig.build.json
Normal file
10
tsconfig.build.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"declaration": true,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
]
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
import dts from 'vite-plugin-dts';
|
||||||
import { dirname, resolve } from 'node:path'
|
import { dirname, resolve } from 'node:path'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
|
|
||||||
@ -7,20 +8,29 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
|
|||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [vue()],
|
plugins: [vue(), dts({rollupTypes: true, tsconfigPath: './tsconfig.app.json',insertTypesEntry: true})],
|
||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'src/lib/index.ts'),
|
entry: resolve(__dirname, 'src/lib/index.ts'),
|
||||||
name: 'MaterialEditor',
|
name: 'MaterialEditor',
|
||||||
fileName: (format) => `material-editor.${format}.js`
|
fileName: (format) => `material-editor.${format}.js`,
|
||||||
|
formats: ['es']
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
external: ['vue'],
|
// external: ['vue'],
|
||||||
output: {
|
output: {
|
||||||
globals: {
|
globals: {
|
||||||
vue: 'Vue'
|
vue: 'Vue'
|
||||||
}
|
},
|
||||||
}
|
// manualChunks: (id) => {
|
||||||
|
// if (id.includes('node_modules'))
|
||||||
|
// {
|
||||||
|
// if(/three/.test(id))
|
||||||
|
// return 'three';
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user