sunrize 1.11.0 → 1.11.2
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 +14 -13
- package/src/Application/Application.js +1 -1
- package/src/Application/Dashboard.js +12 -3
- package/src/Application/Document.js +13 -8
- package/src/Application/Hierarchy.js +10 -3
- package/src/Controls/AddPrototypePopover.js +2 -2
- package/src/Controls/AnimationPropertiesPopover.js +12 -1
- package/src/Controls/Dialog.js +5 -2
- package/src/Controls/EditNodePopover.js +1 -1
- package/src/Controls/EditUserDefinedFieldPopover.js +1 -1
- package/src/Editors/AnimationEditor.js +105 -73
- package/src/Editors/AnimationMemberList.js +2 -2
- package/src/Editors/BrowserFrame.js +5 -3
- package/src/Editors/Console.js +253 -17
- package/src/Editors/Library.js +1 -1
- package/src/Editors/MaterialsLibrary.js +5 -3
- package/src/Editors/OutlineEditor.js +342 -224
- package/src/Editors/OutlineView.js +149 -174
- package/src/Editors/Panel.js +55 -1
- package/src/Editors/SceneProperties.js +188 -49
- package/src/Fields/MFStringTextArea.js +13 -11
- package/src/Fields/SFStringInput.js +12 -12
- package/src/Tools/Core/X3DNodeTool.js +1 -1
- package/src/Undo/Editor.js +93 -74
- package/src/assets/X3DUOM.xml +13 -4
- package/src/assets/themes/default.css +274 -67
- package/src/assets/themes/media-template.css +1 -9
- package/src/assets/themes/media.css +1 -9
- package/src/assets/themes/system-colors.css +63 -61
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sunrize",
|
|
3
3
|
"productName": "Sunrize X3D Editor",
|
|
4
|
-
"version": "1.11.
|
|
4
|
+
"version": "1.11.2",
|
|
5
5
|
"description": "A Multi-Platform X3D Editor",
|
|
6
6
|
"main": "src/main.js",
|
|
7
7
|
"bin": {
|
|
@@ -78,19 +78,20 @@
|
|
|
78
78
|
"url": "https://patreon.com/X_ITE"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@electron-forge/cli": "^7.
|
|
82
|
-
"@electron-forge/maker-deb": "^7.
|
|
83
|
-
"@electron-forge/maker-dmg": "^7.
|
|
84
|
-
"@electron-forge/maker-rpm": "^7.
|
|
85
|
-
"@electron-forge/maker-squirrel": "^7.
|
|
86
|
-
"@electron-forge/maker-zip": "^7.
|
|
87
|
-
"@electron-forge/publisher-github": "^7.
|
|
81
|
+
"@electron-forge/cli": "^7.10.2",
|
|
82
|
+
"@electron-forge/maker-deb": "^7.10.2",
|
|
83
|
+
"@electron-forge/maker-dmg": "^7.10.2",
|
|
84
|
+
"@electron-forge/maker-rpm": "^7.10.2",
|
|
85
|
+
"@electron-forge/maker-squirrel": "^7.10.2",
|
|
86
|
+
"@electron-forge/maker-zip": "^7.10.2",
|
|
87
|
+
"@electron-forge/publisher-github": "^7.10.2",
|
|
88
88
|
"shell-tools": "^1.1.9"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
+
"@vscode/codicons": "^0.0.41",
|
|
91
92
|
"capitalize": "^2.0.4",
|
|
92
93
|
"console": "^0.7.2",
|
|
93
|
-
"electron": "^38.
|
|
94
|
+
"electron": "^38.3.0",
|
|
94
95
|
"electron-prompt": "^1.7.0",
|
|
95
96
|
"electron-squirrel-startup": "^1.0.1",
|
|
96
97
|
"electron-tabs": "^1.0.4",
|
|
@@ -99,17 +100,17 @@
|
|
|
99
100
|
"jquery-ui-dist": "^1.13.3",
|
|
100
101
|
"jstree": "^3.3.17",
|
|
101
102
|
"material-icons": "^1.13.14",
|
|
102
|
-
"material-symbols": "^0.
|
|
103
|
+
"material-symbols": "^0.37.0",
|
|
103
104
|
"md5": "^2.3.0",
|
|
104
105
|
"mime-types": "^3.0.1",
|
|
105
|
-
"monaco-editor": "^0.
|
|
106
|
+
"monaco-editor": "^0.54.0",
|
|
106
107
|
"node-localstorage": "^3.0.5",
|
|
107
108
|
"qtip2": "^3.0.3",
|
|
108
109
|
"spectrum-colorpicker2": "^2.0.10",
|
|
109
110
|
"string-similarity": "^4.0.4",
|
|
110
111
|
"tweakpane": "^3.1.10",
|
|
111
112
|
"update-electron-app": "^3.1.1",
|
|
112
|
-
"x_ite": "^12.1.
|
|
113
|
-
"x3d-traverse": "^1.0.
|
|
113
|
+
"x_ite": "^12.1.2",
|
|
114
|
+
"x3d-traverse": "^1.0.22"
|
|
114
115
|
}
|
|
115
116
|
}
|
|
@@ -180,10 +180,19 @@ module .exports = class Dashboard extends Interface
|
|
|
180
180
|
for (const node of nodes)
|
|
181
181
|
outlineEditor .expandTo (node, { expandObject: true, expandAll: true });
|
|
182
182
|
|
|
183
|
-
const elements = nodes .map (node => outlineEditor .sceneGraph
|
|
183
|
+
const elements = nodes .map (node => outlineEditor .sceneGraph
|
|
184
|
+
.find (`:is(.node, .imported-node.proxy)[node-id="${node .getId ()}"]`));
|
|
184
185
|
|
|
185
|
-
|
|
186
|
-
|
|
186
|
+
outlineEditor .deselectAll ({ target: false });
|
|
187
|
+
|
|
188
|
+
for (const element of elements)
|
|
189
|
+
{
|
|
190
|
+
if (element .is (".node"))
|
|
191
|
+
outlineEditor .selectNodeElement (element, { add: true });
|
|
192
|
+
|
|
193
|
+
else if (element .is (".imported-node.proxy"))
|
|
194
|
+
outlineEditor .selectPrimaryElement (element, { add: true });
|
|
195
|
+
}
|
|
187
196
|
|
|
188
197
|
// Scroll element into view.
|
|
189
198
|
// Hide scrollbars during scroll to prevent overlay issue.
|
|
@@ -55,6 +55,7 @@ module .exports = class Document extends Interface
|
|
|
55
55
|
*/
|
|
56
56
|
async initialize ()
|
|
57
57
|
{
|
|
58
|
+
$("html") .attr ("platform", process .platform);
|
|
58
59
|
$("body") .addClass ("modal");
|
|
59
60
|
|
|
60
61
|
// Actions
|
|
@@ -184,6 +185,10 @@ module .exports = class Document extends Interface
|
|
|
184
185
|
|
|
185
186
|
// Restore
|
|
186
187
|
|
|
188
|
+
const pkg = require ("../../package.json");
|
|
189
|
+
|
|
190
|
+
console .info (`Welcome to ${pkg .productName} v${pkg .version}.`);
|
|
191
|
+
|
|
187
192
|
await this .restoreFile ();
|
|
188
193
|
|
|
189
194
|
if (!this .isInitialScene)
|
|
@@ -319,8 +324,8 @@ module .exports = class Document extends Interface
|
|
|
319
324
|
|
|
320
325
|
const activeElement = this .activeElement;
|
|
321
326
|
|
|
322
|
-
if (activeElement .is ("input"))
|
|
323
|
-
return
|
|
327
|
+
if (activeElement .is ("input:not([type]), input[type=text]"))
|
|
328
|
+
return true;
|
|
324
329
|
|
|
325
330
|
if (activeElement .is ("textarea"))
|
|
326
331
|
return true;
|
|
@@ -451,16 +456,16 @@ Viewpoint {
|
|
|
451
456
|
pkg = require ("../../package.json"),
|
|
452
457
|
generator = scene .getMetaData ("generator") ?.filter (value => !value .startsWith (pkg .productName)) ?? [ ];
|
|
453
458
|
|
|
454
|
-
generator .
|
|
455
|
-
|
|
456
|
-
if (!scene .getMetaData ("created"))
|
|
457
|
-
scene .setMetaData ("created", new Date () .toUTCString ());
|
|
459
|
+
generator .unshift (`${pkg .productName} V${pkg .version}, ${pkg .homepage}`);
|
|
458
460
|
|
|
459
461
|
if (!scene .getMetaData ("creator") ?.some (value => value .includes (this .fullname)))
|
|
460
462
|
scene .addMetaData ("creator", this .fullname);
|
|
461
463
|
|
|
462
|
-
scene .
|
|
464
|
+
if (!scene .getMetaData ("created"))
|
|
465
|
+
scene .setMetaData ("created", new Date () .toUTCString ());
|
|
466
|
+
|
|
463
467
|
scene .setMetaData ("modified", new Date () .toUTCString ());
|
|
468
|
+
scene .setMetaData ("generator", generator);
|
|
464
469
|
|
|
465
470
|
// Save source code.
|
|
466
471
|
|
|
@@ -630,7 +635,7 @@ Viewpoint {
|
|
|
630
635
|
if (this .activeElementIsMonacoEditor ())
|
|
631
636
|
return;
|
|
632
637
|
|
|
633
|
-
this .sidebar .outlineEditor .copyNodes (
|
|
638
|
+
this .sidebar .outlineEditor .copyNodes ();
|
|
634
639
|
return false;
|
|
635
640
|
}
|
|
636
641
|
|
|
@@ -36,8 +36,8 @@ module .exports = new class Hierarchy extends Interface
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
#targetTypes = new Set ([
|
|
39
|
-
X3D .X3DConstants .X3DShapeNode,
|
|
40
39
|
X3D .X3DConstants .Inline,
|
|
40
|
+
X3D .X3DConstants .X3DShapeNode,
|
|
41
41
|
]);
|
|
42
42
|
|
|
43
43
|
target (node)
|
|
@@ -70,10 +70,17 @@ module .exports = new class Hierarchy extends Interface
|
|
|
70
70
|
|
|
71
71
|
const node = object .getValue () .valueOf ();
|
|
72
72
|
|
|
73
|
-
if (!node .getType () .some (type => this .#targetTypes .has (type))
|
|
73
|
+
if (!node .getType () .some (type => this .#targetTypes .has (type)) &&
|
|
74
|
+
!(node instanceof X3D .X3DImportedNodeProxy))
|
|
75
|
+
{
|
|
74
76
|
continue;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const target = node .getType () .includes (X3D .X3DConstants .X3DShapeNode)
|
|
80
|
+
? node .getGeometry () ?.valueOf () ?? node
|
|
81
|
+
: node;
|
|
75
82
|
|
|
76
|
-
targets .push (
|
|
83
|
+
targets .push (target);
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
for (const hierarchy of this .#find (targets))
|
|
@@ -40,7 +40,7 @@ $.fn.addPrototypePopover = function (executionContext, type)
|
|
|
40
40
|
.appendTo (content);
|
|
41
41
|
|
|
42
42
|
const nameInput = $("<input></input>")
|
|
43
|
-
.attr ("placeholder", _("Enter name"))
|
|
43
|
+
.attr ("placeholder", _("Enter a name"))
|
|
44
44
|
.appendTo (content);
|
|
45
45
|
|
|
46
46
|
// Create tooltip.
|
|
@@ -55,7 +55,7 @@ $.fn.addPrototypePopover = function (executionContext, type)
|
|
|
55
55
|
electron .shell .beep ();
|
|
56
56
|
nameInput .highlight ();
|
|
57
57
|
})
|
|
58
|
-
.on ("keydown
|
|
58
|
+
.on ("keydown", event =>
|
|
59
59
|
{
|
|
60
60
|
if (event .key !== "Enter")
|
|
61
61
|
return;
|
|
@@ -12,7 +12,8 @@ $.fn.animationPropertiesPopover = function (editor)
|
|
|
12
12
|
{
|
|
13
13
|
// Create content.
|
|
14
14
|
|
|
15
|
-
const content = $("<div></div>")
|
|
15
|
+
const content = $("<div></div>")
|
|
16
|
+
.css ("width", "200px");
|
|
16
17
|
|
|
17
18
|
$("<span></span>")
|
|
18
19
|
.text (_("Frames"))
|
|
@@ -35,6 +36,7 @@ $.fn.animationPropertiesPopover = function (editor)
|
|
|
35
36
|
.attr ("type", "number")
|
|
36
37
|
.attr ("step", 1)
|
|
37
38
|
.attr ("min", 1)
|
|
39
|
+
.attr ("max", 60)
|
|
38
40
|
.attr ("placeholder", _("Enter frame rate"))
|
|
39
41
|
.val (editor .getFrameRate ())
|
|
40
42
|
.on ("change input", updateTime)
|
|
@@ -84,6 +86,15 @@ $.fn.animationPropertiesPopover = function (editor)
|
|
|
84
86
|
events: {
|
|
85
87
|
show: (event, api) =>
|
|
86
88
|
{
|
|
89
|
+
content .children () .off () .on ("keydown", (event) =>
|
|
90
|
+
{
|
|
91
|
+
if (event .key !== "Enter")
|
|
92
|
+
return;
|
|
93
|
+
|
|
94
|
+
applyButton .trigger ("click");
|
|
95
|
+
api .toggle (false);
|
|
96
|
+
})
|
|
97
|
+
|
|
87
98
|
applyButton .on ("click", (event) =>
|
|
88
99
|
{
|
|
89
100
|
api .toggle (false);
|
package/src/Controls/Dialog.js
CHANGED
|
@@ -47,9 +47,12 @@ module .exports = class Dialog extends Interface
|
|
|
47
47
|
{
|
|
48
48
|
// Set default config values.
|
|
49
49
|
|
|
50
|
+
defaults .minSize ??= defaults .size;
|
|
51
|
+
|
|
50
52
|
this .config .file .setDefaultValues (Object .assign ({
|
|
51
53
|
position: undefined,
|
|
52
54
|
size: [400, 250],
|
|
55
|
+
minSize: [400, 250],
|
|
53
56
|
},
|
|
54
57
|
defaults));
|
|
55
58
|
}
|
|
@@ -58,8 +61,8 @@ module .exports = class Dialog extends Interface
|
|
|
58
61
|
{
|
|
59
62
|
this .element .dialog ({
|
|
60
63
|
position: { ... this .config .file .position, of: $("body") },
|
|
61
|
-
minWidth: this .config .file .
|
|
62
|
-
minHeight: this .config .file .
|
|
64
|
+
minWidth: this .config .file .minSize [0],
|
|
65
|
+
minHeight: this .config .file .minSize [1],
|
|
63
66
|
width: this .config .file .size [0],
|
|
64
67
|
height: this .config .file .size [1],
|
|
65
68
|
})
|
|
@@ -19,7 +19,7 @@ $.fn.editNodePopover = function (node)
|
|
|
19
19
|
.appendTo (content);
|
|
20
20
|
|
|
21
21
|
const nameInput = $("<input></input>")
|
|
22
|
-
.attr ("placeholder", _("Enter name"))
|
|
22
|
+
.attr ("placeholder", _("Enter a name"))
|
|
23
23
|
.appendTo (content);
|
|
24
24
|
|
|
25
25
|
if (node instanceof X3D .X3DProtoDeclaration)
|
|
@@ -97,7 +97,7 @@ $.fn.editUserDefinedFieldPopover = function (executionContext, node, field = -1)
|
|
|
97
97
|
.appendTo (content);
|
|
98
98
|
|
|
99
99
|
const nameInput = $("<input></input>")
|
|
100
|
-
.attr ("placeholder", _("Enter name"))
|
|
100
|
+
.attr ("placeholder", _("Enter a name"))
|
|
101
101
|
.appendTo (content);
|
|
102
102
|
|
|
103
103
|
if (field instanceof X3D .X3DField)
|
|
@@ -139,7 +139,7 @@ module .exports = class AnimationEditor extends Interface
|
|
|
139
139
|
.attr ("min", 0)
|
|
140
140
|
.attr ("max", 0)
|
|
141
141
|
.attr ("title", _("Current frame."))
|
|
142
|
-
.css ("width", "
|
|
142
|
+
.css ("width", "70px")
|
|
143
143
|
.appendTo (this .toolbar)
|
|
144
144
|
.on ("change input", () => this .setCurrentFrame (this .getCurrentFrame ()));
|
|
145
145
|
|
|
@@ -166,7 +166,7 @@ module .exports = class AnimationEditor extends Interface
|
|
|
166
166
|
this .timeElement = $("<span></span>")
|
|
167
167
|
.addClass (["text", "right"])
|
|
168
168
|
.attr ("title", _("Current frame time (hours:minutes:seconds:frames)."))
|
|
169
|
-
.css ("top", "
|
|
169
|
+
.css ("top", "7.5px")
|
|
170
170
|
.css ("margin-right", "6px")
|
|
171
171
|
.text (this .formatFrames (0, 10))
|
|
172
172
|
.appendTo (this .toolbar);
|
|
@@ -315,8 +315,10 @@ module .exports = class AnimationEditor extends Interface
|
|
|
315
315
|
this .timeSensor ._isActive .removeInterest ("set_active", this);
|
|
316
316
|
this .timeSensor ._fraction_changed .removeInterest ("set_fraction", this);
|
|
317
317
|
|
|
318
|
-
this .timeSensor ._evenLive
|
|
319
|
-
this .timeSensor ._range
|
|
318
|
+
this .timeSensor ._evenLive = false;
|
|
319
|
+
this .timeSensor ._range = [0, 0, 1];
|
|
320
|
+
this .timeSensor ._resumeTime = 0;
|
|
321
|
+
this .timeSensor ._pauseTime = 0;
|
|
320
322
|
|
|
321
323
|
if (this .timeSensor ._loop .getValue () && this .timeSensor ._isActive .getValue ())
|
|
322
324
|
{
|
|
@@ -358,8 +360,6 @@ module .exports = class AnimationEditor extends Interface
|
|
|
358
360
|
this .set_loop (this .timeSensor ._loop);
|
|
359
361
|
this .set_active (this .timeSensor ._isActive);
|
|
360
362
|
|
|
361
|
-
this .updateRange ();
|
|
362
|
-
|
|
363
363
|
// Show Member List
|
|
364
364
|
|
|
365
365
|
this .animation ._children .addInterest ("updateMemberList", this);
|
|
@@ -405,8 +405,9 @@ module .exports = class AnimationEditor extends Interface
|
|
|
405
405
|
|
|
406
406
|
this .setSelection (require ("../Application/Selection"));
|
|
407
407
|
this .zoomFit ();
|
|
408
|
-
this .setCurrentFrame (0);
|
|
409
408
|
this .requestDrawTimeline ();
|
|
409
|
+
|
|
410
|
+
this .browser .nextFrame () .then (() => this .setCurrentFrame (0));
|
|
410
411
|
}
|
|
411
412
|
|
|
412
413
|
enableIcons (enabled)
|
|
@@ -704,9 +705,12 @@ module .exports = class AnimationEditor extends Interface
|
|
|
704
705
|
|
|
705
706
|
for (const route of interpolator ._value_changed .getOutputRoutes ())
|
|
706
707
|
{
|
|
707
|
-
const
|
|
708
|
-
|
|
709
|
-
|
|
708
|
+
const node = route .getDestinationNode ();
|
|
709
|
+
|
|
710
|
+
if (!(node instanceof X3D .X3DNode))
|
|
711
|
+
continue;
|
|
712
|
+
|
|
713
|
+
const field = node .getField (route .getDestinationField ());
|
|
710
714
|
|
|
711
715
|
this .members .add (node);
|
|
712
716
|
this .fields .set (field, interpolator);
|
|
@@ -1916,15 +1920,24 @@ module .exports = class AnimationEditor extends Interface
|
|
|
1916
1920
|
|
|
1917
1921
|
if (selectionRange [0] === selectionRange [1])
|
|
1918
1922
|
{
|
|
1919
|
-
this .timeSensor ._range [1]
|
|
1920
|
-
|
|
1923
|
+
if (this .timeSensor ._range [1] !== 0 && this .timeSensor ._range [2] !== 1)
|
|
1924
|
+
{
|
|
1925
|
+
this .timeSensor ._range [1] = 0;
|
|
1926
|
+
this .timeSensor ._range [2] = 1;
|
|
1927
|
+
}
|
|
1921
1928
|
}
|
|
1922
1929
|
else
|
|
1923
1930
|
{
|
|
1924
|
-
const
|
|
1931
|
+
const
|
|
1932
|
+
duration = this .getDuration (),
|
|
1933
|
+
begin = selectionRange [0] / duration,
|
|
1934
|
+
end = selectionRange [1] / duration;
|
|
1925
1935
|
|
|
1926
|
-
this .timeSensor ._range [1]
|
|
1927
|
-
|
|
1936
|
+
if (this .timeSensor ._range [1] !== begin && this .timeSensor ._range [2] !== end)
|
|
1937
|
+
{
|
|
1938
|
+
this .timeSensor ._range [1] = begin;
|
|
1939
|
+
this .timeSensor ._range [2] = end;
|
|
1940
|
+
}
|
|
1928
1941
|
}
|
|
1929
1942
|
}
|
|
1930
1943
|
|
|
@@ -2319,10 +2332,7 @@ module .exports = class AnimationEditor extends Interface
|
|
|
2319
2332
|
|
|
2320
2333
|
const pickedKeyframes = this .pickKeyframes ();
|
|
2321
2334
|
|
|
2322
|
-
|
|
2323
|
-
this .setCurrentFrame (this .getFrameFromPointer (this .pointer .x));
|
|
2324
|
-
|
|
2325
|
-
this .startMovingFrame = this .getFrameFromPointer (this .pointer .x);
|
|
2335
|
+
this .startMovingFrame = this .getFrameFromPointer ();
|
|
2326
2336
|
|
|
2327
2337
|
if (event .shiftKey && pickedKeyframes .length)
|
|
2328
2338
|
{
|
|
@@ -2330,34 +2340,49 @@ module .exports = class AnimationEditor extends Interface
|
|
|
2330
2340
|
}
|
|
2331
2341
|
else if (event .shiftKey)
|
|
2332
2342
|
{
|
|
2343
|
+
const frame = this .getFrameFromPointer ();
|
|
2344
|
+
|
|
2345
|
+
this .timeSensor ._pauseTime = Date .now () / 1000;
|
|
2346
|
+
|
|
2333
2347
|
this .setPickedKeyframes ([ ]);
|
|
2334
2348
|
this .setSelectedKeyframes ([ ]);
|
|
2335
|
-
this .expandSelectionRange (
|
|
2349
|
+
this .expandSelectionRange (frame);
|
|
2336
2350
|
}
|
|
2337
2351
|
else
|
|
2338
2352
|
{
|
|
2353
|
+
this .timeSensor ._pauseTime = Date .now () / 1000;
|
|
2354
|
+
|
|
2339
2355
|
if (!pickedKeyframes .length || !pickedKeyframes .every (p => this .getSelectedKeyframes () .some (s => this .equalKeyframe (p, s))))
|
|
2340
2356
|
{
|
|
2357
|
+
// There are not picked keyframes or an unselected keyframe is picked.
|
|
2358
|
+
|
|
2359
|
+
const frame = this .getFrameFromPointer ();
|
|
2360
|
+
|
|
2361
|
+
if (!pickedKeyframes .length)
|
|
2362
|
+
this .setCurrentFrame (frame);
|
|
2363
|
+
|
|
2341
2364
|
this .setPickedKeyframes (pickedKeyframes);
|
|
2342
2365
|
this .setSelectedKeyframes (pickedKeyframes);
|
|
2343
|
-
this .setSelectionRange (
|
|
2366
|
+
this .setSelectionRange (frame, frame);
|
|
2344
2367
|
}
|
|
2345
2368
|
else
|
|
2346
2369
|
{
|
|
2370
|
+
// A selected keyframe is picked.
|
|
2371
|
+
|
|
2347
2372
|
this .setPickedKeyframes (this .getSelectedKeyframes ());
|
|
2348
2373
|
}
|
|
2349
2374
|
}
|
|
2350
2375
|
|
|
2351
|
-
this .timeSensor ._pauseTime = Date .now () / 1000;
|
|
2352
2376
|
break;
|
|
2353
2377
|
}
|
|
2354
2378
|
}
|
|
2355
2379
|
}
|
|
2356
2380
|
|
|
2357
|
-
on_mouseup ()
|
|
2381
|
+
on_mouseup (event)
|
|
2358
2382
|
{
|
|
2359
2383
|
$(document) .off (".AnimationEditor");
|
|
2360
2384
|
|
|
2385
|
+
this .updatePointer (event);
|
|
2361
2386
|
this .removeAutoScroll ();
|
|
2362
2387
|
|
|
2363
2388
|
if (this .#movingKeyframesOffset)
|
|
@@ -2425,9 +2450,9 @@ module .exports = class AnimationEditor extends Interface
|
|
|
2425
2450
|
this .requestDrawTimeline ();
|
|
2426
2451
|
}
|
|
2427
2452
|
|
|
2428
|
-
getFrameFromPointer (
|
|
2453
|
+
getFrameFromPointer (x = this .pointer .x)
|
|
2429
2454
|
{
|
|
2430
|
-
const frame = Math .round ((
|
|
2455
|
+
const frame = Math .round ((x - this .getTranslation ()) / this .getScale ());
|
|
2431
2456
|
|
|
2432
2457
|
return X3D .Algorithm .clamp (frame, 0, this .getDuration ());
|
|
2433
2458
|
}
|
|
@@ -2492,10 +2517,6 @@ module .exports = class AnimationEditor extends Interface
|
|
|
2492
2517
|
|
|
2493
2518
|
this .#defaultIntegers .length = 0;
|
|
2494
2519
|
|
|
2495
|
-
const
|
|
2496
|
-
translation = this .getTranslation (),
|
|
2497
|
-
scale = this .getScale ();
|
|
2498
|
-
|
|
2499
2520
|
const
|
|
2500
2521
|
key = interpolator .getMetaData ("Interpolator/key", this .#defaultIntegers),
|
|
2501
2522
|
first = X3D .Algorithm .lowerBound (key, 0, key .length, firstFrame),
|
|
@@ -2627,10 +2648,13 @@ module .exports = class AnimationEditor extends Interface
|
|
|
2627
2648
|
|
|
2628
2649
|
setSelectionRange (start, end)
|
|
2629
2650
|
{
|
|
2651
|
+
if (start !== end || this .#selectionRange [0] !== this .#selectionRange [1])
|
|
2652
|
+
this .setCurrentFrame (this .getFrameFromPointer ());
|
|
2653
|
+
|
|
2630
2654
|
this .#selectionRange = [start, end];
|
|
2631
2655
|
|
|
2632
|
-
this .selectKeyframesInRange ();
|
|
2633
2656
|
this .updateRange ();
|
|
2657
|
+
this .selectKeyframesInRange ();
|
|
2634
2658
|
this .requestDrawTimeline ();
|
|
2635
2659
|
}
|
|
2636
2660
|
|
|
@@ -2674,20 +2698,20 @@ module .exports = class AnimationEditor extends Interface
|
|
|
2674
2698
|
{
|
|
2675
2699
|
// Move keyframes or select range.
|
|
2676
2700
|
|
|
2701
|
+
const frame = this .getFrameFromPointer ();
|
|
2702
|
+
|
|
2677
2703
|
if (this .getPickedKeyframes () .length)
|
|
2678
2704
|
{
|
|
2679
|
-
this .#movingKeyframesOffset =
|
|
2705
|
+
this .#movingKeyframesOffset = frame - this .startMovingFrame;
|
|
2680
2706
|
}
|
|
2681
2707
|
else
|
|
2682
2708
|
{
|
|
2683
2709
|
// Select range.
|
|
2684
2710
|
|
|
2685
|
-
this .setCurrentFrame (this .getFrameFromPointer (this .pointer .x));
|
|
2686
|
-
|
|
2687
2711
|
if (event ?.shiftKey)
|
|
2688
|
-
this .expandSelectionRange (
|
|
2712
|
+
this .expandSelectionRange (frame);
|
|
2689
2713
|
else
|
|
2690
|
-
this .setSelectionRange (this .#selectionRange [0],
|
|
2714
|
+
this .setSelectionRange (this .#selectionRange [0], frame);
|
|
2691
2715
|
}
|
|
2692
2716
|
}
|
|
2693
2717
|
|
|
@@ -2952,43 +2976,25 @@ module .exports = class AnimationEditor extends Interface
|
|
|
2952
2976
|
{
|
|
2953
2977
|
case "main":
|
|
2954
2978
|
{
|
|
2955
|
-
const
|
|
2956
|
-
.every (field => this .getSelectedKeyframes () .some (keyframe => field === keyframe .field));
|
|
2957
|
-
|
|
2958
|
-
if (allSelected)
|
|
2959
|
-
{
|
|
2960
|
-
for (const field of this .fields .keys ())
|
|
2961
|
-
{
|
|
2962
|
-
this .drawSelectedKeyframes (context, field, bottom - this .TRACK_PADDING, red);
|
|
2963
|
-
break;
|
|
2964
|
-
}
|
|
2965
|
-
}
|
|
2979
|
+
const fields = new Set (this .fields .keys ())
|
|
2966
2980
|
|
|
2981
|
+
this .drawSelectedKeyframes (context, fields, bottom - this .TRACK_PADDING, red);
|
|
2967
2982
|
break;
|
|
2968
2983
|
}
|
|
2969
2984
|
case "node":
|
|
2970
2985
|
{
|
|
2971
2986
|
const
|
|
2972
2987
|
node = item .data ("node"),
|
|
2973
|
-
fields =
|
|
2974
|
-
|
|
2975
|
-
const allSelected = fields
|
|
2976
|
-
.every (field => this .getSelectedKeyframes () .some (keyframe => field === keyframe .field));
|
|
2977
|
-
|
|
2978
|
-
if (allSelected)
|
|
2979
|
-
{
|
|
2980
|
-
for (const field of fields)
|
|
2981
|
-
{
|
|
2982
|
-
this .drawSelectedKeyframes (context, field, bottom - this .TRACK_PADDING, red);
|
|
2983
|
-
break;
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
2988
|
+
fields = new Set (node .getFields ());
|
|
2986
2989
|
|
|
2990
|
+
this .drawSelectedKeyframes (context, fields, bottom - this .TRACK_PADDING, red);
|
|
2987
2991
|
break;
|
|
2988
2992
|
}
|
|
2989
2993
|
case "field":
|
|
2990
2994
|
{
|
|
2991
|
-
|
|
2995
|
+
const fields = new Set ([item .data ("field")]);
|
|
2996
|
+
|
|
2997
|
+
this .drawSelectedKeyframes (context, fields, bottom - this .TRACK_PADDING, red);
|
|
2992
2998
|
break;
|
|
2993
2999
|
}
|
|
2994
3000
|
}
|
|
@@ -3012,6 +3018,7 @@ module .exports = class AnimationEditor extends Interface
|
|
|
3012
3018
|
}
|
|
3013
3019
|
|
|
3014
3020
|
#defaultIntegers = new X3D .MFInt32 ();
|
|
3021
|
+
#frames = [ ];
|
|
3015
3022
|
|
|
3016
3023
|
drawKeyframes (context, field, firstFrame, lastFrame, bottom, color)
|
|
3017
3024
|
{
|
|
@@ -3022,10 +3029,7 @@ module .exports = class AnimationEditor extends Interface
|
|
|
3022
3029
|
|
|
3023
3030
|
this .#defaultIntegers .length = 0;
|
|
3024
3031
|
|
|
3025
|
-
const
|
|
3026
|
-
left = this .getLeft (),
|
|
3027
|
-
translation = this .getTranslation (),
|
|
3028
|
-
scale = this .getScale ();
|
|
3032
|
+
const left = this .getLeft ();
|
|
3029
3033
|
|
|
3030
3034
|
const
|
|
3031
3035
|
key = interpolator .getMetaData ("Interpolator/key", this .#defaultIntegers),
|
|
@@ -3044,24 +3048,52 @@ module .exports = class AnimationEditor extends Interface
|
|
|
3044
3048
|
}
|
|
3045
3049
|
}
|
|
3046
3050
|
|
|
3047
|
-
drawSelectedKeyframes (context,
|
|
3051
|
+
drawSelectedKeyframes (context, fields, bottom, selectedColor)
|
|
3048
3052
|
{
|
|
3053
|
+
if (!this .getSelectedKeyframes () .length)
|
|
3054
|
+
return;
|
|
3055
|
+
|
|
3049
3056
|
const
|
|
3050
|
-
left
|
|
3051
|
-
|
|
3052
|
-
scale = this .getScale ();
|
|
3057
|
+
left = this .getLeft (),
|
|
3058
|
+
frames = this .#frames;
|
|
3053
3059
|
|
|
3054
|
-
|
|
3060
|
+
frames .length = 0;
|
|
3061
|
+
|
|
3062
|
+
// Count keyframes to avoid overdrawing.
|
|
3063
|
+
|
|
3064
|
+
for (const field of fields)
|
|
3055
3065
|
{
|
|
3056
|
-
|
|
3066
|
+
const interpolator = this .fields .get (field);
|
|
3067
|
+
|
|
3068
|
+
if (!interpolator)
|
|
3057
3069
|
continue;
|
|
3058
3070
|
|
|
3059
3071
|
this .#defaultIntegers .length = 0;
|
|
3060
3072
|
|
|
3073
|
+
const key = interpolator .getMetaData ("Interpolator/key", this .#defaultIntegers);
|
|
3074
|
+
|
|
3075
|
+
for (const frame of key)
|
|
3076
|
+
frames [frame] = (frames [frame] ?? 0) + 1;
|
|
3077
|
+
}
|
|
3078
|
+
|
|
3079
|
+
// Draw keyframes.
|
|
3080
|
+
|
|
3081
|
+
for (const { field, interpolator, index } of this .getSelectedKeyframes ())
|
|
3082
|
+
{
|
|
3083
|
+
if (!fields .has (field))
|
|
3084
|
+
continue
|
|
3085
|
+
|
|
3086
|
+
this .#defaultIntegers .length = 0;
|
|
3087
|
+
|
|
3061
3088
|
const key = interpolator .getMetaData ("Interpolator/key", this .#defaultIntegers);
|
|
3062
|
-
const frame = key [index]
|
|
3063
|
-
|
|
3064
|
-
|
|
3089
|
+
const frame = key [index];
|
|
3090
|
+
|
|
3091
|
+
if (-- frames [frame])
|
|
3092
|
+
continue;
|
|
3093
|
+
|
|
3094
|
+
const moving = frame + this .#movingKeyframesOffset;
|
|
3095
|
+
const x = Math .floor (left + this .getPointerFromFrame (moving));
|
|
3096
|
+
const x1 = x - (this .FRAME_SIZE / 2) + 0.5;
|
|
3065
3097
|
|
|
3066
3098
|
context .fillStyle = selectedColor;
|
|
3067
3099
|
|
|
@@ -142,7 +142,7 @@ module .exports = class AnimationMembersList extends Interface
|
|
|
142
142
|
|
|
143
143
|
addNodes (nodes)
|
|
144
144
|
{
|
|
145
|
-
nodes = nodes .filter (node => !this .#nodes .includes (node));
|
|
145
|
+
nodes = nodes .map (node => node .valueOf ()) .filter (node => !this .#nodes .includes (node .valueOf ()));
|
|
146
146
|
|
|
147
147
|
let i = this .#nodes .length;
|
|
148
148
|
|
|
@@ -286,7 +286,7 @@ module .exports = class AnimationMembersList extends Interface
|
|
|
286
286
|
|
|
287
287
|
removeNodes (nodes)
|
|
288
288
|
{
|
|
289
|
-
for (const node of nodes)
|
|
289
|
+
for (const node of nodes .map (node => node .valueOf ()))
|
|
290
290
|
{
|
|
291
291
|
this .#list .find (`li[node-id=${node .getId ()}]`) .remove ();
|
|
292
292
|
|