sunrize
Version:
Sunrize — A Multi-Platform X3D Editor
245 lines (190 loc) • 6.58 kB
JavaScript
"use strict";
const
$ = require ("jquery"),
X3D = require ("../X3D"),
LibraryPane = require ("./LibraryPane"),
Editor = require ("../Undo/Editor"),
UndoManager = require ("../Undo/UndoManager"),
_ = require ("../Application/GetText");
module .exports = class NodesLibrary extends LibraryPane
{
id = "NODES";
description = "Nodes";
#list;
open ()
{
// Set default config values.
this .config .global .setDefaultValues ({
recentNodes: [ ],
});
// Clear output.
this .#list ?.remove ();
this .#list = undefined;
}
update ()
{
// Fill output.
if (this .#list)
{
this .output .append (this .#list);
return;
}
// Create list.
this .#list = $("<ul></ul>")
.appendTo (this .output)
.addClass ("library-list");
// Get protos.
const protos = Array .from (this .getProtos () .values ())
.sort ((a, b) => a .name .localeCompare (b .name));
// Get supported nodes.
const nodes = [... this .browser .getConcreteNodes ()]
.sort ((a, b) => a .typeName .localeCompare (b .typeName))
.sort ((a, b) => a .componentInfo .name .localeCompare (b .componentInfo .name));
// Get recently used elements.
const recentNodes = this .config .global .recentNodes .map (typeName => $.try (() => this .browser .getConcreteNode (typeName))) .filter (node => node);
// Create list for recently used elements.
if (recentNodes .length)
{
$("<li></li>")
.addClass ("component")
.attr ("name", "recent")
.text ("Recently Used Nodes")
.appendTo (this .#list);
for (const node of recentNodes)
{
$("<li></li>")
.addClass ("node")
.text (node .typeName)
.attr ("componentName", node .componentInfo .name)
.appendTo (this .#list)
.on ("dblclick", () => this .createNode (node .typeName, node .componentInfo .name));
}
}
// Create list for proto elements.
if (protos .length)
{
$("<li></li>")
.addClass ("component")
.attr ("name", "prototypes")
.text ("Prototypes")
.appendTo (this .#list);
for (const proto of protos)
{
$("<li></li>")
.addClass ("node")
.text (proto .name)
.appendTo (this .#list)
.on ("dblclick", () => this .createProto (proto));
}
}
// Create list for nodes elements.
let componentName = "";
for (const node of nodes)
{
if (node .componentInfo .name !== componentName)
{
componentName = node .componentInfo .name;
$("<li></li>")
.addClass ("component")
.attr ("name", node .componentInfo .name)
.text (this .browser .getSupportedComponents () .get (node .componentInfo .name) .title)
.appendTo (this .#list);
}
$("<li></li>")
.addClass ("node")
.text (node .typeName)
.attr ("componentName", node .componentInfo .name)
.appendTo (this .#list)
.on ("dblclick", () => this .createNode (node .typeName, node .componentInfo .name));
}
}
getProtos (executionContext = this .executionContext, protos = new Map (), outerNode)
{
if (!executionContext)
return protos;
for (const proto of executionContext .protos)
{
if (proto === outerNode)
break;
if (protos .has (proto .name))
continue;
protos .set (proto .name, proto);
}
for (const proto of executionContext .externprotos)
{
if (proto === outerNode)
break;
if (protos .has (proto .name))
continue;
protos .set (proto .name, proto);
}
if (!(executionContext instanceof X3D .X3DScene))
this .getProtos (executionContext .getExecutionContext (), protos, executionContext .getOuterNode ());
return protos;
}
async createNode (typeName, componentName)
{
const recentNodes = this .config .global .recentNodes .filter (name => name !== typeName);
recentNodes .unshift (typeName);
recentNodes .splice (10);
this .config .global .recentNodes = recentNodes;
UndoManager .shared .beginUndo (_("Create Node %s"), typeName);
await Editor .addComponent (this .executionContext, componentName);
const node = this .executionContext .createNode (typeName);
this .initializeNode (node);
this .addNode (node);
UndoManager .shared .endUndo ();
await this .expandToAndSelectNode (node .getValue ());
}
initializeNode (node)
{
for (const type of node .getNodeType () .reverse ())
{
switch (type)
{
case X3D .X3DConstants .ElevationGrid:
{
node .xDimension = 10;
node .zDimension = 10;
break;
}
case X3D .X3DConstants .X3DEnvironmentalSensorNode:
{
node .size = new X3D .SFVec3f (2, 2, 2);
break;
}
}
}
}
async createProto (proto)
{
UndoManager .shared .beginUndo (_("Create Proto Instance %s"), proto .name);
const node = proto .createInstance (this .executionContext);
this .addNode (node);
UndoManager .shared .endUndo ();
await this .expandToAndSelectNode (node .getValue ());
}
addNode (node)
{
const field = this .field
?? $.try (() => this .node ?.getField (node .getValue () .getContainerField ()));
switch (field ?.getType ())
{
case X3D .X3DConstants .SFNode:
{
Editor .setFieldValue (this .executionContext, this .node, field, node);
break;
}
case X3D .X3DConstants .MFNode:
{
Editor .insertValueIntoArray (this .executionContext, this .node, field, field .length, node);
break;
}
default:
{
Editor .insertValueIntoArray (this .executionContext, this .executionContext, this .executionContext .rootNodes, this .executionContext .rootNodes .length, node);
break;
}
}
}
};