2022-04-19 03:26:30 +08:00
|
|
|
<script lang="ts">
|
2022-04-20 23:43:21 +08:00
|
|
|
import { createEventDispatcher, tick, afterUpdate } from "svelte";
|
2022-04-19 03:26:30 +08:00
|
|
|
import { Upload, ModifyUpload } from "@gradio/upload";
|
|
|
|
import type { FileData } from "@gradio/upload";
|
2022-04-26 22:48:39 +08:00
|
|
|
import { BlockLabel } from "@gradio/atoms";
|
2022-04-19 03:26:30 +08:00
|
|
|
|
|
|
|
import file_icon from "./file.svg";
|
|
|
|
|
|
|
|
export let value: null | FileData;
|
|
|
|
|
|
|
|
export let drop_text: string = "Drop a file";
|
|
|
|
export let or_text: string = "or";
|
|
|
|
export let upload_text: string = "click to upload";
|
|
|
|
export let label: string = "";
|
2022-04-27 18:47:15 +08:00
|
|
|
export let show_label: boolean;
|
2022-04-19 03:26:30 +08:00
|
|
|
export let style: string;
|
|
|
|
|
2022-04-20 23:43:21 +08:00
|
|
|
afterUpdate(() => {
|
|
|
|
if (value != null && value.is_example) {
|
|
|
|
addNewModel();
|
|
|
|
}
|
|
|
|
});
|
2022-04-19 03:26:30 +08:00
|
|
|
|
|
|
|
async function handle_upload({ detail }: CustomEvent<FileData>) {
|
|
|
|
value = detail;
|
|
|
|
await tick();
|
|
|
|
dispatch("change", value);
|
|
|
|
addNewModel();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function handle_clear({ detail }: CustomEvent<null>) {
|
|
|
|
value = null;
|
|
|
|
await tick();
|
|
|
|
dispatch("clear");
|
|
|
|
}
|
|
|
|
|
2022-04-26 22:48:39 +08:00
|
|
|
const dispatch = createEventDispatcher<{
|
|
|
|
change: FileData | null;
|
|
|
|
clear: undefined;
|
|
|
|
drag: boolean;
|
|
|
|
}>();
|
2022-04-19 03:26:30 +08:00
|
|
|
|
|
|
|
let dragging = false;
|
|
|
|
|
|
|
|
import * as BABYLON from "babylonjs";
|
2022-04-26 21:03:09 +08:00
|
|
|
import * as BABYLON_LOADERS from "babylonjs-loaders";
|
|
|
|
|
|
|
|
BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS = true;
|
2022-04-19 03:26:30 +08:00
|
|
|
|
|
|
|
let canvas: HTMLCanvasElement;
|
|
|
|
let scene: BABYLON.Scene;
|
|
|
|
|
|
|
|
function addNewModel() {
|
|
|
|
const engine = new BABYLON.Engine(canvas, true);
|
|
|
|
scene = new BABYLON.Scene(engine);
|
|
|
|
scene.createDefaultCameraOrLight();
|
|
|
|
scene.clearColor = new BABYLON.Color4(0.2, 0.2, 0.2, 1);
|
|
|
|
engine.runRenderLoop(() => {
|
|
|
|
scene.render();
|
|
|
|
});
|
|
|
|
|
|
|
|
window.addEventListener("resize", () => {
|
|
|
|
engine.resize();
|
|
|
|
});
|
|
|
|
|
2022-04-27 18:47:15 +08:00
|
|
|
if (!value) return;
|
|
|
|
|
2022-04-20 23:43:21 +08:00
|
|
|
let url: string;
|
|
|
|
if (value.is_example) {
|
|
|
|
url = value.data;
|
|
|
|
} else {
|
|
|
|
let base64_model_content = value.data;
|
|
|
|
let raw_content = BABYLON.Tools.DecodeBase64(base64_model_content);
|
|
|
|
let blob = new Blob([raw_content]);
|
|
|
|
url = URL.createObjectURL(blob);
|
|
|
|
}
|
|
|
|
|
2022-04-19 03:26:30 +08:00
|
|
|
BABYLON.SceneLoader.Append(
|
|
|
|
"",
|
|
|
|
url,
|
|
|
|
scene,
|
|
|
|
() => {
|
|
|
|
scene.createDefaultCamera(true, true, true);
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
"." + value.name.split(".")[1]
|
|
|
|
);
|
|
|
|
}
|
2022-04-26 22:48:39 +08:00
|
|
|
|
|
|
|
$: dispatch("drag", dragging);
|
2022-04-19 03:26:30 +08:00
|
|
|
</script>
|
|
|
|
|
2022-04-27 18:47:15 +08:00
|
|
|
<BlockLabel {show_label} image={file_icon} label={label || "3D Model"} />
|
2022-04-26 22:48:39 +08:00
|
|
|
|
|
|
|
{#if value === null}
|
|
|
|
<Upload on:load={handle_upload} filetype=".obj, .gltf, .glb" bind:dragging>
|
|
|
|
{drop_text}
|
|
|
|
<br />- {or_text} -<br />
|
|
|
|
{upload_text}
|
|
|
|
</Upload>
|
|
|
|
{:else}
|
|
|
|
<ModifyUpload on:clear={handle_clear} absolute />
|
|
|
|
<div
|
|
|
|
class="input-model w-full h-60 flex justify-center items-center bg-gray-200 dark:bg-gray-600 relative"
|
|
|
|
>
|
|
|
|
<canvas class="w-full h-full object-contain" bind:this={canvas} />
|
|
|
|
</div>
|
|
|
|
{/if}
|