import { defineStore } from "pinia"; import { computed, ref } from "vue"; import { MaterialEditor } from "../common/MaterialEditor"; import { Database, ObjectId, PhysicalMaterialRecord, TextureTableRecord } from "webcad_ue4_api"; import { LoadImageFromUrl } from "../helpers/helper.imageLoader"; import { Texture } from "three"; import { materialRenderer } from "../common/MaterialRenderer"; import { MaterialIn, MaterialOut } from "../common/MaterialSerializer"; const sceneSetup = () => { let _editor: MaterialEditor | undefined; let _database: Database | undefined; const _currGeometry = ref('球'); const _currTexture = ref(); const CurrGeometry = computed({ get: () => _currGeometry.value, set: (val: string) => ChangeGeometry(val) }) const CurrTexture = computed(() => _currTexture.value); const Geometries = ref([]); const Material = ref(new PhysicalMaterialRecord()); function Initial(canvas: HTMLElement) { if (_editor) { console.warn("SceneStore has already been initialized"); return; } // 初始化Database _database = new Database(); _database.hm.Enable = false; // 关闭历史记录功能 Material.value.Name = _database.MaterialTable.AllocateName(); // 使用Database为材质分配材质名 _database.MaterialTable.Add(Material.value as PhysicalMaterialRecord); // 为Material配置一个ObjectId,否则其无法被序列化 // Material.value.objectId = new ObjectId(undefined, undefined); _editor = new MaterialEditor(); Geometries.value = Array.from(_editor.Geometrys.keys()); _currGeometry.value = _editor.CurGeometryName; _editor.SetViewer(canvas); _editor.setMaterial((Material.value) as PhysicalMaterialRecord); const view = _editor.Viewer; window.onresize = () => { view.SetSize(canvas.clientWidth, canvas.clientHeight); view.UpdateRender(); } } function Dispose() { Material.value.GoodBye(); _editor?.Dispose(); _editor = undefined; _database.Destroy(); _database = undefined; window.onresize = undefined; } function ChangeGeometry(geoName: string) { _currGeometry.value = geoName; let geo = _editor.Geometrys.get(_currGeometry.value); if (geo) { _editor.ShowMesh.geometry = geo; _editor.Viewer.UpdateRender(); } } function Update() { _editor.Viewer.UpdateRender(); } async function UpdateMaterialAsync() { await Material.value.Update(); await _editor.Update(); Update(); } async function ChangeTextureFromUrlAsync(url: string) { const img = await LoadImageFromUrl(url); // 关联贴图 const db = Material.value.Db; const record = new TextureTableRecord(); // record.objectId = new ObjectId(undefined, record); record.Name = db.TextureTable.AllocateName(); db.TextureTable.Add(record); // 设置Store _currTexture.value = record['texture'] as Texture; _currTexture.value.image = img; // 替换map Material.value.map = img ? record.Id : undefined; _currTexture.value.needsUpdate = true; await UpdateMaterialAsync(); } async function SerializeMaterialAsync() { const matJson = MaterialOut(Material.value as PhysicalMaterialRecord); console.log(matJson); return matJson; } async function ApplyTextureAsync(textureRecord: TextureTableRecord) { if (!textureRecord.imageUrl) { alert("该纹理无效"); return; } // 绑定纹理 let newTexture = textureRecord.Clone() as TextureTableRecord; newTexture.Owner = undefined; newTexture.Name = _database.TextureTable.AllocateName(); _database.TextureTable.Add(newTexture); // 替换map Material.value.map = newTexture.Id; await UpdateMaterialAsync(); } async function ImportMaterialAsync(materialJson: string) { const material = MaterialIn(JSON.parse(materialJson)); Material.value = material; _editor.setMaterial(material); await UpdateMaterialAsync(); } async function GenerateMaterialLogoAsync() { const blob = await materialRenderer.getBlob(Material.value.Material); return blob; // const file = new File([blob], "blob.png", { type: blob.type }); // const formData = new FormData(); // formData.append("file", file); // let data = await Post(ImgsUrl.logo, formData); // let logoPath = ""; // if (data.err_code === RequestStatus.Ok) { // logoPath = data.images.path; // } // return logoPath; } return { CurrGeometry, CurrTexture, Geometries, Material, Initial, Update, UpdateMaterialAsync, ChangeTextureFromUrlAsync, SerializeMaterialAsync, ImportMaterialAsync, GenerateMaterialLogoAsync, Dispose }; }; export const useScene = defineStore('scene', sceneSetup); export const useSceneRaw = defineStore('sceneRaw', sceneSetup); // 独立场景,用来静默执行材质序列化 export type TextureAdjustment = { wrapS: number, wrapT: number, rotation: number, repeatX: number, repeatY: number, moveX: number, moveY: number } export interface UploadMaterialRequest { dirId: string; materialName: string; }