change from always add to also update in persistenceManager.ts

This commit is contained in:
Michael Mainguy 2023-07-28 13:04:08 -05:00
parent b375005b33
commit 156d0858d8
8 changed files with 115 additions and 48 deletions

View File

@ -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%";

View File

@ -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;
}

View File

@ -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);

View File

@ -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()});
}

View File

@ -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;
}
}

View File

@ -11,12 +11,11 @@ export interface IPersistenceManager {
initialize();
getConfig(): AppConfigType;
setConfig(config: AppConfigType);
changeColor(oldColor: Color3, newColor: Color3)
updateObserver: Observable<DiagramEntity>;
configObserver: Observable<AppConfigType>;
}

View File

@ -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);

View File

@ -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();
}
}