@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
package/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ### [1.2.2](https://github.com/things-scene/operato-scene/compare/v1.2.1...v1.2.2) (2023-02-09)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * migrate scene-urdf from things-factory ([3f75f87](https://github.com/things-scene/operato-scene/commit/3f75f8743e993a9a3ed595eed8f94b15da042a31))
package/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # \<scene-urdf>
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ npm i scene-urdf
7
+ ```
8
+
9
+ ## Usage
10
+
11
+ ```html
12
+
13
+ ```
14
+
15
+ ## Linting and formatting
16
+
17
+ To scan the project for linting and formatting errors, run
18
+
19
+ ```bash
20
+ npm run lint
21
+ ```
22
+
23
+ To automatically fix linting and formatting errors, run
24
+
25
+ ```bash
26
+ npm run format
27
+ ```
28
+
29
+ ## Tooling configs
30
+
31
+ For most of the tools, the configuration is in the `package.json` to reduce the amount of files in your project.
32
+
33
+ If you customize the configuration a lot, you can consider moving them to individual files.
34
+
35
+ ## Local Demo with `web-dev-server`
36
+
37
+ ```bash
38
+ npm start
39
+ ```
40
+
41
+ To run a local development server that serves the basic demo located in `demo/index.html`
Binary file
@@ -0,0 +1,109 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en-GB">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" />
6
+ <style>
7
+ body {
8
+ margin: 0;
9
+ padding: 0;
10
+ overflow: hidden;
11
+
12
+ /* This is a font-stack that tries to use the system-default sans-serifs first */
13
+ font-family: Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
14
+ line-height: 1.5;
15
+ -webkit-font-smoothing: antialiased;
16
+ }
17
+
18
+ ox-board-viewer {
19
+ width: 100vw;
20
+ height: 100vh;
21
+ }
22
+ </style>
23
+ <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet" />
24
+ <link href="https://fonts.googleapis.com/css?family=Material+Icons&display=block" rel="stylesheet" />
25
+ </head>
26
+ <body>
27
+ <div id="demo"></div>
28
+ <script type="module">
29
+ import { html, render } from 'lit'
30
+ import { ReferenceMap, create, error } from '@hatiolab/things-scene'
31
+ import '@operato/board/ox-board-viewer.js'
32
+ import '../dist/simple-switch.js'
33
+
34
+ const colors = ['red', 'blue', 'orange', 'yellow', 'magenta', 'violet', 'navy', 'green', 'cyan', 'lime']
35
+ const boards = colors.map((color, idx) => {
36
+ var to = colors[(idx + 1) % colors.length]
37
+ return {
38
+ id: color,
39
+ model: {
40
+ width: 400,
41
+ height: 300,
42
+ fillStyle: color,
43
+ components: [
44
+ {
45
+ type: 'text',
46
+ left: 100,
47
+ top: 100,
48
+ width: 200,
49
+ height: 30,
50
+ text: `Click to move to ${to}`,
51
+ event: {
52
+ tap: {
53
+ action: 'goto',
54
+ target: to
55
+ }
56
+ }
57
+ },
58
+ {
59
+ type: 'simple-switch',
60
+ left: 100,
61
+ top: 200,
62
+ width: 100,
63
+ height: 30
64
+ }
65
+ ]
66
+ }
67
+ }
68
+ })
69
+
70
+ var provider = new ReferenceMap(
71
+ async (boardId, resolve, reject) => {
72
+ try {
73
+ const board = boards.find(board => {
74
+ return board.id === boardId
75
+ })
76
+ if (!board) {
77
+ throw `no board named as ${boardId}`
78
+ }
79
+
80
+ var scene
81
+
82
+ try {
83
+ scene = await provider.get(boardId)
84
+ console.warn('Board fetched more than twice.', boardId)
85
+ } catch (e) {
86
+ scene = create({
87
+ model: JSON.parse(JSON.stringify(board.model)),
88
+ mode: 0,
89
+ refProvider: provider
90
+ })
91
+ }
92
+ resolve(scene, board)
93
+ } catch (e) {
94
+ error(e)
95
+ reject(e)
96
+ }
97
+ },
98
+ async (id, ref) => {
99
+ ref.dispose()
100
+ }
101
+ )
102
+
103
+ render(
104
+ html` <ox-board-viewer .board=${boards[0]} .provider=${provider}></ox-board-viewer> `,
105
+ document.querySelector('#demo')
106
+ )
107
+ </script>
108
+ </body>
109
+ </html>
File without changes
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/editors/index.ts"],"names":[],"mappings":"","sourcesContent":[""]}
@@ -0,0 +1,2 @@
1
+ import URDFViewerElement from './urdf-viewer-element';
2
+ export declare function registerDragEvents(viewer: URDFViewerElement, callback: () => void): void;
@@ -0,0 +1,126 @@
1
+ // Converts a datatransfer structer into an object with all paths and files
2
+ // listed out. Returns a promise that resolves with the file structure.
3
+ function dataTransferToFiles(dataTransfer) {
4
+ if (!(dataTransfer instanceof DataTransfer)) {
5
+ throw new Error('Data must be of type "DataTransfer"');
6
+ }
7
+ const files = {};
8
+ // recurse down the webkit file structure resolving
9
+ // the paths to files names to store in the `files`
10
+ // object
11
+ function recurseDirectory(item) {
12
+ if (item.isFile) {
13
+ return new Promise(resolve => {
14
+ item.file((file) => {
15
+ files[item.fullPath] = file;
16
+ resolve();
17
+ });
18
+ });
19
+ }
20
+ else {
21
+ const reader = item.createReader();
22
+ return new Promise(resolve => {
23
+ const promises = [];
24
+ // exhaustively read all the directory entries
25
+ function readNextEntries() {
26
+ reader.readEntries((et) => {
27
+ if (et.length === 0) {
28
+ Promise.all(promises).then(() => resolve());
29
+ }
30
+ else {
31
+ et.forEach((e) => {
32
+ promises.push(recurseDirectory(e));
33
+ });
34
+ readNextEntries();
35
+ }
36
+ });
37
+ }
38
+ readNextEntries();
39
+ });
40
+ }
41
+ }
42
+ return new Promise(resolve => {
43
+ // Traverse down the tree and add the files into the zip
44
+ // const dtitems = dataTransfer.items && [...dataTransfer.items]
45
+ // const dtfiles = [...dataTransfer.files]
46
+ var dtitems = [];
47
+ if (dataTransfer.items) {
48
+ for (let i = 0; i < dataTransfer.items.length; i++) {
49
+ dtitems.push(dataTransfer.items[i]);
50
+ }
51
+ }
52
+ var dtfiles = [];
53
+ if (dataTransfer.files) {
54
+ for (let i = 0; i < dataTransfer.files.length; i++) {
55
+ dtfiles.push(dataTransfer.files[i]);
56
+ }
57
+ }
58
+ if (dtitems.length && dtitems[0].webkitGetAsEntry) {
59
+ const promises = [];
60
+ for (let i = 0; i < dtitems.length; i++) {
61
+ const item = dtitems[i];
62
+ const entry = item.webkitGetAsEntry();
63
+ promises.push(recurseDirectory(entry));
64
+ }
65
+ Promise.all(promises).then(() => resolve(files));
66
+ }
67
+ else {
68
+ // add a '/' prefix to math the file directory entry
69
+ // on webkit browsers
70
+ dtfiles.filter(f => f.size !== 0).forEach(f => (files['/' + f.name] = f));
71
+ resolve(files);
72
+ }
73
+ });
74
+ }
75
+ export function registerDragEvents(viewer, callback) {
76
+ document.addEventListener('dragover', e => e.preventDefault());
77
+ document.addEventListener('dragenter', e => e.preventDefault());
78
+ document.addEventListener('drop', e => {
79
+ e.preventDefault();
80
+ // convert the files
81
+ dataTransferToFiles(e.dataTransfer).then((files) => {
82
+ // removes '..' and '.' tokens and normalizes slashes
83
+ const cleanFilePath = (path) => {
84
+ return path
85
+ .replace(/\\/g, '/')
86
+ .split(/\//g)
87
+ .reduce((acc, el) => {
88
+ if (el === '..')
89
+ acc.pop();
90
+ else if (el !== '.')
91
+ acc.push(el);
92
+ return acc;
93
+ }, [])
94
+ .join('/');
95
+ };
96
+ // set the loader url modifier to check the list
97
+ // of files
98
+ const fileNames = Object.keys(files).map(n => cleanFilePath(n));
99
+ viewer.urlModifierFunc = (url) => {
100
+ // find the matching file given the requested url
101
+ const cleaned = cleanFilePath(url.replace(viewer.package, ''));
102
+ const fileName = fileNames
103
+ .filter(name => {
104
+ // check if the end of file and url are the same
105
+ const len = Math.min(name.length, cleaned.length);
106
+ return cleaned.substr(cleaned.length - len) === name.substr(name.length - len);
107
+ })
108
+ .pop();
109
+ if (fileName !== undefined) {
110
+ // revoke the url after it's been used
111
+ const bloburl = URL.createObjectURL(files[fileName]);
112
+ requestAnimationFrame(() => URL.revokeObjectURL(bloburl));
113
+ return bloburl;
114
+ }
115
+ return url;
116
+ };
117
+ // set the source of the element to the most likely intended display model
118
+ const filesNames = Object.keys(files);
119
+ viewer.up = '+Z';
120
+ document.getElementById('up-select').value = viewer.up;
121
+ viewer.urdf = filesNames.filter(n => /urdf$/i.test(n)).shift();
122
+ });
123
+ callback();
124
+ });
125
+ }
126
+ //# sourceMappingURL=drag-n-drop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drag-n-drop.js","sourceRoot":"","sources":["../../src/elements/drag-n-drop.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAI3E,uEAAuE;AACvE,SAAS,mBAAmB,CAAC,YAA0B;IACrD,IAAI,CAAC,CAAC,YAAY,YAAY,YAAY,CAAC,EAAE;QAC3C,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;KACvD;IAED,MAAM,KAAK,GAAG,EAAS,CAAA;IAEvB,mDAAmD;IACnD,mDAAmD;IACnD,SAAS;IACT,SAAS,gBAAgB,CAAC,IAAS;QACjC,IAAI,IAAI,CAAC,MAAM,EAAE;YACf,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC3B,IAAI,CAAC,IAAI,CAAC,CAAC,IAAS,EAAE,EAAE;oBACtB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAA;oBAC3B,OAAO,EAAE,CAAA;gBACX,CAAC,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;SACH;aAAM;YACL,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;YAElC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC3B,MAAM,QAAQ,GAAG,EAAS,CAAA;gBAE1B,8CAA8C;gBAC9C,SAAS,eAAe;oBACtB,MAAM,CAAC,WAAW,CAAC,CAAC,EAAO,EAAE,EAAE;wBAC7B,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE;4BACnB,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;yBAC5C;6BAAM;4BACL,EAAE,CAAC,OAAO,CAAC,CAAC,CAAM,EAAE,EAAE;gCACpB,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAA;4BACpC,CAAC,CAAC,CAAA;4BACF,eAAe,EAAE,CAAA;yBAClB;oBACH,CAAC,CAAC,CAAA;gBACJ,CAAC;gBAED,eAAe,EAAE,CAAA;YACnB,CAAC,CAAC,CAAA;SACH;IACH,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;QAC3B,wDAAwD;QACxD,gEAAgE;QAChE,0CAA0C;QAC1C,IAAI,OAAO,GAAG,EAAwB,CAAA;QACtC,IAAI,YAAY,CAAC,KAAK,EAAE;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBAClD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;aACpC;SACF;QAED,IAAI,OAAO,GAAG,EAAY,CAAA;QAC1B,IAAI,YAAY,CAAC,KAAK,EAAE;YACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBAClD,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;aACpC;SACF;QAED,IAAI,OAAO,CAAC,MAAM,IAAK,OAAO,CAAC,CAAC,CAAC,CAAC,gBAAwB,EAAE;YAC1D,MAAM,QAAQ,GAAG,EAAE,CAAA;YACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACvC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;gBACvB,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAA;gBAErC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAA;aACvC;YACD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;SACjD;aAAM;YACL,oDAAoD;YACpD,qBAAqB;YACrB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAEzE,OAAO,CAAC,KAAK,CAAC,CAAA;SACf;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAyB,EAAE,QAAoB;IAChF,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAA;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAA;IAC/D,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE;QACpC,CAAC,CAAC,cAAc,EAAE,CAAA;QAElB,oBAAoB;QACpB,mBAAmB,CAAC,CAAC,CAAC,YAAa,CAAC,CAAC,IAAI,CAAC,CAAC,KAAU,EAAE,EAAE;YACvD,qDAAqD;YACrD,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,EAAE;gBACrC,OAAO,IAAI;qBACR,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;qBACnB,KAAK,CAAC,KAAK,CAAC;qBACZ,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE;oBAClB,IAAI,EAAE,KAAK,IAAI;wBAAE,GAAG,CAAC,GAAG,EAAE,CAAA;yBACrB,IAAI,EAAE,KAAK,GAAG;wBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;oBACjC,OAAO,GAAG,CAAA;gBACZ,CAAC,EAAE,EAAc,CAAC;qBACjB,IAAI,CAAC,GAAG,CAAC,CAAA;YACd,CAAC,CAAA;YAED,gDAAgD;YAChD,WAAW;YACX,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;YAC/D,MAAM,CAAC,eAAe,GAAG,CAAC,GAAW,EAAE,EAAE;gBACvC,iDAAiD;gBACjD,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;gBAC9D,MAAM,QAAQ,GAAG,SAAS;qBACvB,MAAM,CAAC,IAAI,CAAC,EAAE;oBACb,gDAAgD;oBAChD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;oBACjD,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAA;gBAChF,CAAC,CAAC;qBACD,GAAG,EAAE,CAAA;gBAER,IAAI,QAAQ,KAAK,SAAS,EAAE;oBAC1B,sCAAsC;oBACtC,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;oBACpD,qBAAqB,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAA;oBAEzD,OAAO,OAAO,CAAA;iBACf;gBAED,OAAO,GAAG,CAAA;YACZ,CAAC,CAAA;YAED,0EAA0E;YAC1E,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACrC,MAAM,CAAC,EAAE,GAAG,IAAI,CACf;YAAC,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAU,CAAC,KAAK,GAAG,MAAM,CAAC,EAAE,CAAA;YAEjE,MAAM,CAAC,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAG,CAAA;QACjE,CAAC,CAAC,CAAA;QAEF,QAAQ,EAAE,CAAA;IACZ,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["// Converts a datatransfer structer into an object with all paths and files\n\nimport URDFViewerElement from './urdf-viewer-element'\n\n// listed out. Returns a promise that resolves with the file structure.\nfunction dataTransferToFiles(dataTransfer: DataTransfer) {\n if (!(dataTransfer instanceof DataTransfer)) {\n throw new Error('Data must be of type \"DataTransfer\"')\n }\n\n const files = {} as any\n\n // recurse down the webkit file structure resolving\n // the paths to files names to store in the `files`\n // object\n function recurseDirectory(item: any): Promise<void> {\n if (item.isFile) {\n return new Promise(resolve => {\n item.file((file: any) => {\n files[item.fullPath] = file\n resolve()\n })\n })\n } else {\n const reader = item.createReader()\n\n return new Promise(resolve => {\n const promises = [] as any\n\n // exhaustively read all the directory entries\n function readNextEntries() {\n reader.readEntries((et: any) => {\n if (et.length === 0) {\n Promise.all(promises).then(() => resolve())\n } else {\n et.forEach((e: any) => {\n promises.push(recurseDirectory(e))\n })\n readNextEntries()\n }\n })\n }\n\n readNextEntries()\n })\n }\n }\n\n return new Promise(resolve => {\n // Traverse down the tree and add the files into the zip\n // const dtitems = dataTransfer.items && [...dataTransfer.items]\n // const dtfiles = [...dataTransfer.files]\n var dtitems = [] as DataTransferItem[]\n if (dataTransfer.items) {\n for (let i = 0; i < dataTransfer.items.length; i++) {\n dtitems.push(dataTransfer.items[i])\n }\n }\n\n var dtfiles = [] as File[]\n if (dataTransfer.files) {\n for (let i = 0; i < dataTransfer.files.length; i++) {\n dtfiles.push(dataTransfer.files[i])\n }\n }\n\n if (dtitems.length && (dtitems[0].webkitGetAsEntry as any)) {\n const promises = []\n for (let i = 0; i < dtitems.length; i++) {\n const item = dtitems[i]\n const entry = item.webkitGetAsEntry()\n\n promises.push(recurseDirectory(entry))\n }\n Promise.all(promises).then(() => resolve(files))\n } else {\n // add a '/' prefix to math the file directory entry\n // on webkit browsers\n dtfiles.filter(f => f.size !== 0).forEach(f => (files['/' + f.name] = f))\n\n resolve(files)\n }\n })\n}\n\nexport function registerDragEvents(viewer: URDFViewerElement, callback: () => void) {\n document.addEventListener('dragover', e => e.preventDefault())\n document.addEventListener('dragenter', e => e.preventDefault())\n document.addEventListener('drop', e => {\n e.preventDefault()\n\n // convert the files\n dataTransferToFiles(e.dataTransfer!).then((files: any) => {\n // removes '..' and '.' tokens and normalizes slashes\n const cleanFilePath = (path: string) => {\n return path\n .replace(/\\\\/g, '/')\n .split(/\\//g)\n .reduce((acc, el) => {\n if (el === '..') acc.pop()\n else if (el !== '.') acc.push(el)\n return acc\n }, [] as string[])\n .join('/')\n }\n\n // set the loader url modifier to check the list\n // of files\n const fileNames = Object.keys(files).map(n => cleanFilePath(n))\n viewer.urlModifierFunc = (url: string) => {\n // find the matching file given the requested url\n const cleaned = cleanFilePath(url.replace(viewer.package, ''))\n const fileName = fileNames\n .filter(name => {\n // check if the end of file and url are the same\n const len = Math.min(name.length, cleaned.length)\n return cleaned.substr(cleaned.length - len) === name.substr(name.length - len)\n })\n .pop()\n\n if (fileName !== undefined) {\n // revoke the url after it's been used\n const bloburl = URL.createObjectURL(files[fileName])\n requestAnimationFrame(() => URL.revokeObjectURL(bloburl))\n\n return bloburl\n }\n\n return url\n }\n\n // set the source of the element to the most likely intended display model\n const filesNames = Object.keys(files)\n viewer.up = '+Z'\n ;(document.getElementById('up-select') as any)!.value = viewer.up\n\n viewer.urdf = filesNames.filter(n => /urdf$/i.test(n)).shift()!\n })\n\n callback()\n })\n}\n"]}
@@ -0,0 +1,12 @@
1
+ import { LitElement, PropertyValues } from 'lit';
2
+ import { URDFRobot } from 'urdf-loader';
3
+ import URDFManipulatorElement from './urdf-manipulator-element';
4
+ export default class URDFControllerElement extends LitElement {
5
+ static styles: import("lit").CSSResult[];
6
+ viewer?: URDFManipulatorElement;
7
+ robot?: URDFRobot;
8
+ render(): import("lit-html").TemplateResult<1>;
9
+ updated(changes: PropertyValues<this>): void;
10
+ _setupViewer(viewer?: URDFManipulatorElement): void;
11
+ setColor(color: string): void;
12
+ }
@@ -0,0 +1,283 @@
1
+ import { __decorate } from "tslib";
2
+ import { LitElement, css, html } from 'lit';
3
+ import { customElement, property } from 'lit/decorators.js';
4
+ import * as THREE from 'three';
5
+ import { registerDragEvents } from './drag-n-drop';
6
+ import { ScrollbarStyles } from '@operato/styles';
7
+ const DEG2RAD = Math.PI / 180;
8
+ const RAD2DEG = 1 / DEG2RAD;
9
+ let URDFControllerElement = class URDFControllerElement extends LitElement {
10
+ render() {
11
+ const { joints = {} } = this.robot || {};
12
+ const { ignoreLimits = false } = this.viewer || {};
13
+ const jointsArray = Object.values(joints);
14
+ return html `
15
+ <ul>
16
+ ${jointsArray.map(joint => {
17
+ var { jointType, name, angle, limit } = joint;
18
+ var degVal = Number(angle || 0);
19
+ if (jointType === 'revolute' || jointType === 'continuous') {
20
+ degVal *= RAD2DEG;
21
+ }
22
+ if (Math.abs(degVal) > 1) {
23
+ degVal = degVal.toFixed(1);
24
+ }
25
+ else {
26
+ degVal = degVal.toPrecision(2);
27
+ }
28
+ var sliderMin;
29
+ var sliderMax;
30
+ var inputMin;
31
+ var inputMax;
32
+ if (ignoreLimits || jointType === 'continuous') {
33
+ sliderMin = -6.28;
34
+ sliderMax = 6.28;
35
+ inputMin = -6.28 * RAD2DEG;
36
+ inputMax = 6.28 * RAD2DEG;
37
+ }
38
+ else {
39
+ sliderMin = limit.lower;
40
+ sliderMax = limit.upper;
41
+ inputMin = Number(limit.lower) * RAD2DEG;
42
+ inputMax = Number(limit.upper) * RAD2DEG;
43
+ }
44
+ return html `
45
+ <li joint-type=${jointType} joint-name=${name}>
46
+ <span title=${name}>${name}</span>
47
+ <input
48
+ type="range"
49
+ .value=${String(angle)}
50
+ step="0.0001"
51
+ min=${sliderMin}
52
+ max=${sliderMax}
53
+ @input=${(e) => {
54
+ var _a;
55
+ (_a = this.viewer) === null || _a === void 0 ? void 0 : _a.setJointValue(name, e.target.value);
56
+ }}
57
+ />
58
+ <input
59
+ type="number"
60
+ .value=${degVal}
61
+ step="0.0001"
62
+ min=${inputMin}
63
+ max=${inputMax}
64
+ @change=${(e) => {
65
+ var _a;
66
+ (_a = this.viewer) === null || _a === void 0 ? void 0 : _a.setJointValue(name, Number(e.target.value) * DEG2RAD);
67
+ }}
68
+ />
69
+ </li>
70
+ `;
71
+ })}
72
+ </ul>
73
+ `;
74
+ }
75
+ updated(changes) {
76
+ if (changes.has('viewer')) {
77
+ this._setupViewer(this.viewer);
78
+ }
79
+ }
80
+ _setupViewer(viewer) {
81
+ if (!viewer) {
82
+ return;
83
+ }
84
+ this.robot = viewer.robot;
85
+ viewer.addEventListener('urdf-processed', () => {
86
+ this.robot = viewer.robot;
87
+ });
88
+ viewer.addEventListener('ignore-limits-change', () => {
89
+ this.requestUpdate();
90
+ });
91
+ viewer.addEventListener('angle-change', (e) => {
92
+ this.requestUpdate();
93
+ });
94
+ viewer.addEventListener('joint-mouseover', (e) => {
95
+ const j = this.renderRoot.querySelector(`li[joint-name="${e.detail}"]`);
96
+ if (j) {
97
+ j.setAttribute('robot-hovered', 'true');
98
+ }
99
+ });
100
+ viewer.addEventListener('joint-mouseout', (e) => {
101
+ const j = this.renderRoot.querySelector(`li[joint-name="${e.detail}"]`);
102
+ if (j) {
103
+ j.removeAttribute('robot-hovered');
104
+ }
105
+ });
106
+ let originalNoAutoRecenter;
107
+ viewer.addEventListener('manipulate-start', (e) => {
108
+ const j = this.renderRoot.querySelector(`li[joint-name="${e.detail}"]`);
109
+ if (j) {
110
+ // ??
111
+ j.scrollIntoView({ block: 'nearest' });
112
+ window.scrollTo(0, 0);
113
+ }
114
+ originalNoAutoRecenter = viewer.noAutoRecenter;
115
+ viewer.noAutoRecenter = true;
116
+ });
117
+ viewer.addEventListener('manipulate-end', (e) => {
118
+ viewer.noAutoRecenter = originalNoAutoRecenter;
119
+ });
120
+ registerDragEvents(viewer, () => {
121
+ this.setColor('#263238');
122
+ });
123
+ }
124
+ setColor(color) {
125
+ this.viewer.highlightColor = '#' + new THREE.Color(0xffffff).lerp(new THREE.Color(color), 0.35).getHexString();
126
+ }
127
+ };
128
+ URDFControllerElement.styles = [
129
+ ScrollbarStyles,
130
+ css `
131
+ :host {
132
+ display: flex;
133
+ flex-direction: column;
134
+ width: 100%;
135
+ margin: 15px 0;
136
+ overflow: hidden;
137
+ user-select: none;
138
+ }
139
+
140
+ :host > * {
141
+ margin: 5px 0;
142
+ }
143
+
144
+ input[type='number'] {
145
+ color: white;
146
+ border: none;
147
+ font-weight: 300;
148
+ background: rgba(255, 255, 255, 0.25);
149
+ padding: 1px 2px;
150
+ }
151
+
152
+ ul {
153
+ list-style: none;
154
+ padding: 0;
155
+ margin: 0;
156
+ }
157
+
158
+ input[type='range'] {
159
+ -webkit-appearance: none;
160
+ border: none;
161
+ outline: none;
162
+ width: 100%;
163
+ flex: 1;
164
+ height: 16px;
165
+ background-color: transparent;
166
+ }
167
+ input[type='range']::-webkit-slider-runnable-track {
168
+ width: 100%;
169
+ height: 1px;
170
+ background: white;
171
+ border: none;
172
+ border-radius: 5px;
173
+ }
174
+ input[type='range']::-webkit-slider-thumb {
175
+ -webkit-appearance: none;
176
+ border: none;
177
+ height: 10px;
178
+ width: 10px;
179
+ border-radius: 50%;
180
+ background: white;
181
+ margin-top: -5px;
182
+ }
183
+ input[type='range']:focus {
184
+ outline: none;
185
+ }
186
+ input[type='range']:focus::-webkit-slider-runnable-track {
187
+ background: white;
188
+ }
189
+
190
+ input[type='range']::-moz-range-track {
191
+ width: 100%;
192
+ height: 1px;
193
+ background: white;
194
+ border: none;
195
+ border-radius: 5px;
196
+ }
197
+ input[type='range']::-moz-range-thumb {
198
+ border: none;
199
+ height: 10px;
200
+ width: 10px;
201
+ border-radius: 50%;
202
+ background: white;
203
+ }
204
+
205
+ input[type='range']:-moz-focusring {
206
+ outline: 1px solid white;
207
+ outline-offset: -1px;
208
+ }
209
+
210
+ input[type='range']::-ms-track {
211
+ width: 100%;
212
+ height: 1px;
213
+ background: white;
214
+ border-radius: 10px;
215
+ color: transparent;
216
+ border: none;
217
+ outline: none;
218
+ }
219
+ input[type='range']::-ms-thumb {
220
+ height: 10px;
221
+ width: 10px;
222
+ border-radius: 50%;
223
+ background: white;
224
+ border: none;
225
+ outline: none;
226
+ margin-top: 2px;
227
+ }
228
+
229
+ input:focus {
230
+ outline: none;
231
+ opacity: 1;
232
+ }
233
+
234
+ /* list of joint sliders */
235
+ ul {
236
+ flex: 1;
237
+ overflow-y: auto;
238
+ }
239
+
240
+ li {
241
+ font-size: 16px;
242
+ display: flex;
243
+ align-items: center;
244
+ padding: 1px 0;
245
+
246
+ width: 100%;
247
+ user-select: text;
248
+
249
+ transition: background 0.25s ease;
250
+ }
251
+
252
+ li[robot-hovered] {
253
+ background: rgba(255, 255, 255, 0.35);
254
+ }
255
+
256
+ li:hover {
257
+ background: rgba(255, 255, 255, 0.35);
258
+ }
259
+
260
+ li span {
261
+ padding: 0 5px;
262
+ max-width: 125px;
263
+ text-overflow: ellipsis;
264
+ overflow: hidden;
265
+ }
266
+
267
+ li input[type='number'] {
268
+ width: 50px;
269
+ overflow: hidden;
270
+ }
271
+ `
272
+ ];
273
+ __decorate([
274
+ property({ type: Object })
275
+ ], URDFControllerElement.prototype, "viewer", void 0);
276
+ __decorate([
277
+ property({ type: Object })
278
+ ], URDFControllerElement.prototype, "robot", void 0);
279
+ URDFControllerElement = __decorate([
280
+ customElement('urdf-controller')
281
+ ], URDFControllerElement);
282
+ export default URDFControllerElement;
283
+ //# sourceMappingURL=urdf-controller-element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urdf-controller-element.js","sourceRoot":"","sources":["../../src/elements/urdf-controller-element.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, PropertyValues } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport * as THREE from 'three'\nimport { registerDragEvents } from './drag-n-drop'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { URDFRobot } from 'urdf-loader'\nimport URDFManipulatorElement from './urdf-manipulator-element'\n\nconst DEG2RAD = Math.PI / 180\nconst RAD2DEG = 1 / DEG2RAD\n\n@customElement('urdf-controller')\nexport default class URDFControllerElement extends LitElement {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n width: 100%;\n margin: 15px 0;\n overflow: hidden;\n user-select: none;\n }\n\n :host > * {\n margin: 5px 0;\n }\n\n input[type='number'] {\n color: white;\n border: none;\n font-weight: 300;\n background: rgba(255, 255, 255, 0.25);\n padding: 1px 2px;\n }\n\n ul {\n list-style: none;\n padding: 0;\n margin: 0;\n }\n\n input[type='range'] {\n -webkit-appearance: none;\n border: none;\n outline: none;\n width: 100%;\n flex: 1;\n height: 16px;\n background-color: transparent;\n }\n input[type='range']::-webkit-slider-runnable-track {\n width: 100%;\n height: 1px;\n background: white;\n border: none;\n border-radius: 5px;\n }\n input[type='range']::-webkit-slider-thumb {\n -webkit-appearance: none;\n border: none;\n height: 10px;\n width: 10px;\n border-radius: 50%;\n background: white;\n margin-top: -5px;\n }\n input[type='range']:focus {\n outline: none;\n }\n input[type='range']:focus::-webkit-slider-runnable-track {\n background: white;\n }\n\n input[type='range']::-moz-range-track {\n width: 100%;\n height: 1px;\n background: white;\n border: none;\n border-radius: 5px;\n }\n input[type='range']::-moz-range-thumb {\n border: none;\n height: 10px;\n width: 10px;\n border-radius: 50%;\n background: white;\n }\n\n input[type='range']:-moz-focusring {\n outline: 1px solid white;\n outline-offset: -1px;\n }\n\n input[type='range']::-ms-track {\n width: 100%;\n height: 1px;\n background: white;\n border-radius: 10px;\n color: transparent;\n border: none;\n outline: none;\n }\n input[type='range']::-ms-thumb {\n height: 10px;\n width: 10px;\n border-radius: 50%;\n background: white;\n border: none;\n outline: none;\n margin-top: 2px;\n }\n\n input:focus {\n outline: none;\n opacity: 1;\n }\n\n /* list of joint sliders */\n ul {\n flex: 1;\n overflow-y: auto;\n }\n\n li {\n font-size: 16px;\n display: flex;\n align-items: center;\n padding: 1px 0;\n\n width: 100%;\n user-select: text;\n\n transition: background 0.25s ease;\n }\n\n li[robot-hovered] {\n background: rgba(255, 255, 255, 0.35);\n }\n\n li:hover {\n background: rgba(255, 255, 255, 0.35);\n }\n\n li span {\n padding: 0 5px;\n max-width: 125px;\n text-overflow: ellipsis;\n overflow: hidden;\n }\n\n li input[type='number'] {\n width: 50px;\n overflow: hidden;\n }\n `\n ]\n\n @property({ type: Object }) viewer?: URDFManipulatorElement\n @property({ type: Object }) robot?: URDFRobot\n\n render() {\n const { joints = {} } = this.robot || {}\n const { ignoreLimits = false } = this.viewer || {}\n const jointsArray = Object.values(joints)\n\n return html`\n <ul>\n ${jointsArray.map(joint => {\n var { jointType, name, angle, limit } = joint\n var degVal: number | string = Number(angle || 0)\n\n if (jointType === 'revolute' || jointType === 'continuous') {\n degVal *= RAD2DEG\n }\n\n if (Math.abs(degVal) > 1) {\n degVal = degVal.toFixed(1)\n } else {\n degVal = degVal.toPrecision(2)\n }\n\n var sliderMin\n var sliderMax\n var inputMin\n var inputMax\n\n if (ignoreLimits || jointType === 'continuous') {\n sliderMin = -6.28\n sliderMax = 6.28\n\n inputMin = -6.28 * RAD2DEG\n inputMax = 6.28 * RAD2DEG\n } else {\n sliderMin = limit.lower\n sliderMax = limit.upper\n\n inputMin = Number(limit.lower) * RAD2DEG\n inputMax = Number(limit.upper) * RAD2DEG\n }\n\n return html`\n <li joint-type=${jointType} joint-name=${name}>\n <span title=${name}>${name}</span>\n <input\n type=\"range\"\n .value=${String(angle)}\n step=\"0.0001\"\n min=${sliderMin}\n max=${sliderMax}\n @input=${(e: Event) => {\n this.viewer?.setJointValue(name, (e.target as any).value)\n }}\n />\n <input\n type=\"number\"\n .value=${degVal}\n step=\"0.0001\"\n min=${inputMin}\n max=${inputMax}\n @change=${(e: Event) => {\n this.viewer?.setJointValue(name, Number((e.target as HTMLInputElement).value) * DEG2RAD)\n }}\n />\n </li>\n `\n })}\n </ul>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('viewer')) {\n this._setupViewer(this.viewer)\n }\n }\n\n _setupViewer(viewer?: URDFManipulatorElement) {\n if (!viewer) {\n return\n }\n\n this.robot = viewer.robot\n\n viewer.addEventListener('urdf-processed', () => {\n this.robot = viewer.robot\n })\n\n viewer.addEventListener('ignore-limits-change', () => {\n this.requestUpdate()\n })\n\n viewer.addEventListener('angle-change', (e: Event) => {\n this.requestUpdate()\n })\n\n viewer.addEventListener('joint-mouseover', (e: Event) => {\n const j = this.renderRoot.querySelector(`li[joint-name=\"${(e as CustomEvent).detail}\"]`)\n if (j) {\n j.setAttribute('robot-hovered', 'true')\n }\n })\n\n viewer.addEventListener('joint-mouseout', (e: Event) => {\n const j = this.renderRoot.querySelector(`li[joint-name=\"${(e as CustomEvent).detail}\"]`)\n if (j) {\n j.removeAttribute('robot-hovered')\n }\n })\n\n let originalNoAutoRecenter: boolean\n viewer.addEventListener('manipulate-start', (e: Event) => {\n const j = this.renderRoot.querySelector(`li[joint-name=\"${(e as CustomEvent).detail}\"]`)\n if (j) {\n // ??\n j.scrollIntoView({ block: 'nearest' })\n window.scrollTo(0, 0)\n }\n\n originalNoAutoRecenter = viewer.noAutoRecenter\n viewer.noAutoRecenter = true\n })\n\n viewer.addEventListener('manipulate-end', (e: Event) => {\n viewer.noAutoRecenter = originalNoAutoRecenter\n })\n\n registerDragEvents(viewer, () => {\n this.setColor('#263238')\n })\n }\n\n setColor(color: string) {\n this.viewer!.highlightColor = '#' + new THREE.Color(0xffffff).lerp(new THREE.Color(color), 0.35).getHexString()\n }\n}\n"]}