150 lines
4.8 KiB
TypeScript
150 lines
4.8 KiB
TypeScript
|
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
|
|||
|
}
|