Add external triangle scene GLTF and update file import handling
This commit is contained in:
65
fixtures/assets/external-triangle/scene.gltf
Normal file
65
fixtures/assets/external-triangle/scene.gltf
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"asset": {
|
||||
"version": "2.0",
|
||||
"generator": "webeditor3d fixture"
|
||||
},
|
||||
"scene": 0,
|
||||
"scenes": [
|
||||
{
|
||||
"name": "External Triangle Scene",
|
||||
"nodes": [0]
|
||||
}
|
||||
],
|
||||
"nodes": [
|
||||
{
|
||||
"mesh": 0,
|
||||
"name": "External Triangle Node"
|
||||
}
|
||||
],
|
||||
"meshes": [
|
||||
{
|
||||
"name": "External Triangle Mesh",
|
||||
"primitives": [
|
||||
{
|
||||
"attributes": {
|
||||
"POSITION": 0
|
||||
},
|
||||
"material": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"materials": [
|
||||
{
|
||||
"name": "External Material",
|
||||
"pbrMetallicRoughness": {
|
||||
"baseColorFactor": [0.2, 0.6, 0.85, 1],
|
||||
"metallicFactor": 0,
|
||||
"roughnessFactor": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"buffers": [
|
||||
{
|
||||
"byteLength": 36,
|
||||
"uri": "triangle.bin"
|
||||
}
|
||||
],
|
||||
"bufferViews": [
|
||||
{
|
||||
"buffer": 0,
|
||||
"byteOffset": 0,
|
||||
"byteLength": 36
|
||||
}
|
||||
],
|
||||
"accessors": [
|
||||
{
|
||||
"bufferView": 0,
|
||||
"componentType": 5126,
|
||||
"count": 3,
|
||||
"type": "VEC3",
|
||||
"min": [0, 0, 0],
|
||||
"max": [1, 1, 0]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
} from "../assets/model-instance-labels";
|
||||
import {
|
||||
importModelAssetFromFile,
|
||||
importModelAssetFromFiles,
|
||||
loadModelAssetFromStorage,
|
||||
disposeModelTemplate,
|
||||
type ImportedModelAssetResult,
|
||||
@@ -1938,9 +1939,9 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
||||
|
||||
const handleImportModelChange = async (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const input = event.currentTarget;
|
||||
const file = input.files?.[0];
|
||||
const files = Array.from(input.files ?? []);
|
||||
|
||||
if (file === undefined) {
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1953,7 +1954,9 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
||||
let importedModelForCleanup: ImportedModelAssetResult | null = null;
|
||||
|
||||
try {
|
||||
const importedModel = await importModelAssetFromFile(file, projectAssetStorage);
|
||||
const importedModel = files.length === 1
|
||||
? await importModelAssetFromFile(files[0], projectAssetStorage)
|
||||
: await importModelAssetFromFiles(files, projectAssetStorage);
|
||||
importedModelForCleanup = importedModel;
|
||||
|
||||
store.executeCommand(
|
||||
@@ -4014,6 +4017,7 @@ export function App({ store, initialStatusMessage }: AppProps) {
|
||||
ref={importModelInputRef}
|
||||
className="visually-hidden"
|
||||
type="file"
|
||||
multiple
|
||||
accept=".glb,.gltf,model/gltf-binary,model/gltf+json,application/octet-stream"
|
||||
onChange={handleImportModelChange}
|
||||
/>
|
||||
|
||||
@@ -4,21 +4,31 @@ import { createProjectAssetStorageKey } from "../../src/assets/project-assets";
|
||||
import { createInMemoryProjectAssetStorage } from "../../src/assets/project-asset-storage";
|
||||
|
||||
describe("project asset storage", () => {
|
||||
it("stores, clones, and deletes binary asset payloads", async () => {
|
||||
it("stores, clones, and deletes binary asset file packages", async () => {
|
||||
const storage = createInMemoryProjectAssetStorage();
|
||||
const storageKey = createProjectAssetStorageKey("asset-model-triangle");
|
||||
const bytes = new Uint8Array([0, 1, 2, 3, 4]).buffer;
|
||||
const sidecarBytes = new Uint8Array([9, 8, 7]).buffer;
|
||||
|
||||
await storage.putAsset(storageKey, {
|
||||
bytes,
|
||||
mimeType: "model/gltf+json"
|
||||
files: {
|
||||
"tiny-triangle.gltf": {
|
||||
bytes,
|
||||
mimeType: "model/gltf+json"
|
||||
},
|
||||
"triangle.bin": {
|
||||
bytes: sidecarBytes,
|
||||
mimeType: "application/octet-stream"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const loadedAsset = await storage.getAsset(storageKey);
|
||||
|
||||
expect(loadedAsset).not.toBeNull();
|
||||
expect(loadedAsset?.mimeType).toBe("model/gltf+json");
|
||||
expect(Array.from(new Uint8Array(loadedAsset?.bytes ?? new ArrayBuffer(0)))).toEqual([0, 1, 2, 3, 4]);
|
||||
expect(Object.keys(loadedAsset?.files ?? {})).toEqual(["tiny-triangle.gltf", "triangle.bin"]);
|
||||
expect(Array.from(new Uint8Array(loadedAsset?.files["tiny-triangle.gltf"].bytes ?? new ArrayBuffer(0)))).toEqual([0, 1, 2, 3, 4]);
|
||||
expect(Array.from(new Uint8Array(loadedAsset?.files["triangle.bin"].bytes ?? new ArrayBuffer(0)))).toEqual([9, 8, 7]);
|
||||
|
||||
await storage.deleteAsset(storageKey);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user