@colijnit/configurator 1.0.19 → 1.0.21

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 (158) hide show
  1. package/.idea/Configurator.iml +12 -0
  2. package/.idea/codeStyles/Project.xml +21 -0
  3. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  4. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  5. package/.idea/misc.xml +9 -0
  6. package/.idea/modules.xml +8 -0
  7. package/.idea/vcs.xml +6 -0
  8. package/angular.json +193 -0
  9. package/configurator.iml +11 -0
  10. package/dist/configurator/index.html +14 -0
  11. package/dist/configurator/main-es2015.js +3129 -0
  12. package/dist/configurator/main-es2015.js.map +1 -0
  13. package/dist/configurator/main-es5.js +5482 -0
  14. package/dist/configurator/main-es5.js.map +1 -0
  15. package/dist/configurator/polyfills-es2015.js +4520 -0
  16. package/dist/configurator/polyfills-es2015.js.map +1 -0
  17. package/dist/configurator/polyfills-es5.js +18375 -0
  18. package/dist/configurator/polyfills-es5.js.map +1 -0
  19. package/dist/configurator/runtime-es2015.js +155 -0
  20. package/dist/configurator/runtime-es2015.js.map +1 -0
  21. package/dist/configurator/runtime-es5.js +155 -0
  22. package/dist/configurator/runtime-es5.js.map +1 -0
  23. package/dist/configurator/styles-es2015.js +450 -0
  24. package/dist/configurator/styles-es2015.js.map +1 -0
  25. package/dist/configurator/styles-es5.js +432 -0
  26. package/dist/configurator/styles-es5.js.map +1 -0
  27. package/dist/configurator/vendor-es2015.js +155551 -0
  28. package/dist/configurator/vendor-es2015.js.map +1 -0
  29. package/dist/configurator/vendor-es5.js +183588 -0
  30. package/dist/configurator/vendor-es5.js.map +1 -0
  31. package/ng-package.json +9 -0
  32. package/package.json +47 -14
  33. package/src/app/app.component.ts +222 -0
  34. package/src/app/app.module.ts +34 -0
  35. package/src/app/builder.ts +480 -0
  36. package/src/app/components/answers/answer/answer.component.ts +61 -0
  37. package/src/app/components/answers/answers.component.ts +41 -0
  38. package/src/app/components/answers/answers.module.ts +26 -0
  39. package/src/app/components/selections/selections.component.ts +131 -0
  40. package/src/app/components/selections/selections.module.ts +20 -0
  41. package/src/app/components/shared/loader/loader.component.scss +33 -0
  42. package/src/app/components/shared/loader/loader.component.ts +20 -0
  43. package/src/app/components/shared/shared.module.ts +16 -0
  44. package/src/app/directives/visibility-observer-master.directive.ts +71 -0
  45. package/src/app/directives/visibility-observer.directive.ts +74 -0
  46. package/src/app/services/configurator.service.ts +86 -0
  47. package/src/app/services/image-cache.service.ts +56 -0
  48. package/src/app/services/locator.service.ts +6 -0
  49. package/src/environments/environment.prod.ts +3 -0
  50. package/src/environments/environment.ts +8 -0
  51. package/src/helper/variation-helper.ts +220 -0
  52. package/src/index.html +14 -0
  53. package/src/main.ts +11 -0
  54. package/src/model/material.ts +22 -0
  55. package/src/model/variation-settings.ts +14 -0
  56. package/src/model/variation.ts +11 -0
  57. package/src/polyfills.ts +73 -0
  58. package/{public_api.d.ts → src/public_api.ts} +6 -6
  59. package/src/style/shared.scss +173 -0
  60. package/src/style/styles.scss +45 -0
  61. package/src/tsconfig.app.json +16 -0
  62. package/src/tsconfig.spec.json +19 -0
  63. package/src/utils/asset.utils.ts +88 -0
  64. package/src/utils/file.utils.ts +156 -0
  65. package/src/utils/file.utils.unit.test.ts +8 -0
  66. package/src/utils/image.utils.ts +54 -0
  67. package/src/utils/object.utils.ts +52 -0
  68. package/src/utils/scene-utils.ts +119 -0
  69. package/src/utils/threed.utils.ts +219 -0
  70. package/src/utils/variation-utils.ts +216 -0
  71. package/tsconfig.json +23 -0
  72. package/tslint.json +132 -0
  73. package/app/builder.d.ts +0 -53
  74. package/app/components/answers/answer/answer.component.d.ts +0 -11
  75. package/app/components/answers/answers.component.d.ts +0 -8
  76. package/app/components/answers/answers.module.d.ts +0 -2
  77. package/app/components/selections/selections.component.d.ts +0 -22
  78. package/app/components/selections/selections.module.d.ts +0 -2
  79. package/app/components/shared/loader/loader.component.d.ts +0 -2
  80. package/app/components/shared/shared.module.d.ts +0 -2
  81. package/app/directives/visibility-observer-master.directive.d.ts +0 -9
  82. package/app/directives/visibility-observer.directive.d.ts +0 -13
  83. package/app/services/configurator.service.d.ts +0 -22
  84. package/app/services/image-cache.service.d.ts +0 -10
  85. package/app/services/locator.service.d.ts +0 -4
  86. package/bundles/colijnit-configurator.umd.js +0 -2745
  87. package/bundles/colijnit-configurator.umd.js.map +0 -1
  88. package/bundles/colijnit-configurator.umd.min.js +0 -17
  89. package/bundles/colijnit-configurator.umd.min.js.map +0 -1
  90. package/colijnit-configurator.d.ts +0 -10
  91. package/colijnit-configurator.metadata.json +0 -1
  92. package/esm2015/app/builder.js +0 -477
  93. package/esm2015/app/components/answers/answer/answer.component.js +0 -69
  94. package/esm2015/app/components/answers/answers.component.js +0 -43
  95. package/esm2015/app/components/answers/answers.module.js +0 -29
  96. package/esm2015/app/components/selections/selections.component.js +0 -134
  97. package/esm2015/app/components/selections/selections.module.js +0 -23
  98. package/esm2015/app/components/shared/loader/loader.component.js +0 -24
  99. package/esm2015/app/components/shared/shared.module.js +0 -21
  100. package/esm2015/app/directives/visibility-observer-master.directive.js +0 -51
  101. package/esm2015/app/directives/visibility-observer.directive.js +0 -57
  102. package/esm2015/app/services/configurator.service.js +0 -94
  103. package/esm2015/app/services/image-cache.service.js +0 -66
  104. package/esm2015/app/services/locator.service.js +0 -10
  105. package/esm2015/colijnit-configurator.js +0 -11
  106. package/esm2015/helper/variation-helper.js +0 -216
  107. package/esm2015/model/material.js +0 -11
  108. package/esm2015/model/variation-settings.js +0 -6
  109. package/esm2015/model/variation.js +0 -3
  110. package/esm2015/public_api.js +0 -7
  111. package/esm2015/utils/asset.utils.js +0 -74
  112. package/esm2015/utils/file.utils.js +0 -139
  113. package/esm2015/utils/image.utils.js +0 -52
  114. package/esm2015/utils/object.utils.js +0 -49
  115. package/esm2015/utils/scene-utils.js +0 -94
  116. package/esm2015/utils/threed.utils.js +0 -222
  117. package/esm2015/utils/variation-utils.js +0 -224
  118. package/esm5/app/builder.js +0 -591
  119. package/esm5/app/components/answers/answer/answer.component.js +0 -64
  120. package/esm5/app/components/answers/answers.component.js +0 -27
  121. package/esm5/app/components/answers/answers.module.js +0 -32
  122. package/esm5/app/components/selections/selections.component.js +0 -104
  123. package/esm5/app/components/selections/selections.module.js +0 -26
  124. package/esm5/app/components/shared/loader/loader.component.js +0 -16
  125. package/esm5/app/components/shared/shared.module.js +0 -24
  126. package/esm5/app/directives/visibility-observer-master.directive.js +0 -64
  127. package/esm5/app/directives/visibility-observer.directive.js +0 -59
  128. package/esm5/app/services/configurator.service.js +0 -160
  129. package/esm5/app/services/image-cache.service.js +0 -69
  130. package/esm5/app/services/locator.service.js +0 -13
  131. package/esm5/colijnit-configurator.js +0 -11
  132. package/esm5/helper/variation-helper.js +0 -268
  133. package/esm5/model/material.js +0 -13
  134. package/esm5/model/variation-settings.js +0 -8
  135. package/esm5/model/variation.js +0 -7
  136. package/esm5/public_api.js +0 -7
  137. package/esm5/utils/asset.utils.js +0 -106
  138. package/esm5/utils/file.utils.js +0 -151
  139. package/esm5/utils/image.utils.js +0 -56
  140. package/esm5/utils/object.utils.js +0 -56
  141. package/esm5/utils/scene-utils.js +0 -98
  142. package/esm5/utils/threed.utils.js +0 -279
  143. package/esm5/utils/variation-utils.js +0 -327
  144. package/fesm2015/colijnit-configurator.js +0 -2109
  145. package/fesm2015/colijnit-configurator.js.map +0 -1
  146. package/fesm5/colijnit-configurator.js +0 -2527
  147. package/fesm5/colijnit-configurator.js.map +0 -1
  148. package/helper/variation-helper.d.ts +0 -14
  149. package/model/material.d.ts +0 -17
  150. package/model/variation-settings.d.ts +0 -14
  151. package/model/variation.d.ts +0 -10
  152. package/utils/asset.utils.d.ts +0 -13
  153. package/utils/file.utils.d.ts +0 -27
  154. package/utils/image.utils.d.ts +0 -8
  155. package/utils/object.utils.d.ts +0 -7
  156. package/utils/scene-utils.d.ts +0 -7
  157. package/utils/threed.utils.d.ts +0 -16
  158. package/utils/variation-utils.d.ts +0 -12
@@ -0,0 +1,119 @@
1
+ import * as THREE from 'three';
2
+
3
+ export class SceneUtils {
4
+
5
+ public static TrySelectorConnection(scene: THREE.Scene, parent: THREE.Object3D,
6
+ part1: any, part2: any, createAddableFn?: Function): boolean {
7
+ let addable: any;
8
+ if (createAddableFn) {
9
+ addable = part2;
10
+ part2 = createAddableFn(addable);
11
+ }
12
+ for (let i = 0; i < part1.children.length; i++) {
13
+ for (let ii = 0; ii < part2.children.length; ii++) {
14
+ const con1: THREE.Object3D = part1.children[i];
15
+ const con2: THREE.Object3D = part2.children[ii];
16
+ // if these connectors can connect connect them
17
+ if (!con1['connected'] && !con2['connected'] && this.CanSelectorConnect(con1, con2)) {
18
+ // if addable, continue this loop with a new addable
19
+ if (addable) {
20
+ const newPart2: THREE.Object3D = createAddableFn(addable, part2, part1);
21
+ // reference of part2 changed, so refresh con2
22
+ this.SelectorConnect(scene, parent, con1, newPart2.children[ii]);
23
+ } else {
24
+ return this.SelectorConnect(scene, parent, con1, con2);
25
+ }
26
+ }
27
+ }
28
+ }
29
+ return false;
30
+ }
31
+
32
+ public static Convert3DPointToScreenPoint(point: THREE.Vector3, camera: THREE.Camera, width: number, height: number): THREE.Vector2 {
33
+ if (!point) {
34
+ return new THREE.Vector2();
35
+ }
36
+ const vector: THREE.Vector3 = point.clone().project(camera);
37
+ vector.x = (vector.x + 1) / 2 * width;
38
+ vector.y = -(vector.y - 1) / 2 * height;
39
+ return new THREE.Vector2(vector.x, vector.y);
40
+ }
41
+
42
+ public static CanSelectorConnect(con1: THREE.Object3D | any, con2: THREE.Object3D | any): boolean {
43
+ const con1Name: string = con1 instanceof THREE.Object3D ? con1.name : con1.connector;
44
+ const con2Name: string = con2 instanceof THREE.Object3D ? con2.name : con2.connector;
45
+ const sameParent: boolean = con1 instanceof THREE.Object3D && con2 instanceof THREE.Object3D ? con1.parent === con2.parent : false;
46
+ const parts1: string[] = con1Name.toUpperCase().split('_'),
47
+ parts2: string[] = con2Name.toUpperCase().split('_');
48
+ if (parts1.length >= 3 && parts2.length >= 3 && !sameParent) {
49
+ const connectable: boolean = parts1[0] === 'C' && parts2[0] === 'C' &&
50
+ parts1[1] === parts2[1] && parts1[2] !== parts2[2];
51
+ return connectable;
52
+ }
53
+ return false;
54
+ }
55
+
56
+ private static SelectorConnect(scene: THREE.Scene, parent: THREE.Object3D, con1: THREE.Object3D, con2: THREE.Object3D): boolean {
57
+ if (!scene || !parent) {
58
+ return false;
59
+ }
60
+ con1['connectedTo'] = con2.parent.name;
61
+ con2['connectedTo'] = con1.parent.name;
62
+
63
+ const motherRotation: THREE.Euler = new THREE.Euler(0, 0, 0);
64
+ const motherPosition: THREE.Vector3 = new THREE.Vector3(0, 0, 0);
65
+
66
+ scene.updateMatrixWorld(true);
67
+ motherRotation.copy(parent.rotation);
68
+ parent.getWorldPosition(motherPosition);
69
+
70
+ parent.rotation.set(0, 0, 0);
71
+ parent.position.set(0, 0, 0);
72
+
73
+ const con1Quat: THREE.Quaternion = new THREE.Quaternion();
74
+ con1.getWorldQuaternion(con1Quat);
75
+ const con2Quat: THREE.Quaternion = new THREE.Quaternion();
76
+ con2.getWorldQuaternion(con2Quat);
77
+ const con1QuatParent: THREE.Quaternion = new THREE.Quaternion();
78
+ con1.parent.getWorldQuaternion(con1QuatParent);
79
+ const con2QuatParent: THREE.Quaternion = new THREE.Quaternion();
80
+ con2.parent.getWorldQuaternion(con2QuatParent);
81
+
82
+ const rotation: THREE.Quaternion = new THREE.Quaternion().multiplyQuaternions(
83
+ con1Quat.invert(),
84
+ con2Quat
85
+ ).multiply(
86
+ new THREE.Quaternion().multiplyQuaternions(
87
+ con1QuatParent,
88
+ con1QuatParent
89
+ )
90
+ );
91
+
92
+ con2.parent.quaternion.copy(rotation);
93
+ // Update because the matrix has been tempered with
94
+ scene.updateMatrixWorld(true);
95
+
96
+ // Move the connectors towards eachother
97
+ const con1Pos: THREE.Vector3 = new THREE.Vector3();
98
+ con1.getWorldPosition(con1Pos);
99
+ const con2Pos: THREE.Vector3 = new THREE.Vector3();
100
+ con2.getWorldPosition(con2Pos);
101
+
102
+ const move: THREE.Vector3 = con1Pos.sub(con2Pos);
103
+ con2.parent.position.x += move.x;
104
+ con2.parent.position.y += move.y;
105
+ con2.parent.position.z += move.z;
106
+
107
+ // reset parent's objects rotation and position
108
+ parent.rotation.copy(motherRotation);
109
+ parent.position.copy(motherPosition);
110
+
111
+ scene.updateMatrixWorld(true);
112
+
113
+ // Set the connected flag
114
+ con1['connected'] = true;
115
+ con2['connected'] = true;
116
+ return true;
117
+ }
118
+
119
+ }
@@ -0,0 +1,219 @@
1
+ import * as THREE from "three";
2
+ import {ObjectUtils} from "./object.utils";
3
+ import {FileUtils} from "./file.utils";
4
+
5
+ export class ThreedUtils {
6
+
7
+ private _objectCache: Map<string, THREE.Object3D> = new Map();
8
+
9
+ public clearCache(): void {
10
+ const objs: THREE.Object3D[] = Array.from(this._objectCache.values());
11
+ objs.forEach(o => ObjectUtils.DisposeObject(o));
12
+ this._objectCache.clear();
13
+ }
14
+
15
+ public download3DSource(fileName: string): Promise<THREE.Object3D> {
16
+ return new Promise(async (resolve: Function, reject: Function) => {
17
+ fileName = fileName.replace('.unity3d', '');
18
+ let lookupFileName: string = fileName + (fileName.indexOf('.glb') < 0 ? '.glb' : '');
19
+ if (this._objectCache.has(lookupFileName)) {
20
+ resolve(this._objectCache.get(lookupFileName));
21
+ return;
22
+ }
23
+ if (await FileUtils.FileExists(lookupFileName, 'https://cdn1.colijn-it.nl/content43/')) {
24
+ this.loadGlbSource(lookupFileName).then((obj: THREE.Object3D) => {
25
+ this._objectCache.set(lookupFileName, obj);
26
+ resolve(obj);
27
+ });
28
+ } else {
29
+ reject(`GLB source not found! (${lookupFileName})`);
30
+ }
31
+ });
32
+ }
33
+
34
+ public readFileAsText(file: File): Promise<string> {
35
+ const fileReader = new FileReader();
36
+ return new Promise((resolve, reject) => {
37
+ fileReader.onload = (e: any) => resolve(e.target.result);
38
+ fileReader.onerror = error => reject(error);
39
+ fileReader.readAsText(file);
40
+ });
41
+ }
42
+
43
+ public async loadJsonModel(filePath: string): Promise<any> {
44
+ if (this._objectCache.has(filePath)) {
45
+ return Promise.resolve(this._objectCache.get(filePath));
46
+ }
47
+ const json: string = await this._readJsonFile(filePath);
48
+ const loader = new THREE.ObjectLoader();
49
+ loader.crossOrigin = 'Anonymous';
50
+ return new Promise((resolve, reject) => {
51
+ try {
52
+ const obj = loader.parse(json);
53
+ this._objectCache.set(filePath, obj);
54
+ resolve(obj);
55
+ } catch (e) {
56
+ reject(null);
57
+ }
58
+ });
59
+ }
60
+
61
+ public async loadJsonObjectModel(filePath: string): Promise<any> {
62
+ if (this._objectCache.has(filePath)) {
63
+ return Promise.resolve(this._objectCache.get(filePath));
64
+ }
65
+ const loader = new THREE.ObjectLoader();
66
+ loader.setCrossOrigin('Anonymous');
67
+ loader.setResourcePath('');
68
+ return new Promise((resolve, reject) => {
69
+ loader.load(filePath,
70
+ (object: any) => {
71
+ const obj: THREE.Object3D = (object.type === 'Scene' && object.children[0].type === 'Object3D') ? object.children[0] : object;
72
+ this._objectCache.set(filePath, obj);
73
+ resolve(obj as THREE.Object3D);
74
+ },
75
+ xhr => null,
76
+ error => reject(error)
77
+ );
78
+ });
79
+ }
80
+
81
+ public async loadGlbModel(file: string, cleanUp: boolean = true): Promise<THREE.Object3D> {
82
+ if (this._objectCache.has(file)) {
83
+ return Promise.resolve(this._objectCache.get(file));
84
+ }
85
+ if (!window.hasOwnProperty('loadGLTF')) {
86
+ console.error('loadGLTF not defined in window global');
87
+ return null;
88
+ }
89
+ // const loader = new GLTFLoader();
90
+ const obj: THREE.Object3D = await (window as any).loadGLTF(file);
91
+ if (obj) {
92
+ this._cleanedUpObjects(obj, cleanUp);
93
+ this._objectCache.set(file, obj);
94
+ return obj;
95
+ } else {
96
+ return null;
97
+ }
98
+ }
99
+
100
+ public async loadGlbSource(file: string): Promise<THREE.Object3D> {
101
+ const obj = await this.loadGlbModel(file, false);
102
+ if (obj) {
103
+ obj.children = obj.children.filter(c => !(c instanceof THREE.Camera));
104
+ obj.children.sort((a, b) => a['name'] < b['name'] ? 1 : -1);
105
+ obj.children.forEach((c: THREE.Object3D) => {
106
+ c.traverse((t: THREE.Object3D) => {
107
+ t.visible = !t.name.toLowerCase().startsWith('c_');
108
+ });
109
+ c.visible = false;
110
+ });
111
+ if (obj.children.length === 1 && obj.children[0] instanceof THREE.Group) { // flatten children
112
+ const children: any = obj.children[0].children.slice();
113
+ obj.children.length = 0;
114
+ obj.children = children;
115
+ }
116
+ }
117
+ return obj;
118
+ }
119
+
120
+ public async textureFromUrl(url: string): Promise<any> {
121
+ // url = this._includeBaseUrl(url);
122
+ return new Promise((resolve, reject) => {
123
+ const textureLoader = new THREE.TextureLoader();
124
+ // textureLoader.setBaseU(this._settingsService.settings.assetPath);
125
+ textureLoader.load(url,
126
+ (texture: THREE.Texture) => {
127
+ texture.wrapT = THREE.RepeatWrapping;
128
+ texture.wrapS = THREE.RepeatWrapping;
129
+ texture.repeat.set(1, 1);
130
+ texture.needsUpdate = true;
131
+ return resolve(texture);
132
+ },
133
+ null,
134
+ reject
135
+ );
136
+ });
137
+ }
138
+
139
+ private _cleanedUpObjects(object: THREE.Object3D, cleanUp: boolean = true): THREE.Object3D {
140
+ let obj: THREE.Object3D = new THREE.Object3D();
141
+ object.children.forEach((c: THREE.Object3D) => {
142
+ if (!(c instanceof THREE.Camera)) {
143
+ if (cleanUp && c instanceof THREE.Group || (c.children.length === 1 && c.children[0] instanceof THREE.Group)) {
144
+ this._addGroupChildrenToObject(c, obj);
145
+ } else if ((cleanUp && !(c instanceof THREE.Mesh)) || (!(c instanceof THREE.Mesh) && !c.name && c.children.length > 0)) {
146
+ c.children.forEach((child) => {
147
+ child.translateY(c.position.y);
148
+ });
149
+ c.translateY(-c.position.y);
150
+ if (obj.children.length > 0) {
151
+ obj.add(c.clone());
152
+ } else {
153
+ obj = c.clone();
154
+ }
155
+ } else {
156
+ // if (c.position.y > 0 || c.position.y < 0) {
157
+ // c.children.forEach((child) => {
158
+ // child.translateY(c.position.y);
159
+ // });
160
+ // c.translateY(-c.position.y);
161
+ // }
162
+ obj.add(c.clone());
163
+ }
164
+ }
165
+ });
166
+ const boundingBox = new THREE.Box3().setFromObject(obj);
167
+ const bbCenterPivot = new THREE.Vector3();
168
+ boundingBox.getCenter(bbCenterPivot);
169
+ const delta: THREE.Vector3 = new THREE.Vector3().add(bbCenterPivot).negate();
170
+ obj.children.forEach((cc) => {
171
+ cc.position.add(delta);
172
+ });
173
+ return obj;
174
+ }
175
+
176
+ private _addGroupChildrenToObject(group: THREE.Object3D, obj: THREE.Object3D, cleanUp: boolean = true): void {
177
+ group.children.forEach((gc: THREE.Object3D) => {
178
+ if (cleanUp && gc instanceof THREE.Group) {
179
+ this._addGroupChildrenToObject(gc, obj);
180
+ } else {
181
+ // gc.translateX(-group.position.x);
182
+ gc.translateY(group.position.y);
183
+ // gc.translateZ(-group.position.z);
184
+ obj.add(gc.clone());
185
+ }
186
+ });
187
+ }
188
+
189
+ private _iterateChildren(children: THREE.Object3D[], callback: (child: THREE.Mesh) => {}): void {
190
+ for (let i = 0; i < children.length; i++) {
191
+ const child: THREE.Object3D = children[i];
192
+ if (child instanceof THREE.Mesh) {
193
+ callback(child);
194
+ } else {
195
+ this._iterateChildren(child.children, callback);
196
+ }
197
+ }
198
+ }
199
+
200
+ private async _readJsonFile(filePath: string): Promise<any> {
201
+ try {
202
+ const response = await fetch(filePath);
203
+ if (!response.ok) {
204
+ return '';
205
+ } else {
206
+ let empty = false;
207
+ await response.clone().text().then((value) => {
208
+ if (value === '') {
209
+ empty = true;
210
+ }
211
+ });
212
+ return empty ? {} : response.json();
213
+ }
214
+ } catch (e) {
215
+ return '';
216
+ }
217
+ }
218
+
219
+ }
@@ -0,0 +1,216 @@
1
+ import * as JSZip from 'jszip';
2
+ import * as THREE from 'three';
3
+ import {FileUtils} from "./file.utils";
4
+ import {VariationSettings} from "../model/variation-settings";
5
+ import axios from "axios";
6
+
7
+ // @dynamic
8
+ export class VariationUtils {
9
+ private static MaterialCache: Map<string, THREE.MeshStandardMaterial> = new Map();
10
+
11
+ public static async LoadVariation(assetPath: string, fileName: string): Promise<VariationSettings> {
12
+ if (!fileName) {
13
+ return null;
14
+ }
15
+ if (fileName.indexOf('ione3d') < 0) {
16
+ fileName = fileName.concat('.ione3d');
17
+ }
18
+ const id: string = fileName.substr(0, fileName.lastIndexOf('.ione3d'));
19
+ try {
20
+ if (!assetPath.endsWith('/')) {
21
+ assetPath += '/';
22
+ }
23
+ if (!window.hasOwnProperty('downloadVariation')) {
24
+ console.error('downloadVariation not defined in window global');
25
+ return null;
26
+ }
27
+ const file: any = await (window as any).downloadVariation(`${assetPath.replace('https://cdn1.colijn-it.nl/', '')}variation/${fileName}`);
28
+ return await VariationUtils.GetVariationSettingsFromFile(id, file);
29
+ } catch (err) {
30
+ const mute = err;
31
+ return null;
32
+ }
33
+ }
34
+
35
+ // public static GetMaterialFromName(variationFolder: string, material: any): Promise<MeshStandardMaterial> {
36
+ // return new Promise((resolve: Function) => {
37
+ // if (!material) {
38
+ // resolve(null);
39
+ // }
40
+ // if (this.MaterialCache.has(material.name)) {
41
+ // resolve(this.MaterialCache.get(material.name).clone());
42
+ // } else {
43
+ // VariationUtils.LoadVariation(variationFolder, material.name, false).then((settings: VariationSettings) => {
44
+ // if (settings) {
45
+ // AssetUtils.CreateMaterialFromAsset(settings).then((materialObj: Material) => {
46
+ // const materialParams: MeshStandardMaterialParameters = {};
47
+ // materialParams.name = material.name;
48
+ // materialParams.map = materialObj.texture;
49
+ // materialParams.normalMap = materialObj.normal;
50
+ // materialParams.aoMap = materialObj.ao;
51
+ // materialParams.roughnessMap = materialObj.roughness;
52
+ // materialParams.metalnessMap = materialObj.metalness;
53
+ // materialParams.roughness = 1;
54
+ // materialParams.metalness = 1;
55
+ // const pbrMat: MeshStandardMaterial = new MeshStandardMaterial(materialParams);
56
+ // this.MaterialCache.set(material.name, pbrMat);
57
+ // resolve(pbrMat.clone());
58
+ // });
59
+ // } else {
60
+ // resolve(material);
61
+ // }
62
+ // });
63
+ // }
64
+ // });
65
+ // }
66
+
67
+ private static async GetVariationSettingsFromFile(id: string, compressedFile: any): Promise<VariationSettings> {
68
+ if (!compressedFile) {
69
+ return null;
70
+ }
71
+ const zipContent = await VariationUtils.GetZipContent(compressedFile);
72
+ const variationSettings: VariationSettings = new VariationSettings();
73
+ let index;
74
+ variationSettings.id = id;
75
+
76
+ if (zipContent.files['index.json']) {
77
+ const indexFile: string = await zipContent.files['index.json'].async('string');
78
+ index = JSON.parse(indexFile);
79
+ }
80
+ if (index) {
81
+ await VariationUtils.CreateSettingsBasedOnIndex(index, variationSettings, zipContent);
82
+ } else {
83
+ await VariationUtils.CreateSettingsBasedOnFileName(variationSettings, zipContent);
84
+ }
85
+ return variationSettings;
86
+ }
87
+
88
+ private static async CreateSettingsBasedOnIndex(index: any, variationSettings: VariationSettings, zipContent: any): Promise<void> {
89
+ if (index.normalFile) {
90
+ variationSettings.normal = await VariationUtils.LoadFileContentFromZip(zipContent.files[index.normalFile], index.normalFile);
91
+ variationSettings.normalFilename = index.normalFile;
92
+ }
93
+ if (index.aoFile) {
94
+ variationSettings.ao = await VariationUtils.LoadFileContentFromZip(zipContent.files[index.aoFile], index.aoFile);
95
+ variationSettings.aoFilename = index.aoFile;
96
+ }
97
+ if (index.metalnessFile) {
98
+ variationSettings.metalness = await VariationUtils.LoadFileContentFromZip(zipContent.files[index.metalnessFile], index.metalnessFile);
99
+ variationSettings.metalnessFilename = index.metalnessFile;
100
+ }
101
+ if (index.roughnessFile) {
102
+ variationSettings.roughness = await VariationUtils.LoadFileContentFromZip(zipContent.files[index.roughnessFile], index.roughnessFile);
103
+ variationSettings.roughnessFilename = index.roughnessFile;
104
+ }
105
+ if (index.diffuseFile) {
106
+ variationSettings.texture = await VariationUtils.LoadFileContentFromZip(zipContent.files[index.diffuseFile], index.diffuseFile);
107
+ variationSettings.textureFilename = index.diffuseFile;
108
+ }
109
+ variationSettings.settings =
110
+ await VariationUtils.LoadFileContentFromZip(zipContent.files['repeat.json'], 'repeat.json', false) || {};
111
+ Object.assign(variationSettings.settings, index.repeat);
112
+ variationSettings.settings.metalness = index.metalness;
113
+ variationSettings.settings.roughness = index.roughness;
114
+ }
115
+
116
+ private static async CreateSettingsBasedOnFileName(variationSettings: VariationSettings, zipContent: any): Promise<void> {
117
+ const allLoaded: Promise<VariationSettings>[] = [];
118
+ for (const fileName in zipContent.files) {
119
+ if (zipContent.files[fileName]) {
120
+ const file: any = await zipContent.files[fileName];
121
+ if (file.name.toLowerCase().indexOf('normal') > -1 && this.FileIsImage(file.name)) {
122
+ allLoaded.push(zipContent.files[fileName].async('base64').then((normalFile: any) => {
123
+ variationSettings.normal = `data:image/${this.GetBase64FileType(file.name)};base64,${normalFile}`;
124
+ variationSettings.normalFilename = fileName;
125
+ }));
126
+ } else if (file.name.toLowerCase().indexOf('ao') > -1 && this.FileIsImage(file.name)) {
127
+ allLoaded.push(zipContent.files[fileName].async('base64').then((aoFile: any) => {
128
+ variationSettings.ao = `data:image/${this.GetBase64FileType(file.name)};base64,${aoFile}`;
129
+ variationSettings.aoFilename = fileName;
130
+ }));
131
+ } else if (file.name.toLowerCase().indexOf('metalness') > -1 && this.FileIsImage(file.name)) {
132
+ allLoaded.push(zipContent.files[fileName].async('base64').then((metalnessFile: any) => {
133
+ variationSettings.metalness = `data:image/${this.GetBase64FileType(file.name)};base64,${metalnessFile}`;
134
+ variationSettings.metalnessFilename = fileName;
135
+ }));
136
+ } else if (file.name.toLowerCase().indexOf('roughness') > -1 && this.FileIsImage(file.name)) {
137
+ allLoaded.push(zipContent.files[fileName].async('base64').then((roughnessFile: any) => {
138
+ variationSettings.roughness = `data:image/${this.GetBase64FileType(file.name)};base64,${roughnessFile}`;
139
+ variationSettings.roughnessFilename = fileName;
140
+ }));
141
+ } else if (file.name.toLowerCase().indexOf('diffuse') > -1 && this.FileIsImage(file.name)) {
142
+ allLoaded.push(zipContent.files[fileName].async('base64').then((diffuseFile: any) => {
143
+ variationSettings.texture = `data:image/${this.GetBase64FileType(file.name)};base64,${diffuseFile}`;
144
+ variationSettings.textureFilename = fileName;
145
+ }));
146
+ } else if (file.name.indexOf('.jp') > -1) {
147
+ allLoaded.push(zipContent.files[fileName].async('base64').then((textureFile: any) => {
148
+ variationSettings.texture = 'data:image/jpeg;base64,' + textureFile;
149
+ variationSettings.textureFilename = fileName;
150
+ }));
151
+ } else if (file.name.indexOf('.json') > -1) {
152
+ allLoaded.push(zipContent.files[fileName].async('string').then((settingsFile: any) => {
153
+ const settingsFileObj = JSON.parse(settingsFile);
154
+ for (const key in settingsFileObj) {
155
+ if (settingsFileObj[key]) {
156
+ variationSettings.settings[key] = settingsFileObj[key];
157
+ }
158
+ }
159
+ }));
160
+ }
161
+ }
162
+ }
163
+ await Promise.all(allLoaded);
164
+ }
165
+
166
+ private static LoadFileContentFromZip(zip: any, fileName: string, base64: boolean = true): Promise<string> {
167
+ return new Promise((resolve: Function) => {
168
+ if (zip && fileName) {
169
+ zip.async(base64 ? 'base64' : 'string').then((fileContent: any) => {
170
+ if (base64) {
171
+ resolve(`data:image/${this.GetBase64FileType(fileName)};base64,${fileContent}`);
172
+ } else {
173
+ resolve(fileContent);
174
+ }
175
+ });
176
+ } else {
177
+ resolve(undefined);
178
+ }
179
+ });
180
+ }
181
+
182
+ private static FileIsImage(fileName: string): boolean {
183
+ const ext: string = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length).toLowerCase();
184
+ switch (ext) {
185
+ case 'jpg':
186
+ case 'jpeg':
187
+ case 'png':
188
+ case 'bmp':
189
+ return true;
190
+ default:
191
+ return false;
192
+ }
193
+ }
194
+
195
+ private static GetBase64FileType(fileName: string): string {
196
+ const ext: string = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length).toLowerCase();
197
+ switch (ext) {
198
+ case 'jpg':
199
+ case 'jpeg':
200
+ return 'jpeg';
201
+ case 'png':
202
+ return 'png';
203
+ case 'bmp':
204
+ return 'bmp';
205
+ default:
206
+ return 'jpeg';
207
+ }
208
+ }
209
+
210
+ // Get the content
211
+ private static async GetZipContent(file): Promise<any> {
212
+ const jszip = new JSZip();
213
+ const content = await jszip.loadAsync(file);
214
+ return content;
215
+ }
216
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "compileOnSave": false,
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "outDir": "./dist/out-tsc",
6
+ "sourceMap": false,
7
+ "declaration": false,
8
+ "module": "commonjs",
9
+ "moduleResolution": "node",
10
+ "emitDecoratorMetadata": true,
11
+ "experimentalDecorators": true,
12
+ "importHelpers": true,
13
+ "target": "es6",
14
+ "typeRoots": [
15
+ "node_modules/@types"
16
+ ],
17
+ "allowJs": true,
18
+ "lib": [
19
+ "es2017",
20
+ "dom"
21
+ ]
22
+ }
23
+ }