@operato/scene-urdf 1.2.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +41 -0
  3. package/assets/images/spinner.png +0 -0
  4. package/demo/index.html +109 -0
  5. package/dist/editors/index.d.ts +0 -0
  6. package/dist/editors/index.js +2 -0
  7. package/dist/editors/index.js.map +1 -0
  8. package/dist/elements/drag-n-drop.d.ts +2 -0
  9. package/dist/elements/drag-n-drop.js +126 -0
  10. package/dist/elements/drag-n-drop.js.map +1 -0
  11. package/dist/elements/urdf-controller-element.d.ts +12 -0
  12. package/dist/elements/urdf-controller-element.js +283 -0
  13. package/dist/elements/urdf-controller-element.js.map +1 -0
  14. package/dist/elements/urdf-drag-controls.d.ts +32 -0
  15. package/dist/elements/urdf-drag-controls.js +185 -0
  16. package/dist/elements/urdf-drag-controls.js.map +1 -0
  17. package/dist/elements/urdf-manipulator-element.d.ts +15 -0
  18. package/dist/elements/urdf-manipulator-element.js +110 -0
  19. package/dist/elements/urdf-manipulator-element.js.map +1 -0
  20. package/dist/elements/urdf-viewer-element.d.ts +53 -0
  21. package/dist/elements/urdf-viewer-element.js +401 -0
  22. package/dist/elements/urdf-viewer-element.js.map +1 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +3 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/templates/index.d.ts +14 -0
  27. package/dist/templates/index.js +4 -0
  28. package/dist/templates/index.js.map +1 -0
  29. package/dist/templates/urdf-controller.d.ts +14 -0
  30. package/dist/templates/urdf-controller.js +16 -0
  31. package/dist/templates/urdf-controller.js.map +1 -0
  32. package/dist/templates/urdf-viewer.d.ts +14 -0
  33. package/dist/templates/urdf-viewer.js +16 -0
  34. package/dist/templates/urdf-viewer.js.map +1 -0
  35. package/dist/urdf-controller.d.ts +27 -0
  36. package/dist/urdf-controller.js +65 -0
  37. package/dist/urdf-controller.js.map +1 -0
  38. package/dist/urdf-viewer.d.ts +50 -0
  39. package/dist/urdf-viewer.js +198 -0
  40. package/dist/urdf-viewer.js.map +1 -0
  41. package/icons/urdf-controller.png +0 -0
  42. package/icons/urdf-viewer.png +0 -0
  43. package/package.json +66 -0
  44. package/src/editors/index.ts +0 -0
  45. package/src/elements/drag-n-drop.ts +142 -0
  46. package/src/elements/urdf-controller-element.ts +297 -0
  47. package/src/elements/urdf-drag-controls.ts +248 -0
  48. package/src/elements/urdf-manipulator-element.ts +133 -0
  49. package/src/elements/urdf-viewer-element.ts +495 -0
  50. package/src/index.ts +2 -0
  51. package/src/templates/index.ts +4 -0
  52. package/src/templates/urdf-controller.ts +16 -0
  53. package/src/templates/urdf-viewer.ts +16 -0
  54. package/src/urdf-controller.ts +82 -0
  55. package/src/urdf-viewer.ts +249 -0
  56. package/things-scene.config.js +7 -0
  57. package/translations/en.json +16 -0
  58. package/translations/ko.json +16 -0
  59. package/translations/ms.json +16 -0
  60. package/translations/zh.json +16 -0
  61. package/tsconfig.json +22 -0
  62. package/tsconfig.tsbuildinfo +1 -0
  63. package/web-dev-server.config.mjs +27 -0
@@ -0,0 +1,65 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ const NATURE = {
5
+ mutable: false,
6
+ resizable: true,
7
+ rotatable: true,
8
+ properties: [
9
+ {
10
+ type: 'id-input',
11
+ label: 'urdf-reference',
12
+ name: 'reference',
13
+ property: {
14
+ component: 'urdf-viewer'
15
+ }
16
+ }
17
+ ]
18
+ };
19
+ import { Component, HTMLOverlayContainer } from '@hatiolab/things-scene';
20
+ import './elements/urdf-controller-element';
21
+ export default class UrdfController extends HTMLOverlayContainer {
22
+ static get nature() {
23
+ return NATURE;
24
+ }
25
+ oncreate_element(controller) { }
26
+ dispose() {
27
+ super.dispose();
28
+ }
29
+ /*
30
+ * 컴포넌트의 생성 또는 속성 변화 시에 호출되며,
31
+ * 그에 따른 html element의 반영이 필요한 부분을 구현한다.
32
+ *
33
+ * ThingsComponent state => HTML element properties
34
+ */
35
+ setElementProperties(controller) {
36
+ var reference = this.reference;
37
+ controller.viewer = reference ? reference.element : undefined;
38
+ }
39
+ /*
40
+ * 컴포넌트가 ready 상태가 되거나, 컴포넌트의 속성이 변화될 시 setElementProperties 뒤에 호출된다.
41
+ * 변화에 따른 기본적인 html 속성이 super.reposition()에서 진행되고, 그 밖의 작업이 필요할 때, 오버라이드 한다.
42
+ */
43
+ reposition() {
44
+ super.reposition();
45
+ }
46
+ get tagName() {
47
+ return 'urdf-controller';
48
+ }
49
+ get reference() {
50
+ var { reference } = this.state;
51
+ if (!reference) {
52
+ return;
53
+ }
54
+ if (!this._reference) {
55
+ this._reference = this.root.findById(reference);
56
+ }
57
+ return this._reference;
58
+ }
59
+ set reference(reference) {
60
+ delete this._reference;
61
+ this.state.reference = reference;
62
+ }
63
+ }
64
+ Component.register('urdf-controller', UrdfController);
65
+ //# sourceMappingURL=urdf-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urdf-controller.js","sourceRoot":"","sources":["../src/urdf-controller.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,GAAG;IACb,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE;QACV;YACE,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,gBAAgB;YACvB,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE;gBACR,SAAS,EAAE,aAAa;aACzB;SACF;KACF;CACF,CAAA;AAED,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,oCAAoC,CAAA;AAK3C,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,oBAAoB;IAG9D,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,gBAAgB,CAAC,UAAiC,IAAG,CAAC;IAEtD,OAAO;QACL,KAAK,CAAC,OAAO,EAAE,CAAA;IACjB,CAAC;IAED;;;;;OAKG;IACH,oBAAoB,CAAC,UAAiC;QACpD,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAA;QAC9B,UAAU,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAE,SAAS,CAAC,OAAkC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC3F,CAAC;IAED;;;OAGG;IACH,UAAU;QACR,KAAK,CAAC,UAAU,EAAE,CAAA;IACpB,CAAC;IAED,IAAI,OAAO;QACT,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAED,IAAI,SAAS;QACX,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QAC9B,IAAI,CAAC,SAAS,EAAE;YACd,OAAM;SACP;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAe,CAAA;SAC9D;QAED,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED,IAAI,SAAS,CAAC,SAAS;QACrB,OAAO,IAAI,CAAC,UAAU,CAAA;QACtB,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,SAAS,CAAA;IAClC,CAAC;CACF;AAED,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n */\n\nconst NATURE = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n {\n type: 'id-input',\n label: 'urdf-reference',\n name: 'reference',\n property: {\n component: 'urdf-viewer'\n }\n }\n ]\n}\n\nimport { Component, HTMLOverlayContainer } from '@hatiolab/things-scene'\nimport './elements/urdf-controller-element'\nimport URDFControllerElement from './elements/urdf-controller-element'\nimport URDFManipulatorElement from './elements/urdf-manipulator-element'\nimport UrdfViewer from './urdf-viewer'\n\nexport default class UrdfController extends HTMLOverlayContainer {\n _reference?: UrdfViewer\n\n static get nature() {\n return NATURE\n }\n\n oncreate_element(controller: URDFControllerElement) {}\n\n dispose() {\n super.dispose()\n }\n\n /*\n * 컴포넌트의 생성 또는 속성 변화 시에 호출되며,\n * 그에 따른 html element의 반영이 필요한 부분을 구현한다.\n *\n * ThingsComponent state => HTML element properties\n */\n setElementProperties(controller: URDFControllerElement) {\n var reference = this.reference\n controller.viewer = reference ? (reference.element as URDFManipulatorElement) : undefined\n }\n\n /*\n * 컴포넌트가 ready 상태가 되거나, 컴포넌트의 속성이 변화될 시 setElementProperties 뒤에 호출된다.\n * 변화에 따른 기본적인 html 속성이 super.reposition()에서 진행되고, 그 밖의 작업이 필요할 때, 오버라이드 한다.\n */\n reposition() {\n super.reposition()\n }\n\n get tagName() {\n return 'urdf-controller'\n }\n\n get reference() {\n var { reference } = this.state\n if (!reference) {\n return\n }\n\n if (!this._reference) {\n this._reference = this.root.findById(reference) as UrdfViewer\n }\n\n return this._reference\n }\n\n set reference(reference) {\n delete this._reference\n this.state.reference = reference\n }\n}\n\nComponent.register('urdf-controller', UrdfController)\n"]}
@@ -0,0 +1,50 @@
1
+ import { HTMLOverlayElement, Properties } from '@hatiolab/things-scene';
2
+ import './elements/urdf-manipulator-element';
3
+ import URDFManipulatorElement from './elements/urdf-manipulator-element';
4
+ export default class UrdfViewer extends HTMLOverlayElement {
5
+ static get nature(): {
6
+ mutable: boolean;
7
+ resizable: boolean;
8
+ rotatable: boolean;
9
+ properties: ({
10
+ type: string;
11
+ label: string;
12
+ name: string;
13
+ property?: undefined;
14
+ placeholder?: undefined;
15
+ } | {
16
+ type: string;
17
+ label: string;
18
+ name: string;
19
+ property: {
20
+ options: string[];
21
+ step?: undefined;
22
+ max?: undefined;
23
+ min?: undefined;
24
+ };
25
+ placeholder?: undefined;
26
+ } | {
27
+ type: string;
28
+ label: string;
29
+ name: string;
30
+ placeholder: number;
31
+ property: {
32
+ step: number;
33
+ max: number;
34
+ min: number;
35
+ options?: undefined;
36
+ };
37
+ })[];
38
+ 'value-property': string;
39
+ };
40
+ oncreate_element(element: URDFManipulatorElement): void;
41
+ dispose(): void;
42
+ setElementProperties(element: URDFManipulatorElement): void;
43
+ reposition(): void;
44
+ get tagName(): string;
45
+ get angles(): any;
46
+ set angles(angles: any);
47
+ get highlightColor(): string;
48
+ set highlightColor(highlightColor: string);
49
+ onchange(after: Properties, before: Properties): void;
50
+ }
@@ -0,0 +1,198 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import { Component, HTMLOverlayElement } from '@hatiolab/things-scene';
5
+ import * as THREE from 'three';
6
+ import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
7
+ import { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader.js';
8
+ import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
9
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
10
+ import './elements/urdf-manipulator-element';
11
+ const NATURE = {
12
+ mutable: false,
13
+ resizable: true,
14
+ rotatable: true,
15
+ properties: [
16
+ {
17
+ type: 'string',
18
+ label: 'package',
19
+ name: 'package'
20
+ },
21
+ {
22
+ type: 'string',
23
+ label: 'urdf',
24
+ name: 'urdf'
25
+ },
26
+ {
27
+ type: 'select',
28
+ label: 'up',
29
+ name: 'up',
30
+ property: {
31
+ options: ['', '+X', '-X', '+Y', '-Y', '+Z', '-Z']
32
+ }
33
+ },
34
+ {
35
+ type: 'checkbox',
36
+ label: 'display-shadow',
37
+ name: 'displayShadow'
38
+ },
39
+ {
40
+ type: 'color',
41
+ label: 'ambient-color',
42
+ name: 'ambientColor'
43
+ },
44
+ {
45
+ type: 'color',
46
+ label: 'highlight-color',
47
+ name: 'highlightColor'
48
+ },
49
+ {
50
+ type: 'checkbox',
51
+ label: 'ignore-limits',
52
+ name: 'ignoreLimits'
53
+ },
54
+ {
55
+ type: 'checkbox',
56
+ label: 'no-auto-recenter',
57
+ name: 'noAutoRecenter'
58
+ },
59
+ {
60
+ type: 'checkbox',
61
+ label: 'disable-dragging',
62
+ name: 'disableDragging'
63
+ },
64
+ {
65
+ type: 'checkbox',
66
+ label: 'no-camera-control',
67
+ name: 'noCameraControl'
68
+ },
69
+ {
70
+ type: 'range-input',
71
+ label: 'init-camera-pos-x',
72
+ name: 'initCameraPosX',
73
+ placeholder: 1,
74
+ property: {
75
+ step: 0.1,
76
+ max: 180,
77
+ min: -180
78
+ }
79
+ },
80
+ {
81
+ type: 'range-input',
82
+ label: 'init-camera-pos-y',
83
+ name: 'initCameraPosY',
84
+ placeholder: 1,
85
+ property: {
86
+ step: 0.1,
87
+ max: 180,
88
+ min: -180
89
+ }
90
+ },
91
+ {
92
+ type: 'range-input',
93
+ label: 'init-camera-pos-z',
94
+ name: 'initCameraPosZ',
95
+ placeholder: 1,
96
+ property: {
97
+ step: 0.1,
98
+ max: 180,
99
+ min: -180
100
+ }
101
+ }
102
+ ],
103
+ 'value-property': 'angles'
104
+ };
105
+ export default class UrdfViewer extends HTMLOverlayElement {
106
+ static get nature() {
107
+ return NATURE;
108
+ }
109
+ oncreate_element(element) {
110
+ element.addEventListener('angle-change', (e) => {
111
+ this.data = element.angles;
112
+ });
113
+ element.loadMeshFunc = (path, manager, done) => {
114
+ const ext = path.split(/\./g).pop().toLowerCase();
115
+ switch (ext) {
116
+ case 'gltf':
117
+ case 'glb':
118
+ new GLTFLoader(manager).load(path, result => done(result.scene), undefined, err => done(null, err));
119
+ break;
120
+ case 'obj':
121
+ new OBJLoader(manager).load(path, result => done(result), undefined, err => done(null, err));
122
+ break;
123
+ case 'dae':
124
+ new ColladaLoader(manager).load(path, result => done(result.scene), undefined, err => done(null, err));
125
+ break;
126
+ case 'stl':
127
+ new STLLoader(manager).load(path, result => {
128
+ const material = new THREE.MeshPhongMaterial();
129
+ const mesh = new THREE.Mesh(result, material);
130
+ done(mesh);
131
+ }, undefined, err => done(null, err));
132
+ break;
133
+ }
134
+ };
135
+ // initialize first camera position
136
+ var { initCameraPosX = 1, initCameraPosY = 1, initCameraPosZ = 1 } = this.state;
137
+ element.camera.position.set(initCameraPosX, initCameraPosY, initCameraPosZ);
138
+ }
139
+ dispose() {
140
+ super.dispose();
141
+ }
142
+ /*
143
+ * 컴포넌트의 생성 또는 속성 변화 시에 호출되며,
144
+ * 그에 따른 html element의 반영이 필요한 부분을 구현한다.
145
+ *
146
+ * ThingsComponent state => HTML element properties
147
+ */
148
+ setElementProperties(element) {
149
+ var { package: _package, urdf, displayShadow, ignoreLimits, up, ambientColor, highlightColor, noAutoRecenter, disableDragging, noCameraControl, angles } = this.state;
150
+ element.style.pointerEvents = 'auto'; //'inherit'
151
+ element.package = _package;
152
+ element.urdf = urdf;
153
+ element.displayShadow = displayShadow;
154
+ element.ignoreLimits = ignoreLimits;
155
+ element.up = up;
156
+ element.ambientColor = ambientColor;
157
+ element.highlightColor = highlightColor;
158
+ element.noAutoRecenter = noAutoRecenter;
159
+ element.disableDragging = disableDragging;
160
+ element.controls.enabled = !noCameraControl;
161
+ element.angles = angles;
162
+ requestAnimationFrame(() => element.redraw());
163
+ }
164
+ /*
165
+ * 컴포넌트가 ready 상태가 되거나, 컴포넌트의 속성이 변화될 시 setElementProperties 뒤에 호출된다.
166
+ * 변화에 따른 기본적인 html 속성이 super.reposition()에서 진행되고, 그 밖의 작업이 필요할 때, 오버라이드 한다.
167
+ */
168
+ reposition() {
169
+ super.reposition();
170
+ }
171
+ get tagName() {
172
+ return 'urdf-viewer';
173
+ }
174
+ get angles() {
175
+ // return this.element.angles
176
+ return this.state.angles;
177
+ }
178
+ set angles(angles) {
179
+ // this.element.angles = angles
180
+ this.setState({ angles });
181
+ }
182
+ get highlightColor() {
183
+ return this.state.highlightColor;
184
+ }
185
+ set highlightColor(highlightColor) {
186
+ this.setState({ highlightColor });
187
+ }
188
+ onchange(after, before) {
189
+ if ('initCameraPosX' in after || 'initCameraPosY' in after || 'initCameraPosZ' in after) {
190
+ const { initCameraPosX = 1, initCameraPosY = 1, initCameraPosZ = 1 } = this.state;
191
+ this.element &&
192
+ this.element.camera.position.set(initCameraPosX, initCameraPosY, initCameraPosZ);
193
+ }
194
+ super.onchange && super.onchange(after, before);
195
+ }
196
+ }
197
+ Component.register('urdf-viewer', UrdfViewer);
198
+ //# sourceMappingURL=urdf-viewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urdf-viewer.js","sourceRoot":"","sources":["../src/urdf-viewer.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n */\nimport { Component, HTMLOverlayElement, error, Properties } from '@hatiolab/things-scene'\nimport * as THREE from 'three'\nimport { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'\nimport { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader.js'\nimport { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js'\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'\nimport './elements/urdf-manipulator-element'\nimport URDFManipulatorElement from './elements/urdf-manipulator-element'\n\nconst NATURE = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n {\n type: 'string',\n label: 'package',\n name: 'package'\n },\n {\n type: 'string',\n label: 'urdf',\n name: 'urdf'\n },\n {\n type: 'select',\n label: 'up',\n name: 'up',\n property: {\n options: ['', '+X', '-X', '+Y', '-Y', '+Z', '-Z']\n }\n },\n {\n type: 'checkbox',\n label: 'display-shadow',\n name: 'displayShadow'\n },\n {\n type: 'color',\n label: 'ambient-color',\n name: 'ambientColor'\n },\n {\n type: 'color',\n label: 'highlight-color',\n name: 'highlightColor'\n },\n {\n type: 'checkbox',\n label: 'ignore-limits',\n name: 'ignoreLimits'\n },\n {\n type: 'checkbox',\n label: 'no-auto-recenter',\n name: 'noAutoRecenter'\n },\n {\n type: 'checkbox',\n label: 'disable-dragging',\n name: 'disableDragging'\n },\n {\n type: 'checkbox',\n label: 'no-camera-control',\n name: 'noCameraControl'\n },\n {\n type: 'range-input',\n label: 'init-camera-pos-x',\n name: 'initCameraPosX',\n placeholder: 1,\n property: {\n step: 0.1,\n max: 180,\n min: -180\n }\n },\n {\n type: 'range-input',\n label: 'init-camera-pos-y',\n name: 'initCameraPosY',\n placeholder: 1,\n property: {\n step: 0.1,\n max: 180,\n min: -180\n }\n },\n {\n type: 'range-input',\n label: 'init-camera-pos-z',\n name: 'initCameraPosZ',\n placeholder: 1,\n property: {\n step: 0.1,\n max: 180,\n min: -180\n }\n }\n ],\n 'value-property': 'angles'\n}\n\nexport default class UrdfViewer extends HTMLOverlayElement {\n static get nature() {\n return NATURE\n }\n\n oncreate_element(element: URDFManipulatorElement) {\n element.addEventListener('angle-change', (e: Event) => {\n this.data = element.angles\n })\n\n element.loadMeshFunc = (path: string, manager: THREE.LoadingManager, done: (result: any, err?: any) => void) => {\n const ext = path.split(/\\./g).pop()!.toLowerCase()\n switch (ext) {\n case 'gltf':\n case 'glb':\n new GLTFLoader(manager).load(\n path,\n result => done(result.scene),\n undefined,\n err => done(null, err)\n )\n break\n case 'obj':\n new OBJLoader(manager).load(\n path,\n result => done(result),\n undefined,\n err => done(null, err)\n )\n break\n case 'dae':\n new ColladaLoader(manager).load(\n path,\n result => done(result.scene),\n undefined,\n err => done(null, err)\n )\n break\n case 'stl':\n new STLLoader(manager).load(\n path,\n result => {\n const material = new THREE.MeshPhongMaterial()\n const mesh = new THREE.Mesh(result, material)\n done(mesh)\n },\n undefined,\n err => done(null, err)\n )\n break\n }\n }\n\n // initialize first camera position\n var { initCameraPosX = 1, initCameraPosY = 1, initCameraPosZ = 1 } = this.state\n element.camera.position.set(initCameraPosX, initCameraPosY, initCameraPosZ)\n }\n\n dispose() {\n super.dispose()\n }\n\n /*\n * 컴포넌트의 생성 또는 속성 변화 시에 호출되며,\n * 그에 따른 html element의 반영이 필요한 부분을 구현한다.\n *\n * ThingsComponent state => HTML element properties\n */\n setElementProperties(element: URDFManipulatorElement) {\n var {\n package: _package,\n urdf,\n displayShadow,\n ignoreLimits,\n up,\n ambientColor,\n highlightColor,\n noAutoRecenter,\n disableDragging,\n noCameraControl,\n angles\n } = this.state\n\n element.style.pointerEvents = 'auto' //'inherit'\n\n element.package = _package\n element.urdf = urdf\n element.displayShadow = displayShadow\n element.ignoreLimits = ignoreLimits\n element.up = up\n element.ambientColor = ambientColor\n element.highlightColor = highlightColor\n element.noAutoRecenter = noAutoRecenter\n element.disableDragging = disableDragging\n element.controls.enabled = !noCameraControl\n element.angles = angles\n\n requestAnimationFrame(() => element.redraw())\n }\n\n /*\n * 컴포넌트가 ready 상태가 되거나, 컴포넌트의 속성이 변화될 시 setElementProperties 뒤에 호출된다.\n * 변화에 따른 기본적인 html 속성이 super.reposition()에서 진행되고, 그 밖의 작업이 필요할 때, 오버라이드 한다.\n */\n reposition() {\n super.reposition()\n }\n\n get tagName() {\n return 'urdf-viewer'\n }\n\n get angles() {\n // return this.element.angles\n return this.state.angles\n }\n\n set angles(angles) {\n // this.element.angles = angles\n this.setState({ angles })\n }\n\n get highlightColor() {\n return this.state.highlightColor\n }\n\n set highlightColor(highlightColor: string) {\n this.setState({ highlightColor })\n }\n\n onchange(after: Properties, before: Properties) {\n if ('initCameraPosX' in after || 'initCameraPosY' in after || 'initCameraPosZ' in after) {\n const { initCameraPosX = 1, initCameraPosY = 1, initCameraPosZ = 1 } = this.state\n this.element &&\n (this.element as URDFManipulatorElement).camera.position.set(initCameraPosX, initCameraPosY, initCameraPosZ)\n }\n\n super.onchange && super.onchange(after, before)\n }\n}\n\nComponent.register('urdf-viewer', UrdfViewer)\n"]}
Binary file
Binary file
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@operato/scene-urdf",
3
+ "description": "Scene module for manipulating robot simulation through URDF format",
4
+ "author": "heartyoh",
5
+ "version": "1.2.2",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "things-scene": true,
9
+ "publishConfig": {
10
+ "access": "public",
11
+ "@oprato:registry": "https://registry.npmjs.org"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/things-scene/operato-scene.git",
16
+ "directory": "packages/urdf"
17
+ },
18
+ "scripts": {
19
+ "serve": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"things-factory-dev\"",
20
+ "serve:dev": "npm run serve",
21
+ "start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
22
+ "build": "tsc",
23
+ "prepublish": "tsc",
24
+ "lint": "eslint --ext .ts,.html . --ignore-path .gitignore && prettier \"**/*.ts\" --check --ignore-path .gitignore",
25
+ "format": "eslint --ext .ts,.html . --fix --ignore-path .gitignore && prettier \"**/*.ts\" --write --ignore-path .gitignore",
26
+ "migration": "things-factory-migration"
27
+ },
28
+ "dependencies": {
29
+ "@hatiolab/things-scene": "^3.2.0",
30
+ "@operato/styles": "^1.0.0",
31
+ "lit": "^2.5.0",
32
+ "three": "^0.122.0",
33
+ "urdf-loader": "^0.10.4",
34
+ "xacro-parser": "^0.3.9"
35
+ },
36
+ "devDependencies": {
37
+ "@hatiolab/prettier-config": "^1.0.0",
38
+ "@things-factory/builder": "^6.0.0",
39
+ "@things-factory/operato-board": "^6.0.0",
40
+ "@types/tinycolor2": "^1.4.3",
41
+ "@typescript-eslint/eslint-plugin": "^4.33.0",
42
+ "@typescript-eslint/parser": "^4.33.0",
43
+ "@web/dev-server": "^0.1.28",
44
+ "concurrently": "^5.3.0",
45
+ "eslint": "^7.32.0",
46
+ "eslint-config-prettier": "^8.3.0",
47
+ "husky": "^4.3.8",
48
+ "lint-staged": "^10.5.4",
49
+ "prettier": "^2.4.1",
50
+ "tslib": "^2.3.1",
51
+ "typescript": "^4.9.4"
52
+ },
53
+ "prettier": "@hatiolab/prettier-config",
54
+ "husky": {
55
+ "hooks": {
56
+ "pre-commit": "lint-staged"
57
+ }
58
+ },
59
+ "lint-staged": {
60
+ "*.ts": [
61
+ "eslint --fix",
62
+ "prettier --write"
63
+ ]
64
+ },
65
+ "gitHead": "9fa14a34d4629bf22be3184e5826480f52bf2604"
66
+ }
File without changes
@@ -0,0 +1,142 @@
1
+ // Converts a datatransfer structer into an object with all paths and files
2
+
3
+ import URDFViewerElement from './urdf-viewer-element'
4
+
5
+ // listed out. Returns a promise that resolves with the file structure.
6
+ function dataTransferToFiles(dataTransfer: DataTransfer) {
7
+ if (!(dataTransfer instanceof DataTransfer)) {
8
+ throw new Error('Data must be of type "DataTransfer"')
9
+ }
10
+
11
+ const files = {} as any
12
+
13
+ // recurse down the webkit file structure resolving
14
+ // the paths to files names to store in the `files`
15
+ // object
16
+ function recurseDirectory(item: any): Promise<void> {
17
+ if (item.isFile) {
18
+ return new Promise(resolve => {
19
+ item.file((file: any) => {
20
+ files[item.fullPath] = file
21
+ resolve()
22
+ })
23
+ })
24
+ } else {
25
+ const reader = item.createReader()
26
+
27
+ return new Promise(resolve => {
28
+ const promises = [] as any
29
+
30
+ // exhaustively read all the directory entries
31
+ function readNextEntries() {
32
+ reader.readEntries((et: any) => {
33
+ if (et.length === 0) {
34
+ Promise.all(promises).then(() => resolve())
35
+ } else {
36
+ et.forEach((e: any) => {
37
+ promises.push(recurseDirectory(e))
38
+ })
39
+ readNextEntries()
40
+ }
41
+ })
42
+ }
43
+
44
+ readNextEntries()
45
+ })
46
+ }
47
+ }
48
+
49
+ return new Promise(resolve => {
50
+ // Traverse down the tree and add the files into the zip
51
+ // const dtitems = dataTransfer.items && [...dataTransfer.items]
52
+ // const dtfiles = [...dataTransfer.files]
53
+ var dtitems = [] as DataTransferItem[]
54
+ if (dataTransfer.items) {
55
+ for (let i = 0; i < dataTransfer.items.length; i++) {
56
+ dtitems.push(dataTransfer.items[i])
57
+ }
58
+ }
59
+
60
+ var dtfiles = [] as File[]
61
+ if (dataTransfer.files) {
62
+ for (let i = 0; i < dataTransfer.files.length; i++) {
63
+ dtfiles.push(dataTransfer.files[i])
64
+ }
65
+ }
66
+
67
+ if (dtitems.length && (dtitems[0].webkitGetAsEntry as any)) {
68
+ const promises = []
69
+ for (let i = 0; i < dtitems.length; i++) {
70
+ const item = dtitems[i]
71
+ const entry = item.webkitGetAsEntry()
72
+
73
+ promises.push(recurseDirectory(entry))
74
+ }
75
+ Promise.all(promises).then(() => resolve(files))
76
+ } else {
77
+ // add a '/' prefix to math the file directory entry
78
+ // on webkit browsers
79
+ dtfiles.filter(f => f.size !== 0).forEach(f => (files['/' + f.name] = f))
80
+
81
+ resolve(files)
82
+ }
83
+ })
84
+ }
85
+
86
+ export function registerDragEvents(viewer: URDFViewerElement, callback: () => void) {
87
+ document.addEventListener('dragover', e => e.preventDefault())
88
+ document.addEventListener('dragenter', e => e.preventDefault())
89
+ document.addEventListener('drop', e => {
90
+ e.preventDefault()
91
+
92
+ // convert the files
93
+ dataTransferToFiles(e.dataTransfer!).then((files: any) => {
94
+ // removes '..' and '.' tokens and normalizes slashes
95
+ const cleanFilePath = (path: string) => {
96
+ return path
97
+ .replace(/\\/g, '/')
98
+ .split(/\//g)
99
+ .reduce((acc, el) => {
100
+ if (el === '..') acc.pop()
101
+ else if (el !== '.') acc.push(el)
102
+ return acc
103
+ }, [] as string[])
104
+ .join('/')
105
+ }
106
+
107
+ // set the loader url modifier to check the list
108
+ // of files
109
+ const fileNames = Object.keys(files).map(n => cleanFilePath(n))
110
+ viewer.urlModifierFunc = (url: string) => {
111
+ // find the matching file given the requested url
112
+ const cleaned = cleanFilePath(url.replace(viewer.package, ''))
113
+ const fileName = fileNames
114
+ .filter(name => {
115
+ // check if the end of file and url are the same
116
+ const len = Math.min(name.length, cleaned.length)
117
+ return cleaned.substr(cleaned.length - len) === name.substr(name.length - len)
118
+ })
119
+ .pop()
120
+
121
+ if (fileName !== undefined) {
122
+ // revoke the url after it's been used
123
+ const bloburl = URL.createObjectURL(files[fileName])
124
+ requestAnimationFrame(() => URL.revokeObjectURL(bloburl))
125
+
126
+ return bloburl
127
+ }
128
+
129
+ return url
130
+ }
131
+
132
+ // set the source of the element to the most likely intended display model
133
+ const filesNames = Object.keys(files)
134
+ viewer.up = '+Z'
135
+ ;(document.getElementById('up-select') as any)!.value = viewer.up
136
+
137
+ viewer.urdf = filesNames.filter(n => /urdf$/i.test(n)).shift()!
138
+ })
139
+
140
+ callback()
141
+ })
142
+ }