@ -1,45 +0,0 @@ | 
				
			|||||
.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg | 
					 | 
				
			||||
    :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html | 
					 | 
				
			||||
    :alt: License: LGPL-3 | 
					 | 
				
			||||
Model Viewer Widget | 
					 | 
				
			||||
================ | 
					 | 
				
			||||
This module helps to render interactive 3D models.. | 
					 | 
				
			||||
 | 
					 | 
				
			||||
Configuration | 
					 | 
				
			||||
============= | 
					 | 
				
			||||
* It only support 3D images with .glb extension | 
					 | 
				
			||||
 | 
					 | 
				
			||||
Company | 
					 | 
				
			||||
------- | 
					 | 
				
			||||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | 
					 | 
				
			||||
 | 
					 | 
				
			||||
Credits | 
					 | 
				
			||||
------- | 
					 | 
				
			||||
* Developers: version 16: Athira Premanand @cybrosys | 
					 | 
				
			||||
 | 
					 | 
				
			||||
Contacts | 
					 | 
				
			||||
-------- | 
					 | 
				
			||||
* Mail Contact : odoo@cybrosys.com | 
					 | 
				
			||||
* Website : https://cybrosys.com | 
					 | 
				
			||||
 | 
					 | 
				
			||||
License | 
					 | 
				
			||||
------- | 
					 | 
				
			||||
General Public License, Version 3 (LGPL v3). | 
					 | 
				
			||||
(https://www.odoo.com/documentation/user/13.0/legal/licenses/licenses.html) | 
					 | 
				
			||||
 | 
					 | 
				
			||||
Bug Tracker | 
					 | 
				
			||||
----------- | 
					 | 
				
			||||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. | 
					 | 
				
			||||
 | 
					 | 
				
			||||
Maintainer | 
					 | 
				
			||||
========== | 
					 | 
				
			||||
.. image:: https://cybrosys.com/images/logo.png | 
					 | 
				
			||||
   :target: https://cybrosys.com | 
					 | 
				
			||||
 | 
					 | 
				
			||||
This module is maintained by Cybrosys Technologies. | 
					 | 
				
			||||
 | 
					 | 
				
			||||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ | 
					 | 
				
			||||
 | 
					 | 
				
			||||
Further information | 
					 | 
				
			||||
=================== | 
					 | 
				
			||||
HTML Description: `<static/description/index.html>`__ | 
					 | 
				
			||||
@ -1,22 +0,0 @@ | 
				
			|||||
# -*- coding: utf-8 -*- | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Cybrosys Technologies Pvt. Ltd. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
					 | 
				
			||||
#    Author: Cybrosys Technologies (<https://www.cybrosys.com>) | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You can modify it under the terms of the GNU LESSER | 
					 | 
				
			||||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    This program is distributed in the hope that it will be useful, | 
					 | 
				
			||||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					 | 
				
			||||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					 | 
				
			||||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
					 | 
				
			||||
#    (LGPL v3) along with this program. | 
					 | 
				
			||||
#    If not, see <http://www.gnu.org/licenses/>. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
from . import models | 
					 | 
				
			||||
@ -1,49 +0,0 @@ | 
				
			|||||
# -*- coding: utf-8 -*- | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Cybrosys Technologies Pvt. Ltd. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
					 | 
				
			||||
#    Author: Cybrosys Technologies (<https://www.cybrosys.com>) | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You can modify it under the terms of the GNU LESSER | 
					 | 
				
			||||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    This program is distributed in the hope that it will be useful, | 
					 | 
				
			||||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					 | 
				
			||||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					 | 
				
			||||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
					 | 
				
			||||
#    (LGPL v3) along with this program. | 
					 | 
				
			||||
#    If not, see <http://www.gnu.org/licenses/>. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
{ | 
					 | 
				
			||||
    'name': 'Model Viewer Widget', | 
					 | 
				
			||||
    'version': '16.0.1.0.0', | 
					 | 
				
			||||
    'summary': """It helps to render interactive 3D models.""", | 
					 | 
				
			||||
    'description': """It helps to render interactive 3D models. Zoom in and | 
					 | 
				
			||||
     zoom out feature is available and also can move in in any direction""", | 
					 | 
				
			||||
    'author': 'Cybrosys Techno Solutions', | 
					 | 
				
			||||
    'company': 'Cybrosys Techno Solutions', | 
					 | 
				
			||||
    'website': "https://www.cybrosys.com", | 
					 | 
				
			||||
    'category': 'Sales, Extra Tools', | 
					 | 
				
			||||
    'maintainer': 'Cybrosys Techno Solutions', | 
					 | 
				
			||||
    'depends': ['base', 'product'], | 
					 | 
				
			||||
    'data': [ | 
					 | 
				
			||||
        'views/product_template_views.xml', | 
					 | 
				
			||||
    ], | 
					 | 
				
			||||
    'assets': { | 
					 | 
				
			||||
        'web.assets_backend': [ | 
					 | 
				
			||||
            'https://unpkg.com/@egjs/view3d@2.10.1/dist/view3d.pkgd.min.js', | 
					 | 
				
			||||
            'model_viewer_widget/static/src/js/widget.js', | 
					 | 
				
			||||
            'model_viewer_widget/static/src/xml/widget.xml', | 
					 | 
				
			||||
        ] | 
					 | 
				
			||||
    }, | 
					 | 
				
			||||
    'images': ['static/description/banner.png'], | 
					 | 
				
			||||
    'license': 'LGPL-3', | 
					 | 
				
			||||
    'installable': True, | 
					 | 
				
			||||
    'auto_install': False, | 
					 | 
				
			||||
    'application': False, | 
					 | 
				
			||||
} | 
					 | 
				
			||||
@ -1,6 +0,0 @@ | 
				
			|||||
## Module <model_viewer_widget> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
#### 26.07.2023 | 
					 | 
				
			||||
#### Version 16.0.1.0.0 | 
					 | 
				
			||||
#### ADD | 
					 | 
				
			||||
Initial Commit for Model Viewer Widget | 
					 | 
				
			||||
@ -1,22 +0,0 @@ | 
				
			|||||
# -*- coding: utf-8 -*- | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Cybrosys Technologies Pvt. Ltd. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
					 | 
				
			||||
#    Author: Cybrosys Technologies (<https://www.cybrosys.com>) | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You can modify it under the terms of the GNU LESSER | 
					 | 
				
			||||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    This program is distributed in the hope that it will be useful, | 
					 | 
				
			||||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					 | 
				
			||||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					 | 
				
			||||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
					 | 
				
			||||
#    (LGPL v3) along with this program. | 
					 | 
				
			||||
#    If not, see <http://www.gnu.org/licenses/>. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
from . import product_template | 
					 | 
				
			||||
@ -1,30 +0,0 @@ | 
				
			|||||
""""Model Viewer Widget""" | 
					 | 
				
			||||
# -*- coding: utf-8 -*- | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Cybrosys Technologies Pvt. Ltd. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
					 | 
				
			||||
#    Author: Cybrosys Technologies (<https://www.cybrosys.com>) | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You can modify it under the terms of the GNU LESSER | 
					 | 
				
			||||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    This program is distributed in the hope that it will be useful, | 
					 | 
				
			||||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					 | 
				
			||||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					 | 
				
			||||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
					 | 
				
			||||
#    (LGPL v3) along with this program. | 
					 | 
				
			||||
#    If not, see <http://www.gnu.org/licenses/>. | 
					 | 
				
			||||
# | 
					 | 
				
			||||
############################################################################# | 
					 | 
				
			||||
from odoo import fields, models | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
class ProductTemplate(models.Model): | 
					 | 
				
			||||
    """ This class inherit the product template. """ | 
					 | 
				
			||||
    _inherit = 'product.template' | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    model_3d = fields.Binary(string="Product", help="Used to upload images") | 
					 | 
				
			||||
| 
		 Before Width: | Height: | Size: 3.6 KiB  | 
| 
		 Before Width: | Height: | Size: 310 B  | 
| 
		 Before Width: | Height: | Size: 1.3 KiB  | 
| 
		 Before Width: | Height: | Size: 1.4 KiB  | 
| 
		 Before Width: | Height: | Size: 576 B  | 
| 
		 Before Width: | Height: | Size: 733 B  | 
| 
		 Before Width: | Height: | Size: 911 B  | 
| 
		 Before Width: | Height: | Size: 1.1 KiB  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 673 B  | 
| 
		 Before Width: | Height: | Size: 878 B  | 
| 
		 Before Width: | Height: | Size: 653 B  | 
| 
		 Before Width: | Height: | Size: 905 B  | 
| 
		 Before Width: | Height: | Size: 839 B  | 
| 
		 Before Width: | Height: | Size: 427 B  | 
| 
		 Before Width: | Height: | Size: 627 B  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 988 B  | 
| 
		 Before Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 1.5 KiB  | 
| 
		 Before Width: | Height: | Size: 1.1 KiB  | 
| 
		 Before Width: | Height: | Size: 1.9 KiB  | 
| 
		 Before Width: | Height: | Size: 1.1 KiB  | 
| 
		 Before Width: | Height: | Size: 2.1 KiB  | 
| 
		 Before Width: | Height: | Size: 4.4 KiB  | 
| 
		 Before Width: | Height: | Size: 589 B  | 
| 
		 Before Width: | Height: | Size: 3.4 KiB  | 
| 
		 Before Width: | Height: | Size: 1.7 KiB  | 
| 
		 Before Width: | Height: | Size: 2.3 KiB  | 
| 
		 Before Width: | Height: | Size: 967 B  | 
| 
		 Before Width: | Height: | Size: 1.6 KiB  | 
| 
		 Before Width: | Height: | Size: 3.8 KiB  | 
| 
		 Before Width: | Height: | Size: 5.0 KiB  | 
| 
		 Before Width: | Height: | Size: 86 KiB  | 
| 
		 Before Width: | Height: | Size: 74 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB  | 
| 
		 Before Width: | Height: | Size: 17 KiB  | 
| 
		 Before Width: | Height: | Size: 87 KiB  | 
| 
		 Before Width: | Height: | Size: 85 KiB  | 
| 
		 Before Width: | Height: | Size: 122 KiB  | 
| 
		 Before Width: | Height: | Size: 140 KiB  | 
| 
		 Before Width: | Height: | Size: 92 KiB  | 
| 
		 Before Width: | Height: | Size: 229 KiB  | 
| 
		 Before Width: | Height: | Size: 142 KiB  | 
| 
		 Before Width: | Height: | Size: 66 KiB  | 
| 
		 Before Width: | Height: | Size: 10 KiB  | 
@ -1,690 +0,0 @@ | 
				
			|||||
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;"> | 
					 | 
				
			||||
    <!-- TITLE BAR --> | 
					 | 
				
			||||
    <div class="d-flex align-items-center justify-content-between" | 
					 | 
				
			||||
         style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;"> | 
					 | 
				
			||||
        <img src="assets/misc/cybrosys-logo.png" width="42" height="42" | 
					 | 
				
			||||
             style="width: 42px; height: 42px;"/> | 
					 | 
				
			||||
        <div> | 
					 | 
				
			||||
            <div | 
					 | 
				
			||||
                    style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
					 | 
				
			||||
                    class="mr-2"> | 
					 | 
				
			||||
                <i class="fa fa-check mr-1"></i>Community | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <div style="color: #875A7B; font-size: 14px; font-family: | 
					 | 
				
			||||
            'Montserrat', sans-serif; font-weight: bold; | 
					 | 
				
			||||
             background-color: white; display: inline-block; | 
					 | 
				
			||||
             padding: 3px 10px; border-radius: 50px;" | 
					 | 
				
			||||
                 class="mr-2"> | 
					 | 
				
			||||
                <i class="fa fa-check mr-1"></i>Enterprise | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;" | 
					 | 
				
			||||
                 class="mr-2"> | 
					 | 
				
			||||
                <i class="fa fa-check mr-1"></i>Odoo.sh | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <!-- END OF TITLE BAR --> | 
					 | 
				
			||||
    <div class="container"> | 
					 | 
				
			||||
        <div class="row"> | 
					 | 
				
			||||
            <div class="col-sm-12 col-md-12 col-lg-12"> | 
					 | 
				
			||||
                <!-- APP HERO --> | 
					 | 
				
			||||
                <h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;"> | 
					 | 
				
			||||
                    Model Viewer Widget</h1> | 
					 | 
				
			||||
                <p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;"> | 
					 | 
				
			||||
                    Helps to render interactive 3D models</p> | 
					 | 
				
			||||
                <!-- END OF APP HERO --> | 
					 | 
				
			||||
                <img src="assets/screenshots/hero.gif" class="img-responsive" | 
					 | 
				
			||||
                     style="width: 100%; margin-left: auto; margin-right: auto;"/> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- NAVIGATION SECTION --> | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/compass.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Explore This | 
					 | 
				
			||||
        Module</h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;"> | 
					 | 
				
			||||
    <div class="col-sm-12 col-md-6 my-3"> | 
					 | 
				
			||||
        <a href="#overview"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-between align-items-center" | 
					 | 
				
			||||
                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
					 | 
				
			||||
                <div> | 
					 | 
				
			||||
                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span> | 
					 | 
				
			||||
                    <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">Learn | 
					 | 
				
			||||
            more about this | 
					 | 
				
			||||
            module</span> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </a> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <div class="col-sm-12 col-md-6 my-3"> | 
					 | 
				
			||||
        <a href="#features"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-between align-items-center" | 
					 | 
				
			||||
                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
					 | 
				
			||||
                <div> | 
					 | 
				
			||||
                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span> | 
					 | 
				
			||||
                    <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | 
					 | 
				
			||||
            features of this | 
					 | 
				
			||||
            module</span> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </a> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <div class="col-sm-12 col-md-6 my-3"> | 
					 | 
				
			||||
        <a href="#screenshots"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-between align-items-center" | 
					 | 
				
			||||
                 style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | 
					 | 
				
			||||
                <div> | 
					 | 
				
			||||
                    <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span> | 
					 | 
				
			||||
                    <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | 
					 | 
				
			||||
            screenshots for this | 
					 | 
				
			||||
            module</span> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
                <img src="assets/misc/right-arrow.png" width="36" height="36"/> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </a> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<!-- END OF NAVIGATION SECTION --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- OVERVIEW SECTION --> | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" | 
					 | 
				
			||||
     id="overview"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/pie-chart.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Overview | 
					 | 
				
			||||
    </h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<div class="row" | 
					 | 
				
			||||
     style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> | 
					 | 
				
			||||
    <div class="col-sm-12 py-4"> | 
					 | 
				
			||||
        This module helps to render interactive 3D model. | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<!-- END OF OVERVIEW SECTION --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- FEATURES SECTION --> | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" | 
					 | 
				
			||||
     id="features"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/features.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Features | 
					 | 
				
			||||
    </h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<div class="row" | 
					 | 
				
			||||
     style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> | 
					 | 
				
			||||
    <div class="col-sm-12 col-md-6"> | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 40px; margin-bottom: 40px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">It helps to render interactive 3D models.</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 40px; margin-bottom: 40px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">It only support 3D images with .glb extension.</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 30px; margin-bottom: 30px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Zoom in and zoom out feature is available</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 30px; margin-bottom: 30px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Can be used to move in any direction.</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 30px; margin-bottom: 30px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">You can upload 3D models and use it.</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 30px; margin-bottom: 30px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">It provides a 360 degree view.</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 30px; margin-bottom: 30px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">By default, provides a 3D model.</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <div class="col-sm-12 col-md-6"> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="d-flex align-items-center" | 
					 | 
				
			||||
             style="margin-top: 30px; margin-bottom: 30px"> | 
					 | 
				
			||||
            <img src="assets/misc/check-box.png" class="mr-2"/> | 
					 | 
				
			||||
            <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Available in Odoo 16.0 | 
					 | 
				
			||||
        Community and Enterprise Edition.</span> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<!-- END OF FEATURES SECTION --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- SCREENSHOTS SECTION --> | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;" | 
					 | 
				
			||||
     id="screenshots"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/pictures.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Screenshots | 
					 | 
				
			||||
    </h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<div class="row"> | 
					 | 
				
			||||
    <div class="col-sm-12"> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <video width="320" height="240" controls> | 
					 | 
				
			||||
            <source src="assets/screenshots/3d_model_viewer.mp4" | 
					 | 
				
			||||
                    type="video/mp4"> | 
					 | 
				
			||||
        </video> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div style="display: block; margin: 30px auto;"> | 
					 | 
				
			||||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
					 | 
				
			||||
                3D model viewer | 
					 | 
				
			||||
            </h3> | 
					 | 
				
			||||
            <p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> | 
					 | 
				
			||||
                Here you can add a 3D model</p> | 
					 | 
				
			||||
            <img src="assets/screenshots/1.png" class="img-thumbnail"> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div style="display: block; margin: 30px auto;"> | 
					 | 
				
			||||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
					 | 
				
			||||
                Upload 3D model. | 
					 | 
				
			||||
            </h3> | 
					 | 
				
			||||
            <p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> | 
					 | 
				
			||||
                Here you can upload a 3D model. It provides a 3D effect and | 
					 | 
				
			||||
                also the zoom in and zoom out options | 
					 | 
				
			||||
                are available. It is also possible to move it in any | 
					 | 
				
			||||
                direction.</p> | 
					 | 
				
			||||
            <img src="assets/screenshots/2.png" class="img-thumbnail"> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div style="display: block; margin: 30px auto;"> | 
					 | 
				
			||||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
					 | 
				
			||||
                Default view. | 
					 | 
				
			||||
            </h3> | 
					 | 
				
			||||
            <p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> | 
					 | 
				
			||||
                If there is no 3d model uploaded, then by default this is the | 
					 | 
				
			||||
                3D model you can see. | 
					 | 
				
			||||
                It provides a 360 degree view. </p> | 
					 | 
				
			||||
            <img src="assets/screenshots/3.png" class="img-thumbnail"> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div style="display: block; margin: 30px auto;"> | 
					 | 
				
			||||
            <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | 
					 | 
				
			||||
                360 degree view. | 
					 | 
				
			||||
            </h3> | 
					 | 
				
			||||
            <p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"> | 
					 | 
				
			||||
                The 3D model is also possible to move in any | 
					 | 
				
			||||
                direction.</p> | 
					 | 
				
			||||
            <img src="assets/screenshots/4.png" class="img-thumbnail"> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<!-- END OF SCREENSHOTS SECTION --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- RELATED PRODUCTS --> | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/categories.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Related | 
					 | 
				
			||||
        Products | 
					 | 
				
			||||
    </h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<div class="row"> | 
					 | 
				
			||||
    <div class="col-sm-12"> | 
					 | 
				
			||||
        <div id="demo1" class="row carousel slide" data-ride="carousel"> | 
					 | 
				
			||||
            <!-- The slideshow --> | 
					 | 
				
			||||
            <div class="carousel-inner" style="padding: 30px;"> | 
					 | 
				
			||||
                <div class="carousel-item" style="min-height: 198.656px;"> | 
					 | 
				
			||||
                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
					 | 
				
			||||
                         style="float:left"> | 
					 | 
				
			||||
                        <a href="https://apps.odoo.com/apps/modules/16.0/website_product_attachments/" | 
					 | 
				
			||||
                           target="_blank"> | 
					 | 
				
			||||
                            <div style="border-radius:10px"> | 
					 | 
				
			||||
                                <img class="img img-responsive center-block" | 
					 | 
				
			||||
                                     style="border-radius: 0px;" | 
					 | 
				
			||||
                                     src="assets/modules/1.png"> | 
					 | 
				
			||||
                            </div> | 
					 | 
				
			||||
                        </a> | 
					 | 
				
			||||
                    </div> | 
					 | 
				
			||||
                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
					 | 
				
			||||
                         style="float:left"> | 
					 | 
				
			||||
                        <a href="https://apps.odoo.com/apps/modules/16.0/customer_geolocation/" | 
					 | 
				
			||||
                           target="_blank"> | 
					 | 
				
			||||
                            <div style="border-radius:10px"> | 
					 | 
				
			||||
                                <img class="img img-responsive center-block" | 
					 | 
				
			||||
                                     style="border-radius: 0px;" | 
					 | 
				
			||||
                                     src="assets/modules/2.png"> | 
					 | 
				
			||||
                            </div> | 
					 | 
				
			||||
                        </a> | 
					 | 
				
			||||
                    </div> | 
					 | 
				
			||||
                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
					 | 
				
			||||
                         style="float:left"> | 
					 | 
				
			||||
                        <a href="https://apps.odoo.com/apps/modules/16.0/website_cart_clear/" | 
					 | 
				
			||||
                           target="_blank"> | 
					 | 
				
			||||
                            <div style="border-radius:10px"> | 
					 | 
				
			||||
                                <img class="img img-responsive center-block" | 
					 | 
				
			||||
                                     style="border-radius: 0px;" | 
					 | 
				
			||||
                                     src="assets/modules/3.png"> | 
					 | 
				
			||||
                            </div> | 
					 | 
				
			||||
                        </a> | 
					 | 
				
			||||
                    </div> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
                <div class="carousel-item active" | 
					 | 
				
			||||
                     style="min-height: 198.656px;"> | 
					 | 
				
			||||
                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
					 | 
				
			||||
                         style="float:left"> | 
					 | 
				
			||||
                        <a href="https://apps.odoo.com/apps/modules/16.0/ecommerce_barcode_search/" | 
					 | 
				
			||||
                           target="_blank"> | 
					 | 
				
			||||
                            <div style="border-radius:10px"> | 
					 | 
				
			||||
                                <img class="img img-responsive center-block" | 
					 | 
				
			||||
                                     style="border-radius: 0px;" | 
					 | 
				
			||||
                                     src="assets/modules/4.png"> | 
					 | 
				
			||||
                            </div> | 
					 | 
				
			||||
                        </a> | 
					 | 
				
			||||
                    </div> | 
					 | 
				
			||||
                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
					 | 
				
			||||
                         style="float:left"> | 
					 | 
				
			||||
                        <a href="https://apps.odoo.com/apps/modules/16.0/website_return_management/" | 
					 | 
				
			||||
                           target="_blank"> | 
					 | 
				
			||||
                            <div style="border-radius:10px"> | 
					 | 
				
			||||
                                <img class="img img-responsive center-block" | 
					 | 
				
			||||
                                     style="border-radius: 0px;" | 
					 | 
				
			||||
                                     src="assets/modules/5.png"> | 
					 | 
				
			||||
                            </div> | 
					 | 
				
			||||
                        </a> | 
					 | 
				
			||||
                    </div> | 
					 | 
				
			||||
                    <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
					 | 
				
			||||
                         style="float:left"> | 
					 | 
				
			||||
                        <a href="https://apps.odoo.com/apps/modules/16.0/product_visibility_website/" | 
					 | 
				
			||||
                           target="_blank"> | 
					 | 
				
			||||
                            <div style="border-radius:10px"> | 
					 | 
				
			||||
                                <img class="img img-responsive center-block" | 
					 | 
				
			||||
                                     style="border-radius: 0px;" | 
					 | 
				
			||||
                                     src="assets/modules/6.png"> | 
					 | 
				
			||||
                            </div> | 
					 | 
				
			||||
                        </a> | 
					 | 
				
			||||
                    </div> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <!-- Left and right controls --> | 
					 | 
				
			||||
            <a class="carousel-control-prev" href="#demo1" data-slide="prev" | 
					 | 
				
			||||
               style="width:35px; color:#000"> <span | 
					 | 
				
			||||
                    class="carousel-control-prev-icon"><i | 
					 | 
				
			||||
                    class="fa fa-chevron-left" | 
					 | 
				
			||||
                    style="font-size:24px"></i></span> | 
					 | 
				
			||||
            </a> <a class="carousel-control-next" href="#demo1" | 
					 | 
				
			||||
                    data-slide="next" style="width:35px; color:#000"> | 
					 | 
				
			||||
            <span class="carousel-control-next-icon"><i | 
					 | 
				
			||||
                    class="fa fa-chevron-right" | 
					 | 
				
			||||
                    style="font-size:24px"></i></span> | 
					 | 
				
			||||
        </a> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<!-- END OF RELATED PRODUCTS --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- OUR SERVICES --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/star.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Our Services | 
					 | 
				
			||||
    </h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<div class="container my-5"> | 
					 | 
				
			||||
    <div class="row"> | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/cogs.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Customization</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/wrench.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Implementation</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/lifebuoy.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Support</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/user.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Hire | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Developer</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #54a0ff  !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/puzzle.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Integration</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/update.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Migration</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/consultation.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Consultancy</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/training.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Implementation</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4"> | 
					 | 
				
			||||
            <div class="d-flex justify-content-center align-items-center mx-3 my-3" | 
					 | 
				
			||||
                 style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;"> | 
					 | 
				
			||||
                <img src="assets/icons/license.png" class="img-responsive" | 
					 | 
				
			||||
                     height="48px" width="48px"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
            <h6 class="text-center" | 
					 | 
				
			||||
                style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;"> | 
					 | 
				
			||||
                Odoo | 
					 | 
				
			||||
                Licensing Consultancy</h6> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- END OF OUR SERVICES --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- OUR INDUSTRIES --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/corporate.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Our | 
					 | 
				
			||||
        Industries | 
					 | 
				
			||||
    </h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<div class="container my-5"> | 
					 | 
				
			||||
    <div class="row"> | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/trading-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    Trading | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    Easily procure | 
					 | 
				
			||||
                    and | 
					 | 
				
			||||
                    sell your products</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/pos-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    POS | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    Easy | 
					 | 
				
			||||
                    configuration | 
					 | 
				
			||||
                    and convivial experience</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/education-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    Education | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    A platform for | 
					 | 
				
			||||
                    educational management</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/manufacturing-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    Manufacturing | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    Plan, track and | 
					 | 
				
			||||
                    schedule your operations</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/ecom-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    E-commerce & Website | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    Mobile | 
					 | 
				
			||||
                    friendly, | 
					 | 
				
			||||
                    awe-inspiring product pages</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/service-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    Service Management | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    Keep track of | 
					 | 
				
			||||
                    services and invoice</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/restaurant-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    Restaurant | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    Run your bar or | 
					 | 
				
			||||
                    restaurant methodically</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        <div class="col-lg-3"> | 
					 | 
				
			||||
            <div class="my-4 d-flex flex-column justify-content-center" | 
					 | 
				
			||||
                 style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | 
					 | 
				
			||||
                <img src="assets/icons/hotel-black.png" | 
					 | 
				
			||||
                     class="img-responsive mb-3" height="48px" width="48px"> | 
					 | 
				
			||||
                <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | 
					 | 
				
			||||
                    Hotel Management | 
					 | 
				
			||||
                </h5> | 
					 | 
				
			||||
                <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | 
					 | 
				
			||||
                    An | 
					 | 
				
			||||
                    all-inclusive | 
					 | 
				
			||||
                    hotel management application</p> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!--END OF OUR INDUSTRIES --> | 
					 | 
				
			||||
 | 
					 | 
				
			||||
<!-- SUPPORT --> | 
					 | 
				
			||||
<div class="d-flex align-items-center" | 
					 | 
				
			||||
     style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | 
					 | 
				
			||||
    <div class="d-flex justify-content-center align-items-center mr-2" | 
					 | 
				
			||||
         style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | 
					 | 
				
			||||
        <img src="assets/misc/customer-support.png"/> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <h2 class="mt-2" | 
					 | 
				
			||||
        style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | 
					 | 
				
			||||
        Support | 
					 | 
				
			||||
    </h2> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<div class="container mt-5"> | 
					 | 
				
			||||
    <div class="row"> | 
					 | 
				
			||||
        <div class="col-sm-12 col-md-6"> | 
					 | 
				
			||||
            <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | 
					 | 
				
			||||
                <div class="mr-4 d-flex justify-content-center align-items-center" | 
					 | 
				
			||||
                     style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | 
					 | 
				
			||||
                    <img src="assets/misc/support.png" height="48" width="48" | 
					 | 
				
			||||
                         style="width: 42px; height: 42px;"/> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
                <div> | 
					 | 
				
			||||
                    <h4>Need Help?</h4> | 
					 | 
				
			||||
                    <p style="line-height: 100%;">Got questions or need help? | 
					 | 
				
			||||
                        Get in touch.</p> | 
					 | 
				
			||||
                    <a href="mailto:odoo@cybrosys.com"> | 
					 | 
				
			||||
                        <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | 
					 | 
				
			||||
                            odoo@cybrosys.com</p> | 
					 | 
				
			||||
                    </a> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
        <div class="col-sm-12 col-md-6"> | 
					 | 
				
			||||
            <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | 
					 | 
				
			||||
                <div class="mr-4 d-flex justify-content-center align-items-center" | 
					 | 
				
			||||
                     style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | 
					 | 
				
			||||
                    <img src="assets/misc/whatsapp.png" height="52" width="52" | 
					 | 
				
			||||
                         style="width: 52px; height: 52px;"/> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
                <div> | 
					 | 
				
			||||
                    <h4>WhatsApp</h4> | 
					 | 
				
			||||
                    <p style="line-height: 100%;">Say hi to us on WhatsApp!</p> | 
					 | 
				
			||||
                    <a href="https://api.whatsapp.com/send?phone=918606827707"> | 
					 | 
				
			||||
                        <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | 
					 | 
				
			||||
                            +91 86068 | 
					 | 
				
			||||
                            27707</p> | 
					 | 
				
			||||
                    </a> | 
					 | 
				
			||||
                </div> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
    <div class="row"> | 
					 | 
				
			||||
        <div class="col-sm-12 my-5 d-flex justify-content-center align-items-center"> | 
					 | 
				
			||||
            <img src="assets/misc/logo.png" width="144" height="31" | 
					 | 
				
			||||
                 style="width:144px; height: 31px; margin-top: 40px;"/> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </div> | 
					 | 
				
			||||
</div> | 
					 | 
				
			||||
<!-- END OF SUPPORT --> | 
					 | 
				
			||||
@ -1,69 +0,0 @@ | 
				
			|||||
 /** @odoo-module **/ | 
					 | 
				
			||||
import { registry } from "@web/core/registry"; | 
					 | 
				
			||||
import { useInputField } from "@web/views/fields/input_field_hook"; | 
					 | 
				
			||||
import { isBinarySize } from "@web/core/utils/binary"; | 
					 | 
				
			||||
import { url } from "@web/core/utils/urls"; | 
					 | 
				
			||||
import basic_fields from 'web.basic_fields'; | 
					 | 
				
			||||
import {ImageField, imageCacheKey} from "@web/views/fields/image/image_field"; | 
					 | 
				
			||||
import time from 'web.time'; | 
					 | 
				
			||||
var translation = require('web.translation'); | 
					 | 
				
			||||
var _t = translation._t; | 
					 | 
				
			||||
var FieldImage = basic_fields.image1920; | 
					 | 
				
			||||
const { Component,useEffect,useRef, onMounted, useState} = owl; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
 /** | 
					 | 
				
			||||
  * Create canvas for adding 3D model | 
					 | 
				
			||||
  */ | 
					 | 
				
			||||
export class Field3D extends ImageField { | 
					 | 
				
			||||
   setup(){ | 
					 | 
				
			||||
    super.setup(); | 
					 | 
				
			||||
    this.useRef = useRef("field_3d") | 
					 | 
				
			||||
    this.elId = `#${this.props.name}_el` | 
					 | 
				
			||||
    this.state = useState({ | 
					 | 
				
			||||
        isValid: true, | 
					 | 
				
			||||
        value: url('/model_viewer_widget/static/src/assets/3d.glb') | 
					 | 
				
			||||
    }); | 
					 | 
				
			||||
    this.canvasEl = '<canvas class="view3d-canvas"/>' | 
					 | 
				
			||||
    useEffect(() => { | 
					 | 
				
			||||
        this.createCanvas() | 
					 | 
				
			||||
        if (isBinarySize(this.props.value)) { | 
					 | 
				
			||||
            this.state.value = url("/web/content", { | 
					 | 
				
			||||
                model: this.props.record.resModel, | 
					 | 
				
			||||
                id: this.props.record.resId, | 
					 | 
				
			||||
                field: this.props.name, | 
					 | 
				
			||||
                unique: imageCacheKey(this.rawCacheKey), | 
					 | 
				
			||||
            }); | 
					 | 
				
			||||
        } else if(this.props.value){ | 
					 | 
				
			||||
            this.state.value = `data:model/gltf-binary;base64, ${this.props.value}` | 
					 | 
				
			||||
        } | 
					 | 
				
			||||
        this.view3D = new View3D(this.elId, { | 
					 | 
				
			||||
            src: this.state.value | 
					 | 
				
			||||
        }); | 
					 | 
				
			||||
    }) | 
					 | 
				
			||||
   } | 
					 | 
				
			||||
    /** | 
					 | 
				
			||||
  * At the time of removing file, a default 3D model will be displayed | 
					 | 
				
			||||
  */ | 
					 | 
				
			||||
   onFileRemove(){ | 
					 | 
				
			||||
    super.onFileRemove(); | 
					 | 
				
			||||
    this.createCanvas() | 
					 | 
				
			||||
    this.state.value = url('/model_viewer_widget/static/src/assets/3d.glb'); | 
					 | 
				
			||||
    if(this.view3D){ | 
					 | 
				
			||||
        this.view3D.load(this.state.value) | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
   } | 
					 | 
				
			||||
   createCanvas(){ | 
					 | 
				
			||||
       var elem = this.useRef.el.querySelector(this.elId) | 
					 | 
				
			||||
       const prevCanvas = this.useRef.el.querySelector('canvas'); | 
					 | 
				
			||||
       if(prevCanvas) | 
					 | 
				
			||||
           elem.removeChild(prevCanvas) | 
					 | 
				
			||||
       const canvas = document.createElement('canvas'); | 
					 | 
				
			||||
       canvas.width = 600; | 
					 | 
				
			||||
       canvas.height = 500; | 
					 | 
				
			||||
       canvas.classList.add('view3d-canvas') | 
					 | 
				
			||||
       elem.appendChild(canvas); | 
					 | 
				
			||||
   } | 
					 | 
				
			||||
} | 
					 | 
				
			||||
Field3D.acceptedFileExtensions = "*" | 
					 | 
				
			||||
Field3D.template = "Field3DWidget" | 
					 | 
				
			||||
registry.category("fields").add("3D_widget", Field3D); | 
					 | 
				
			||||
@ -1,715 +0,0 @@ | 
				
			|||||
 | 
					 | 
				
			||||
/** | 
					 | 
				
			||||
 * @author mrdoob / http://mrdoob.com/
 | 
					 | 
				
			||||
 */ | 
					 | 
				
			||||
 | 
					 | 
				
			||||
THREE.OBJLoader = function(manager) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    this.materials = null; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    this.regexp = { | 
					 | 
				
			||||
        // v float float float
 | 
					 | 
				
			||||
        vertex_pattern: /^v\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/, | 
					 | 
				
			||||
        // vn float float float
 | 
					 | 
				
			||||
        normal_pattern: /^vn\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/, | 
					 | 
				
			||||
        // vt float float
 | 
					 | 
				
			||||
        uv_pattern: /^vt\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/, | 
					 | 
				
			||||
        // f vertex vertex vertex
 | 
					 | 
				
			||||
        face_vertex: /^f\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)(?:\s+(-?\d+))?/, | 
					 | 
				
			||||
        // f vertex/uv vertex/uv vertex/uv
 | 
					 | 
				
			||||
        face_vertex_uv: /^f\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+))?/, | 
					 | 
				
			||||
        // f vertex/uv/normal vertex/uv/normal vertex/uv/normal
 | 
					 | 
				
			||||
        face_vertex_uv_normal: /^f\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+)\/(-?\d+))?/, | 
					 | 
				
			||||
        // f vertex//normal vertex//normal vertex//normal
 | 
					 | 
				
			||||
        face_vertex_normal: /^f\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)(?:\s+(-?\d+)\/\/(-?\d+))?/, | 
					 | 
				
			||||
        // o object_name | g group_name
 | 
					 | 
				
			||||
        object_pattern: /^[og]\s*(.+)?/, | 
					 | 
				
			||||
        // s boolean
 | 
					 | 
				
			||||
        smoothing_pattern: /^s\s+(\d+|on|off)/, | 
					 | 
				
			||||
        // mtllib file_reference
 | 
					 | 
				
			||||
        material_library_pattern: /^mtllib /, | 
					 | 
				
			||||
        // usemtl material_name
 | 
					 | 
				
			||||
        material_use_pattern: /^usemtl / | 
					 | 
				
			||||
    }; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
THREE.OBJLoader.prototype = { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    constructor: THREE.OBJLoader, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    load: function(url, onLoad, onProgress, onError) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        var scope = this; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        var loader = new THREE.XHRLoader(scope.manager); | 
					 | 
				
			||||
        loader.setPath(this.path); | 
					 | 
				
			||||
        loader.load(url, function(text) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            onLoad(scope.parse(text)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        }, onProgress, onError); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    setPath: function(value) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        this.path = value; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    setMaterials: function(materials) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        this.materials = materials; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    _createParserState: function() { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        var state = { | 
					 | 
				
			||||
            objects: [], | 
					 | 
				
			||||
            object: {}, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            vertices: [], | 
					 | 
				
			||||
            normals: [], | 
					 | 
				
			||||
            uvs: [], | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            materialLibraries: [], | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            startObject: function(name, fromDeclaration) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // If the current object (initial from reset) is not from a g/o declaration in the parsed
 | 
					 | 
				
			||||
                // file. We need to use it for the first parsed g/o to keep things in sync.
 | 
					 | 
				
			||||
                if (this.object && this.object.fromDeclaration === false) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    this.object.name = name; | 
					 | 
				
			||||
                    this.object.fromDeclaration = (fromDeclaration !== false); | 
					 | 
				
			||||
                    return; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (this.object && typeof this.object._finalize === 'function') { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    this.object._finalize(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var previousMaterial = (this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                this.object = { | 
					 | 
				
			||||
                    name: name || '', | 
					 | 
				
			||||
                    fromDeclaration: (fromDeclaration !== false), | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    geometry: { | 
					 | 
				
			||||
                        vertices: [], | 
					 | 
				
			||||
                        normals: [], | 
					 | 
				
			||||
                        uvs: [] | 
					 | 
				
			||||
                    }, | 
					 | 
				
			||||
                    materials: [], | 
					 | 
				
			||||
                    smooth: true, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    startMaterial: function(name, libraries) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        var previous = this._finalize(false); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        // New usemtl declaration overwrites an inherited material, except if faces were declared
 | 
					 | 
				
			||||
                        // after the material, then it must be preserved for proper MultiMaterial continuation.
 | 
					 | 
				
			||||
                        if (previous && (previous.inherited || previous.groupCount <= 0)) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                            this.materials.splice(previous.index, 1); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        var material = { | 
					 | 
				
			||||
                            index: this.materials.length, | 
					 | 
				
			||||
                            name: name || '', | 
					 | 
				
			||||
                            mtllib: (Array.isArray(libraries) && libraries.length > 0 ? libraries[libraries.length - 1] : ''), | 
					 | 
				
			||||
                            smooth: (previous !== undefined ? previous.smooth : this.smooth), | 
					 | 
				
			||||
                            groupStart: (previous !== undefined ? previous.groupEnd : 0), | 
					 | 
				
			||||
                            groupEnd: -1, | 
					 | 
				
			||||
                            groupCount: -1, | 
					 | 
				
			||||
                            inherited: false, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                            clone: function(index) { | 
					 | 
				
			||||
                                return { | 
					 | 
				
			||||
                                    index: (typeof index === 'number' ? index : this.index), | 
					 | 
				
			||||
                                    name: this.name, | 
					 | 
				
			||||
                                    mtllib: this.mtllib, | 
					 | 
				
			||||
                                    smooth: this.smooth, | 
					 | 
				
			||||
                                    groupStart: this.groupEnd, | 
					 | 
				
			||||
                                    groupEnd: -1, | 
					 | 
				
			||||
                                    groupCount: -1, | 
					 | 
				
			||||
                                    inherited: false | 
					 | 
				
			||||
                                }; | 
					 | 
				
			||||
                            } | 
					 | 
				
			||||
                        }; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        this.materials.push(material); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        return material; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    currentMaterial: function() { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        if (this.materials.length > 0) { | 
					 | 
				
			||||
                            return this.materials[this.materials.length - 1]; | 
					 | 
				
			||||
                        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        return undefined; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    _finalize: function(end) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        var lastMultiMaterial = this.currentMaterial(); | 
					 | 
				
			||||
                        if (lastMultiMaterial && lastMultiMaterial.groupEnd === -1) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                            lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3; | 
					 | 
				
			||||
                            lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart; | 
					 | 
				
			||||
                            lastMultiMaterial.inherited = false; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        // Guarantee at least one empty material, this makes the creation later more straight forward.
 | 
					 | 
				
			||||
                        if (end !== false && this.materials.length === 0) { | 
					 | 
				
			||||
                            this.materials.push({ | 
					 | 
				
			||||
                                name: '', | 
					 | 
				
			||||
                                smooth: this.smooth | 
					 | 
				
			||||
                            }); | 
					 | 
				
			||||
                        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        return lastMultiMaterial; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    } | 
					 | 
				
			||||
                }; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // Inherit previous objects material.
 | 
					 | 
				
			||||
                // Spec tells us that a declared material must be set to all objects until a new material is declared.
 | 
					 | 
				
			||||
                // If a usemtl declaration is encountered while this new object is being parsed, it will
 | 
					 | 
				
			||||
                // overwrite the inherited material. Exception being that there was already face declarations
 | 
					 | 
				
			||||
                // to the inherited material, then it will be preserved for proper MultiMaterial continuation.
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (previousMaterial && previousMaterial.name && typeof previousMaterial.clone === "function") { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    var declared = previousMaterial.clone(0); | 
					 | 
				
			||||
                    declared.inherited = true; | 
					 | 
				
			||||
                    this.object.materials.push(declared); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                this.objects.push(this.object); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            finalize: function() { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (this.object && typeof this.object._finalize === 'function') { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    this.object._finalize(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            parseVertexIndex: function(value, len) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var index = parseInt(value, 10); | 
					 | 
				
			||||
                return (index >= 0 ? index - 1 : index + len / 3) * 3; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            parseNormalIndex: function(value, len) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var index = parseInt(value, 10); | 
					 | 
				
			||||
                return (index >= 0 ? index - 1 : index + len / 3) * 3; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            parseUVIndex: function(value, len) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var index = parseInt(value, 10); | 
					 | 
				
			||||
                return (index >= 0 ? index - 1 : index + len / 2) * 2; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            addVertex: function(a, b, c) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var src = this.vertices; | 
					 | 
				
			||||
                var dst = this.object.geometry.vertices; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                dst.push(src[a + 0]); | 
					 | 
				
			||||
                dst.push(src[a + 1]); | 
					 | 
				
			||||
                dst.push(src[a + 2]); | 
					 | 
				
			||||
                dst.push(src[b + 0]); | 
					 | 
				
			||||
                dst.push(src[b + 1]); | 
					 | 
				
			||||
                dst.push(src[b + 2]); | 
					 | 
				
			||||
                dst.push(src[c + 0]); | 
					 | 
				
			||||
                dst.push(src[c + 1]); | 
					 | 
				
			||||
                dst.push(src[c + 2]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            addVertexLine: function(a) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var src = this.vertices; | 
					 | 
				
			||||
                var dst = this.object.geometry.vertices; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                dst.push(src[a + 0]); | 
					 | 
				
			||||
                dst.push(src[a + 1]); | 
					 | 
				
			||||
                dst.push(src[a + 2]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            addNormal: function(a, b, c) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var src = this.normals; | 
					 | 
				
			||||
                var dst = this.object.geometry.normals; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                dst.push(src[a + 0]); | 
					 | 
				
			||||
                dst.push(src[a + 1]); | 
					 | 
				
			||||
                dst.push(src[a + 2]); | 
					 | 
				
			||||
                dst.push(src[b + 0]); | 
					 | 
				
			||||
                dst.push(src[b + 1]); | 
					 | 
				
			||||
                dst.push(src[b + 2]); | 
					 | 
				
			||||
                dst.push(src[c + 0]); | 
					 | 
				
			||||
                dst.push(src[c + 1]); | 
					 | 
				
			||||
                dst.push(src[c + 2]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            addUV: function(a, b, c) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var src = this.uvs; | 
					 | 
				
			||||
                var dst = this.object.geometry.uvs; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                dst.push(src[a + 0]); | 
					 | 
				
			||||
                dst.push(src[a + 1]); | 
					 | 
				
			||||
                dst.push(src[b + 0]); | 
					 | 
				
			||||
                dst.push(src[b + 1]); | 
					 | 
				
			||||
                dst.push(src[c + 0]); | 
					 | 
				
			||||
                dst.push(src[c + 1]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            addUVLine: function(a) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var src = this.uvs; | 
					 | 
				
			||||
                var dst = this.object.geometry.uvs; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                dst.push(src[a + 0]); | 
					 | 
				
			||||
                dst.push(src[a + 1]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            addFace: function(a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var vLen = this.vertices.length; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var ia = this.parseVertexIndex(a, vLen); | 
					 | 
				
			||||
                var ib = this.parseVertexIndex(b, vLen); | 
					 | 
				
			||||
                var ic = this.parseVertexIndex(c, vLen); | 
					 | 
				
			||||
                var id; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (d === undefined) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    this.addVertex(ia, ib, ic); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    id = this.parseVertexIndex(d, vLen); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    this.addVertex(ia, ib, id); | 
					 | 
				
			||||
                    this.addVertex(ib, ic, id); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (ua !== undefined) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    var uvLen = this.uvs.length; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    ia = this.parseUVIndex(ua, uvLen); | 
					 | 
				
			||||
                    ib = this.parseUVIndex(ub, uvLen); | 
					 | 
				
			||||
                    ic = this.parseUVIndex(uc, uvLen); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    if (d === undefined) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        this.addUV(ia, ib, ic); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        id = this.parseUVIndex(ud, uvLen); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        this.addUV(ia, ib, id); | 
					 | 
				
			||||
                        this.addUV(ib, ic, id); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (na !== undefined) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // Normals are many times the same. If so, skip function call and parseInt.
 | 
					 | 
				
			||||
                    var nLen = this.normals.length; | 
					 | 
				
			||||
                    ia = this.parseNormalIndex(na, nLen); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    ib = na === nb ? ia : this.parseNormalIndex(nb, nLen); | 
					 | 
				
			||||
                    ic = na === nc ? ia : this.parseNormalIndex(nc, nLen); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    if (d === undefined) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        this.addNormal(ia, ib, ic); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        id = this.parseNormalIndex(nd, nLen); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        this.addNormal(ia, ib, id); | 
					 | 
				
			||||
                        this.addNormal(ib, ic, id); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            addLineGeometry: function(vertices, uvs) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                this.object.geometry.type = 'Line'; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var vLen = this.vertices.length; | 
					 | 
				
			||||
                var uvLen = this.uvs.length; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                for (var vi = 0, l = vertices.length; vi < l; vi++) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    this.addVertexLine(this.parseVertexIndex(vertices[vi], vLen)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                for (var uvi = 0, l = uvs.length; uvi < l; uvi++) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    this.addUVLine(this.parseUVIndex(uvs[uvi], uvLen)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        }; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        state.startObject('', false); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        return state; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    }, | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    parse: function(text) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        console.time('OBJLoader'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        var state = this._createParserState(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        if (text.indexOf('\r\n') !== -1) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            // This is faster than String.split with regex that splits on both
 | 
					 | 
				
			||||
            text = text.replace('\r\n', '\n'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        var lines = text.split('\n'); | 
					 | 
				
			||||
        var line = '', | 
					 | 
				
			||||
            lineFirstChar = '', | 
					 | 
				
			||||
            lineSecondChar = ''; | 
					 | 
				
			||||
        var lineLength = 0; | 
					 | 
				
			||||
        var result = []; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        // Faster to just trim left side of the line. Use if available.
 | 
					 | 
				
			||||
        var trimLeft = (typeof ''.trimLeft === 'function'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        for (var i = 0, l = lines.length; i < l; i++) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            line = lines[i]; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            line = trimLeft ? line.trimLeft() : line.trim(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            lineLength = line.length; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            if (lineLength === 0) continue; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            lineFirstChar = line.charAt(0); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            // @todo invoke passed in handler if any
 | 
					 | 
				
			||||
            if (lineFirstChar === '#') continue; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            if (lineFirstChar === 'v') { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                lineSecondChar = line.charAt(1); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (lineSecondChar === ' ' && (result = this.regexp.vertex_pattern.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // 0                  1      2      3
 | 
					 | 
				
			||||
                    // ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    state.vertices.push( | 
					 | 
				
			||||
                    parseFloat(result[1]), | 
					 | 
				
			||||
                    parseFloat(result[2]), | 
					 | 
				
			||||
                    parseFloat(result[3])); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else if (lineSecondChar === 'n' && (result = this.regexp.normal_pattern.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // 0                   1      2      3
 | 
					 | 
				
			||||
                    // ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    state.normals.push( | 
					 | 
				
			||||
                    parseFloat(result[1]), | 
					 | 
				
			||||
                    parseFloat(result[2]), | 
					 | 
				
			||||
                    parseFloat(result[3])); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else if (lineSecondChar === 't' && (result = this.regexp.uv_pattern.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // 0               1      2
 | 
					 | 
				
			||||
                    // ["vt 0.1 0.2", "0.1", "0.2"]
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    state.uvs.push( | 
					 | 
				
			||||
                    parseFloat(result[1]), | 
					 | 
				
			||||
                    parseFloat(result[2])); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    throw new Error("Unexpected vertex/normal/uv line: '" + line + "'"); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else if (lineFirstChar === "f") { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if ((result = this.regexp.face_vertex_uv_normal.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // f vertex/uv/normal vertex/uv/normal vertex/uv/normal
 | 
					 | 
				
			||||
                    // 0                        1    2    3    4    5    6    7    8    9   10         11         12
 | 
					 | 
				
			||||
                    // ["f 1/1/1 2/2/2 3/3/3", "1", "1", "1", "2", "2", "2", "3", "3", "3", undefined, undefined, undefined]
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    state.addFace( | 
					 | 
				
			||||
                    result[1], result[4], result[7], result[10], | 
					 | 
				
			||||
                    result[2], result[5], result[8], result[11], | 
					 | 
				
			||||
                    result[3], result[6], result[9], result[12]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else if ((result = this.regexp.face_vertex_uv.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // f vertex/uv vertex/uv vertex/uv
 | 
					 | 
				
			||||
                    // 0                  1    2    3    4    5    6   7          8
 | 
					 | 
				
			||||
                    // ["f 1/1 2/2 3/3", "1", "1", "2", "2", "3", "3", undefined, undefined]
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    state.addFace( | 
					 | 
				
			||||
                    result[1], result[3], result[5], result[7], | 
					 | 
				
			||||
                    result[2], result[4], result[6], result[8]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else if ((result = this.regexp.face_vertex_normal.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // f vertex//normal vertex//normal vertex//normal
 | 
					 | 
				
			||||
                    // 0                     1    2    3    4    5    6   7          8
 | 
					 | 
				
			||||
                    // ["f 1//1 2//2 3//3", "1", "1", "2", "2", "3", "3", undefined, undefined]
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    state.addFace( | 
					 | 
				
			||||
                    result[1], result[3], result[5], result[7], | 
					 | 
				
			||||
                    undefined, undefined, undefined, undefined, | 
					 | 
				
			||||
                    result[2], result[4], result[6], result[8]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else if ((result = this.regexp.face_vertex.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // f vertex vertex vertex
 | 
					 | 
				
			||||
                    // 0            1    2    3   4
 | 
					 | 
				
			||||
                    // ["f 1 2 3", "1", "2", "3", undefined]
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    state.addFace( | 
					 | 
				
			||||
                    result[1], result[2], result[3], result[4]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    throw new Error("Unexpected face line: '" + line + "'"); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else if (lineFirstChar === "l") { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var lineParts = line.substring(1).trim().split(" "); | 
					 | 
				
			||||
                var lineVertices = [], | 
					 | 
				
			||||
                    lineUVs = []; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (line.indexOf("/") === -1) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    lineVertices = lineParts; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    for (var li = 0, llen = lineParts.length; li < llen; li++) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        var parts = lineParts[li].split("/"); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        if (parts[0] !== "") lineVertices.push(parts[0]); | 
					 | 
				
			||||
                        if (parts[1] !== "") lineUVs.push(parts[1]); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
                state.addLineGeometry(lineVertices, lineUVs); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else if ((result = this.regexp.object_pattern.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // o object_name
 | 
					 | 
				
			||||
                // or
 | 
					 | 
				
			||||
                // g group_name
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var name = result[0].substr(1).trim(); | 
					 | 
				
			||||
                state.startObject(name); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else if (this.regexp.material_use_pattern.test(line)) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // material
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                state.object.startMaterial(line.substring(7).trim(), state.materialLibraries); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else if (this.regexp.material_library_pattern.test(line)) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // mtl file
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                state.materialLibraries.push(line.substring(7).trim()); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else if ((result = this.regexp.smoothing_pattern.exec(line)) !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // smooth shading
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // @todo Handle files that have varying smooth values for a set of faces inside one geometry,
 | 
					 | 
				
			||||
                // but does not define a usemtl for each face set.
 | 
					 | 
				
			||||
                // This should be detected and a dummy material created (later MultiMaterial and geometry groups).
 | 
					 | 
				
			||||
                // This requires some care to not create extra material on each smooth value for "normal" obj files.
 | 
					 | 
				
			||||
                // where explicit usemtl defines geometry groups.
 | 
					 | 
				
			||||
                // Example asset: examples/models/obj/cerberus/Cerberus.obj
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var value = result[1].trim().toLowerCase(); | 
					 | 
				
			||||
                state.object.smooth = (value === '1' || value === 'on'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var material = state.object.currentMaterial(); | 
					 | 
				
			||||
                if (material) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    material.smooth = state.object.smooth; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                // Handle null terminated files without exception
 | 
					 | 
				
			||||
                if (line === '\0') continue; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                throw new Error("Unexpected line: '" + line + "'"); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        state.finalize(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        var container = new THREE.Group(); | 
					 | 
				
			||||
        container.materialLibraries = [].concat(state.materialLibraries); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        for (var i = 0, l = state.objects.length; i < l; i++) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            var object = state.objects[i]; | 
					 | 
				
			||||
            var geometry = object.geometry; | 
					 | 
				
			||||
            var materials = object.materials; | 
					 | 
				
			||||
            var isLine = (geometry.type === 'Line'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            // Skip o/g line declarations that did not follow with any faces
 | 
					 | 
				
			||||
            if (geometry.vertices.length === 0) continue; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            var buffergeometry = new THREE.BufferGeometry(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            buffergeometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(geometry.vertices), 3)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            if (geometry.normals.length > 0) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                buffergeometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(geometry.normals), 3)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                buffergeometry.computeVertexNormals(); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            if (geometry.uvs.length > 0) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                buffergeometry.addAttribute('uv', new THREE.BufferAttribute(new Float32Array(geometry.uvs), 2)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            // Create materials
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            var createdMaterials = []; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            for (var mi = 0, miLen = materials.length; mi < miLen; mi++) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var sourceMaterial = materials[mi]; | 
					 | 
				
			||||
                var material = undefined; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (this.materials !== null) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    material = this.materials.create(sourceMaterial.name); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
 | 
					 | 
				
			||||
                    if (isLine && material && !(material instanceof THREE.LineBasicMaterial)) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                        var materialLine = new THREE.LineBasicMaterial(); | 
					 | 
				
			||||
                        materialLine.copy(material); | 
					 | 
				
			||||
                        material = materialLine; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                if (!material) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    material = (!isLine ? new THREE.MeshPhongMaterial() : new THREE.LineBasicMaterial()); | 
					 | 
				
			||||
                    material.name = sourceMaterial.name; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                material.shading = sourceMaterial.smooth ? THREE.SmoothShading : THREE.FlatShading; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                createdMaterials.push(material); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            // Create mesh
 | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            var mesh; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            if (createdMaterials.length > 1) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                for (var mi = 0, miLen = materials.length; mi < miLen; mi++) { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                    var sourceMaterial = materials[mi]; | 
					 | 
				
			||||
                    buffergeometry.addGroup(sourceMaterial.groupStart, sourceMaterial.groupCount, mi); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                var multiMaterial = new THREE.MultiMaterial(createdMaterials); | 
					 | 
				
			||||
                mesh = (!isLine ? new THREE.Mesh(buffergeometry, multiMaterial) : new THREE.Line(buffergeometry, multiMaterial)); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            } else { | 
					 | 
				
			||||
 | 
					 | 
				
			||||
                mesh = (!isLine ? new THREE.Mesh(buffergeometry, createdMaterials[0]) : new THREE.Line(buffergeometry, createdMaterials[0])); | 
					 | 
				
			||||
            } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            mesh.name = object.name; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
            container.add(mesh); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        console.timeEnd('OBJLoader'); | 
					 | 
				
			||||
 | 
					 | 
				
			||||
        return container; | 
					 | 
				
			||||
 | 
					 | 
				
			||||
    } | 
					 | 
				
			||||
 | 
					 | 
				
			||||
}; | 
					 | 
				
			||||
@ -1,31 +0,0 @@ | 
				
			|||||
<?xml version="1.0" encoding="UTF-8"?> | 
					 | 
				
			||||
<templates> | 
					 | 
				
			||||
<!--    Added an edit and delete button for 3D model also can upload 3D model--> | 
					 | 
				
			||||
    <t t-name="Field3DWidget" owl="1"> | 
					 | 
				
			||||
        <div t-ref="field_3d"> | 
					 | 
				
			||||
            <t t-if="!props.readonly"> | 
					 | 
				
			||||
                <FileUploader onUploaded.bind="onFileUploaded"> | 
					 | 
				
			||||
                    <t t-set-slot="toggler"> | 
					 | 
				
			||||
                        <button class="o_select_file_button btn btn-light | 
					 | 
				
			||||
                                border-0 rounded-circle m-1 p-1" | 
					 | 
				
			||||
                                data-tooltip="Edit" | 
					 | 
				
			||||
                                aria-label="Edit"> | 
					 | 
				
			||||
                            <i class="fa fa-pencil fa-fw"/> | 
					 | 
				
			||||
                        </button> | 
					 | 
				
			||||
                    </t> | 
					 | 
				
			||||
                    <button t-if="props.value and state.isValid" | 
					 | 
				
			||||
                            class="o_clear_file_button btn btn-light | 
					 | 
				
			||||
                            border-0 rounded-circle m-1 p-1" | 
					 | 
				
			||||
                            data-tooltip="Clear" | 
					 | 
				
			||||
                            aria-label="Clear" | 
					 | 
				
			||||
                            t-on-click="onFileRemove"> | 
					 | 
				
			||||
                        <i class="fa fa-trash-o fa-fw"/> | 
					 | 
				
			||||
                    </button> | 
					 | 
				
			||||
                </FileUploader> | 
					 | 
				
			||||
            </t> | 
					 | 
				
			||||
            <div t-attf-id="{{props.name}}_el" | 
					 | 
				
			||||
                 class="view3d-wrapper view3d-square"> | 
					 | 
				
			||||
            </div> | 
					 | 
				
			||||
        </div> | 
					 | 
				
			||||
    </t> | 
					 | 
				
			||||
</templates> | 
					 | 
				
			||||
@ -1,20 +0,0 @@ | 
				
			|||||
<?xml version="1.0" encoding="utf-8"?> | 
					 | 
				
			||||
<odoo> | 
					 | 
				
			||||
    <!-- Added a notebook and inside that added a field for uploading the 3D model--> | 
					 | 
				
			||||
    <record id="product_template_only_form_view" | 
					 | 
				
			||||
            model="ir.ui.view"> | 
					 | 
				
			||||
        <field name="name">product.template.view.form.inherit.model.viewer.widget</field> | 
					 | 
				
			||||
        <field name="model">product.template</field> | 
					 | 
				
			||||
        <field name="inherit_id" | 
					 | 
				
			||||
               ref="product.product_template_only_form_view"/> | 
					 | 
				
			||||
        <field name="arch" type="xml"> | 
					 | 
				
			||||
            <xpath expr="//notebook/page[@name='variants']" position="after"> | 
					 | 
				
			||||
                <page string="3D model viewer" name="viewer"> | 
					 | 
				
			||||
                    <div id="3d_model_div" class="3d_model_viewer"/> | 
					 | 
				
			||||
                    <field name="model_3d" string="Product" | 
					 | 
				
			||||
                           widget="3D_widget"/> | 
					 | 
				
			||||
                </page> | 
					 | 
				
			||||
            </xpath> | 
					 | 
				
			||||
        </field> | 
					 | 
				
			||||
    </record> | 
					 | 
				
			||||
</odoo> | 
					 | 
				
			||||