@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
145 lines (129 loc) • 4.04 kB
text/typescript
import {PolyScene} from '../../../scene/PolyScene';
import {ManifestContent} from '../import/SceneData';
import {NodeJsonExporterData} from '../../json/export/Node';
import {SceneJsonExporter, SceneJsonExporterDataProperties} from '../../json/export/Scene';
import {PolyDictionary} from '../../../../types/GlobalTypes';
interface SceneDataManifestExporterData {
properties: SceneJsonExporterDataProperties;
root: NodeJsonExporterData;
nodes: PolyDictionary<NodeJsonExporterData>;
}
export interface ChildDataContainer {
childName: string;
childData: NodeJsonExporterData;
nodeFullPath: string;
}
interface SaveNodeDataOptions {
nodeName: string;
nodeData: NodeJsonExporterData;
parentFullPath?: string;
now: string;
}
export class SceneDataManifestExporter {
private _manifestContent: ManifestContent = {
properties: '',
root: '',
nodes: {},
shaders: {},
jsFunctionBodies: {},
};
private _data: SceneDataManifestExporterData = {
properties: {
frame: 0,
maxFrame: 100,
maxFrameLocked: false,
realtimeState: true,
mainCameraNodePath: '/',
},
root: {type: 'root'},
nodes: {},
};
constructor(public readonly scene: PolyScene) {}
async data() {
const now = `${Date.now()}`;
this._manifestContent = {
properties: now,
root: now,
nodes: {},
shaders: {},
jsFunctionBodies: {},
};
const exporter = new SceneJsonExporter(this.scene);
const sceneData = await exporter.data({versions: {polygonjs: 'ENGINE_VERSION'}, withPersistedConfig: true});
this._data = {
properties: sceneData.properties!,
root: {type: 'root'},
nodes: {},
};
const rootData = sceneData.root;
if (rootData) {
this._saveNodeData({
nodeName: 'root',
nodeData: rootData,
// parentFullPath: '',
now: now,
});
}
// check if root is present in nodes
const rootInNode = this._data.nodes['root'];
if (rootInNode) {
throw 'root should not be in node';
}
return {sceneData: this._data, manifest: this._manifestContent};
}
private _saveNodeData(options: SaveNodeDataOptions) {
const {nodeName, nodeData, parentFullPath, now} = options;
const nodeFullPath = parentFullPath ? `${parentFullPath}/${nodeName}` : nodeName;
// we remove the prefix 'root/' if needed
const manifestPath = parentFullPath ? nodeFullPath.substring(5) : nodeFullPath;
// const manifestPath = nodeFullPath;
const children = nodeData.nodes;
if (!children) {
return;
}
const childrenDataToWriteSeparately: ChildDataContainer[] = [];
const childrenNames = Object.keys(children);
for (let childName of childrenNames) {
const childData = children[childName];
// if the child has itself children, it should end up in a separate file
if (childData.nodes) {
delete children[childName];
childrenDataToWriteSeparately.push({
childName,
childData,
nodeFullPath,
});
}
}
// compare with previously existing data and update node timestamp if required
// let timestamp: string = `${Date.now()}`; //this._save_timestamp;
// const manifest_content = main_controller.manifest.content();
// if (manifest_content) {
// const old_timestamp = manifest_content.nodes[manifest_path];
// const data_changed = this._scene_data_cache.has_data_for_node_changed(manifest_path, node_data);
// if (!data_changed) {
// timestamp = old_timestamp;
// }
// }
// write data
if (parentFullPath) {
this._manifestContent.nodes[manifestPath] = now;
this._data.nodes[`${nodeFullPath}.json`] = nodeData;
} else {
this._data.root = nodeData;
}
// main_controller.file_writer.write_scene_data({file: node_full_path, content: node_data});
// if (parent_full_path != '') {
// this._manifest_nodes_data[manifest_path] = timestamp;
// }
for (let childDataContainer of childrenDataToWriteSeparately) {
const {childName, childData, nodeFullPath} = childDataContainer;
this._saveNodeData({
nodeName: childName,
nodeData: childData,
parentFullPath: nodeFullPath,
now: now,
});
}
}
}