mirror of
https://github.com/nerfstudio-project/nerfstudio.git
synced 2026-11-13 19:33:46 +08:00
Prettified Code!
This commit is contained in:
1 parent
e38c1abf7f
commit
0b246d6978
6 files changed
+453
-453
No files matched your search
@@ -12,38 +12,38 @@ import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUti
|
||||
// * A new merged `BufferGeometry` if the input contains meshes
|
||||
// * empty `BufferGeometry` otherwise
|
||||
function merge_geometries(object, preserve_materials = false) {
|
||||
let materials = [];
|
||||
let geometries = [];
|
||||
let root_transform = object.matrix.clone();
|
||||
let materials = [];
|
||||
let geometries = [];
|
||||
let root_transform = object.matrix.clone();
|
||||
|
||||
function collectGeometries(node, parent_transform) {
|
||||
let transform = parent_transform.clone().multiply(node.matrix);
|
||||
if (node.type === "Mesh") {
|
||||
node.geometry.applyMatrix(transform);
|
||||
geometries.push(node.geometry);
|
||||
materials.push(node.material);
|
||||
}
|
||||
for (let child of node.children) {
|
||||
collectGeometries(child, transform);
|
||||
}
|
||||
function collectGeometries(node, parent_transform) {
|
||||
let transform = parent_transform.clone().multiply(node.matrix);
|
||||
if (node.type === "Mesh") {
|
||||
node.geometry.applyMatrix(transform);
|
||||
geometries.push(node.geometry);
|
||||
materials.push(node.material);
|
||||
}
|
||||
for (let child of node.children) {
|
||||
collectGeometries(child, transform);
|
||||
}
|
||||
}
|
||||
|
||||
collectGeometries(object, root_transform);
|
||||
let result = null;
|
||||
if (geometries.length === 1) {
|
||||
result = geometries[0];
|
||||
if (preserve_materials) {
|
||||
result.material = materials[0];
|
||||
}
|
||||
} else if (geometries.length > 1) {
|
||||
result = BufferGeometryUtils.mergeBufferGeometries(geometries, true);
|
||||
if (preserve_materials) {
|
||||
result.material = materials;
|
||||
}
|
||||
} else {
|
||||
result = new THREE.BufferGeometry();
|
||||
collectGeometries(object, root_transform);
|
||||
let result = null;
|
||||
if (geometries.length === 1) {
|
||||
result = geometries[0];
|
||||
if (preserve_materials) {
|
||||
result.material = materials[0];
|
||||
}
|
||||
return result;
|
||||
} else if (geometries.length > 1) {
|
||||
result = BufferGeometryUtils.mergeBufferGeometries(geometries, true);
|
||||
if (preserve_materials) {
|
||||
result.material = materials;
|
||||
}
|
||||
} else {
|
||||
result = new THREE.BufferGeometry();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Handler for special texture types that we want to support
|
||||
@@ -53,28 +53,28 @@ function merge_geometries(object, preserve_materials = false) {
|
||||
// * A new `THREE.Texture` if that json represents a special texture
|
||||
// * `null` otherwise
|
||||
function handle_special_texture(json) {
|
||||
if (json.type === "_text") {
|
||||
let canvas = document.createElement("canvas");
|
||||
// canvas width and height should be in the power of 2; otherwise although
|
||||
// the page usually loads successfully, WebGL does complain/warn
|
||||
canvas.width = 256;
|
||||
canvas.height = 256;
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.textAlign = "center";
|
||||
let font_size = json.font_size;
|
||||
// auto-resing the font_size to fit in the canvas
|
||||
ctx.font = font_size + "px " + json.font_face;
|
||||
while (ctx.measureText(json.text).width > canvas.width) {
|
||||
font_size--;
|
||||
ctx.font = font_size + "px " + json.font_face;
|
||||
}
|
||||
ctx.fillText(json.text, canvas.width / 2, canvas.height / 2);
|
||||
let canvas_texture = new THREE.CanvasTexture(canvas);
|
||||
canvas_texture.uuid = json.uuid;
|
||||
return canvas_texture;
|
||||
} else {
|
||||
return null;
|
||||
if (json.type === "_text") {
|
||||
let canvas = document.createElement("canvas");
|
||||
// canvas width and height should be in the power of 2; otherwise although
|
||||
// the page usually loads successfully, WebGL does complain/warn
|
||||
canvas.width = 256;
|
||||
canvas.height = 256;
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.textAlign = "center";
|
||||
let font_size = json.font_size;
|
||||
// auto-resing the font_size to fit in the canvas
|
||||
ctx.font = font_size + "px " + json.font_face;
|
||||
while (ctx.measureText(json.text).width > canvas.width) {
|
||||
font_size--;
|
||||
ctx.font = font_size + "px " + json.font_face;
|
||||
}
|
||||
ctx.fillText(json.text, canvas.width / 2, canvas.height / 2);
|
||||
let canvas_texture = new THREE.CanvasTexture(canvas);
|
||||
canvas_texture.uuid = json.uuid;
|
||||
return canvas_texture;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for special geometry types that we want to support
|
||||
@@ -84,41 +84,41 @@ function handle_special_texture(json) {
|
||||
// * A new `THREE.Mesh` if that json represents a special geometry
|
||||
// * `null` otherwise
|
||||
function handle_special_geometry(geom) {
|
||||
if (geom.type === "_meshfile") {
|
||||
console.warn(
|
||||
"_meshfile is deprecated. Please use _meshfile_geometry for geometries and _meshfile_object for objects with geometry and material"
|
||||
);
|
||||
geom.type = "_meshfile_geometry";
|
||||
if (geom.type === "_meshfile") {
|
||||
console.warn(
|
||||
"_meshfile is deprecated. Please use _meshfile_geometry for geometries and _meshfile_object for objects with geometry and material"
|
||||
);
|
||||
geom.type = "_meshfile_geometry";
|
||||
}
|
||||
if (geom.type === "_meshfile_geometry") {
|
||||
if (geom.format === "obj") {
|
||||
let loader = new OBJLoader();
|
||||
let obj = loader.parse(geom.data + "\n");
|
||||
let loaded_geom = merge_geometries(obj);
|
||||
loaded_geom.uuid = geom.uuid;
|
||||
return loaded_geom;
|
||||
} else if (geom.format === "dae") {
|
||||
let loader = new ColladaLoader();
|
||||
let obj = loader.parse(geom.data);
|
||||
let result = merge_geometries(obj.scene);
|
||||
result.uuid = geom.uuid;
|
||||
return result;
|
||||
} else if (geom.format === "stl") {
|
||||
let loader = new STLLoader();
|
||||
let loaded_geom = loader.parse(geom.data.buffer);
|
||||
loaded_geom.uuid = geom.uuid;
|
||||
return loaded_geom;
|
||||
} else if (geom.format === "ply") {
|
||||
let loader = new PLYLoader();
|
||||
let loaded_geom = loader.parse(geom.data.buffer);
|
||||
loaded_geom.uuid = geom.uuid;
|
||||
return loaded_geom;
|
||||
} else {
|
||||
console.error("Unsupported mesh type:", geom);
|
||||
return null;
|
||||
}
|
||||
if (geom.type === "_meshfile_geometry") {
|
||||
if (geom.format === "obj") {
|
||||
let loader = new OBJLoader();
|
||||
let obj = loader.parse(geom.data + "\n");
|
||||
let loaded_geom = merge_geometries(obj);
|
||||
loaded_geom.uuid = geom.uuid;
|
||||
return loaded_geom;
|
||||
} else if (geom.format === "dae") {
|
||||
let loader = new ColladaLoader();
|
||||
let obj = loader.parse(geom.data);
|
||||
let result = merge_geometries(obj.scene);
|
||||
result.uuid = geom.uuid;
|
||||
return result;
|
||||
} else if (geom.format === "stl") {
|
||||
let loader = new STLLoader();
|
||||
let loaded_geom = loader.parse(geom.data.buffer);
|
||||
loaded_geom.uuid = geom.uuid;
|
||||
return loaded_geom;
|
||||
} else if (geom.format === "ply") {
|
||||
let loader = new PLYLoader();
|
||||
let loaded_geom = loader.parse(geom.data.buffer);
|
||||
loaded_geom.uuid = geom.uuid;
|
||||
return loaded_geom;
|
||||
} else {
|
||||
console.error("Unsupported mesh type:", geom);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// The ExtensibleObjectLoader extends the THREE.ObjectLoader
|
||||
@@ -135,148 +135,148 @@ function handle_special_geometry(geom) {
|
||||
// * Converting "_text" textures into text by drawing the
|
||||
// requested text onto a canvas.
|
||||
export class ExtensibleObjectLoader extends THREE.ObjectLoader {
|
||||
delegate(special_handler, base_handler, json, additional_objects) {
|
||||
let result = {};
|
||||
if (json === undefined) {
|
||||
return result;
|
||||
delegate(special_handler, base_handler, json, additional_objects) {
|
||||
let result = {};
|
||||
if (json === undefined) {
|
||||
return result;
|
||||
}
|
||||
let remaining_json = [];
|
||||
for (let data of json) {
|
||||
let x = special_handler(data);
|
||||
if (x !== null) {
|
||||
result[x.uuid] = x;
|
||||
} else {
|
||||
remaining_json.push(data);
|
||||
}
|
||||
}
|
||||
return Object.assign(
|
||||
result,
|
||||
base_handler(remaining_json, additional_objects)
|
||||
);
|
||||
}
|
||||
|
||||
parseTextures(json, images) {
|
||||
return this.delegate(
|
||||
handle_special_texture,
|
||||
super.parseTextures,
|
||||
json,
|
||||
images
|
||||
);
|
||||
}
|
||||
|
||||
parseGeometries(json, shapes) {
|
||||
return this.delegate(
|
||||
handle_special_geometry,
|
||||
super.parseGeometries,
|
||||
json,
|
||||
shapes
|
||||
);
|
||||
}
|
||||
|
||||
parseObject(json, geometries, materials) {
|
||||
if (json.type === "_meshfile_object") {
|
||||
let geometry;
|
||||
let material;
|
||||
let manager = new THREE.LoadingManager();
|
||||
let path =
|
||||
json.url === undefined
|
||||
? undefined
|
||||
: THREE.LoaderUtils.extractUrlBase(json.url);
|
||||
manager.setURLModifier((url) => {
|
||||
if (json.resources[url] !== undefined) {
|
||||
return json.resources[url];
|
||||
}
|
||||
let remaining_json = [];
|
||||
for (let data of json) {
|
||||
let x = special_handler(data);
|
||||
if (x !== null) {
|
||||
result[x.uuid] = x;
|
||||
} else {
|
||||
remaining_json.push(data);
|
||||
}
|
||||
return url;
|
||||
});
|
||||
if (json.format === "obj") {
|
||||
let loader = new OBJLoader(manager);
|
||||
if (json.mtl_library) {
|
||||
let mtl_loader = new MTLLoader(manager);
|
||||
let mtl_parse_result = mtl_loader.parse(json.mtl_library + "\n", "");
|
||||
let materials =
|
||||
MtlObjBridge.addMaterialsFromMtlLoader(mtl_parse_result);
|
||||
loader.setMaterials(materials);
|
||||
this.onTextureLoad();
|
||||
}
|
||||
return Object.assign(
|
||||
result,
|
||||
base_handler(remaining_json, additional_objects)
|
||||
);
|
||||
let obj = loader.parse(json.data + "\n", path);
|
||||
geometry = merge_geometries(obj, true);
|
||||
geometry.uuid = json.uuid;
|
||||
material = geometry.material;
|
||||
} else if (json.format === "dae") {
|
||||
let loader = new ColladaLoader(manager);
|
||||
loader.onTextureLoad = this.onTextureLoad;
|
||||
let obj = loader.parse(json.data, path);
|
||||
geometry = merge_geometries(obj.scene, true);
|
||||
geometry.uuid = json.uuid;
|
||||
material = geometry.material;
|
||||
} else if (json.format === "stl") {
|
||||
let loader = new STLLoader();
|
||||
geometry = loader.parse(json.data.buffer, path);
|
||||
geometry.uuid = json.uuid;
|
||||
material = geometry.material;
|
||||
} else {
|
||||
console.error("Unsupported mesh type:", json);
|
||||
return null;
|
||||
}
|
||||
let object = new THREE.Mesh(geometry, material);
|
||||
|
||||
// Copied from ObjectLoader
|
||||
object.uuid = json.uuid;
|
||||
|
||||
if (json.name !== undefined) object.name = json.name;
|
||||
|
||||
if (json.matrix !== undefined) {
|
||||
object.matrix.fromArray(json.matrix);
|
||||
|
||||
if (json.matrixAutoUpdate !== undefined)
|
||||
object.matrixAutoUpdate = json.matrixAutoUpdate;
|
||||
if (object.matrixAutoUpdate)
|
||||
object.matrix.decompose(
|
||||
object.position,
|
||||
object.quaternion,
|
||||
object.scale
|
||||
);
|
||||
} else {
|
||||
if (json.position !== undefined)
|
||||
object.position.fromArray(json.position);
|
||||
if (json.rotation !== undefined)
|
||||
object.rotation.fromArray(json.rotation);
|
||||
if (json.quaternion !== undefined)
|
||||
object.quaternion.fromArray(json.quaternion);
|
||||
if (json.scale !== undefined) object.scale.fromArray(json.scale);
|
||||
}
|
||||
|
||||
if (json.castShadow !== undefined) object.castShadow = json.castShadow;
|
||||
if (json.receiveShadow !== undefined)
|
||||
object.receiveShadow = json.receiveShadow;
|
||||
|
||||
if (json.shadow) {
|
||||
if (json.shadow.bias !== undefined)
|
||||
object.shadow.bias = json.shadow.bias;
|
||||
if (json.shadow.radius !== undefined)
|
||||
object.shadow.radius = json.shadow.radius;
|
||||
if (json.shadow.mapSize !== undefined)
|
||||
object.shadow.mapSize.fromArray(json.shadow.mapSize);
|
||||
if (json.shadow.camera !== undefined)
|
||||
object.shadow.camera = this.parseObject(json.shadow.camera);
|
||||
}
|
||||
|
||||
if (json.visible !== undefined) object.visible = json.visible;
|
||||
if (json.frustumCulled !== undefined)
|
||||
object.frustumCulled = json.frustumCulled;
|
||||
if (json.renderOrder !== undefined) object.renderOrder = json.renderOrder;
|
||||
if (json.userjson !== undefined) object.userjson = json.userData;
|
||||
if (json.layers !== undefined) object.layers.mask = json.layers;
|
||||
|
||||
return object;
|
||||
} else if (json.type === "CameraHelper") {
|
||||
console.log("processing CameraHelper");
|
||||
console.log(json);
|
||||
console.log(geometries);
|
||||
console.log(materials);
|
||||
return super.parseObject(json, geometries, materials);
|
||||
} else {
|
||||
return super.parseObject(json, geometries, materials);
|
||||
}
|
||||
|
||||
parseTextures(json, images) {
|
||||
return this.delegate(
|
||||
handle_special_texture,
|
||||
super.parseTextures,
|
||||
json,
|
||||
images
|
||||
);
|
||||
}
|
||||
|
||||
parseGeometries(json, shapes) {
|
||||
return this.delegate(
|
||||
handle_special_geometry,
|
||||
super.parseGeometries,
|
||||
json,
|
||||
shapes
|
||||
);
|
||||
}
|
||||
|
||||
parseObject(json, geometries, materials) {
|
||||
if (json.type === "_meshfile_object") {
|
||||
let geometry;
|
||||
let material;
|
||||
let manager = new THREE.LoadingManager();
|
||||
let path =
|
||||
json.url === undefined ?
|
||||
undefined :
|
||||
THREE.LoaderUtils.extractUrlBase(json.url);
|
||||
manager.setURLModifier((url) => {
|
||||
if (json.resources[url] !== undefined) {
|
||||
return json.resources[url];
|
||||
}
|
||||
return url;
|
||||
});
|
||||
if (json.format === "obj") {
|
||||
let loader = new OBJLoader(manager);
|
||||
if (json.mtl_library) {
|
||||
let mtl_loader = new MTLLoader(manager);
|
||||
let mtl_parse_result = mtl_loader.parse(json.mtl_library + "\n", "");
|
||||
let materials =
|
||||
MtlObjBridge.addMaterialsFromMtlLoader(mtl_parse_result);
|
||||
loader.setMaterials(materials);
|
||||
this.onTextureLoad();
|
||||
}
|
||||
let obj = loader.parse(json.data + "\n", path);
|
||||
geometry = merge_geometries(obj, true);
|
||||
geometry.uuid = json.uuid;
|
||||
material = geometry.material;
|
||||
} else if (json.format === "dae") {
|
||||
let loader = new ColladaLoader(manager);
|
||||
loader.onTextureLoad = this.onTextureLoad;
|
||||
let obj = loader.parse(json.data, path);
|
||||
geometry = merge_geometries(obj.scene, true);
|
||||
geometry.uuid = json.uuid;
|
||||
material = geometry.material;
|
||||
} else if (json.format === "stl") {
|
||||
let loader = new STLLoader();
|
||||
geometry = loader.parse(json.data.buffer, path);
|
||||
geometry.uuid = json.uuid;
|
||||
material = geometry.material;
|
||||
} else {
|
||||
console.error("Unsupported mesh type:", json);
|
||||
return null;
|
||||
}
|
||||
let object = new THREE.Mesh(geometry, material);
|
||||
|
||||
// Copied from ObjectLoader
|
||||
object.uuid = json.uuid;
|
||||
|
||||
if (json.name !== undefined) object.name = json.name;
|
||||
|
||||
if (json.matrix !== undefined) {
|
||||
object.matrix.fromArray(json.matrix);
|
||||
|
||||
if (json.matrixAutoUpdate !== undefined)
|
||||
object.matrixAutoUpdate = json.matrixAutoUpdate;
|
||||
if (object.matrixAutoUpdate)
|
||||
object.matrix.decompose(
|
||||
object.position,
|
||||
object.quaternion,
|
||||
object.scale
|
||||
);
|
||||
} else {
|
||||
if (json.position !== undefined)
|
||||
object.position.fromArray(json.position);
|
||||
if (json.rotation !== undefined)
|
||||
object.rotation.fromArray(json.rotation);
|
||||
if (json.quaternion !== undefined)
|
||||
object.quaternion.fromArray(json.quaternion);
|
||||
if (json.scale !== undefined) object.scale.fromArray(json.scale);
|
||||
}
|
||||
|
||||
if (json.castShadow !== undefined) object.castShadow = json.castShadow;
|
||||
if (json.receiveShadow !== undefined)
|
||||
object.receiveShadow = json.receiveShadow;
|
||||
|
||||
if (json.shadow) {
|
||||
if (json.shadow.bias !== undefined)
|
||||
object.shadow.bias = json.shadow.bias;
|
||||
if (json.shadow.radius !== undefined)
|
||||
object.shadow.radius = json.shadow.radius;
|
||||
if (json.shadow.mapSize !== undefined)
|
||||
object.shadow.mapSize.fromArray(json.shadow.mapSize);
|
||||
if (json.shadow.camera !== undefined)
|
||||
object.shadow.camera = this.parseObject(json.shadow.camera);
|
||||
}
|
||||
|
||||
if (json.visible !== undefined) object.visible = json.visible;
|
||||
if (json.frustumCulled !== undefined)
|
||||
object.frustumCulled = json.frustumCulled;
|
||||
if (json.renderOrder !== undefined) object.renderOrder = json.renderOrder;
|
||||
if (json.userjson !== undefined) object.userjson = json.userData;
|
||||
if (json.layers !== undefined) object.layers.mask = json.layers;
|
||||
|
||||
return object;
|
||||
} else if (json.type === "CameraHelper") {
|
||||
console.log("processing CameraHelper");
|
||||
console.log(json);
|
||||
console.log(geometries);
|
||||
console.log(materials);
|
||||
return super.parseObject(json, geometries, materials);
|
||||
} else {
|
||||
return super.parseObject(json, geometries, materials);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+116
-116
@@ -3,142 +3,142 @@ import * as THREE from "three";
|
||||
const dat = require("dat.gui");
|
||||
|
||||
function remove_folders(gui) {
|
||||
for (let name of Object.keys(gui.__folders)) {
|
||||
let folder = gui.__folders[name];
|
||||
remove_folders(folder);
|
||||
dat.dom.dom.unbind(window, "resize", folder.__resizeHandler);
|
||||
gui.removeFolder(folder);
|
||||
}
|
||||
for (let name of Object.keys(gui.__folders)) {
|
||||
let folder = gui.__folders[name];
|
||||
remove_folders(folder);
|
||||
dat.dom.dom.unbind(window, "resize", folder.__resizeHandler);
|
||||
gui.removeFolder(folder);
|
||||
}
|
||||
}
|
||||
|
||||
function dispose(object) {
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
if (object.geometry) {
|
||||
object.geometry.dispose();
|
||||
}
|
||||
if (object.material) {
|
||||
if (Array.isArray(object.material)) {
|
||||
for (let material of object.material) {
|
||||
if (material.map) {
|
||||
material.map.dispose();
|
||||
}
|
||||
material.dispose();
|
||||
}
|
||||
} else {
|
||||
if (object.material.map) {
|
||||
object.material.map.dispose();
|
||||
}
|
||||
object.material.dispose();
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
if (object.geometry) {
|
||||
object.geometry.dispose();
|
||||
}
|
||||
if (object.material) {
|
||||
if (Array.isArray(object.material)) {
|
||||
for (let material of object.material) {
|
||||
if (material.map) {
|
||||
material.map.dispose();
|
||||
}
|
||||
material.dispose();
|
||||
}
|
||||
} else {
|
||||
if (object.material.map) {
|
||||
object.material.map.dispose();
|
||||
}
|
||||
object.material.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SceneNode {
|
||||
constructor(object, folder) {
|
||||
this.object = object;
|
||||
this.folder = folder;
|
||||
this.children = {};
|
||||
this.create_controls();
|
||||
for (let c of this.object.children) {
|
||||
this.add_child(c);
|
||||
}
|
||||
constructor(object, folder) {
|
||||
this.object = object;
|
||||
this.folder = folder;
|
||||
this.children = {};
|
||||
this.create_controls();
|
||||
for (let c of this.object.children) {
|
||||
this.add_child(c);
|
||||
}
|
||||
}
|
||||
|
||||
add_child(object) {
|
||||
let f = this.folder.addFolder(object.name);
|
||||
let node = new SceneNode(object, f);
|
||||
this.children[object.name] = node;
|
||||
return node;
|
||||
}
|
||||
add_child(object) {
|
||||
let f = this.folder.addFolder(object.name);
|
||||
let node = new SceneNode(object, f);
|
||||
this.children[object.name] = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
create_child(name) {
|
||||
let obj = new THREE.Group();
|
||||
obj.name = name;
|
||||
this.object.add(obj);
|
||||
return this.add_child(obj);
|
||||
}
|
||||
create_child(name) {
|
||||
let obj = new THREE.Group();
|
||||
obj.name = name;
|
||||
this.object.add(obj);
|
||||
return this.add_child(obj);
|
||||
}
|
||||
|
||||
find(path) {
|
||||
if (path.length == 0) {
|
||||
return this;
|
||||
} else {
|
||||
let name = path[0];
|
||||
let child = this.children[name];
|
||||
if (child === undefined) {
|
||||
child = this.create_child(name);
|
||||
}
|
||||
return child.find(path.slice(1));
|
||||
}
|
||||
find(path) {
|
||||
if (path.length == 0) {
|
||||
return this;
|
||||
} else {
|
||||
let name = path[0];
|
||||
let child = this.children[name];
|
||||
if (child === undefined) {
|
||||
child = this.create_child(name);
|
||||
}
|
||||
return child.find(path.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
create_controls() {
|
||||
if (this.vis_controller !== undefined) {
|
||||
this.folder.domElement.removeChild(this.vis_controller.domElement);
|
||||
}
|
||||
this.vis_controller = new dat.controllers.BooleanController(
|
||||
this.object,
|
||||
"visible"
|
||||
);
|
||||
this.folder.domElement.prepend(this.vis_controller.domElement);
|
||||
this.vis_controller.domElement.style.height = "0";
|
||||
this.vis_controller.domElement.style.float = "right";
|
||||
create_controls() {
|
||||
if (this.vis_controller !== undefined) {
|
||||
this.folder.domElement.removeChild(this.vis_controller.domElement);
|
||||
}
|
||||
this.vis_controller = new dat.controllers.BooleanController(
|
||||
this.object,
|
||||
"visible"
|
||||
);
|
||||
this.folder.domElement.prepend(this.vis_controller.domElement);
|
||||
this.vis_controller.domElement.style.height = "0";
|
||||
this.vis_controller.domElement.style.float = "right";
|
||||
}
|
||||
|
||||
set_property(property, value) {
|
||||
if (property === "position") {
|
||||
this.object.position.set(value[0], value[1], value[2]);
|
||||
} else if (property === "quaternion") {
|
||||
this.object.quaternion.set(value[0], value[1], value[2], value[3]);
|
||||
} else if (property === "scale") {
|
||||
this.object.scale.set(value[0], value[1], value[2]);
|
||||
} else {
|
||||
this.object[property] = value;
|
||||
}
|
||||
this.vis_controller.updateDisplay();
|
||||
set_property(property, value) {
|
||||
if (property === "position") {
|
||||
this.object.position.set(value[0], value[1], value[2]);
|
||||
} else if (property === "quaternion") {
|
||||
this.object.quaternion.set(value[0], value[1], value[2], value[3]);
|
||||
} else if (property === "scale") {
|
||||
this.object.scale.set(value[0], value[1], value[2]);
|
||||
} else {
|
||||
this.object[property] = value;
|
||||
}
|
||||
this.vis_controller.updateDisplay();
|
||||
}
|
||||
|
||||
set_transform(matrix) {
|
||||
let mat = new THREE.Matrix4();
|
||||
mat.fromArray(matrix);
|
||||
mat.decompose(
|
||||
this.object.position,
|
||||
this.object.quaternion,
|
||||
this.object.scale
|
||||
);
|
||||
}
|
||||
set_transform(matrix) {
|
||||
let mat = new THREE.Matrix4();
|
||||
mat.fromArray(matrix);
|
||||
mat.decompose(
|
||||
this.object.position,
|
||||
this.object.quaternion,
|
||||
this.object.scale
|
||||
);
|
||||
}
|
||||
|
||||
set_object(object) {
|
||||
let parent = this.object.parent;
|
||||
this.dispose_recursive();
|
||||
this.object.parent.remove(this.object);
|
||||
this.object = object;
|
||||
parent.add(object);
|
||||
this.create_controls();
|
||||
}
|
||||
set_object(object) {
|
||||
let parent = this.object.parent;
|
||||
this.dispose_recursive();
|
||||
this.object.parent.remove(this.object);
|
||||
this.object = object;
|
||||
parent.add(object);
|
||||
this.create_controls();
|
||||
}
|
||||
|
||||
dispose_recursive() {
|
||||
for (let name of Object.keys(this.children)) {
|
||||
this.children[name].dispose_recursive();
|
||||
}
|
||||
dispose(this.object);
|
||||
dispose_recursive() {
|
||||
for (let name of Object.keys(this.children)) {
|
||||
this.children[name].dispose_recursive();
|
||||
}
|
||||
dispose(this.object);
|
||||
}
|
||||
|
||||
delete(path) {
|
||||
if (path.length == 0) {
|
||||
console.error("Can't delete an empty path");
|
||||
} else {
|
||||
let parent = this.find(path.slice(0, path.length - 1));
|
||||
let name = path[path.length - 1];
|
||||
let child = parent.children[name];
|
||||
if (child !== undefined) {
|
||||
child.dispose_recursive();
|
||||
parent.object.remove(child.object);
|
||||
remove_folders(child.folder);
|
||||
parent.folder.removeFolder(child.folder);
|
||||
delete parent.children[name];
|
||||
}
|
||||
}
|
||||
delete(path) {
|
||||
if (path.length == 0) {
|
||||
console.error("Can't delete an empty path");
|
||||
} else {
|
||||
let parent = this.find(path.slice(0, path.length - 1));
|
||||
let name = path[path.length - 1];
|
||||
let child = parent.children[name];
|
||||
if (child !== undefined) {
|
||||
child.dispose_recursive();
|
||||
parent.object.remove(child.object);
|
||||
remove_folders(child.folder);
|
||||
parent.folder.removeFolder(child.folder);
|
||||
delete parent.children[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ import * as serviceWorker from "./serviceWorker";
|
||||
import { Viewer } from "./Viewer";
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById("root"));
|
||||
root.render( < Viewer / > );
|
||||
root.render(<Viewer />);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister();
|
||||
serviceWorker.unregister();
|
||||
@@ -11,131 +11,131 @@
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === "localhost" ||
|
||||
window.location.hostname === "localhost" ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === "[::1]" ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
);
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
"This web app is being served cache-first by a service " +
|
||||
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
"This web app is being served cache-first by a service " +
|
||||
"worker. To learn more, visit https://bit.ly/CRA-PWA"
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === "installed") {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
"New content is available and will be used when all " +
|
||||
"tabs for this page are closed. See https://bit.ly/CRA-PWA."
|
||||
);
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === "installed") {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
"New content is available and will be used when all " +
|
||||
"tabs for this page are closed. See https://bit.ly/CRA-PWA."
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log("Content is cached for offline use.");
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log("Content is cached for offline use.");
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error during service worker registration:", error);
|
||||
});
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error during service worker registration:", error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { "Service-Worker": "script" },
|
||||
})
|
||||
.then((response) => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf("javascript") === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
"No internet connection found. App is running in offline mode."
|
||||
);
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { "Service-Worker": "script" },
|
||||
})
|
||||
.then((response) => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf("javascript") === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
"No internet connection found. App is running in offline mode."
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
if ("serviceWorker" in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,4 @@
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
@@ -1,3 +1,3 @@
|
||||
export function split_path(path_str) {
|
||||
return path_str.split("/").filter((x) => x.length > 0);
|
||||
}
|
||||
return path_str.split("/").filter((x) => x.length > 0);
|
||||
}
|
||||
Reference in new issue
Block a user