Skip to content

Commit

Permalink
some further refining work
Browse files Browse the repository at this point in the history
  • Loading branch information
sdumetz committed Jan 9, 2024
1 parent 3c51e3b commit e5c7a90
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 25 deletions.
9 changes: 7 additions & 2 deletions source/server/utils/merge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ export {

/**
* like `diff()` but dereferences a document's pointers first to make a cleaner diff
* @returns
* @see diff
*/
export function diffDoc(from:IDocument,to:IDocument){
return diff( toPointers(from), toPointers(to));
}


/**
* like `apply()` but dereferences a document's pointers first to make a cleaner diff, then re-references the result
* @see apply
* @see fromPointers
* @see toPointers
*/
export function applyDoc(from:IDocument, diff:Diff<DerefDocument>){
return fromPointers(apply(toPointers(from), diff));
}
46 changes: 23 additions & 23 deletions source/server/utils/merge/pointers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import { ISetup } from "../schema/setup.js";
import { DerefDocument, DerefNode, DerefScene } from "./types.js";


type DocumentCollections = keyof Omit<IDocument, "asset"|"scene">;

/**
* Dereference all indexed values into pointers in a SVX document
* It effectively forgets about all unreachable nodes (scenes, setups, etc...).
*
* It's something of an emulation of what DPO-voyager does when building a scene graph from a document.
* See CVScene.ts and CVNode.ts in voyager.
*/
export function toPointers(src :IDocument) :DerefDocument {
const nodes = src.nodes?.map(iNode=>{
Expand Down Expand Up @@ -72,17 +76,18 @@ export function toPointers(src :IDocument) :DerefDocument {

export function fromPointers({asset, scene} :DerefDocument): IDocument{


let collections = {
//The output document
let document :Required<IDocument> = {
asset,
scene: -1,
"scenes": [] as IScene[],
"nodes": [] as INode[],
"cameras": [] as ICamera[],
"lights": [] as ILight[],
"models": [] as IModel[],
"metas": [] as IMeta[],
"setups": [] as ISetup[],

} as const;
};


function appendScene(scene :DerefScene){
Expand All @@ -96,12 +101,12 @@ export function fromPointers({asset, scene} :DerefDocument): IDocument{
for(let key of ["setup", "meta"] as const){
const value = scene[key];
if(!value) continue;
let colKey = key+"s" as keyof typeof collections;
const idx = collections[colKey].length;
collections[colKey].push(value as any);
let colKey = key+"s" as DocumentCollections;
const idx = document[colKey]!.length;
document[colKey]!.push(value as any);
iScene[key] = idx as any;
}
return collections.scenes.push(iScene) - 1;
return document.scenes.push(iScene) - 1;
}

function appendNode(node :DerefNode){
Expand All @@ -110,7 +115,7 @@ export function fromPointers({asset, scene} :DerefDocument): IDocument{
if(node.name) iNode.name = node.name;

//Push to collection before appending children because that's a more "natural" order to have
const idx = collections.nodes.push(iNode) - 1;
const idx = document.nodes.push(iNode) - 1;

if(node.children?.length){
iNode.children = node.children.map((child)=>appendNode(child));
Expand All @@ -125,28 +130,23 @@ export function fromPointers({asset, scene} :DerefDocument): IDocument{
for(let key of ["camera", "light", "model", "meta"] as const){
const value = node[key];
if(!value) continue;
let colKey = key+"s" as keyof typeof collections;
const idx = collections[colKey].length;
collections[colKey].push(value as any);
let colKey = key+"s" as DocumentCollections;
const idx = document[colKey].length;
document[colKey].push(value as any);
iNode[key] = idx as any;
}
return idx;
}


let sceneIndex = appendScene(scene);
document.scene = appendScene(scene);


let out :IDocument = {
asset,
scene: sceneIndex,
...collections,
};

for(let key in out){
let v = out[key as keyof typeof out];
if(typeof v === "undefined" || (Array.isArray(v) && v.length == 0)) delete out[key as keyof typeof out];
//Remove empty collections
for(let key in document){
let v = document[key as keyof typeof document];
if(typeof v === "undefined" || (Array.isArray(v) && v.length == 0)) delete document[key as keyof typeof document];
}

return out;
return document;
}

0 comments on commit e5c7a90

Please sign in to comment.