material-editor/src/stores/sceneStore.ts

150 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from "pinia";
import { computed, ref, watch } 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 { ImgsUrl, MaterialUrls } from "../api/Api";
import { Post, PostJson, RequestStatus } from "../api/Request";
import { MaterialOut } from "../common/MaterialSerializer";
import { DeflateAsync } from "../helpers/helper.compression";
export const useScene = defineStore('scene', () => {
let _editor: MaterialEditor;
const _currGeometry = ref<string>('球');
const _currTexture = ref<Texture>();
const CurrGeometry = computed({
get: () => _currGeometry.value,
set: (val: string) => ChangeGeometry(val)
})
const CurrTexture = computed<Texture>(() => _currTexture.value);
const Geometries = ref<string[]>([]);
const Material = ref<PhysicalMaterialRecord>(new PhysicalMaterialRecord());
function Initial(canvas: HTMLElement) {
if (_editor) {
console.warn("SceneStore has already been initialized");
return;
}
// 为Material配置一个ObjectId否则其无法被序列化
Material.value.objectId = new ObjectId(undefined, undefined);
_editor = MaterialEditor.GetInstance();
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.OnSize(canvas.clientWidth, canvas.clientHeight);
view.UpdateRender();
}
}
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 ChangeTextureAsync(url: string) {
const record = new TextureTableRecord();
record.objectId = new ObjectId(undefined, record);
const img = await LoadImageFromUrl(url);
_currTexture.value = record['texture'] as Texture;
_currTexture.value.image = img;
Material.value.map = record.Id;
_currTexture.value.needsUpdate = true;
await UpdateMaterialAsync();
}
function UpdateTexture(adjustment: TextureAdjustment) {
const texture = _currTexture.value;
texture.wrapS = adjustment.wrapS;
texture.wrapT = adjustment.wrapT;
texture.anisotropy = 16;
texture.rotation = adjustment.rotation;
texture.repeat.set(adjustment.repeatX, adjustment.repeatY);
texture.offset.set(adjustment.moveX, adjustment.moveY);
texture.needsUpdate = true;
Update();
}
interface UploadMaterialRequest {
dirId: string;
materialName: string;
}
async function UploadMaterialAsync(request: UploadMaterialRequest) {
const logoPath = await HandleUpdateLogo();
const matJson = MaterialOut(Material.value as PhysicalMaterialRecord);
const data = await PostJson(MaterialUrls.create, {
dir_id: request,
name: request.materialName,
logo: logoPath,
// jsonString -> Deflate -> BinaryString -> Base64
file: btoa(String.fromCharCode(...await DeflateAsync(matJson))),
zip_type: 'gzip',
});
if (data.err_code !== RequestStatus.Ok) {
throw new Error(data.err_msg);
}
}
async function HandleUpdateLogo() {
const blob = await materialRenderer.getBlob(Material.value.Material);
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,
Geometries,
Material,
Initial,
Update,
UpdateMaterialAsync,
ChangeTextureAsync,
UpdateTexture,
UploadMaterialAsync,
};
});
export type TextureAdjustment = {
wrapS: number,
wrapT: number,
rotation: number,
repeatX: number,
repeatY: number,
moveX: number,
moveY: number
}