change from always add to also update in persistenceManager.ts
This commit is contained in:
parent
b375005b33
commit
156d0858d8
@ -32,6 +32,7 @@ export class App {
|
||||
//preTasks = [havokModule];
|
||||
private logger = log.getLogger('App');
|
||||
|
||||
|
||||
private scene: Scene;
|
||||
private xr: WebXRDefaultExperience;
|
||||
private rig: Rigplatform;
|
||||
@ -40,6 +41,9 @@ export class App {
|
||||
const config = AppConfig.config;
|
||||
|
||||
log.setLevel('info');
|
||||
log.getLogger('AppConfig').setLevel('debug');
|
||||
log.getLogger('IndexdbPersistenceManager').setLevel('debug');
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.style.width = "100%";
|
||||
canvas.style.height = "100%";
|
||||
|
||||
@ -105,7 +105,11 @@ export class Base {
|
||||
newMesh.material = mesh.material;
|
||||
newMesh.metadata = mesh.metadata;
|
||||
newMesh && newMesh.setParent(this.controller.motionController.rootMesh);
|
||||
|
||||
const event: DiagramEvent = {
|
||||
type: DiagramEventType.ADD,
|
||||
entity: MeshConverter.toDiagramEntity(newMesh)
|
||||
}
|
||||
this.diagramManager.onDiagramEventObservable.notifyObservers(event);
|
||||
this.grabbedMesh = newMesh;
|
||||
this.previousParent = null;
|
||||
}
|
||||
|
||||
@ -56,12 +56,14 @@ export class DiagramManager {
|
||||
case DiagramEventType.DROPPED:
|
||||
break;
|
||||
case DiagramEventType.DROP:
|
||||
this.getPersistenceManager()?.add(mesh)
|
||||
this.getPersistenceManager()?.modify(mesh);
|
||||
MeshConverter.updateTextNode(mesh, entity.text);
|
||||
break;
|
||||
case DiagramEventType.ADD:
|
||||
this.getPersistenceManager()?.add(mesh);
|
||||
break;
|
||||
case DiagramEventType.MODIFY:
|
||||
this.getPersistenceManager()?.modify(mesh)
|
||||
this.getPersistenceManager()?.modify(mesh);
|
||||
break;
|
||||
case DiagramEventType.CHANGECOLOR:
|
||||
this.getPersistenceManager()?.changeColor(event.oldColor, event.newColor);
|
||||
|
||||
@ -4,18 +4,25 @@ import {DiagramEntity} from "./diagramEntity";
|
||||
import Dexie from "dexie";
|
||||
import {MeshConverter} from "./meshConverter";
|
||||
import log from "loglevel";
|
||||
import {AppConfigType} from "../util/appConfig";
|
||||
|
||||
export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
|
||||
export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
private readonly logger = log.getLogger('IndexdbPersistenceManager');
|
||||
public updateObserver: Observable<DiagramEntity> = new Observable<DiagramEntity>();
|
||||
public readonly updateObserver: Observable<DiagramEntity> = new Observable<DiagramEntity>();
|
||||
public readonly configObserver: Observable<AppConfigType> = new Observable<AppConfigType>();
|
||||
private db: Dexie;
|
||||
|
||||
constructor(name: string) {
|
||||
this.db = new Dexie(name);
|
||||
this.db.version(1).stores({entities: "id,position,rotation,last_seen,template,text,scale,color"});
|
||||
const version = 2;
|
||||
this.db.version(2).stores({config: "id,gridSnap,rotateSnap,createSnap"});
|
||||
this.db.version(2).stores({entities: "id,position,rotation,last_seen,template,text,scale,color"});
|
||||
this.logger.debug("IndexdbPersistenceManager constructed");
|
||||
|
||||
}
|
||||
public add(mesh: AbstractMesh) {
|
||||
|
||||
public add(mesh: AbstractMesh) {
|
||||
if (!mesh) {
|
||||
this.logger.error("Adding null mesh, early return");
|
||||
return;
|
||||
@ -24,27 +31,35 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
entity.position = this.vectoxys(mesh.position);
|
||||
entity.rotation = this.vectoxys(mesh.rotation);
|
||||
entity.scale = this.vectoxys(mesh.scaling);
|
||||
|
||||
this.db["entities"].add(entity);
|
||||
this.logger.debug('add', mesh, entity);
|
||||
}
|
||||
|
||||
public remove(mesh: AbstractMesh) {
|
||||
if (!mesh) {
|
||||
this.logger.error("Removing null mesh, early return");
|
||||
return;
|
||||
}
|
||||
this.db["entities"].delete(mesh.id);
|
||||
}
|
||||
|
||||
public getConfig(): any {
|
||||
this.logger.warn('getConfig not implemented');
|
||||
//@todo implement
|
||||
}
|
||||
|
||||
public setConfig(config: any) {
|
||||
this.logger.warn('setConfig not implemented, value not persisted', config);
|
||||
//@todo implement
|
||||
public setConfig(config: AppConfigType) {
|
||||
config.id = 1;
|
||||
this.db["config"].put(config);
|
||||
this.logger.debug('setConfig', config);
|
||||
this.configObserver.notifyObservers(config);
|
||||
}
|
||||
|
||||
public modify(mesh) {
|
||||
if (!mesh) {
|
||||
this.logger.error("Modifying null mesh, early return");
|
||||
return;
|
||||
}
|
||||
const entity = <any>MeshConverter.toDiagramEntity(mesh);
|
||||
if (!entity) {
|
||||
this.logger.error("Modifying null mesh, early return");
|
||||
return;
|
||||
}
|
||||
entity.position = this.vectoxys(mesh.position);
|
||||
entity.rotation = this.vectoxys(mesh.rotation);
|
||||
entity.scale = this.vectoxys(mesh.scaling);
|
||||
@ -61,10 +76,17 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
this.logger.debug('adding', e);
|
||||
this.updateObserver.notifyObservers(e);
|
||||
});
|
||||
this.db['config'].each((c) => {
|
||||
this.configObserver.notifyObservers(c);
|
||||
});
|
||||
this.logger.info("initialize finished");
|
||||
}
|
||||
|
||||
public changeColor(oldColor, newColor) {
|
||||
if (!oldColor || !newColor) {
|
||||
this.logger.error("changeColor called with null color, early return");
|
||||
return;
|
||||
}
|
||||
this.logger.debug(`changeColor ${oldColor.toHexString()} to ${newColor.toHexString()}`);
|
||||
this.db['entities'].where('color').equals(oldColor.toHexString()).modify({color: newColor.toHexString()});
|
||||
}
|
||||
|
||||
@ -15,7 +15,12 @@ import log from "loglevel";
|
||||
|
||||
|
||||
export class MeshConverter {
|
||||
private static logger = log.getLogger('MeshConverter');
|
||||
public static toDiagramEntity(mesh: AbstractMesh): DiagramEntity {
|
||||
if (!mesh) {
|
||||
this.logger.error("toDiagramEntity: mesh is null");
|
||||
return null;
|
||||
}
|
||||
const entity = <DiagramEntity>{};
|
||||
if ("new" == mesh?.id) {
|
||||
mesh.id = "id" + uuidv4();
|
||||
@ -29,11 +34,17 @@ export class MeshConverter {
|
||||
entity.scale = mesh.scaling;
|
||||
if (mesh.material) {
|
||||
entity.color = (mesh.material as any).diffuseColor.toHexString();
|
||||
} else {
|
||||
this.logger.error("toDiagramEntity: mesh.material is null");
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
public static fromDiagramEntity(entity: DiagramEntity, scene: Scene): AbstractMesh {
|
||||
if (!entity) {
|
||||
this.logger.error("fromDiagramEntity: entity is null");
|
||||
return null;
|
||||
}
|
||||
if (!entity.id) {
|
||||
entity.id = "id" + uuidv4();
|
||||
}
|
||||
@ -64,10 +75,7 @@ export class MeshConverter {
|
||||
|
||||
if (mesh) {
|
||||
mesh.metadata = {template: entity.template};
|
||||
if (entity.text) {
|
||||
mesh.metadata.text = entity.text;
|
||||
this.updateTextNode(mesh, entity.text);
|
||||
}
|
||||
|
||||
if (entity.position) {
|
||||
mesh.position = entity.position;
|
||||
}
|
||||
@ -85,7 +93,12 @@ export class MeshConverter {
|
||||
material.diffuseColor = Color3.FromHexString(entity.color);
|
||||
mesh.material = material;
|
||||
}
|
||||
|
||||
if (entity.text) {
|
||||
mesh.metadata.text = entity.text;
|
||||
this.updateTextNode(mesh, entity.text);
|
||||
}
|
||||
} else {
|
||||
this.logger.error("fromDiagramEntity: mesh is null after it should have been created");
|
||||
}
|
||||
|
||||
return mesh;
|
||||
@ -93,12 +106,19 @@ export class MeshConverter {
|
||||
}
|
||||
|
||||
public static updateTextNode(mesh: AbstractMesh, text: string) {
|
||||
if (!mesh) {
|
||||
this.logger.error("updateTextNode: mesh is null");
|
||||
return null;
|
||||
}
|
||||
let textNode = (mesh.getChildren((node) => {
|
||||
return node.name == 'text'
|
||||
})[0] as Mesh);
|
||||
if (textNode) {
|
||||
textNode.dispose(false, true);
|
||||
}
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Set font
|
||||
const height = 0.125;
|
||||
@ -110,7 +130,7 @@ export class MeshConverter {
|
||||
const ratio = height / DTHeight;
|
||||
|
||||
//Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas
|
||||
const temp = new DynamicTexture("DynamicTexture", 64, mesh.getScene());
|
||||
const temp = new DynamicTexture("DynamicTexture", 32, mesh.getScene());
|
||||
const tmpctx = temp.getContext();
|
||||
tmpctx.font = font;
|
||||
const DTWidth = tmpctx.measureText(text).width + 8;
|
||||
@ -133,9 +153,7 @@ export class MeshConverter {
|
||||
plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
||||
//textNode = this.updateTextNode(mesh, entity.text);
|
||||
plane.parent = mesh;
|
||||
log.getLogger('bmenu').debug("max y", mesh.getBoundingInfo().boundingBox.maximum.y);
|
||||
plane.position.y = .5+ (height / 2);
|
||||
|
||||
plane.position.y = .5 + (.125 / 2);
|
||||
return plane;
|
||||
}
|
||||
}
|
||||
@ -11,12 +11,11 @@ export interface IPersistenceManager {
|
||||
|
||||
initialize();
|
||||
|
||||
getConfig(): AppConfigType;
|
||||
|
||||
setConfig(config: AppConfigType);
|
||||
|
||||
changeColor(oldColor: Color3, newColor: Color3)
|
||||
|
||||
updateObserver: Observable<DiagramEntity>;
|
||||
configObserver: Observable<AppConfigType>;
|
||||
|
||||
}
|
||||
|
||||
@ -26,21 +26,24 @@ export class ConfigMenu {
|
||||
this.configPlane = null;
|
||||
return;
|
||||
}
|
||||
const width = .25;
|
||||
const height = .55;
|
||||
const res = 256;
|
||||
const heightPixels = Math.round((height / width) * res);
|
||||
this.configPlane = MeshBuilder
|
||||
.CreatePlane("gridSizePlane",
|
||||
{
|
||||
width: .25,
|
||||
height: .5
|
||||
}, this.scene);
|
||||
const configTexture = AdvancedDynamicTexture.CreateForMesh(this.configPlane, 256, 512);
|
||||
const configTexture = AdvancedDynamicTexture.CreateForMesh(this.configPlane, res, heightPixels);
|
||||
configTexture.background = "white";
|
||||
const selectionPanel = new SelectionPanel("selectionPanel");
|
||||
selectionPanel.fontSize = "24px";
|
||||
selectionPanel.height = "100%";
|
||||
configTexture.addControl(selectionPanel)
|
||||
selectionPanel.addGroup(this.buildGridSizeControl());
|
||||
selectionPanel.addGroup(this.buildRotationSnapControl());
|
||||
selectionPanel.addGroup(this.buildCreateScaleControl());
|
||||
this.buildGridSizeControl(selectionPanel);
|
||||
this.buildRotationSnapControl(selectionPanel);
|
||||
this.buildCreateScaleControl(selectionPanel);
|
||||
|
||||
this.configPlane.position = CameraHelper.getFrontPosition(2, this.scene);
|
||||
this.configPlane.rotation.y = Angle.FromDegrees(180).radians();
|
||||
}
|
||||
@ -50,8 +53,10 @@ export class ConfigMenu {
|
||||
log.debug("configMenu", "create Snap", value);
|
||||
}
|
||||
|
||||
private buildCreateScaleControl(): RadioGroup {
|
||||
private buildCreateScaleControl(selectionPanel: SelectionPanel): RadioGroup {
|
||||
const radio = new RadioGroup("Create Scale");
|
||||
selectionPanel.addGroup(radio);
|
||||
|
||||
for (const [index, snap] of AppConfig.config.createSnaps().entries()) {
|
||||
const selected = AppConfig.config.currentCreateSnapIndex == index;
|
||||
radio.addRadio(snap.label, this.createVal, selected);
|
||||
@ -59,8 +64,9 @@ export class ConfigMenu {
|
||||
return radio;
|
||||
}
|
||||
|
||||
private buildRotationSnapControl(): RadioGroup {
|
||||
private buildRotationSnapControl(selectionPanel: SelectionPanel): RadioGroup {
|
||||
const radio = new RadioGroup("Rotation Snap");
|
||||
selectionPanel.addGroup(radio);
|
||||
for (const [index, snap] of AppConfig.config.rotateSnaps().entries()) {
|
||||
const selected = AppConfig.config.currentRotateSnapIndex == index;
|
||||
radio.addRadio(snap.label, this.rotateVal, selected);
|
||||
@ -68,8 +74,9 @@ export class ConfigMenu {
|
||||
return radio;
|
||||
}
|
||||
|
||||
private buildGridSizeControl(): RadioGroup {
|
||||
private buildGridSizeControl(selectionPanel: SelectionPanel): RadioGroup {
|
||||
const radio = new RadioGroup("Grid Snap");
|
||||
selectionPanel.addGroup(radio);
|
||||
for (const [index, snap] of AppConfig.config.gridSnaps().entries()) {
|
||||
const selected = AppConfig.config.currentGridSnapIndex == index;
|
||||
radio.addRadio(snap.label, this.gridVal, selected);
|
||||
|
||||
@ -8,13 +8,15 @@ export type SnapValue = {
|
||||
label: string
|
||||
}
|
||||
export type AppConfigType = {
|
||||
id?: number,
|
||||
gridSnap: number,
|
||||
rotateSnap: number,
|
||||
createSnap: number
|
||||
}
|
||||
|
||||
export class AppConfig {
|
||||
private gridSnap = 0;
|
||||
private readonly logger = log.getLogger('AppConfig');
|
||||
private gridSnap = 1;
|
||||
private rotateSnap = 0;
|
||||
private createSnap = 0;
|
||||
private readonly defaultGridSnapIndex = 1;
|
||||
@ -75,7 +77,7 @@ export class AppConfig {
|
||||
this.createSnap = val;
|
||||
if (this.currentGridSnapIndex == this.defaultGridSnapIndex) {
|
||||
this.currentGridSnap.value = this.currentCreateSnap.value / 2;
|
||||
log.getLogger('AppConfig').debug("Set grid snap to " + this.currentGridSnap.value);
|
||||
this.logger.debug("Set grid snap to " + this.currentGridSnap.value);
|
||||
}
|
||||
this.save();
|
||||
}
|
||||
@ -95,7 +97,7 @@ export class AppConfig {
|
||||
|
||||
public setPersistenceManager(persistenceManager: IPersistenceManager) {
|
||||
this.persistenceManager = persistenceManager;
|
||||
this.load();
|
||||
this.persistenceManager.configObserver.add(this.configObserver, -1, false, this);
|
||||
}
|
||||
|
||||
public gridSnaps(): SnapValue[] {
|
||||
@ -141,23 +143,32 @@ export class AppConfig {
|
||||
});
|
||||
}
|
||||
|
||||
private load() {
|
||||
const config = this.persistenceManager.getConfig();
|
||||
private configObserver(config: AppConfigType) {
|
||||
if (config) {
|
||||
this.rotateSnap = this.rotateSnapArray.findIndex((snap) => snap.value == config.rotateSnap);
|
||||
this.createSnap = this.createSnapArray.findIndex((snap) => snap.value == config.createSnap);
|
||||
const gridSnap = this.gridSnapArray.findIndex((snap) => snap.value == config.gridSnap);
|
||||
if (gridSnap == -1) {
|
||||
this.gridSnap = this.defaultGridSnapIndex;
|
||||
this.currentGridSnap.value = config.gridSnap;
|
||||
if (config.createSnap != this.currentCreateSnap.value ||
|
||||
config.gridSnap != this.currentGridSnap.value ||
|
||||
config.rotateSnap != this.currentRotateSnap.value) {
|
||||
this.logger.debug("Config changed", config);
|
||||
|
||||
this.rotateSnap = this.rotateSnapArray.findIndex((snap) => snap.value == config.rotateSnap);
|
||||
this.createSnap = this.createSnapArray.findIndex((snap) => snap.value == config.createSnap);
|
||||
const gridSnap = this.gridSnapArray.findIndex((snap) => snap.value == config.gridSnap);
|
||||
if (gridSnap == -1) {
|
||||
this.gridSnap = this.defaultGridSnapIndex;
|
||||
this.currentGridSnap.value = config.gridSnap;
|
||||
}
|
||||
} else {
|
||||
this.logger.debug("Config unchanged", config);
|
||||
}
|
||||
} else {
|
||||
this.logger.debug("Config not set");
|
||||
}
|
||||
}
|
||||
|
||||
private snapAngle(val: number): number {
|
||||
const deg = Angle.FromRadians(val).degrees();
|
||||
const snappedDegrees = round(deg, this.currentRotateSnap.value);
|
||||
log.getLogger('AppConfig').debug("deg", val, deg, snappedDegrees, this.currentRotateSnap.value);
|
||||
this.logger.debug("deg", val, deg, snappedDegrees, this.currentRotateSnap.value);
|
||||
return Angle.FromDegrees(snappedDegrees).radians();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user