sunrize 2.0.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/Editors/CannonExterior.avif +0 -0
- package/src/Editors/Library.js +1 -1
- package/src/Editors/Materials.x3d +1738 -1699
- package/src/Editors/MaterialsLibrary.js +129 -7
- package/src/Editors/NodesLibrary.js +3 -3
- package/src/Editors/Panel.js +27 -1
- package/src/Editors/Primitives.js +3 -3
- package/src/Editors/PrimitivesLibrary.js +2 -2
- package/src/Undo/Editor.js +35 -14
- package/src/assets/themes/default.css +4 -0
|
@@ -3,14 +3,19 @@
|
|
|
3
3
|
const
|
|
4
4
|
$ = require ("jquery"),
|
|
5
5
|
X3D = require ("../X3D"),
|
|
6
|
-
LibraryPane = require ("./LibraryPane")
|
|
6
|
+
LibraryPane = require ("./LibraryPane"),
|
|
7
|
+
_ = require ("../Application/GetText");
|
|
7
8
|
|
|
8
9
|
module .exports = class Materials extends LibraryPane
|
|
9
10
|
{
|
|
10
11
|
id = "MATERIALS";
|
|
11
12
|
description = "Materials";
|
|
12
13
|
|
|
14
|
+
#scene;
|
|
13
15
|
#list;
|
|
16
|
+
#physicalButton;
|
|
17
|
+
#cancelRendering;
|
|
18
|
+
#rendering;
|
|
14
19
|
|
|
15
20
|
async update ()
|
|
16
21
|
{
|
|
@@ -33,9 +38,29 @@ module .exports = class Materials extends LibraryPane
|
|
|
33
38
|
browser = canvas .prop ("browser"),
|
|
34
39
|
scene = await browser .createX3DFromURL (new X3D .MFString (`file://${__dirname}/Materials.x3d`));
|
|
35
40
|
|
|
41
|
+
// Buttons
|
|
42
|
+
|
|
43
|
+
const buttons = $("<li></li>")
|
|
44
|
+
.appendTo (this .#list);
|
|
45
|
+
|
|
46
|
+
this .#physicalButton = $("<input></input>")
|
|
47
|
+
.attr ("title", _("Requires an EnvironmentLight node."))
|
|
48
|
+
.attr ("type", "checkbox")
|
|
49
|
+
.attr ("id", "use-physical-material")
|
|
50
|
+
.prop ("checked", this .config .global .convertToPhysical)
|
|
51
|
+
.on ("change", () => this .#rendering = this .onChangeMaterials ())
|
|
52
|
+
.appendTo (buttons);
|
|
53
|
+
|
|
54
|
+
$("<label></label>")
|
|
55
|
+
.attr ("title", _("Requires an EnvironmentLight node."))
|
|
56
|
+
.attr ("for", "use-physical-material")
|
|
57
|
+
.text (_("Create Physical Material"))
|
|
58
|
+
.appendTo (buttons);
|
|
59
|
+
|
|
60
|
+
// Materials
|
|
61
|
+
|
|
36
62
|
const
|
|
37
63
|
materials = scene .getExportedNode ("Materials"),
|
|
38
|
-
viewpoint = scene .getExportedNode ("Viewpoint"),
|
|
39
64
|
nodes = [ ];
|
|
40
65
|
|
|
41
66
|
for (const [g, group] of materials .children .entries ())
|
|
@@ -51,16 +76,53 @@ module .exports = class Materials extends LibraryPane
|
|
|
51
76
|
|
|
52
77
|
nodes .push ($("<li></li>")
|
|
53
78
|
.addClass (["node", "icon"])
|
|
79
|
+
.attr ("title", material .getNodeDisplayName ())
|
|
54
80
|
.attr ("group", g)
|
|
55
81
|
.attr ("child", c)
|
|
56
82
|
.append ($("<span></span>")
|
|
57
83
|
.addClass ("text")
|
|
58
84
|
.text (`${group .getNodeName ()} ${c + 1}`))
|
|
59
85
|
.appendTo (this .#list)
|
|
60
|
-
.on ("
|
|
86
|
+
.on ("click", () => this .importMaterial (material .getNodeName ())));
|
|
61
87
|
}
|
|
62
88
|
}
|
|
63
89
|
|
|
90
|
+
browser .dispose ();
|
|
91
|
+
canvas .remove ();
|
|
92
|
+
|
|
93
|
+
this .#rendering = this .onChangeMaterials ();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
importMaterial (name)
|
|
97
|
+
{
|
|
98
|
+
const material = this .#scene .getNamedNode (name);
|
|
99
|
+
|
|
100
|
+
this .importX3D (material .getNodeName (), material .toXMLString ());
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async onChangeMaterials ()
|
|
104
|
+
{
|
|
105
|
+
this .#cancelRendering = true;
|
|
106
|
+
|
|
107
|
+
await this .#rendering;
|
|
108
|
+
|
|
109
|
+
this .#cancelRendering = false;
|
|
110
|
+
|
|
111
|
+
this .config .global .convertToPhysical = this .#physicalButton .is (":checked");
|
|
112
|
+
|
|
113
|
+
const
|
|
114
|
+
canvas = $("<x3d-canvas preserveDrawingBuffer='true' xrSessionMode='NONE'></x3d-canvas>"),
|
|
115
|
+
browser = canvas .prop ("browser"),
|
|
116
|
+
scene = await browser .createX3DFromURL (new X3D .MFString (`file://${__dirname}/Materials.x3d`));
|
|
117
|
+
|
|
118
|
+
scene .addComponent (browser .getComponent ("X_ITE"));
|
|
119
|
+
|
|
120
|
+
this .#scene = scene;
|
|
121
|
+
|
|
122
|
+
const
|
|
123
|
+
materials = scene .getExportedNode ("Materials"),
|
|
124
|
+
viewpoint = scene .getExportedNode ("Viewpoint");
|
|
125
|
+
|
|
64
126
|
// Create icons.
|
|
65
127
|
|
|
66
128
|
canvas
|
|
@@ -72,11 +134,26 @@ module .exports = class Materials extends LibraryPane
|
|
|
72
134
|
|
|
73
135
|
for (const element of Array .from (this .output .find (".node"), e => $(e)))
|
|
74
136
|
{
|
|
137
|
+
if (this .#cancelRendering)
|
|
138
|
+
break;
|
|
139
|
+
|
|
75
140
|
const
|
|
76
|
-
group
|
|
77
|
-
child
|
|
78
|
-
section
|
|
79
|
-
node
|
|
141
|
+
group = element .attr ("group"),
|
|
142
|
+
child = element .attr ("child"),
|
|
143
|
+
section = materials .children [group],
|
|
144
|
+
node = section .children [child],
|
|
145
|
+
appearance = node .children [0] .appearance;
|
|
146
|
+
|
|
147
|
+
if (this .config .global .convertToPhysical)
|
|
148
|
+
{
|
|
149
|
+
const material = this .convertPhongToPhysical (scene, appearance .material);
|
|
150
|
+
|
|
151
|
+
scene .updateNamedNode (appearance .material .getNodeName (), material);
|
|
152
|
+
|
|
153
|
+
appearance .material = material;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// console .log (appearance .material .getNodeName ());
|
|
80
157
|
|
|
81
158
|
materials .whichChoice = group;
|
|
82
159
|
section .whichChoice = child;
|
|
@@ -93,4 +170,49 @@ module .exports = class Materials extends LibraryPane
|
|
|
93
170
|
browser .dispose ();
|
|
94
171
|
canvas .remove ();
|
|
95
172
|
}
|
|
173
|
+
|
|
174
|
+
convertPhongToPhysical (executionContext, phong)
|
|
175
|
+
{
|
|
176
|
+
let
|
|
177
|
+
physical = executionContext .createNode ("PhysicalMaterial"),
|
|
178
|
+
baseColor = phong .diffuseColor .sRGBToLinear (),
|
|
179
|
+
specularColor = phong .specularColor .sRGBToLinear (),
|
|
180
|
+
specularIntensity = Math .max (... specularColor),
|
|
181
|
+
metallic = Math .min (Math .max ((specularIntensity - 0.04) / (1.0 - 0.04), 0), 1) * 0.5,
|
|
182
|
+
roughness = 1 - phong .shininess,
|
|
183
|
+
emissiveColor = phong .emissiveColor .sRGBToLinear (),
|
|
184
|
+
transparency = phong .transparency,
|
|
185
|
+
transmission = transparency ** (1/3);
|
|
186
|
+
|
|
187
|
+
if ([... specularColor] .some (Boolean) && roughness)
|
|
188
|
+
{
|
|
189
|
+
const specularMaterial = executionContext .createNode ("SpecularMaterialExtension");
|
|
190
|
+
|
|
191
|
+
specularMaterial .specularColor = specularColor;
|
|
192
|
+
specularMaterial .specularStrength = 10 * roughness;
|
|
193
|
+
|
|
194
|
+
physical .extensions .push (specularMaterial);
|
|
195
|
+
|
|
196
|
+
metallic *= 0.1;
|
|
197
|
+
roughness *= 0.5;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (transparency)
|
|
201
|
+
{
|
|
202
|
+
const transmissionMaterial = executionContext .createNode ("TransmissionMaterialExtension");
|
|
203
|
+
|
|
204
|
+
transmissionMaterial .transmission = transmission;
|
|
205
|
+
|
|
206
|
+
physical .extensions .push (transmissionMaterial);
|
|
207
|
+
|
|
208
|
+
roughness *= 0.5 * (1 - transparency);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
physical .baseColor = baseColor;
|
|
212
|
+
physical .metallic = metallic;
|
|
213
|
+
physical .roughness = roughness;
|
|
214
|
+
physical .emissiveColor = emissiveColor;
|
|
215
|
+
|
|
216
|
+
return physical;
|
|
217
|
+
}
|
|
96
218
|
};
|
|
@@ -77,7 +77,7 @@ module .exports = class NodesLibrary extends LibraryPane
|
|
|
77
77
|
.text (node .typeName)
|
|
78
78
|
.attr ("componentName", node .componentInfo .name)
|
|
79
79
|
.appendTo (this .#list)
|
|
80
|
-
.on ("
|
|
80
|
+
.on ("click", () => this .createNode (node .typeName, node .componentInfo .name));
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -97,7 +97,7 @@ module .exports = class NodesLibrary extends LibraryPane
|
|
|
97
97
|
.addClass ("node")
|
|
98
98
|
.text (proto .name)
|
|
99
99
|
.appendTo (this .#list)
|
|
100
|
-
.on ("
|
|
100
|
+
.on ("click", () => this .createProto (proto));
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -123,7 +123,7 @@ module .exports = class NodesLibrary extends LibraryPane
|
|
|
123
123
|
.text (node .typeName)
|
|
124
124
|
.attr ("componentName", node .componentInfo .name)
|
|
125
125
|
.appendTo (this .#list)
|
|
126
|
-
.on ("
|
|
126
|
+
.on ("click", () => this .createNode (node .typeName, node .componentInfo .name));
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
package/src/Editors/Panel.js
CHANGED
|
@@ -29,7 +29,10 @@ module .exports = new class Panel extends Interface
|
|
|
29
29
|
"top": "unset",
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
this .container
|
|
32
|
+
this .container
|
|
33
|
+
.on ("mouseenter", event => this .onmouseenter (event))
|
|
34
|
+
.on ("mouseleave", event => this .onmouseleave (event))
|
|
35
|
+
.on ("mousedown", event => this .onmousedown (event));
|
|
33
36
|
|
|
34
37
|
this .browser .getBrowserOptions () ._ColorSpace .addFieldCallback ("Panel", () => this .updateNode ());
|
|
35
38
|
|
|
@@ -65,6 +68,16 @@ module .exports = new class Panel extends Interface
|
|
|
65
68
|
this .container .hide (300, () => this .removeNode (this .node));
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
onmouseenter ()
|
|
72
|
+
{
|
|
73
|
+
this .hovered = true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
onmouseleave ()
|
|
77
|
+
{
|
|
78
|
+
this .hovered = false;
|
|
79
|
+
}
|
|
80
|
+
|
|
68
81
|
onmousedown (event)
|
|
69
82
|
{
|
|
70
83
|
$(document) .on ("mouseup.Panel", () => this .onmouseup ());
|
|
@@ -415,6 +428,9 @@ module .exports = new class Panel extends Interface
|
|
|
415
428
|
|
|
416
429
|
field .addFieldCallback (this, () =>
|
|
417
430
|
{
|
|
431
|
+
if (this .changing)
|
|
432
|
+
return;
|
|
433
|
+
|
|
418
434
|
this .refresh (parameter, node, field);
|
|
419
435
|
input .refresh ();
|
|
420
436
|
});
|
|
@@ -474,6 +490,9 @@ module .exports = new class Panel extends Interface
|
|
|
474
490
|
|
|
475
491
|
field .addFieldCallback (this, () =>
|
|
476
492
|
{
|
|
493
|
+
if (this .changing)
|
|
494
|
+
return;
|
|
495
|
+
|
|
477
496
|
this .refresh (parameter, node, field);
|
|
478
497
|
textarea .val (parameter [field .getName ()]);
|
|
479
498
|
});
|
|
@@ -647,6 +666,13 @@ module .exports = new class Panel extends Interface
|
|
|
647
666
|
executionContext = node .getExecutionContext (),
|
|
648
667
|
category = field .getUnit ();
|
|
649
668
|
|
|
669
|
+
if (!(this .hovered || this .container .find (":focus") .length))
|
|
670
|
+
return;
|
|
671
|
+
|
|
672
|
+
this .changing = true;
|
|
673
|
+
|
|
674
|
+
this .browser .nextFrame () .then (() => this .changing = false);
|
|
675
|
+
|
|
650
676
|
switch (field .getType ())
|
|
651
677
|
{
|
|
652
678
|
case X3D .X3DConstants .SFBool:
|
|
@@ -446,7 +446,7 @@ DEF ScreenText Transform {
|
|
|
446
446
|
componentInfo: { name: "Lighting" },
|
|
447
447
|
typeName: "EnvironmentLight Cannon Exterior",
|
|
448
448
|
x3dSyntax: `
|
|
449
|
-
EnvironmentLight {
|
|
449
|
+
DEF CannonExterior EnvironmentLight {
|
|
450
450
|
specularTexture ImageCubeMapTexture {
|
|
451
451
|
url "https://cdn.jsdelivr.net/npm/x3d-image@2.2.0/src/images/cannon-exterior.avif"
|
|
452
452
|
}
|
|
@@ -457,7 +457,7 @@ EnvironmentLight {
|
|
|
457
457
|
componentInfo: { name: "Lighting" },
|
|
458
458
|
typeName: "EnvironmentLight Helipad",
|
|
459
459
|
x3dSyntax: `
|
|
460
|
-
EnvironmentLight {
|
|
460
|
+
DEF Helipad EnvironmentLight {
|
|
461
461
|
specularTexture ImageCubeMapTexture {
|
|
462
462
|
url "https://cdn.jsdelivr.net/npm/x3d-image@2.2.0/src/images/helipad.avif"
|
|
463
463
|
}
|
|
@@ -468,7 +468,7 @@ EnvironmentLight {
|
|
|
468
468
|
componentInfo: { name: "Lighting" },
|
|
469
469
|
typeName: "EnvironmentLight Footprint Court",
|
|
470
470
|
x3dSyntax: `
|
|
471
|
-
EnvironmentLight {
|
|
471
|
+
DEF FootprintCourt EnvironmentLight {
|
|
472
472
|
specularTexture ImageCubeMapTexture {
|
|
473
473
|
url "https://cdn.jsdelivr.net/npm/x3d-image@2.2.0/src/images/footprint-court.avif"
|
|
474
474
|
}
|
|
@@ -67,7 +67,7 @@ module .exports = class PrimitivesLibrary extends LibraryPane
|
|
|
67
67
|
.addClass ("node")
|
|
68
68
|
.text (typeName)
|
|
69
69
|
.appendTo (this .#list)
|
|
70
|
-
.on ("
|
|
70
|
+
.on ("click", () => this .createRecentNode (nodes, typeName));
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -91,7 +91,7 @@ module .exports = class PrimitivesLibrary extends LibraryPane
|
|
|
91
91
|
.addClass ("node")
|
|
92
92
|
.text (node .typeName)
|
|
93
93
|
.appendTo (this .#list)
|
|
94
|
-
.on ("
|
|
94
|
+
.on ("click", () => this .createNode (node));
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
package/src/Undo/Editor.js
CHANGED
|
@@ -616,6 +616,9 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
|
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
|
|
619
|
+
if (node ._url .equals (newURL))
|
|
620
|
+
return;
|
|
621
|
+
|
|
619
622
|
const uniqueURL = new X3D .MFString (... new Set (newURL));
|
|
620
623
|
|
|
621
624
|
this .setFieldValue (executionContext, node, node ._url, uniqueURL, undoManager);
|
|
@@ -675,16 +678,19 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
|
|
|
675
678
|
*/
|
|
676
679
|
static getUsedComponents (scene)
|
|
677
680
|
{
|
|
678
|
-
const components = new
|
|
681
|
+
const components = new Map ();
|
|
679
682
|
|
|
680
683
|
for (const object of scene .traverse (Traverse .PROTO_DECLARATIONS | Traverse .PROTO_DECLARATION_BODY | Traverse .ROOT_NODES | Traverse .PROTOTYPE_INSTANCES))
|
|
681
684
|
{
|
|
682
685
|
if (!(object instanceof X3D .SFNode))
|
|
683
686
|
continue;
|
|
684
687
|
|
|
685
|
-
const
|
|
688
|
+
const
|
|
689
|
+
node = object .getValue (),
|
|
690
|
+
componentInfo = node .getComponentInfo ();
|
|
686
691
|
|
|
687
|
-
components .
|
|
692
|
+
if (components .get (componentInfo .name) ?? 0 < componentInfo .level)
|
|
693
|
+
components .set (componentInfo .name, componentInfo .level);
|
|
688
694
|
}
|
|
689
695
|
|
|
690
696
|
return components;
|
|
@@ -692,31 +698,46 @@ ${scene .toXMLString ({ html: true, indent: " " .repeat (6) }) .trimEnd () }
|
|
|
692
698
|
|
|
693
699
|
static getProfileAndComponentsFromUsedComponents (browser, usedComponents)
|
|
694
700
|
{
|
|
695
|
-
const profiles = ["
|
|
701
|
+
const profiles = ["Interchange", "Interactive", "Immersive", "Full"] .map (name =>
|
|
696
702
|
{
|
|
697
|
-
return { profile: browser .getProfile (name), components: new
|
|
703
|
+
return { profile: browser .getProfile (name), components: new Map (usedComponents) };
|
|
698
704
|
});
|
|
699
705
|
|
|
700
|
-
profiles .forEach (
|
|
706
|
+
profiles .forEach (({ profile, components }) =>
|
|
701
707
|
{
|
|
702
|
-
for (const component of
|
|
703
|
-
|
|
708
|
+
for (const component of profile .components)
|
|
709
|
+
{
|
|
710
|
+
const level = components .get (component .name);
|
|
711
|
+
|
|
712
|
+
if (level === undefined)
|
|
713
|
+
continue;
|
|
714
|
+
|
|
715
|
+
if (level > component .level)
|
|
716
|
+
continue;
|
|
717
|
+
|
|
718
|
+
components .delete (component .name);
|
|
719
|
+
}
|
|
704
720
|
});
|
|
705
721
|
|
|
706
|
-
const
|
|
722
|
+
const { object } = profiles .reduce ((min, object) =>
|
|
707
723
|
{
|
|
708
|
-
const count =
|
|
724
|
+
const count = new Set ([
|
|
725
|
+
... [... object .profile .components] .map (component => component .name),
|
|
726
|
+
... object .components .keys ()
|
|
727
|
+
]) .size;
|
|
709
728
|
|
|
710
729
|
return min .count < count ? min : {
|
|
711
|
-
count
|
|
712
|
-
object
|
|
730
|
+
count,
|
|
731
|
+
object,
|
|
713
732
|
};
|
|
714
733
|
},
|
|
715
734
|
{ count: Number .POSITIVE_INFINITY });
|
|
716
735
|
|
|
717
736
|
return {
|
|
718
|
-
profile:
|
|
719
|
-
components: Array .from (
|
|
737
|
+
profile: object .profile,
|
|
738
|
+
components: Array .from (object .components .keys ())
|
|
739
|
+
.sort ()
|
|
740
|
+
.map (name => browser .getComponent (name, object .components .get (name))),
|
|
720
741
|
};
|
|
721
742
|
}
|
|
722
743
|
|
|
@@ -895,6 +895,10 @@ body.dark .ui-widget .library-list .component {
|
|
|
895
895
|
background-position: 50%;
|
|
896
896
|
}
|
|
897
897
|
|
|
898
|
+
.library-list.materials .icon:hover {
|
|
899
|
+
border: 1px solid light-dark(var(--system-gray0), var(--system-gray2));
|
|
900
|
+
}
|
|
901
|
+
|
|
898
902
|
.library-list.materials .text {
|
|
899
903
|
display: none;
|
|
900
904
|
}
|