Added Image upload component.
This commit is contained in:
parent
eb4281ac30
commit
d82df88296
@ -156,7 +156,7 @@ h1 {
|
||||
#tutorial {
|
||||
z-index: 15;
|
||||
left: 100px;
|
||||
top: 560px;
|
||||
top: 750px;
|
||||
width: 160px;
|
||||
height: 210px;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {AbstractMesh, ActionManager, InstancedMesh, Mesh, Observable, Scene, TransformNode} from "@babylonjs/core";
|
||||
import {DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import log from "loglevel";
|
||||
import {Controllers} from "../controllers/controllers";
|
||||
import {AppConfig} from "../util/appConfig";
|
||||
@ -43,6 +43,27 @@ export class DiagramManager {
|
||||
this.cleanupOrphanConnections(mesh)
|
||||
}
|
||||
});
|
||||
document.addEventListener('uploadImage', (event: CustomEvent) => {
|
||||
const diagramEntity: DiagramEntity = {
|
||||
template: '#image-template',
|
||||
image: event.detail.data,
|
||||
text: event.detail.name,
|
||||
position: {x: 0, y: 1.6, z: 0},
|
||||
rotation: {x: 0, y: Math.PI, z: 0},
|
||||
scale: {x: 1, y: 1, z: 1},
|
||||
}
|
||||
|
||||
console.log(diagramEntity);
|
||||
//const newMesh = buildMeshFromDiagramEntity(diagramEntity, this._scene);
|
||||
if (this.onDiagramEventObservable) {
|
||||
this.onDiagramEventObservable.notifyObservers({
|
||||
type: DiagramEventType.ADD,
|
||||
entity: diagramEntity
|
||||
}, DiagramEventObserverMask.ALL);
|
||||
|
||||
//this.onDiagramEventObservable.notifyObservers({type: DiagramEventType.ADD, entity: diagramEntity}, DiagramEventObserverMask.FROM_DB);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public get diagramMenuManager(): DiagramMenuManager {
|
||||
|
||||
15
src/diagram/functions/buildImage.ts
Normal file
15
src/diagram/functions/buildImage.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import log from "loglevel";
|
||||
import {AbstractMesh, MeshBuilder, StandardMaterial, Texture} from "@babylonjs/core";
|
||||
import {DefaultScene} from "../../defaultScene";
|
||||
import {DiagramEntity} from "../types/diagramEntity";
|
||||
|
||||
export function buildImage(entity: DiagramEntity): AbstractMesh {
|
||||
const logger = log.getLogger('buildImage');
|
||||
logger.debug("buildImage: entity is image");
|
||||
const scene = DefaultScene.Scene;
|
||||
const plane = MeshBuilder.CreatePlane("plane", {size: 1}, scene);
|
||||
const material = new StandardMaterial("planeMaterial", scene);
|
||||
const texture = new Texture(entity.image, scene);
|
||||
material.emissiveTexture = texture;
|
||||
return plane;
|
||||
}
|
||||
@ -1,12 +1,21 @@
|
||||
import {DiagramEntity, DiagramEntityType} from "../types/diagramEntity";
|
||||
import {AbstractMesh, InstancedMesh, Mesh, Quaternion, Scene, Vector3} from "@babylonjs/core";
|
||||
import {DiagramEntity, DiagramEntityType, DiagramTemplates} from "../types/diagramEntity";
|
||||
import {
|
||||
AbstractMesh,
|
||||
InstancedMesh,
|
||||
Mesh,
|
||||
MeshBuilder,
|
||||
Quaternion,
|
||||
Scene,
|
||||
StandardMaterial,
|
||||
Texture,
|
||||
Vector3
|
||||
} from "@babylonjs/core";
|
||||
import {DiagramConnection} from "../diagramConnection";
|
||||
import {updateTextNode} from "../../util/functions/updateTextNode";
|
||||
import log from "loglevel";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import {buildStandardMaterial} from "../../materials/functions/buildStandardMaterial";
|
||||
|
||||
|
||||
export function buildMeshFromDiagramEntity(entity: DiagramEntity, scene: Scene): AbstractMesh {
|
||||
const logger = log.getLogger('buildMeshFromDiagramEntity');
|
||||
if (!entity) {
|
||||
@ -33,25 +42,58 @@ function createNewInstanceIfNecessary(entity: DiagramEntity, scene: Scene): Abst
|
||||
logger.debug(`mesh ${oldMesh.id} already exists`);
|
||||
newMesh = oldMesh;
|
||||
} else {
|
||||
if (entity.template == "#connection-template") {
|
||||
const connection: DiagramConnection = new DiagramConnection(entity.from, entity.to, entity.id, scene);
|
||||
|
||||
logger.debug(`connection.mesh = ${connection.mesh.id}`);
|
||||
newMesh = connection.mesh;
|
||||
} else {
|
||||
const toolMesh = scene.getMeshById("tool-" + entity.template + "-" + entity.color);
|
||||
if (toolMesh && !oldMesh) {
|
||||
newMesh = new InstancedMesh(entity.id, (toolMesh as Mesh));
|
||||
newMesh.metadata = {template: entity.template, exportable: true, tool: false};
|
||||
} else {
|
||||
switch (entity.template) {
|
||||
case DiagramTemplates.CONNECTION:
|
||||
const connection: DiagramConnection = new DiagramConnection(entity.from, entity.to, entity.id, scene);
|
||||
logger.debug(`connection.mesh = ${connection.mesh.id}`);
|
||||
newMesh = connection.mesh;
|
||||
break;
|
||||
case DiagramTemplates.USER:
|
||||
break;
|
||||
case DiagramTemplates.IMAGE:
|
||||
newMesh = buildImage(entity, scene);
|
||||
newMesh.metadata = {template: entity.template, exportable: true, tool: false}
|
||||
break;
|
||||
case DiagramTemplates.BOX:
|
||||
case DiagramTemplates.SPHERE:
|
||||
case DiagramTemplates.CYLINDER:
|
||||
case DiagramTemplates.CONE:
|
||||
case DiagramTemplates.PLANE:
|
||||
const toolMesh = scene.getMeshById("tool-" + entity.template + "-" + entity.color);
|
||||
if (toolMesh && !oldMesh) {
|
||||
newMesh = new InstancedMesh(entity.id, (toolMesh as Mesh));
|
||||
newMesh.metadata = {template: entity.template, exportable: true, tool: false};
|
||||
} else {
|
||||
logger.warn('no tool mesh found for ' + entity.template + "-" + entity.color);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.warn('no tool mesh found for ' + entity.template + "-" + entity.color);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return newMesh;
|
||||
}
|
||||
|
||||
function buildImage(entity: DiagramEntity, scene: Scene): AbstractMesh {
|
||||
const logger = log.getLogger('buildImage');
|
||||
logger.debug("buildImage: entity is image");
|
||||
const plane = MeshBuilder.CreatePlane(entity.id, {size: 1}, scene);
|
||||
const material = new StandardMaterial("planeMaterial", scene);
|
||||
const image = new Image();
|
||||
image.src = entity.image;
|
||||
const texture = new Texture(entity.image, scene);
|
||||
material.emissiveTexture = texture;
|
||||
material.backFaceCulling = false;
|
||||
material.disableLighting = true;
|
||||
plane.material = material;
|
||||
image.decode().then(() => {
|
||||
plane.scaling.x = image.width / image.height;
|
||||
});
|
||||
return plane;
|
||||
}
|
||||
|
||||
function generateId(entity: DiagramEntity) {
|
||||
if (!entity.id) {
|
||||
entity.id = "id" + uuidv4();
|
||||
@ -104,6 +146,7 @@ function mapMetadata(entity: DiagramEntity, newMesh: AbstractMesh, scene: Scene)
|
||||
}
|
||||
return newMesh;
|
||||
}
|
||||
|
||||
function xyztovec(xyz: { x, y, z }): Vector3 {
|
||||
return new Vector3(xyz.x, xyz.y, xyz.z);
|
||||
}
|
||||
@ -21,6 +21,16 @@ export enum DiagramEventMask {
|
||||
REMOTE = 2,
|
||||
}
|
||||
|
||||
export enum DiagramTemplates {
|
||||
CONNECTION = "#connection-template",
|
||||
USER = "#user-template",
|
||||
BOX = "#box-template",
|
||||
SPHERE = "#sphere-template",
|
||||
CYLINDER = "#cylinder-template",
|
||||
CONE = "#cone-template",
|
||||
IMAGE = "#image-template",
|
||||
PLANE = "#plane-template",
|
||||
}
|
||||
|
||||
export type DiagramEvent = {
|
||||
type: DiagramEventType;
|
||||
@ -34,6 +44,7 @@ export type DiagramEntity = {
|
||||
id?: string;
|
||||
from?: string;
|
||||
to?: string;
|
||||
image?: string;
|
||||
last_seen?: Date;
|
||||
position?: { x: number, y: number, z: number };
|
||||
rotation?: { x: number, y: number, z: number };
|
||||
|
||||
43
src/react/functions/uploadImage.ts
Normal file
43
src/react/functions/uploadImage.ts
Normal file
@ -0,0 +1,43 @@
|
||||
const uploadImage = async (evt) => {
|
||||
|
||||
const file = (evt.target as HTMLInputElement).files[0];
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
//formData.append('requireSignedURLs', 'true');
|
||||
const formInitData = new FormData();
|
||||
formInitData.append('requireSignedURLs', 'true');
|
||||
|
||||
const initialUpload = await fetch('/api/images', {
|
||||
method: 'POST',
|
||||
body: formInitData
|
||||
|
||||
|
||||
});
|
||||
try {
|
||||
const initialData = await initialUpload.json();
|
||||
if (initialData.success == true) {
|
||||
const upload = await fetch(initialData.result.uploadURL, {
|
||||
method: 'POST', mode: 'cors', body:
|
||||
formData
|
||||
});
|
||||
const uploadData = await upload.json();
|
||||
console.log(uploadData)
|
||||
for (let variant of uploadData.result.variants) {
|
||||
if (variant.indexOf('fullhd') > -1) {
|
||||
const uploadEvent = new CustomEvent('uploadImage', {
|
||||
detail: {
|
||||
name: file.name,
|
||||
data: variant
|
||||
}
|
||||
});
|
||||
document.dispatchEvent(uploadEvent);
|
||||
evt.target.remove();
|
||||
console.log(variant);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
export {uploadImage};
|
||||
@ -1,4 +1,5 @@
|
||||
import {useEffect, useState} from "react";
|
||||
import {uploadImage} from "./functions/uploadImage";
|
||||
|
||||
function MainMenu({onClick}) {
|
||||
return (
|
||||
@ -7,6 +8,7 @@ function MainMenu({onClick}) {
|
||||
<div id="enterXR" className="inactive"><a href="#" id="enterVRLink">Enter VR</a></div>
|
||||
<QuestLink/>
|
||||
<div id="diagrams"><a href="#" id="diagramsLink" onClick={onClick}>Diagrams</a></div>
|
||||
<div id="imageUpload"><a href="#" id="imageUploadLink" onClick={onClick}>Upload Image</a></div>
|
||||
<div id="download"><a href="#" id="downloadLink">Download Model</a></div>
|
||||
</div>
|
||||
)
|
||||
@ -113,7 +115,19 @@ function Menu() {
|
||||
|
||||
function handleDiagramListClick(evt: React.MouseEvent<HTMLAnchorElement>) {
|
||||
evt.preventDefault();
|
||||
setDiagramListState(diagramListState == 'none' ? 'block' : 'none');
|
||||
switch (evt.target.id) {
|
||||
case 'imageUploadLink':
|
||||
const input = document.createElement('input');
|
||||
input.type = 'file';
|
||||
input.accept = 'image/*';
|
||||
input.onchange = uploadImage;
|
||||
|
||||
document.body.appendChild(input);
|
||||
input.click();
|
||||
break;
|
||||
default:
|
||||
setDiagramListState(diagramListState == 'none' ? 'block' : 'none');
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@ -134,49 +148,3 @@ export default function WebApp() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
/*
|
||||
const create = document.querySelector('#startCreateLink');
|
||||
if (create) {
|
||||
create.addEventListener('click', function (evt) {
|
||||
evt.preventDefault();
|
||||
document.querySelector('#main').style.display = 'none';
|
||||
document.querySelector('#create').style.display = 'block';
|
||||
});
|
||||
}
|
||||
const cancel = document.querySelector('#cancelCreateLink');
|
||||
if (cancel) {
|
||||
cancel.addEventListener('click', function (evt) {
|
||||
evt.preventDefault();
|
||||
document.querySelector('#main').style.display = 'block';
|
||||
document.querySelector('#create').style.display = 'none';
|
||||
});
|
||||
}
|
||||
const close = document.querySelector('#closekey a');
|
||||
if (close) {
|
||||
close.addEventListener('click', function (evt) {
|
||||
evt.preventDefault();
|
||||
document.querySelector('#keyboardHelp').style.display = 'none';
|
||||
});
|
||||
}
|
||||
const desktopTutorial = document.querySelector('#desktopLink');
|
||||
if (desktopTutorial) {
|
||||
desktopTutorial.addEventListener('click', function (evt) {
|
||||
evt.preventDefault();
|
||||
// document.querySelector('#tutorial').style.display = 'none';
|
||||
document.querySelector('#keyboardHelp').style.display = 'block';
|
||||
});
|
||||
}
|
||||
const createAction = document.querySelector('#createActionLink');
|
||||
if (createAction) {
|
||||
createAction.addEventListener('click', function (evt) {
|
||||
evt.preventDefault();
|
||||
const value = document.querySelector('#createName').value;
|
||||
if (value && value.length > 4) {
|
||||
document.location.href = '/db/' + value;
|
||||
} else {
|
||||
window.alert('Name must be longer than 4 characters');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
*/
|
||||
@ -22,7 +22,11 @@ export default defineConfig({
|
||||
'^/create-db': {
|
||||
target: 'https://www.deepdiagram.com/',
|
||||
changeOrigin: true,
|
||||
}
|
||||
},
|
||||
'^/api/images': {
|
||||
target: 'https://www.deepdiagram.com/',
|
||||
changeOrigin: true,
|
||||
},
|
||||
}
|
||||
},
|
||||
base: "/"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user