PageSourceSearch

https://www.sokkel.nl/modules/isemanticsconfigurator/webroot/configurator/js/core/core.js

js sokkel.nl collected 2026-10-09 17:09:19 UTC 14,601 bytes, 480 lines download raw bytes

1'use strict';
2
3/**
4 * Isemantics. Michel Peters
5 *
6 * Redistributions of files must retain the above copyright notice.
7 * If you did not receive a copy of the license and are unable to obtain it through
8 * the web, please send a note to [email protected] so we can mail you a
9 * copy immediately.
10 *
11 * @category  Javascript
12 * @package   App
13 * @author    Michel Peters <[email protected]>
14 * @copyright 2015-2018 Isemantics
15 * @license   Proprietary licence
16 * @version   GIT: $Id$
17 * @link      https://www.isemantics.nl
18 * @since     1.0.0
19 */
20
21 /**
22  * Main configurator class/handler
23  */
24function Configurator(domElementId) {
25    if (domElementId == null || domElementId == "") {
26        console.error('Creating configurator failed because no DOM element ID was given.');
27        return false;
28    }
29    // Self-reference
30    let self = this;
31
32    // HTML elements for configurator and preview
33    self.element = $(domElementId);
34
35    // GLTF exporter
36    self.exporter = new ConfiguratorExporter();
37
38    // Create UI component
39    self.ui = new ConfiguratorUI(self, { element: self.element });   
40
41    // Main renderer for everything 3D/view
42    self.renderer = new ConfiguratorRenderer(self, 'configuratorRenderer');
43
44    // Create asset loader
45    self.assetLoader = new ConfiguratorLoader(self, CONFIGURATOR_PATHS);    
46
47    // Scene manager
48    self.scene = new ConfiguratorScene(self);
49
50    // Data processor/manager
51    self.data = new ConfiguratorData(self);
52
53    /**
54     * Bootstrap
55     */
56    self.start = function () {
57        logger.debug('core::start');
58        // First of all: Check browser support
59        if (browser_detector.detect() === false) {
60            self.ui.showNoBrowserSupportMessage();
61            return false;
62        }
63        // Set state/UI to loading
64        self.ui.setLoading(true);
65        // Create asset loader and add all known assets
66        self.assetLoader.setLoadingCompletedCallback(self.eventAssetLoadingFinished);
67        self.assetLoader.start();
68    }
69    
70    self.eventAssetLoadingFinished = function ()
71    {
72        logger.debug('core::eventAssetLoadingFinished: done preloading all assets for configurator, starting render');
73        // Trigger initialize for further loading
74        self.initialize();
75    };
76
77    /**
78     * Initialize
79     */
80    self.initialize = function() {     
81        logger.debug('core::initialize');         
82        // Initialize renderer
83        self.renderer.initialize();
84        // Let UI update to current state
85        self.ui.initialize();        
86        // Done loading everything
87        self.ui.setLoading(false);
88        // Create intial scene
89        self.scene.initialize();
90        // Start actually rendering
91        self.renderer.start();
92        
93        self.eventModelChanged();
94    }
95
96    self.setConnectorPosition = function (pos) {
97        if (self.getModel() == null) return false;
98        // Update model
99        self.getModel().setConnectorPosition(pos); 
100        // Refresh
101        self.refresh();
102        self.ui.refresh();
103    }
104    
105    self.setDisplayCase = function (id, label) {
106        // Update model        
107        self.getModel().setDisplayCase(id, label);
108        // Refresh
109        self.refresh();
110        self.ui.refresh();
111    }
112    
113    self.setDisplayCaseHeight = function (height) {
114        // Update model
115        self.getModel().setDisplayCaseHeight(height);        
116        // Refresh
117        self.refresh();
118        self.ui.refresh();
119    }
120    
121    self.setProductId = function (productId) {
122        // Update model
123        self.getModel().setProductId(productId);
124        // Refresh
125        self.refresh();
126        self.ui.refresh();
127    }
128
129    self.resetCamera = function () {
130        if (self.renderer === null) return;
131        self.renderer.resetCamera();
132    }
133
134    /**
135     * Export configurator 3D data to GLTF. Will hide the environment and texts, 
136     * among other things. This because we will get a cleaner image of only the model
137     */
138    self.doExport = function (successCallback, errorCallback) {
139        // Hide all non-model meshes/elements
140        self.scene.removeBackgroundScene();
141        // Get/do export
142        // @note: no return value, will call the success/error callback
143        self.exporter.getExport(self.scene.getScene(), successCallback, errorCallback);
144        // Show all non-model meshes/elements again for normal rendering
145        //self.scene.addBackgroundScene();
146    }
147    
148    self.getState = function () {
149        if (self.getModel() == null) return false;
150        return self.getModel().getState();
151    }
152
153    /**
154     * This will remove the entire current model state and initialize/set
155     * the given new state.
156     */
157    self.setState = function (newState) {
158        logger.debug('core::getState: removing old model and initializing new state');
159        // Clear current scene
160        //self.scene.clear();s
161        // Set new state
162        self.scene.createModel(newState);
163    }
164
165    self.getScene = function () {
166        return self.scene;
167    }
168
169    self.getModel = function () {
170        logger.debug('core::getModel');
171        return self.getModel();
172    }
173
174    self.refresh = function () {
175        logger.debug('core::refresh');
176        // Update model state        
177        let state = self.getState();
178        // Refresh scene with model state
179        self.scene.refresh(state);
180    }
181   
182    self.resetMaterialsTab = function (tab) {
183        let type = tab.data('type');
184        $("#product-size-type").val(type);
185    };
186    
187    self.isCustomTopProductId = function (topProductId) {
188        return self.getData().isCustomTopProductId(topProductId);
189    }
190
191    self.isCustomProductId = function (productId) {
192        return self.getData().isCustomProductId(productId);
193    }
194
195    self.convertToCustomProductId = function (productId) {
196        let idPart = productId.substring(0, productId.length - 7);
197        return idPart + "0000000";
198    }
199    
200    self.setPlint = function (uiState) {        
201        // Update model
202        self.getModel().setPlint(uiState);
203        // Refresh
204        self.refresh();        
205        self.ui.refresh();
206    }
207
208    self.setLighting = function (lightingType, lightingId, lightingLabel) {
209        // Update model
210        self.getModel().setLighting(lightingType, lightingId, lightingLabel);
211        // Refresh
212        self.refresh();
213        self.ui.refresh();
214    }
215    
216    self.setLightingCount = function (count) {
217        // Update model
218        self.getModel().setLightingCount(count);
219        // Refresh
220        self.refresh();
221        self.ui.refresh();
222    }
223
224    self.setLightingPattern = function (pattern) {
225        // Update model
226        self.getModel().setLightingPattern(pattern);
227        // Refresh
228        self.refresh();
229        self.ui.refresh();
230    }
231
232    self.setTurnTable = function (turnTable) {        
233        // Get current turn table from list of possibilities
234        // This, so that we can get the name translated for this turn table ( if any )
235        // TODO: check model_id and category_id exist/not empty
236        let turnTableLabel = null;
237        if (turnTable !== null) {
238            let s = this.getState();        
239            let turnTables = self.getData().getTurnTables(s.model_id, s.category_id);
240            if (turnTables[turnTable] != undefined
241                && turnTables[turnTable].name != undefined) {
242                turnTableLabel = turnTables[turnTable].name;
243            }
244        }
245        // Update model state
246        self.getModel().setTurnTable(turnTable, turnTableLabel);
247        // Refresh
248        self.refresh();
249        self.ui.refresh();
250    }
251    
252    self.setTop = function (topProductId) {             
253        // Update model
254        self.getModel().setTop(topProductId);
255        // Refresh
256        self.refresh();
257        self.ui.refresh();
258    }
259
260    self.setDoorPosition = function (newPosition) {
261        // Update model
262        self.getModel().setDoorPosition(newPosition);
263        // Refresh
264        self.refresh();
265        self.ui.refresh();
266    }
267
268    self.setDoorOpening = function (newPosition) {
269        // Update model
270        self.getModel().setDoorOpening(newPosition);
271        // Refresh
272        self.refresh();
273        self.ui.refresh();
274    }
275    
276    self.setMaterialId = function (materialId, categoryId) {
277        const currentMaterialId = self.getModel() ? self.getModel().getState().material_id : null;
278        const currentCategoryId = self.getModel() ? self.getModel().getState().category_id : null;
279
280        if (materialId != currentMaterialId || currentCategoryId != categoryId) {
281            logger.debug('core::setMaterialId: Material (material ID or category ID) has changed');
282            self.eventMaterialChanged(materialId, categoryId);
283            return true;
284        }
285        return false;
286    }
287
288    self.eventMaterialChanged = function (materialId, categoryId) {
289        logger.debug('core::eventMaterialChanged('+materialId+', '+categoryId+'): updating model material');
290        // Update model
291        self.getModel().setMaterialId(materialId, categoryId);
292        // Refresh model
293        self.refresh();
294        self.ui.refresh();        
295    }
296
297    self.setMaterialColor = function (materialColorId) {
298        logger.debug('core::eventMaterialChanged(' + materialColorId + ')');
299        const currentModelId = self.getModel() ? self.getModel().getState().model_id : null;
300        // Update model
301        self.getModel().setMaterialColor(materialColorId);        
302        // Refresh model
303        self.refresh();
304        self.ui.refresh();
305    }
306
307    self.setModelId = function (newModelId) {
308        logger.debug('core::setModelId(' + newModelId + ')');
309        const currentModelId = self.getModel() ? self.getModel().getState().model_id : null;
310
311        // Only trigger on different model
312        if (newModelId == currentModelId) {
313            logger.debug('NOTICE: Model change cancelled, because it is the currently selected model');
314            return false;
315        }
316
317        // Create new model
318        self.scene.createModel({
319            model_id: newModelId
320        });
321        
322        self.eventModelChanged();
323        
324    }
325    
326    self.eventModelChanged = function () {
327        logger.debug('core::eventModelChanged');
328        // ### Update data shown in UI based on current state
329        let state = self.getState();
330        let modelId = parseInt(state.model_id);        
331        let categoryId = parseInt(state.category_id);
332        logger.debug('core::eventModelChanged: model ID = ' + modelId);
333        logger.debug('core::eventModelChanged: category ID = ' + categoryId);
334
335        // Update axes helper
336        self.scene.updateGrid();
337
338        // Let UI refresh to reflect current model state (for example: tabs and selected items)
339        self.ui.refresh();
340    }
341
342    self.getModel = function () {
343        return self.scene.getModel();
344    }
345
346    self.getAsset = function (key) {
347        return self.assetLoader.getAsset(key);
348    }
349
350    self.setDimensions = function (width, height, depth) {
351        if (self.getModel() == null) return false;
352
353        // Note: removed parseInt and used parseFloat because it could have "31.5"
354        width = parseFloat(width);
355        height = parseFloat(height);
356        depth = parseFloat(depth);
357
358        // Set dimensions on model
359        self.getModel().setDimensions(width, height, depth);
360
361        // Refresh
362        self.refresh();
363        self.ui.refresh();
364        
365        return true;
366    }
367    
368    /**
369     * Set wire color for current model
370     */
371    self.setWireColor = function(value) {
372        // Update model
373        self.getModel().setWireColor(value);        
374        // Refresh
375        self.ui.refresh();
376    }
377
378    /**
379     * Resize event handler
380     */
381    self.resize = function () {
382        logger.debug('core::resize');
383        // Update renderer based on new width/height and ratio
384        self.renderer.resize();
385    }
386
387    /**
388     * Returns a reference to the renderer object
389     */
390    self.getRenderer = function () {
391        return self.renderer;
392    }
393
394    /**
395     * Get a frame from the renderer as base64 (for screenshot or saving)
396     */
397    self.getCanvasImageAsBase64 = function () {
398        logger.debug('core::getCanvasImageAsBase64');
399        // Get frame from renderer as base64
400        return self.renderer.getCanvasImageAsBase64();
401    }
402
403    /**
404     * Get reference to main camera
405     */
406    self.getCamera = function()
407    {
408        if (self.renderer != null) return;
409        return self.renderer.getCamera();
410    }
411
412    /**
413     * Pan up
414     */
415    self.panCamera = function (direction)
416    {
417        if (self.renderer == null) return;
418        self.renderer.panCamera(direction);
419    }
420
421    /**
422     * Zoom in
423     */
424    self.zoomCamera = function (direction)
425    {
426        if (self.renderer == null) return;
427        self.renderer.zoomCamera(direction);
428    }
429
430    self.getData = function ()
431    {
432        return self.data;
433    }
434    
435    self.getDPR = function ()
436    {
437        if (self.renderer == null) return;
438        return self.renderer.getDPR();
439    }
440
441    // Return public class method mapping
442    return {
443        // Core methods
444        start: self.start,
445        refresh: self.refresh,
446        getState: self.getState,
447        setState: self.setState,
448        getModel: self.getModel,
449        getDPR: self.getDPR,
450        getCanvasImageAsBase64: self.getCanvasImageAsBase64,
451        getLoadingState: self.getLoadingState,
452        getAsset: self.getAsset,
453        doExport: self.doExport,
454        getScene: self.getScene,
455        getRenderer: self.getRenderer,
456        resize: self.resize,
457        getData: self.getData,
458        isCustomProductId: self.isCustomProductId,
459        // Camera
460        zoomCamera: self.zoomCamera,
461        panCamera: self.panCamera,
462        getCamera: self.getCamera,
463        // Model setters
464        setPlint: self.setPlint,
465        setProductId: self.setProductId,
466        setModelId: self.setModelId,
467        setMaterialId: self.setMaterialId,        
468        setDimensions: self.setDimensions,
469        setDisplayCase: self.setDisplayCase,
470        setDisplayCaseHeight: self.setDisplayCaseHeight,
471        setWireColor: self.setWireColor,
472        setLighting: self.setLighting,
473        setLightingCount: self.setLightingCount,
474        setLightingPattern: self.setLightingPattern,
475        setConnectorPosition: self.setConnectorPosition,
476        setMaterialColor: self.setMaterialColor,
477        setTurnTable: self.setTurnTable,
478        setDoorPosition: self.setDoorPosition,
479    }
480}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.