Merge branch 'dev' into ifcimporter

This commit is contained in:
kovacsv 2021-06-22 12:01:39 +02:00
commit 477dcbe1cd
35 changed files with 673 additions and 690 deletions

View File

@ -1 +1 @@
python -m http.server 8000
python -m http.server 8080

View File

@ -1,7 +1,7 @@
{
"name": "online-3d-viewer",
"description": "Online 3D Viewer",
"version": "0.7.14",
"version": "0.7.15",
"repository": "github:kovacsv/Online3DViewer",
"license": "MIT",
"devDependencies": {

View File

@ -27,6 +27,7 @@
<script type="text/javascript" src="../source/io/fileutils.js"></script>
<script type="text/javascript" src="../source/model/material.js"></script>
<script type="text/javascript" src="../source/model/triangle.js"></script>
<script type="text/javascript" src="../source/model/property.js"></script>
<script type="text/javascript" src="../source/model/element.js"></script>
<script type="text/javascript" src="../source/model/mesh.js"></script>
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>

View File

@ -28,6 +28,7 @@
<script type="text/javascript" src="../source/io/fileutils.js"></script>
<script type="text/javascript" src="../source/model/material.js"></script>
<script type="text/javascript" src="../source/model/triangle.js"></script>
<script type="text/javascript" src="../source/model/property.js"></script>
<script type="text/javascript" src="../source/model/element.js"></script>
<script type="text/javascript" src="../source/model/mesh.js"></script>
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>

View File

@ -27,6 +27,7 @@
<script type="text/javascript" src="../source/io/fileutils.js"></script>
<script type="text/javascript" src="../source/model/material.js"></script>
<script type="text/javascript" src="../source/model/triangle.js"></script>
<script type="text/javascript" src="../source/model/property.js"></script>
<script type="text/javascript" src="../source/model/element.js"></script>
<script type="text/javascript" src="../source/model/mesh.js"></script>
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>

View File

@ -27,6 +27,7 @@
<script type="text/javascript" src="../source/io/fileutils.js"></script>
<script type="text/javascript" src="../source/model/material.js"></script>
<script type="text/javascript" src="../source/model/triangle.js"></script>
<script type="text/javascript" src="../source/model/property.js"></script>
<script type="text/javascript" src="../source/model/element.js"></script>
<script type="text/javascript" src="../source/model/mesh.js"></script>
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>

View File

@ -75,6 +75,7 @@ OV.Importer3dm = class extends OV.ImporterBase
ImportRhinoDocument (rhinoDoc)
{
this.InitRhinoInstances (rhinoDoc);
this.ImportRhinoUserStrings (rhinoDoc);
this.ImportRhinoGeometry (rhinoDoc);
}
@ -95,6 +96,11 @@ OV.Importer3dm = class extends OV.ImporterBase
}
}
ImportRhinoUserStrings (rhinoDoc)
{
// TODO: https://github.com/mcneel/rhino3dm/issues/303
}
ImportRhinoGeometry (rhinoDoc)
{
let rhinoObjects = rhinoDoc.objects ();
@ -113,7 +119,7 @@ OV.Importer3dm = class extends OV.ImporterBase
if (rhinoAttributes.isInstanceDefinitionObject && rhinoInstanceReferences.length === 0) {
return;
}
let rhinoMesh = null;
let deleteMesh = false;
@ -174,6 +180,12 @@ OV.Importer3dm = class extends OV.ImporterBase
let mesh = new OV.Mesh ();
mesh.SetName (rhinoAttributes.name);
let userStrings = rhinoAttributes.getUserStrings ();
for (let i = 0; i < userStrings.length; i++) {
let userString = userStrings[i];
mesh.AddProperty (new OV.Property (OV.PropertyType.Text, userString[0], userString[1]));
}
let materialIndex = this.GetMaterialIndex (rhinoDoc, rhinoObject, rhinoInstanceReferences);
let threeJson = rhinoMesh.toThreejsJSON ();
let vertices = threeJson.data.attributes.position.array;
@ -246,7 +258,7 @@ OV.Importer3dm = class extends OV.ImporterBase
}
} else if (rhinoAttributes.materialSource === rhino.ObjectMaterialSource.MaterialFromLayer) {
let layerIndex = rhinoAttributes.layerIndex;
if (layerIndex > 0) {
if (layerIndex > -1) {
let layer = rhinoDoc.layers ().get (layerIndex);
let layerMaterialIndex = layer.renderMaterialIndex;
if (layerMaterialIndex > -1) {

View File

@ -476,6 +476,8 @@ OV.ImporterGltf = class extends OV.ImporterBase
ProcessMainFile (gltf)
{
this.ImportModelProperties (gltf);
let unsupportedExtensions = this.gltfExtensions.GetUnsupportedExtensions (gltf.extensionsRequired);
if (unsupportedExtensions.length > 0) {
this.SetError ();
@ -504,6 +506,18 @@ OV.ImporterGltf = class extends OV.ImporterBase
}
}
ImportModelProperties (gltf)
{
for (let propertyName in gltf.asset) {
if (gltf.asset.hasOwnProperty (propertyName)) {
if (typeof gltf.asset[propertyName] === 'string') {
const property = new OV.Property (OV.PropertyType.Text, propertyName, gltf.asset[propertyName]);
this.model.AddProperty (property);
}
}
}
}
GetDefaultScene (gltf)
{
let defaultSceneIndex = gltf.scene || 0;
@ -726,6 +740,8 @@ OV.ImporterGltf = class extends OV.ImporterBase
this.model.AddMesh (mesh);
if (gltfMesh.name !== undefined) {
mesh.SetName (gltfMesh.name);
} else if (gltfNode.name !== undefined) {
mesh.SetName (gltfNode.name);
}
for (let i = 0; i < gltfMesh.primitives.length; i++) {

View File

@ -3,6 +3,7 @@ OV.Element = class
constructor ()
{
this.name = '';
this.properties = [];
}
GetName ()
@ -35,6 +36,22 @@ OV.Element = class
return 0;
}
PropertyCount ()
{
return this.properties.length;
}
AddProperty (property)
{
this.properties.push (property);
return this.properties.length - 1;
}
GetProperty (index)
{
return this.properties[index];
}
EnumerateVertices (onVertex)
{

View File

@ -2,13 +2,7 @@ OV.CalculateTriangleNormal = function (v0, v1, v2)
{
let v = OV.SubCoord3D (v1, v0);
let w = OV.SubCoord3D (v2, v0);
let normal = new OV.Coord3D (
v.y * w.z - v.z * w.y,
v.z * w.x - v.x * w.z,
v.x * w.y - v.y * w.x
);
let normal = OV.CrossVector3D (v, w);
normal.Normalize ();
return normal;
};

18
source/model/property.js Normal file
View File

@ -0,0 +1,18 @@
OV.PropertyType =
{
Text : 1,
Integer : 2,
Number : 3,
Percent : 4,
Color : 5
};
OV.Property = class
{
constructor (type, name, value)
{
this.type = type;
this.name = name;
this.value = value;
}
};

View File

@ -184,6 +184,20 @@ describe ('Model Finalization', function() {
});
});
describe ('Model Properties', function() {
let model = new OV.Model ();
model.AddProperty (new OV.Property (OV.PropertyType.Text, 'name 01', 'value 01'));
model.AddProperty (new OV.Property (OV.PropertyType.Integer, 'name 02', 2));
model.AddProperty (new OV.Property (OV.PropertyType.Number, 'name 03', 3.5));
assert.strictEqual (model.PropertyCount (), 3);
assert.strictEqual (model.GetProperty (0).name, 'name 01');
assert.strictEqual (model.GetProperty (0).value, 'value 01');
assert.strictEqual (model.GetProperty (1).name, 'name 02');
assert.strictEqual (model.GetProperty (1).value, 2);
assert.strictEqual (model.GetProperty (2).name, 'name 03');
assert.strictEqual (model.GetProperty (2).value, 3.5);
});
describe ('Color Conversion', function() {
it ('Color equality check', function () {
assert (OV.ColorIsEqual (new OV.Color (10, 20, 30), new OV.Color (10, 20, 30)));

View File

@ -22,6 +22,7 @@
"source/io/fileutils.js",
"source/model/material.js",
"source/model/triangle.js",
"source/model/property.js",
"source/model/element.js",
"source/model/mesh.js",
"source/model/meshbuffer.js",
@ -64,6 +65,7 @@
"website_files" : [
"website/o3dv/featureset.js",
"website/o3dv/utils.js",
"website/o3dv/cookies.js",
"website/o3dv/toolbar.js",
"website/o3dv/treeview.js",
"website/o3dv/modal.js",
@ -72,10 +74,10 @@
"website/o3dv/exportdialog.js",
"website/o3dv/sharingdialog.js",
"website/o3dv/settingsdialog.js",
"website/o3dv/quantitiesdialog.js",
"website/o3dv/cookiedialog.js",
"website/o3dv/modeldata.js",
"website/o3dv/info.js",
"website/o3dv/navigator.js",
"website/o3dv/sidebar.js",
"website/o3dv/hashhandler.js",
"website/o3dv/website.css",
"website/o3dv/loader.js",

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 156 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18" xml:space="preserve"><style/><g style="fill:#263238;fill-opacity:1"><path style="fill:#263238;fill-opacity:1;fill-rule:evenodd;stroke:none" d="M0 0c-8.995 0-16.288-7.293-16.288-16.29 0-7.197 4.667-13.302 11.14-15.457.815-.149 1.112.354 1.112.786 0 .386-.014 1.411-.022 2.77-4.531-.984-5.487 2.184-5.487 2.184-.741 1.881-1.809 2.382-1.809 2.382-1.479 1.011.112.991.112.991 1.635-.116 2.495-1.679 2.495-1.679 1.453-2.489 3.813-1.77 4.741-1.354.148 1.053.568 1.771 1.034 2.178-3.617.411-7.42 1.809-7.42 8.051 0 1.778.635 3.232 1.677 4.371-.168.412-.727 2.068.159 4.311 0 0 1.368.438 4.48-1.67 1.299.361 2.693.542 4.078.548a15.625 15.625 0 0 0 4.078-.548c3.11 2.108 4.475 1.67 4.475 1.67.889-2.243.33-3.899.162-4.311 1.044-1.139 1.675-2.593 1.675-4.371 0-6.258-3.809-7.635-7.438-8.038.585-.503 1.106-1.497 1.106-3.017 0-2.177-.02-3.934-.02-4.468 0-.436.293-.943 1.12-.784 6.468 2.159 11.131 8.26 11.131 15.455C16.291-7.293 8.997 0 0 0" transform="matrix(.5525 0 0 -.5525 9 .444)"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18" xml:space="preserve"><g style="fill:#263238;fill-opacity:1"><path style="fill:#263238;fill-opacity:1;fill-rule:evenodd;stroke:none" d="M0 0c-8.995 0-16.288-7.293-16.288-16.29 0-7.197 4.667-13.302 11.14-15.457.815-.149 1.112.354 1.112.786 0 .386-.014 1.411-.022 2.77-4.531-.984-5.487 2.184-5.487 2.184-.741 1.881-1.809 2.382-1.809 2.382-1.479 1.011.112.991.112.991 1.635-.116 2.495-1.679 2.495-1.679 1.453-2.489 3.813-1.77 4.741-1.354.148 1.053.568 1.771 1.034 2.178-3.617.411-7.42 1.809-7.42 8.051 0 1.778.635 3.232 1.677 4.371-.168.412-.727 2.068.159 4.311 0 0 1.368.438 4.48-1.67 1.299.361 2.693.542 4.078.548a15.625 15.625 0 0 0 4.078-.548c3.11 2.108 4.475 1.67 4.475 1.67.889-2.243.33-3.899.162-4.311 1.044-1.139 1.675-2.593 1.675-4.371 0-6.258-3.809-7.635-7.438-8.038.585-.503 1.106-1.497 1.106-3.017 0-2.177-.02-3.934-.02-4.468 0-.436.293-.943 1.12-.784 6.468 2.159 11.131 8.26 11.131 15.455C16.291-7.293 8.997 0 0 0" transform="matrix(.5525 0 0 -.5525 9 .444)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18" xml:space="preserve"><style/><g style="fill:#3393bd;fill-opacity:1"><path style="fill:#3393bd;fill-opacity:1;fill-rule:evenodd;stroke:none" d="M0 0c-8.995 0-16.288-7.293-16.288-16.29 0-7.197 4.667-13.302 11.14-15.457.815-.149 1.112.354 1.112.786 0 .386-.014 1.411-.022 2.77-4.531-.984-5.487 2.184-5.487 2.184-.741 1.881-1.809 2.382-1.809 2.382-1.479 1.011.112.991.112.991 1.635-.116 2.495-1.679 2.495-1.679 1.453-2.489 3.813-1.77 4.741-1.354.148 1.053.568 1.771 1.034 2.178-3.617.411-7.42 1.809-7.42 8.051 0 1.778.635 3.232 1.677 4.371-.168.412-.727 2.068.159 4.311 0 0 1.368.438 4.48-1.67 1.299.361 2.693.542 4.078.548a15.625 15.625 0 0 0 4.078-.548c3.11 2.108 4.475 1.67 4.475 1.67.889-2.243.33-3.899.162-4.311 1.044-1.139 1.675-2.593 1.675-4.371 0-6.258-3.809-7.635-7.438-8.038.585-.503 1.106-1.497 1.106-3.017 0-2.177-.02-3.934-.02-4.468 0-.436.293-.943 1.12-.784 6.468 2.159 11.131 8.26 11.131 15.455C16.291-7.293 8.997 0 0 0" transform="matrix(.5525 0 0 -.5525 9 .444)"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18" style="enable-background:new 0 0 18 18" xml:space="preserve"><g style="fill:#3393bd;fill-opacity:1"><path style="fill:#3393bd;fill-opacity:1;fill-rule:evenodd;stroke:none" d="M0 0c-8.995 0-16.288-7.293-16.288-16.29 0-7.197 4.667-13.302 11.14-15.457.815-.149 1.112.354 1.112.786 0 .386-.014 1.411-.022 2.77-4.531-.984-5.487 2.184-5.487 2.184-.741 1.881-1.809 2.382-1.809 2.382-1.479 1.011.112.991.112.991 1.635-.116 2.495-1.679 2.495-1.679 1.453-2.489 3.813-1.77 4.741-1.354.148 1.053.568 1.771 1.034 2.178-3.617.411-7.42 1.809-7.42 8.051 0 1.778.635 3.232 1.677 4.371-.168.412-.727 2.068.159 4.311 0 0 1.368.438 4.48-1.67 1.299.361 2.693.542 4.078.548a15.625 15.625 0 0 0 4.078-.548c3.11 2.108 4.475 1.67 4.475 1.67.889-2.243.33-3.899.162-4.311 1.044-1.139 1.675-2.593 1.675-4.371 0-6.258-3.809-7.635-7.438-8.038.585-.503 1.106-1.497 1.106-3.017 0-2.177-.02-3.934-.02-4.468 0-.436.293-.943 1.12-.784 6.468 2.159 11.131 8.26 11.131 15.455C16.291-7.293 8.997 0 0 0" transform="matrix(.5525 0 0 -.5525 9 .444)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 18 18"><path d="m3.5 14.5 11-11m0 11-11-11" stroke-miterlimit="10" stroke-linejoin="round" stroke-linecap="round" stroke="#838383" fill="none"/></svg>

After

Width:  |  Height:  |  Size: 224 B

View File

Before

Width:  |  Height:  |  Size: 333 B

After

Width:  |  Height:  |  Size: 333 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 18 18"><path d="M14.5 16.5h-11c-.5 0-1-.5-1-1v-14c0-.6.5-1 1-1h11c.6 0 1 .4 1 1v14c0 .6-.4 1-1 1zm-7-13h5m-5 3h5m-5 3h5m-5 3h5m-7-9h0m0 3h0m0 3h0m0 3h0" stroke-miterlimit="10" stroke-linejoin="round" stroke-linecap="round" stroke="#3393BD" fill="none"/></svg>

After

Width:  |  Height:  |  Size: 333 B

View File

@ -35,6 +35,7 @@
<script type="text/javascript" src="../source/io/fileutils.js"></script>
<script type="text/javascript" src="../source/model/material.js"></script>
<script type="text/javascript" src="../source/model/triangle.js"></script>
<script type="text/javascript" src="../source/model/property.js"></script>
<script type="text/javascript" src="../source/model/element.js"></script>
<script type="text/javascript" src="../source/model/mesh.js"></script>
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
@ -78,6 +79,7 @@
<!-- website start -->
<script type="text/javascript" src="o3dv/featureset.js"></script>
<script type="text/javascript" src="o3dv/utils.js"></script>
<script type="text/javascript" src="o3dv/cookies.js"></script>
<script type="text/javascript" src="o3dv/toolbar.js"></script>
<script type="text/javascript" src="o3dv/treeview.js"></script>
<script type="text/javascript" src="o3dv/modal.js"></script>
@ -86,10 +88,10 @@
<script type="text/javascript" src="o3dv/exportdialog.js"></script>
<script type="text/javascript" src="o3dv/sharingdialog.js"></script>
<script type="text/javascript" src="o3dv/settingsdialog.js"></script>
<script type="text/javascript" src="o3dv/quantitiesdialog.js"></script>
<script type="text/javascript" src="o3dv/cookiedialog.js"></script>
<script type="text/javascript" src="o3dv/modeldata.js"></script>
<script type="text/javascript" src="o3dv/info.js"></script>
<script type="text/javascript" src="o3dv/navigator.js"></script>
<script type="text/javascript" src="o3dv/sidebar.js"></script>
<script type="text/javascript" src="o3dv/hashhandler.js"></script>
<link rel="stylesheet" type="text/css" href="o3dv/website.css">
<script type="text/javascript" src="o3dv/loader.js"></script>

View File

@ -16,6 +16,7 @@
<li><a href="index.html#model=../test/testfiles/obj/hundred_cubes.obj,../test/testfiles/obj/hundred_cubes.mtl">hundred_cubes.obj</a></li>
<li><a href="index.html#model=../test/testfiles/obj/icosahedron.obj">icosahedron.obj</a></li>
<li><a href="index.html#model=../test/testfiles/obj/error.obj">error.obj</a></li>
<li><a href="index.html#model=../test/testfiles/gltf/Box/glTF-Binary/Box.glb">Box.glb</a></li>
</ul>
</body>

View File

@ -35,6 +35,7 @@
<script type="text/javascript" src="../source/io/fileutils.js"></script>
<script type="text/javascript" src="../source/model/material.js"></script>
<script type="text/javascript" src="../source/model/triangle.js"></script>
<script type="text/javascript" src="../source/model/property.js"></script>
<script type="text/javascript" src="../source/model/element.js"></script>
<script type="text/javascript" src="../source/model/mesh.js"></script>
<script type="text/javascript" src="../source/model/meshbuffer.js"></script>
@ -78,6 +79,7 @@
<!-- website start -->
<script type="text/javascript" src="o3dv/featureset.js"></script>
<script type="text/javascript" src="o3dv/utils.js"></script>
<script type="text/javascript" src="o3dv/cookies.js"></script>
<script type="text/javascript" src="o3dv/toolbar.js"></script>
<script type="text/javascript" src="o3dv/treeview.js"></script>
<script type="text/javascript" src="o3dv/modal.js"></script>
@ -86,10 +88,10 @@
<script type="text/javascript" src="o3dv/exportdialog.js"></script>
<script type="text/javascript" src="o3dv/sharingdialog.js"></script>
<script type="text/javascript" src="o3dv/settingsdialog.js"></script>
<script type="text/javascript" src="o3dv/quantitiesdialog.js"></script>
<script type="text/javascript" src="o3dv/cookiedialog.js"></script>
<script type="text/javascript" src="o3dv/modeldata.js"></script>
<script type="text/javascript" src="o3dv/info.js"></script>
<script type="text/javascript" src="o3dv/navigator.js"></script>
<script type="text/javascript" src="o3dv/sidebar.js"></script>
<script type="text/javascript" src="o3dv/hashhandler.js"></script>
<link rel="stylesheet" type="text/css" href="o3dv/website.css">
<script type="text/javascript" src="o3dv/loader.js"></script>
@ -111,6 +113,7 @@
mainDiv : $('#main'),
introDiv : $('#intro'),
navigatorDiv : $('#main_navigator'),
sidebarDiv : $('#main_sidebar'),
viewerDiv : $('#main_viewer'),
fileInput : $('#open_file')
});
@ -144,6 +147,8 @@
</div>
<div class="main_viewer" id="main_viewer">
</div>
<div class="main_sidebar only_full_width" id="main_sidebar">
</div>
</div>
<div class="intro ov_thin_scrollbar" id="intro">
<div class="intro_section only_full_width only_full_height"><img src="assets/images/3dviewer_net_logo.svg" class="intro_logo"></img></div>

View File

@ -0,0 +1,19 @@
OV.ShowCookieDialog = function (onAccept)
{
let dialog = new OV.ButtonDialog ();
let contentDiv = dialog.Init ('Cookie Consent', [
{
name : 'Accept',
onClick () {
dialog.Hide ();
onAccept ();
}
}
]);
let text = 'This website uses cookies to offer you better user experience. See the details at the <a target="_blank" href="info/cookies.html">Cookies Policy</a> page.';
$('<div>').html (text).addClass ('ov_dialog_section').appendTo (contentDiv);
dialog.SetCloseable (false);
dialog.Show ();
return dialog;
};

46
website/o3dv/cookies.js Normal file
View File

@ -0,0 +1,46 @@
OV.CookieHandler = class
{
constructor ()
{
this.expirationDays = 365;
}
ClearVal (key)
{
this.SetStringVal (key, '');
}
GetBoolVal (key, defVal)
{
let stringVal = this.GetStringVal (key);
if (stringVal === null) {
return defVal;
}
return stringVal === 'true' ? true : false;
}
SetBoolVal (key, value)
{
this.SetStringVal (key, value ? 'true' : false);
}
SetStringVal (key, value)
{
let date = new Date ();
date.setTime (date.getTime () + (this.expirationDays * 24 * 60 * 60 * 1000));
document.cookie = key + '=' + value + '; expires=' + date.toUTCString () + ';';
}
GetStringVal (key)
{
let cookie = decodeURIComponent (document.cookie);
let cookieParts = cookie.split (';');
for (let i = 0; i < cookieParts.length; i++) {
let currentCookie = cookieParts[i].trim ();
if (currentCookie.startsWith (key + '=')) {
return currentCookie.substr (key.length + 1);
}
}
return null;
}
};

View File

@ -1,5 +1,4 @@
OV.FeatureSet =
{
SetDefaultColor : false,
CalculateQuantities : false
SetDefaultColor : false
};

View File

@ -1,173 +0,0 @@
OV.InfoPanel = class
{
constructor (parentDiv)
{
this.mainDiv = $('<div>').addClass ('ov_info_panel_main').appendTo (parentDiv);
this.treeView = new OV.TreeView (this.mainDiv);
this.detailsItem = new OV.TreeViewGroupItem ('Details', 'assets/images/tree/details.svg');
this.detailsItem.ShowChildren (!OV.IsSmallHeight (), null);
this.treeView.AddItem (this.detailsItem);
let childrenDiv = this.detailsItem.CreateChildrenDiv ();
childrenDiv.addClass ('ov_info_panel_content');
this.popup = null;
}
SetOpenCloseHandler (openCloseHandler)
{
this.detailsItem.SetAnimated (false);
this.detailsItem.SetOpenCloseHandler (openCloseHandler);
}
FillWithMaterialInfo (info, callbacks)
{
function AddRow (container, name, fillValue)
{
let row = $('<div>').addClass ('ov_info_box_row').appendTo (container);
$('<div>').addClass ('ov_info_box_row_name').html (name).appendTo (row);
let value = $('<div>').addClass ('ov_info_box_row_value').appendTo (row);
fillValue (value);
}
function AddTextRow (container, name, value)
{
AddRow (container, name, function (valueDiv) {
valueDiv.html (value).attr ('title', value);
});
}
function AddTextureRow (container, textureName)
{
AddRow (container, textureName.type, function (valueDiv) {
valueDiv.html (textureName.name).attr ('title', textureName.path);
});
}
this.Clear ();
if (info === null) {
return;
}
let contentDiv = this.detailsItem.GetChildrenDiv ();
let infoContainer = $('<div>').addClass ('ov_info_box').appendTo (contentDiv);
AddRow (infoContainer, 'Color', function (valueDiv) {
let colorString = '#' + OV.ColorToHexString (info.diffuse);
$('<div>').addClass ('ov_info_box_rgbbox').css ('background', colorString).attr ('title', colorString).appendTo (valueDiv);
$('<div>').addClass ('ov_info_box_rgbtext').html (colorString).attr ('title', colorString).appendTo (valueDiv);
});
let opacityString = parseInt (Math.round (info.opacity * 100.0), 10) + '%';
AddTextRow (infoContainer, 'Opacity', opacityString);
if (info.textureNames.length > 0) {
let texturesContainer = $('<div>').addClass ('ov_info_box').appendTo (contentDiv);
$('<div>').addClass ('ov_info_box_title').html ('Textures').appendTo (texturesContainer);
let texturesContent = $('<div>').addClass ('ov_info_box_details').appendTo (texturesContainer);
for (let i = 0; i < info.textureNames.length; i++) {
let textureName = info.textureNames[i];
AddTextureRow (texturesContent, textureName);
}
}
let meshItems = [];
for (let i = 0; i < info.usedByMeshes.length; i++) {
let meshInfo = info.usedByMeshes[i];
meshItems.push ({
name : OV.GetMeshName (meshInfo.name)
});
}
let obj = this;
let meshesText = 'Meshes (' + meshItems.length + ')';
this.CreateButton (contentDiv, meshesText, function (button) {
if (meshItems.length === 0) {
return;
}
obj.popup = OV.ShowListPopup (button, meshItems, {
onHoverStart : function (index) {
const meshItem = info.usedByMeshes[index];
callbacks.onMeshHover (meshItem.index);
},
onHoverStop : function (index) {
callbacks.onMeshHover (null);
},
onClick : function (index) {
const meshItem = info.usedByMeshes[index];
callbacks.onMeshSelect (meshItem.index);
}
});
});
}
FillWithModelInfo (info, callbacks)
{
function AddCounter (parent, name, value)
{
let infoBox = $('<div>').addClass ('ov_info_box_column').css ('width', '50%').appendTo (parent);
$('<div>').addClass ('ov_info_box_title').html (name).appendTo (infoBox);
$('<div>').addClass ('ov_info_box_content_big').html (value.toLocaleString ('en-US')).appendTo (infoBox);
}
this.Clear ();
if (info === null) {
return;
}
let contentDiv = this.detailsItem.GetChildrenDiv ();
let counterContainer = $('<div>').addClass ('ov_info_box').appendTo (contentDiv);
AddCounter (counterContainer, 'Vertices', info.element.VertexCount ());
AddCounter (counterContainer, 'Triangles', info.element.TriangleCount ());
let sizeContainer = $('<div>').addClass ('ov_info_box').appendTo (contentDiv);
$('<div>').addClass ('ov_info_box_title').html ('Size').appendTo (sizeContainer);
let size = OV.SubCoord3D (info.boundingBox.max, info.boundingBox.min);
let sizeString = size.x.toFixed (1) + ' x ' + size.y.toFixed (1) + ' x ' + size.z.toFixed (1);
$('<div>').addClass ('ov_info_box_content').html (sizeString).attr ('title', sizeString).appendTo (sizeContainer);
let materialItems = [];
for (let i = 0; i < info.usedMaterials.length; i++) {
let usedMaterial = info.usedMaterials[i];
materialItems.push ({
name : OV.GetMaterialName (usedMaterial.name),
color : OV.ColorToHexString (usedMaterial.diffuse)
});
}
let obj = this;
if (OV.FeatureSet.CalculateQuantities) {
this.CreateButton (contentDiv, 'Calculate Quantities', function (button) {
obj.popup = OV.ShowQuantitiesPopup (button, info.element);
});
}
let materialsText = 'Materials (' + materialItems.length + ')';
this.CreateButton (contentDiv, materialsText, function (button) {
obj.popup = OV.ShowListPopup (button, materialItems, {
onClick : function (index) {
let usedMaterial = info.usedMaterials[index];
callbacks.onMaterialSelect (usedMaterial.index);
}
});
});
}
CreateButton (parentDiv, buttonText, onClick)
{
let button = $('<div>').addClass ('ov_info_box_button').appendTo (parentDiv);
$('<div>').addClass ('ov_info_box_button_text').html (buttonText).appendTo (button);
$('<img>').addClass ('ov_info_box_button_icon').attr ('src', 'assets/images/tree/arrow_right.svg').appendTo (button);
button.click (function () {
onClick (button);
});
}
Clear ()
{
if (this.popup !== null) {
this.popup.Hide ();
this.popup = null;
}
let contentDiv = this.detailsItem.GetChildrenDiv ();
contentDiv.empty ();
}
};

View File

@ -165,6 +165,11 @@ OV.ButtonDialog = class
return dialogContentDiv;
}
SetCloseable (closeable)
{
this.modal.SetCloseable (closeable);
}
SetCloseHandler (closeHandler)
{
this.modal.SetCloseHandler (closeHandler);
@ -239,7 +244,9 @@ OV.ListPopup = class extends OV.PopupDialog
{
let listItemDiv = $('<div>').addClass ('ov_popup_list_item').appendTo (this.listDiv);
if (item.color) {
$('<div>').addClass ('ov_popup_list_item_rgbbox').css ('background', '#' + item.color).appendTo (listItemDiv);
let iconDiv = $('<div>').addClass ('ov_popup_list_item_icon').appendTo (listItemDiv);
let colorCircle = OV.CreateInlineColorCircle (item.color);
colorCircle.appendTo (iconDiv);
}
$('<div>').addClass ('ov_popup_list_item_name').html (item.name).appendTo (listItemDiv);
listItemDiv.click (callbacks.onClick);

View File

@ -13,17 +13,111 @@ OV.Selection = class
}
};
OV.Navigator = class
OV.NavigatorInfoPanel = class
{
constructor (parentDiv)
{
this.parentDiv = parentDiv;
this.popup = null;
}
FillWithMaterialInfo (usedByMeshes, callbacks)
{
this.Clear ();
if (usedByMeshes === null) {
return;
}
let meshItems = [];
for (let i = 0; i < usedByMeshes.length; i++) {
let meshInfo = usedByMeshes[i];
meshItems.push ({
name : OV.GetMeshName (meshInfo.name)
});
}
let obj = this;
let meshesText = 'Meshes (' + meshItems.length + ')';
this.CreateButton (this.parentDiv, meshesText, function (button) {
if (meshItems.length === 0) {
return;
}
obj.popup = OV.ShowListPopup (button, meshItems, {
onHoverStart : function (index) {
const meshItem = usedByMeshes[index];
callbacks.onMeshHover (meshItem.index);
},
onHoverStop : function (index) {
callbacks.onMeshHover (null);
},
onClick : function (index) {
const meshItem = usedByMeshes[index];
callbacks.onMeshSelect (meshItem.index);
}
});
});
}
FillWithModelInfo (usedMaterials, callbacks)
{
this.Clear ();
if (usedMaterials === null) {
return;
}
let materialItems = [];
for (let i = 0; i < usedMaterials.length; i++) {
let usedMaterial = usedMaterials[i];
materialItems.push ({
name : OV.GetMaterialName (usedMaterial.name),
color : usedMaterial.diffuse
});
}
let obj = this;
let materialsText = 'Materials (' + materialItems.length + ')';
this.CreateButton (this.parentDiv, materialsText, function (button) {
obj.popup = OV.ShowListPopup (button, materialItems, {
onClick : function (index) {
let usedMaterial = usedMaterials[index];
callbacks.onMaterialSelect (usedMaterial.index);
}
});
});
}
CreateButton (parentDiv, buttonText, onClick)
{
let button = $('<div>').addClass ('ov_navigator_info_button').appendTo (parentDiv);
$('<div>').addClass ('ov_navigator_info_button_text').html (buttonText).appendTo (button);
$('<img>').addClass ('ov_navigator_info_button_icon').attr ('src', 'assets/images/tree/arrow_right.svg').appendTo (button);
button.click (function () {
onClick (button);
});
}
Clear ()
{
if (this.popup !== null) {
this.popup.Hide ();
this.popup = null;
}
this.parentDiv.empty ();
}
};
OV.Navigator = class
{
constructor (parentDiv, sidebar)
{
this.parentDiv = parentDiv;
this.sidebar = sidebar;
this.callbacks = null;
this.titleDiv = $('<div>').addClass ('ov_navigator_tree_title').addClass ('ov_thin_scrollbar').appendTo (parentDiv);
this.titleDiv = $('<div>').addClass ('ov_navigator_tree_title').appendTo (parentDiv);
this.treeDiv = $('<div>').addClass ('ov_navigator_tree_panel').addClass ('ov_thin_scrollbar').appendTo (parentDiv);
this.infoDiv = $('<div>').addClass ('ov_navigator_info_panel').addClass ('ov_thin_scrollbar').appendTo (parentDiv);
this.treeView = new OV.TreeView (this.treeDiv);
this.infoPanel = new OV.InfoPanel (this.infoDiv);
this.infoPanel = new OV.NavigatorInfoPanel (this.infoDiv);
this.modelData = new OV.ModelData ();
this.selection = null;
this.tempSelectedMeshIndex = null;
@ -31,11 +125,7 @@ OV.Navigator = class
Init (callbacks)
{
let obj = this;
this.callbacks = callbacks;
this.infoPanel.SetOpenCloseHandler (function () {
obj.Resize ();
});
}
Resize ()
@ -220,16 +310,18 @@ OV.Navigator = class
{
let obj = this;
if (this.selection === null) {
let modelInfo = this.callbacks.getModelInformation ();
this.infoPanel.FillWithModelInfo (modelInfo, {
let usedMaterials = this.callbacks.getMaterialsForModel ();
this.infoPanel.FillWithModelInfo (usedMaterials, {
onMaterialSelect : function (materialIndex) {
obj.SetSelection (new OV.Selection (OV.SelectionType.Material, materialIndex));
}
});
let model = this.callbacks.getModel ();
this.sidebar.AddElementProperties (model);
} else {
if (this.selection.type === OV.SelectionType.Material) {
let materialInfo = this.callbacks.getMaterialInformation (this.selection.index);
this.infoPanel.FillWithMaterialInfo (materialInfo, {
let usedByMeshes = this.callbacks.getMeshesForMaterial (this.selection.index);
this.infoPanel.FillWithMaterialInfo (usedByMeshes, {
onMeshHover : function (meshIndex) {
obj.SetTempSelectedMeshIndex (meshIndex);
},
@ -237,13 +329,19 @@ OV.Navigator = class
obj.SetSelection (new OV.Selection (OV.SelectionType.Mesh, meshIndex));
}
});
let model = this.callbacks.getModel ();
let material = model.GetMaterial (this.selection.index);
this.sidebar.AddMaterialProperties (material);
} else if (this.selection.type === OV.SelectionType.Mesh) {
let meshInfo = this.callbacks.getMeshInformation (this.selection.index);
this.infoPanel.FillWithModelInfo (meshInfo, {
let usedMaterials = this.callbacks.getMaterialsForMesh (this.selection.index);
this.infoPanel.FillWithModelInfo (usedMaterials, {
onMaterialSelect : function (materialIndex) {
obj.SetSelection (new OV.Selection (OV.SelectionType.Material, materialIndex));
}
});
let model = this.callbacks.getModel ();
let mesh = model.GetMesh (this.selection.index);
this.sidebar.AddElementProperties (mesh);
}
}
this.Resize ();

View File

@ -1,29 +0,0 @@
OV.ShowQuantitiesPopup = function (parentItem, element)
{
let popup = new OV.PopupDialog ();
let contentDiv = popup.Init (parentItem);
$('<div>').addClass ('ov_popup_title').html ('Volume').appendTo (contentDiv);
let volumeDiv = $('<div>').addClass ('ov_popup_text').html ('Calculating...').appendTo (contentDiv);
$('<div>').addClass ('ov_popup_title').html ('Surface Area').appendTo (contentDiv);
let surfaceAreaDiv = $('<div>').addClass ('ov_popup_text').html ('Calculating...').appendTo (contentDiv);
OV.RunTaskAsync (function () {
const volume = OV.CalculateVolume (element);
const surfaceArea = OV.CalculateSurfaceArea (element);
let volumeString = '';
if (volume === null) {
volumeString = 'The model is not closed.';
} else {
volumeString = volume.toFixed (5);
}
let surfaceAreaString = surfaceArea.toFixed (5);
volumeDiv.html (volumeString);
surfaceAreaDiv.html (surfaceAreaString);
});
popup.Show ();
return popup;
};

168
website/o3dv/sidebar.js Normal file
View File

@ -0,0 +1,168 @@
OV.Sidebar = class
{
constructor (parentDiv)
{
this.parentDiv = parentDiv;
this.callbacks = null;
this.visible = true;
this.titleDiv = null;
this.contentDiv = null;
}
Init (callbacks)
{
this.callbacks = callbacks;
this.titleDiv = $('<div>').addClass ('ov_sidebar_title').appendTo (this.parentDiv);
this.contentDiv = $('<div>').addClass ('ov_sidebar_content').addClass ('ov_thin_scrollbar').appendTo (this.parentDiv);
let titleTextDiv = $('<div>').addClass ('ov_sidebar_title_text').html ('Details').appendTo (this.titleDiv);
let titleImg = $('<img>').addClass ('ov_sidebar_title_img').attr ('src', 'assets/images/sidebar/close.svg').appendTo (this.titleDiv);
let obj = this;
titleImg.click (function () {
obj.callbacks.onClose ();
});
}
Show (show)
{
this.visible = show;
if (this.visible) {
this.parentDiv.show ();
} else {
this.parentDiv.hide ();
}
}
IsVisible ()
{
return this.visible;
}
AddProperty (table, property)
{
let row = $('<div>').addClass ('ov_property_table_row').appendTo (table);
let nameColum = $('<div>').addClass ('ov_property_table_cell ov_property_table_name').appendTo (row);
let valueColumn = $('<div>').addClass ('ov_property_table_cell ov_property_table_value').appendTo (row);
nameColum.html (property.name + ':').attr ('title', property.name);
this.DisplayPropertyValue (property, valueColumn);
}
AddCalculatedProperty (table, name, calculateValue)
{
let row = $('<div>').addClass ('ov_property_table_row').appendTo (table);
let nameColum = $('<div>').addClass ('ov_property_table_cell ov_property_table_name').appendTo (row);
let valueColumn = $('<div>').addClass ('ov_property_table_cell ov_property_table_value').appendTo (row);
nameColum.html (name + ':').attr ('title', name);
let obj = this;
let calculateButton = $('<div>').addClass ('ov_property_table_button').html ('Calculate...').appendTo (valueColumn);
calculateButton.click (function () {
valueColumn.empty ();
valueColumn.html ('Please wait...');
OV.RunTaskAsync (function () {
let propertyValue = calculateValue ();
if (propertyValue === null) {
valueColumn.html ('-');
} else {
obj.DisplayPropertyValue (propertyValue, valueColumn);
}
});
});
}
DisplayPropertyValue (property, targetDiv)
{
targetDiv.empty ();
let valueText = null;
if (property.type === OV.PropertyType.Text) {
valueText = property.value;
} else if (property.type === OV.PropertyType.Integer) {
valueText = property.value.toLocaleString ();
} else if (property.type === OV.PropertyType.Number) {
valueText = property.value.toLocaleString (undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
} else if (property.type === OV.PropertyType.Percent) {
valueText = parseInt (property.value * 100, 10).toString () + '%';
} else if (property.type === OV.PropertyType.Color) {
let hexString = '#' + OV.ColorToHexString (property.value);
let colorCircle = OV.CreateInlineColorCircle (property.value);
colorCircle.appendTo (targetDiv);
$('<span>').html (hexString).appendTo (targetDiv);
}
if (valueText !== null) {
targetDiv.html (valueText).attr ('title', valueText);
}
}
AddElementProperties (element)
{
this.Clear ();
let table = $('<div>').addClass ('ov_property_table').appendTo (this.contentDiv);
let boundingBox = OV.GetBoundingBox (element);
let size = OV.SubCoord3D (boundingBox.max, boundingBox.min);
this.AddProperty (table, new OV.Property (OV.PropertyType.Integer, 'Vertex Count', element.VertexCount ()));
this.AddProperty (table, new OV.Property (OV.PropertyType.Integer, 'Triangle Count', element.TriangleCount ()));
this.AddProperty (table, new OV.Property (OV.PropertyType.Number, 'Size X', size.x));
this.AddProperty (table, new OV.Property (OV.PropertyType.Number, 'Size Y', size.y));
this.AddProperty (table, new OV.Property (OV.PropertyType.Number, 'Size Z', size.z));
this.AddCalculatedProperty (table, 'Volume', function () {
const volume = OV.CalculateVolume (element);
if (volume === null) {
return null;
}
return new OV.Property (OV.PropertyType.Number, null, volume);
});
this.AddCalculatedProperty (table, 'Surface Area', function () {
const volume = OV.CalculateSurfaceArea (element);
if (volume === null) {
return null;
}
return new OV.Property (OV.PropertyType.Number, null, volume);
});
if (element.PropertyCount () > 0) {
let customTable = $('<div>').addClass ('ov_property_table ov_property_table_custom').appendTo (this.contentDiv);
for (let i = 0; i < element.PropertyCount (); i++) {
const property = element.GetProperty (i);
this.AddProperty (customTable, property);
}
}
this.Resize ();
}
AddMaterialProperties (material)
{
function AddTextureMap (obj, table, name, map)
{
if (map === null || map.name === null) {
return;
}
let fileName = OV.GetFileName (map.name);
obj.AddProperty (table, new OV.Property (OV.PropertyType.Text, name, fileName));
}
this.Clear ();
let table = $('<div>').addClass ('ov_property_table').appendTo (this.contentDiv);
this.AddProperty (table, new OV.Property (OV.PropertyType.Color, 'Color', material.diffuse));
this.AddProperty (table, new OV.Property (OV.PropertyType.Percent, 'Opacity', material.opacity));
AddTextureMap (this, table, 'Diffuse Map', material.diffuseMap);
AddTextureMap (this, table, 'Specular Map', material.specularMap);
AddTextureMap (this, table, 'Bump Map', material.bumpMap);
AddTextureMap (this, table, 'Normal Map', material.normalMap);
AddTextureMap (this, table, 'Emissive Map', material.emissiveMap);
this.Resize ();
}
Resize ()
{
let titleHeight = this.titleDiv.outerHeight (true);
let height = this.parentDiv.height ();
this.contentDiv.outerHeight (height - titleHeight, true);
}
Clear ()
{
this.contentDiv.empty ();
}
};

View File

@ -12,12 +12,13 @@ OV.ToolbarButton = class
CreateDomElement (parentDiv)
{
this.buttonDiv = $('<div>').addClass ('ov_toolbar_button_div').appendTo (parentDiv);
this.buttonDiv = $('<div>').addClass ('ov_toolbar_button').appendTo (parentDiv);
this.buttonImg = $('<img>').addClass ('ov_toolbar_button').appendTo (this.buttonDiv);
this.buttonImg.attr ('src', this.image);
if (this.onClick !== null) {
this.buttonDiv.click (this.onClick);
}
this.buttonDiv.attr ('alt', this.imageTitle);
OV.InstallTooltip (this.buttonDiv, this.imageTitle);
this.Update ();
}

View File

@ -136,3 +136,15 @@ OV.CreateIconButton = function (iconName, hoverIconName, title, link)
}
return buttonLink;
};
OV.CreateInlineColorCircle = function (color)
{
let hexString = '#' + OV.ColorToHexString (color);
let darkerColor = new OV.Color (
Math.max (0, color.r - 50),
Math.max (0, color.g - 50),
Math.max (0, color.b - 50)
);
let darkerColorHexString = '#' + OV.ColorToHexString (darkerColor);
return $('<div>').addClass ('ov_color_circle').css ('background', hexString).css ('border', '1px solid ' + darkerColorHexString);
};

View File

@ -118,7 +118,7 @@ div.main
div.main_navigator
{
width: 240px;
width: 260px;
margin: 10px 0px 10px 10px;
overflow: none;
float: left;
@ -129,6 +129,14 @@ div.main_viewer
float: left;
}
div.main_sidebar
{
width: 260px;
margin: 10px 10px 10px 0px;
overflow: none;
float: right;
}
div.main_viewer canvas
{
margin: 10px;
@ -167,14 +175,26 @@ div.ov_toolbar
user-select: none;
}
div.ov_toolbar div.ov_toolbar_button_div
div.ov_toolbar div.ov_toolbar_button
{
padding: 10px;
float: left;
cursor: pointer;
}
div.ov_toolbar div.ov_toolbar_button_div.selected
div.ov_toolbar div.ov_toolbar_button
{
padding: 10px;
float: left;
cursor: pointer;
}
div.ov_toolbar div.ov_toolbar_button.right
{
float: right;
}
div.ov_toolbar div.ov_toolbar_button.selected
{
background: #e1e1e1;
}
@ -217,88 +237,7 @@ div.ov_navigator_info_panel
border-top: 1px solid #dddddd;
}
div.ov_navigator_info_panel div.ov_info_panel_main
{
margin-top: 5px;
}
div.ov_navigator_info_panel div.ov_info_panel_content
{
padding: 5px 0px 0px 5px;
}
div.ov_navigator_info_panel div.ov_info_box
{
margin-bottom: 10px;
overflow: auto;
}
div.ov_navigator_info_panel div.ov_info_box_column
{
float: left;
}
div.ov_navigator_info_panel div.ov_info_box_title
{
margin-bottom: 3px;
}
div.ov_navigator_info_panel div.ov_info_box_content
{
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
div.ov_navigator_info_panel div.ov_info_box_content_big
{
font-size: 21px;
font-weight: bold;
}
div.ov_navigator_info_panel div.ov_info_box_details
{
font-size: 14px;
padding-left: 10px;
}
div.ov_navigator_info_panel div.ov_info_box_row
{
padding: 2px 0px;
overflow: auto;
}
div.ov_navigator_info_panel div.ov_info_box_row_name
{
width: 40%;
float: left;
}
div.ov_navigator_info_panel div.ov_info_box_row_value
{
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
div.ov_navigator_info_panel div.ov_info_box_rgbbox
{
width : 32px;
height: 16px;
margin-right: 10px;
border: 1px solid #222222;
border-radius: 5px;
float: left;
}
div.ov_navigator_info_panel div.ov_info_box_rgbtext
{
font-size: 14px;
}
div.ov_navigator_info_panel div.ov_info_box_button
div.ov_navigator_info_panel div.ov_navigator_info_button
{
cursor: pointer;
margin-top: 10px;
@ -307,13 +246,13 @@ div.ov_navigator_info_panel div.ov_info_box_button
overflow: auto;
}
div.ov_navigator_info_panel div.ov_info_box_button_text
div.ov_navigator_info_panel div.ov_navigator_info_button_text
{
padding: 5px;
float: left;
}
div.ov_navigator_info_panel img.ov_info_box_button_icon
div.ov_navigator_info_panel img.ov_navigator_info_button_icon
{
width: 18px;
height: 18px;
@ -321,6 +260,35 @@ div.ov_navigator_info_panel img.ov_info_box_button_icon
float: right;
}
div.ov_sidebar_title
{
font-weight: bold;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #dddddd;
}
div.ov_sidebar_title div.ov_sidebar_title_text
{
float: left;
}
div.ov_sidebar_title img.ov_sidebar_title_img
{
width: 18px;
height: 18px;
float: right;
cursor: pointer;
}
div.ov_sidebar_content
{
overflow: auto;
}
div.ov_tree_view
{
user-select: none;
@ -380,9 +348,21 @@ div.ov_tree_view div.ov_tree_view_children
margin-left: 28px;
}
div.ov_color_circle
{
background: #ffffff;
border: 1px solid #000000;
width: 14px;
height: 14px;
display: inline-block;
margin-right: 5px;
margin-bottom: -2px;
border-radius: 10px;
}
div.ov_modal_overlay
{
}
div.ov_dialog
@ -628,22 +608,6 @@ div.ov_popup
border-radius: 5px;
}
div.ov_popup div.ov_popup_title
{
font-weight: bold;
margin-top: 15px;
margin-bottom: 10px;
margin-left: 10px;
margin-right: 10px;
}
div.ov_popup div.ov_popup_text
{
margin-bottom: 15px;
margin-left: 10px;
margin-right: 10px;
}
div.ov_popup div.ov_popup_list
{
max-height: 200px;
@ -660,12 +624,8 @@ div.ov_popup div.ov_popup_list_item
cursor: pointer;
}
div.ov_popup div.ov_popup_list_item_rgbbox
div.ov_popup div.ov_popup_list_item_icon
{
width: 18px;
height: 18px;
margin-right: 5px;
border: 1px solid #222222;
float: left;
}
@ -697,6 +657,52 @@ div.ov_progress div.ov_progress_text
text-align: center;
}
div.ov_property_table
{
}
div.ov_property_table_custom
{
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid #dddddd;
}
div.ov_property_table div.ov_property_table_row
{
overflow: auto;
}
div.ov_property_table div.ov_property_table_cell
{
padding: 4px 0px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
box-sizing: border-box;
}
div.ov_property_table div.ov_property_table_name
{
width: 49%;
padding-right: 2%;
float: left;
}
div.ov_property_table div.ov_property_table_value
{
width: 49%;
text-align: right;
float: left;
}
div.ov_property_table div.ov_property_table_button
{
color: #3393bd;
cursor: pointer;
}
div.ov_thin_scrollbar
{
scrollbar-color: #cccccc transparent;
@ -722,7 +728,7 @@ a:hover
text-decoration: underline;
}
div.ov_toolbar div.ov_toolbar_button_div:hover
div.ov_toolbar div.ov_toolbar_button:hover
{
background: #c9e5f8;
}
@ -747,7 +753,7 @@ div.ov_popup div.ov_popup_list_item:hover
background: #e4f4ff;
}
div.ov_navigator_info_panel div.ov_info_box_button:hover
div.ov_navigator_info_panel div.ov_navigator_info_button:hover
{
background: #e4f4ff;
}

View File

@ -5,8 +5,10 @@ OV.Website = class
this.parameters = parameters;
this.viewer = new OV.Viewer ();
this.hashHandler = new OV.HashHandler ();
this.cookieHandler = new OV.CookieHandler ();
this.toolbar = new OV.Toolbar (this.parameters.toolbarDiv);
this.navigator = new OV.Navigator (this.parameters.navigatorDiv);
this.sidebar = new OV.Sidebar (this.parameters.sidebarDiv);
this.navigator = new OV.Navigator (this.parameters.navigatorDiv, this.sidebar);
this.importSettings = new OV.ImportSettings ();
this.modelLoader = new OV.ThreeModelLoader ();
this.highlightMaterial = new THREE.MeshPhongMaterial ({
@ -19,6 +21,7 @@ OV.Website = class
Load ()
{
let canvas = $('<canvas>').appendTo (this.parameters.viewerDiv);
this.viewer.Init (canvas.get (0));
this.ShowViewer (false);
@ -27,7 +30,9 @@ OV.Website = class
this.InitToolbar ();
this.InitDragAndDrop ();
this.InitModelLoader ();
this.InitSidebar ();
this.InitNavigator ();
this.InitCookieConsent ();
this.viewer.SetClickHandler (this.OnModelClicked.bind (this));
this.Resize ();
@ -47,18 +52,25 @@ OV.Website = class
let headerHeight = parseInt (this.parameters.headerDiv.outerHeight (true), 10);
let navigatorWidth = 0;
let sidebarWidth = 0;
let safetyMargin = 0;
if (!OV.IsSmallWidth ()) {
navigatorWidth = parseInt (this.parameters.navigatorDiv.outerWidth (true), 10);
if (this.sidebar.IsVisible ()) {
sidebarWidth = parseInt (this.parameters.sidebarDiv.outerWidth (true), 10);
}
safetyMargin = 1;
}
let contentWidth = windowWidth - navigatorWidth - safetyMargin;
let contentWidth = windowWidth - navigatorWidth - sidebarWidth - safetyMargin;
let contentHeight = windowHeight - headerHeight - safetyMargin;
this.parameters.navigatorDiv.outerHeight (contentHeight, true);
this.parameters.sidebarDiv.outerHeight (contentHeight, true);
this.parameters.introDiv.outerHeight (contentHeight, true);
this.navigator.Resize ();
this.sidebar.Resize ();
this.viewer.Resize (contentWidth, contentHeight);
}
@ -71,6 +83,12 @@ OV.Website = class
}
}
ShowSidebar (show)
{
this.sidebar.Show (show);
this.cookieHandler.SetBoolVal ('ov_show_sidebar', show);
}
ClearModel ()
{
if (this.dialog !== null) {
@ -214,8 +232,16 @@ OV.Website = class
if (onlyFullWidth) {
button.AddClass ('only_full_width');
}
return button;
}
function AddRightButton (toolbar, imageName, imageTitle, onlyFullWidth, onClick)
{
let button = AddButton (toolbar, imageName, imageTitle, onlyFullWidth, onClick);
button.AddClass ('right');
return button;
}
function AddRadioButton (toolbar, imageNames, imageTitles, selectedIndex, onlyFullWidth, onClick)
{
let imageData = [];
@ -258,7 +284,7 @@ OV.Website = class
});
});
AddSeparator (this.toolbar);
AddButton (this.toolbar, 'fit', 'Fit model to Window', false, function () {
AddButton (this.toolbar, 'fit', 'Fit model to window', false, function () {
obj.FitModelToWindow (false);
});
AddButton (this.toolbar, 'up_y', 'Set Y axis as up vector', false, function () {
@ -305,6 +331,10 @@ OV.Website = class
});
});
}
AddRightButton (this.toolbar, 'details', 'Details panel', true, function () {
obj.ShowSidebar (!obj.sidebar.IsVisible ());
obj.Resize ();
});
this.parameters.fileInput.on ('change', function (ev) {
if (ev.target.files.length > 0) {
@ -354,6 +384,19 @@ OV.Website = class
});
}
InitSidebar ()
{
let obj = this;
this.sidebar.Init ({
onClose : function () {
obj.ShowSidebar (false);
obj.Resize ();
}
});
let show = this.cookieHandler.GetBoolVal ('ov_show_sidebar', true);
this.ShowSidebar (show);
}
InitNavigator ()
{
function GetMeshUserData (viewer, meshIndex)
@ -367,58 +410,19 @@ OV.Website = class
return userData;
}
function GetBoundingBoxInfo (boundingBox)
function GetMeshesForMaterial (viewer, model, materialIndex)
{
if (boundingBox === null) {
return null;
}
return {
min : new OV.Coord3D (boundingBox.min.x, boundingBox.min.y, boundingBox.min.z),
max : new OV.Coord3D (boundingBox.max.x, boundingBox.max.y, boundingBox.max.z)
};
}
function GetMaterialInfo (viewer, model, materialIndex)
{
function AddTexture (textureNames, type, texture)
{
if (texture === null) {
return;
}
textureNames.push ({
type : type,
name : OV.GetFileName (texture.name),
path : texture.name
});
}
let material = model.GetMaterial (materialIndex);
let materialInfo = {
name : material.name,
ambient : material.ambient.Clone (),
diffuse : material.diffuse.Clone (),
specular : material.specular.Clone (),
opacity : material.opacity,
textureNames : [],
usedByMeshes : []
};
AddTexture (materialInfo.textureNames, 'Base', material.diffuseMap);
AddTexture (materialInfo.textureNames, 'Specular', material.specularMap);
AddTexture (materialInfo.textureNames, 'Bump', material.bumpMap);
AddTexture (materialInfo.textureNames, 'Normal', material.normalMap);
AddTexture (materialInfo.textureNames, 'Emissive', material.emissiveMap);
let usedByMeshes = [];
viewer.EnumerateMeshesUserData (function (meshUserData) {
if (meshUserData.originalMaterials.indexOf (materialIndex) !== -1) {
const mesh = model.GetMesh (meshUserData.originalMeshIndex);
materialInfo.usedByMeshes.push ({
usedByMeshes.push ({
index : meshUserData.originalMeshIndex,
name : mesh.GetName ()
});
}
});
return materialInfo;
return usedByMeshes;
}
function GetMaterialReferenceInfo (model, materialIndex)
@ -431,50 +435,27 @@ OV.Website = class
};
}
function GetMeshInfo (viewer, model, meshIndex)
function GetMaterialsForMesh (viewer, model, meshIndex)
{
let result = {
element : null,
usedMaterials : null,
boundingBox : null
};
let mesh = model.GetMesh (meshIndex);
result.element = mesh;
let usedMaterials = [];
let userData = GetMeshUserData (viewer, meshIndex);
result.usedMaterials = [];
for (let i = 0; i < userData.originalMaterials.length; i++) {
const materialIndex = userData.originalMaterials[i];
result.usedMaterials.push (GetMaterialReferenceInfo (model, materialIndex));
usedMaterials.push (GetMaterialReferenceInfo (model, materialIndex));
}
result.usedMaterials.sort (function (a, b) {
usedMaterials.sort (function (a, b) {
return a.index - b.index;
});
let boundingBox = viewer.GetBoundingBox (function (meshUserData) {
return meshUserData.originalMeshIndex === meshIndex;
});
result.boundingBox = GetBoundingBoxInfo (boundingBox);
return result;
return usedMaterials;
}
function GetModelInfo (model, viewer)
function GetMaterialsForModel (model)
{
let result = {
element : model,
usedMaterials : null,
boundingBox : null
};
let boundingBox = viewer.GetBoundingBox (function (meshUserData) {
return true;
});
result.usedMaterials = [];
let usedMaterials = [];
for (let materialIndex = 0; materialIndex < model.MaterialCount (); materialIndex++) {
result.usedMaterials.push (GetMaterialReferenceInfo (model, materialIndex));
usedMaterials.push (GetMaterialReferenceInfo (model, materialIndex));
}
result.boundingBox = GetBoundingBoxInfo (boundingBox);
return result;
return usedMaterials;
}
let obj = this;
@ -491,15 +472,31 @@ OV.Website = class
fitMeshToWindow : function (meshIndex) {
obj.FitMeshToWindow (meshIndex);
},
getMaterialInformation : function (materialIndex) {
return GetMaterialInfo (obj.viewer, obj.model, materialIndex);
getMeshesForMaterial : function (materialIndex) {
return GetMeshesForMaterial (obj.viewer, obj.model, materialIndex);
},
getMeshInformation : function (meshIndex) {
return GetMeshInfo (obj.viewer, obj.model, meshIndex);
getMaterialsForMesh : function (meshIndex) {
return GetMaterialsForMesh (obj.viewer, obj.model, meshIndex);
},
getModelInformation : function () {
return GetModelInfo (obj.model, obj.viewer);
getMaterialsForModel : function () {
return GetMaterialsForModel (obj.model);
},
getModel : function () {
return obj.model;
}
});
}
}
InitCookieConsent ()
{
let accepted = this.cookieHandler.GetBoolVal ('ov_cookie_consent', false);
if (accepted) {
return;
}
let obj = this;
OV.ShowCookieDialog (function () {
obj.cookieHandler.SetBoolVal ('ov_cookie_consent', true);
});
}
};