Compare commits
73 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
1a78dd0dc8 | |
|
|
c242e364bb | |
|
|
2f1c7d979a | |
|
|
ef7179dc6c | |
|
|
abf899fefd | |
|
|
761cb56fac | |
|
|
d601058b3f | |
|
|
376a4237fa | |
|
|
bc8f70da9c | |
|
|
31bb673b44 | |
|
|
1c687681de | |
|
|
e7698494d5 | |
|
|
f5d6d622ec | |
|
|
e36f08f1df | |
|
|
9dc5dd4aa0 | |
|
|
b90142a6c8 | |
|
|
63b72d0e36 | |
|
|
249d46c7c7 | |
|
|
ce34ecdd4d | |
|
|
168b535953 | |
|
|
ffa60e4a22 | |
|
|
66fc4960bf | |
|
|
48400c7d8c | |
|
|
33d2f03624 | |
|
|
bf34f35d6c | |
|
|
09492a5fdc | |
|
|
f680d6bad2 | |
|
|
fcfa59ec98 | |
|
|
1a6fa9e898 | |
|
|
99ee210ffc | |
|
|
4be23070a1 | |
|
|
eee3eecde3 | |
|
|
f6ed7d18e0 | |
|
|
42629cb193 | |
|
|
ad3a4f3877 | |
|
|
3584359833 | |
|
|
778a56ea39 | |
|
|
7d65070f59 | |
|
|
b7fa6b5fbd | |
|
|
2aab1bc9b4 | |
|
|
2b89977083 | |
|
|
0556cc4ae3 | |
|
|
b4d66a92c5 | |
|
|
405113fa4f | |
|
|
d70f6e0886 | |
|
|
684f85b382 | |
|
|
c248217976 | |
|
|
5b5d8f1c3c | |
|
|
e6bb3f1761 | |
|
|
f28de867c7 | |
|
|
84b28ba12c | |
|
|
e343412468 | |
|
|
4638acc04b | |
|
|
ef5b0a42a6 | |
|
|
be2294d3fa | |
|
|
68e2160ac5 | |
|
|
9e61480ad1 | |
|
|
7e4b91b2da | |
|
|
9dadf6f838 | |
|
|
4ecebd5e79 | |
|
|
6e1f5a7f08 | |
|
|
bf397ff191 | |
|
|
ff994e705d | |
|
|
0a09296022 | |
|
|
bb30202b9b | |
|
|
43accba61c | |
|
|
6d65b2ba41 | |
|
|
1569ed9c23 | |
|
|
f40a6ce38d | |
|
|
a95a7d5c38 | |
|
|
09b1173697 | |
|
|
3aace73a1f | |
|
|
254bec97ab |
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Synology/NODE.DC production BIM Viewer environment.
|
||||||
|
# Copy to the live BIM deployment env and fill secrets from platform .env.synology.
|
||||||
|
|
||||||
|
NODEDC_BIM_HOST_PORT=18100
|
||||||
|
NODEDC_BIM_SERVICE_SLUG=bim-viewer
|
||||||
|
NODEDC_BIM_AUTH_REQUIRED=1
|
||||||
|
NODEDC_BIM_PUBLIC_URL=https://bim.nodedc.tech
|
||||||
|
NODEDC_BIM_ALLOWED_ORIGINS=https://hub.nodedc.ru,https://ops.nodedc.ru,https://bim.nodedc.tech
|
||||||
|
NODEDC_BIM_COOKIE_SECURE=1
|
||||||
|
NODEDC_BIM_COOKIE_SAMESITE=None
|
||||||
|
|
||||||
|
NODEDC_LAUNCHER_BASE_URL=https://hub.nodedc.ru
|
||||||
|
NODEDC_LAUNCHER_INTERNAL_URL=https://hub.nodedc.ru
|
||||||
|
NODEDC_INTERNAL_ACCESS_TOKEN=replace-with-platform-internal-token
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
# .gitignore
|
# .gitignore
|
||||||
node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
server/data/uploads/
|
||||||
|
server/data/shares/
|
||||||
|
server/data/models/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1 \
|
||||||
|
NODEDC_BIM_CONVERTER_UPLOADS_DIR=/beam/uploads \
|
||||||
|
NODEDC_BIM_CONVERTER_INTERVAL_SECONDS=10
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
libgl1 \
|
||||||
|
libglib2.0-0 \
|
||||||
|
libglu1-mesa \
|
||||||
|
nodejs \
|
||||||
|
npm \
|
||||||
|
libsm6 \
|
||||||
|
libxext6 \
|
||||||
|
libxrender1 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci --omit=dev \
|
||||||
|
&& npm cache clean --force
|
||||||
|
|
||||||
|
ENV PATH="/app/node_modules/.bin:${PATH}"
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
CMD ["python", "worker.py"]
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import cadquery as cq
|
||||||
|
|
||||||
|
|
||||||
|
def hash_id(value: str) -> str:
|
||||||
|
return hashlib.sha1(value.encode("utf-8")).hexdigest()[:16]
|
||||||
|
|
||||||
|
|
||||||
|
def json_safe(value: Any) -> Any:
|
||||||
|
if value is None or isinstance(value, (str, int, float, bool)):
|
||||||
|
return value
|
||||||
|
if isinstance(value, dict):
|
||||||
|
return {str(key): json_safe(item) for key, item in value.items()}
|
||||||
|
if isinstance(value, (list, tuple)):
|
||||||
|
return [json_safe(item) for item in value]
|
||||||
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
|
def node_to_metadata(node: cq.Assembly, parent_path: str = "") -> dict[str, Any]:
|
||||||
|
name = node.name or "root"
|
||||||
|
node_path = f"{parent_path}/{name}" if parent_path else name
|
||||||
|
children = [node_to_metadata(child, node_path) for child in node.children]
|
||||||
|
return {
|
||||||
|
"id": hash_id(node_path),
|
||||||
|
"name": name,
|
||||||
|
"path": node_path,
|
||||||
|
"hasShape": bool(node.obj),
|
||||||
|
"metadata": json_safe(node.metadata or {}),
|
||||||
|
"children": children,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def count_nodes(node: dict[str, Any]) -> int:
|
||||||
|
return 1 + sum(count_nodes(child) for child in node.get("children", []))
|
||||||
|
|
||||||
|
|
||||||
|
def metadata_dict(value: Any) -> dict[str, Any]:
|
||||||
|
safe_value = json_safe(value or {})
|
||||||
|
return safe_value if isinstance(safe_value, dict) else {"value": safe_value}
|
||||||
|
|
||||||
|
|
||||||
|
def get_shape_type(value: Any) -> str | None:
|
||||||
|
try:
|
||||||
|
shape_type = value.ShapeType()
|
||||||
|
return str(shape_type) if shape_type else None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def collect_solids(workplane: cq.Workplane) -> list[Any]:
|
||||||
|
solids: list[Any] = []
|
||||||
|
seen: set[int] = set()
|
||||||
|
|
||||||
|
for value in workplane.vals():
|
||||||
|
candidates = []
|
||||||
|
try:
|
||||||
|
candidates = list(value.Solids())
|
||||||
|
except Exception:
|
||||||
|
candidates = []
|
||||||
|
if not candidates and get_shape_type(value) == "Solid":
|
||||||
|
candidates = [value]
|
||||||
|
for solid in candidates:
|
||||||
|
key = hash(solid)
|
||||||
|
if key in seen:
|
||||||
|
continue
|
||||||
|
seen.add(key)
|
||||||
|
solids.append(solid)
|
||||||
|
|
||||||
|
return solids
|
||||||
|
|
||||||
|
|
||||||
|
def unique_assembly_name(parent: Any, requested_name: Any) -> str:
|
||||||
|
base_name = str(requested_name or "component")
|
||||||
|
if base_name not in parent.objects:
|
||||||
|
return base_name
|
||||||
|
|
||||||
|
index = 2
|
||||||
|
while True:
|
||||||
|
candidate = f"{base_name}__{index:03d}"
|
||||||
|
if candidate not in parent.objects:
|
||||||
|
return candidate
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
|
||||||
|
def import_step_with_unique_component_names(source_path: Path) -> cq.Assembly:
|
||||||
|
original_add = cq.Assembly.add
|
||||||
|
|
||||||
|
def add_with_unique_names(self: cq.Assembly, arg: Any, *args: Any, **kwargs: Any) -> Any:
|
||||||
|
if isinstance(arg, cq.Assembly):
|
||||||
|
positional_name = args[0] if args else None
|
||||||
|
requested_name = kwargs.get("name", positional_name) or arg.name
|
||||||
|
unique_name = unique_assembly_name(self, requested_name)
|
||||||
|
|
||||||
|
if unique_name != requested_name:
|
||||||
|
arg.metadata = {
|
||||||
|
**metadata_dict(arg.metadata),
|
||||||
|
"originalName": str(requested_name),
|
||||||
|
}
|
||||||
|
if args:
|
||||||
|
args = (unique_name, *args[1:])
|
||||||
|
else:
|
||||||
|
kwargs = {**kwargs, "name": unique_name}
|
||||||
|
|
||||||
|
return original_add(self, arg, *args, **kwargs)
|
||||||
|
|
||||||
|
cq.Assembly.add = add_with_unique_names
|
||||||
|
try:
|
||||||
|
return cq.Assembly.importStep(str(source_path))
|
||||||
|
finally:
|
||||||
|
cq.Assembly.add = original_add
|
||||||
|
|
||||||
|
|
||||||
|
def import_step_assembly(source_path: Path) -> tuple[cq.Assembly, str]:
|
||||||
|
try:
|
||||||
|
return cq.Assembly.importStep(str(source_path)), "assembly"
|
||||||
|
except ValueError as exc:
|
||||||
|
error_message = str(exc)
|
||||||
|
if "Unique name is required" in error_message and "already in the assembly" in error_message:
|
||||||
|
return import_step_with_unique_component_names(source_path), "assembly-unique-names"
|
||||||
|
if "does not contain an assembly" not in error_message:
|
||||||
|
raise
|
||||||
|
|
||||||
|
step_model = cq.importers.importStep(str(source_path))
|
||||||
|
solids = collect_solids(step_model)
|
||||||
|
assembly = cq.Assembly(name=f"{source_path.stem}_root")
|
||||||
|
|
||||||
|
if len(solids) > 1:
|
||||||
|
for index, solid in enumerate(solids, start=1):
|
||||||
|
assembly.add(solid, name=f"{source_path.stem}_solid_{index:03d}")
|
||||||
|
return assembly, "split-solids"
|
||||||
|
|
||||||
|
assembly.add(step_model, name=source_path.stem)
|
||||||
|
return assembly, "single-shape"
|
||||||
|
|
||||||
|
|
||||||
|
def write_json_atomic(path: Path, payload: dict[str, Any]) -> None:
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
tmp_path = path.with_name(f"{path.name}.tmp")
|
||||||
|
tmp_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||||
|
tmp_path.replace(path)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
source_path = Path(sys.argv[1])
|
||||||
|
glb_path = Path(sys.argv[2])
|
||||||
|
result_path = Path(sys.argv[3])
|
||||||
|
linear_deflection = float(sys.argv[4])
|
||||||
|
angular_deflection = float(sys.argv[5])
|
||||||
|
started_at = time.monotonic()
|
||||||
|
|
||||||
|
try:
|
||||||
|
assembly, import_strategy = import_step_assembly(source_path)
|
||||||
|
tree = node_to_metadata(assembly)
|
||||||
|
glb_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
assembly.export(str(glb_path), tolerance=linear_deflection, angularTolerance=angular_deflection)
|
||||||
|
stats = {
|
||||||
|
"fallback": True,
|
||||||
|
"fileSizeMb": round(source_path.stat().st_size / 1024 / 1024, 2),
|
||||||
|
"importStrategy": import_strategy,
|
||||||
|
"cadqueryVersion": getattr(cq, "__version__", "unknown"),
|
||||||
|
"linearDeflection": linear_deflection,
|
||||||
|
"angularDeflection": angular_deflection,
|
||||||
|
"durationSeconds": round(time.monotonic() - started_at, 2),
|
||||||
|
}
|
||||||
|
write_json_atomic(result_path, {"ok": True, "tree": tree, "stats": stats})
|
||||||
|
return 0
|
||||||
|
except Exception as exc:
|
||||||
|
write_json_atomic(result_path, {"ok": False, "error": str(exc)})
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "nodedc-bim-converter-runtime",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "Pinned Node.js runtime tools for NODE.DC BIM converter",
|
||||||
|
"type": "module",
|
||||||
|
"dependencies": {
|
||||||
|
"@gltf-transform/cli": "4.4.0",
|
||||||
|
"@xeokit/xeokit-convert": "1.3.2",
|
||||||
|
"draco3d": "1.5.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
cadquery==2.7.0
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,43 @@
|
||||||
|
services:
|
||||||
|
ndc-beam-viewer:
|
||||||
|
image: node:22-alpine
|
||||||
|
working_dir: /beam/server
|
||||||
|
command: node index.js
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
PORT: "8080"
|
||||||
|
NODEDC_BIM_SERVICE_SLUG: "${NODEDC_BIM_SERVICE_SLUG:-bim-viewer}"
|
||||||
|
NODEDC_BIM_AUTH_REQUIRED: "${NODEDC_BIM_AUTH_REQUIRED:-0}"
|
||||||
|
NODEDC_BIM_PUBLIC_URL: "${NODEDC_BIM_PUBLIC_URL:-http://localhost:8080}"
|
||||||
|
NODEDC_BIM_DATA_ROOT: "${NODEDC_BIM_DATA_ROOT:-}"
|
||||||
|
NODEDC_BIM_SESSION_COOKIE: "${NODEDC_BIM_SESSION_COOKIE:-nodedc_bim_session}"
|
||||||
|
NODEDC_BIM_SESSION_TTL_MS: "${NODEDC_BIM_SESSION_TTL_MS:-43200000}"
|
||||||
|
NODEDC_BIM_COOKIE_SECURE: "${NODEDC_BIM_COOKIE_SECURE:-0}"
|
||||||
|
NODEDC_BIM_COOKIE_SAMESITE: "${NODEDC_BIM_COOKIE_SAMESITE:-}"
|
||||||
|
NODEDC_LAUNCHER_BASE_URL: "${NODEDC_LAUNCHER_BASE_URL:-http://localhost:5173}"
|
||||||
|
NODEDC_LAUNCHER_INTERNAL_URL: "${NODEDC_LAUNCHER_INTERNAL_URL:-http://host.docker.internal:5173}"
|
||||||
|
NODEDC_INTERNAL_ACCESS_TOKEN: "${NODEDC_INTERNAL_ACCESS_TOKEN:-}"
|
||||||
|
NODEDC_BIM_ALLOWED_ORIGINS: "${NODEDC_BIM_ALLOWED_ORIGINS:-http://localhost:5173,http://localhost:8090}"
|
||||||
|
ports:
|
||||||
|
- "${NODEDC_BIM_HOST_PORT:-8080}:8080"
|
||||||
|
volumes:
|
||||||
|
- ./:/beam
|
||||||
|
|
||||||
|
nodedc-bim-converter:
|
||||||
|
build:
|
||||||
|
context: ./converter
|
||||||
|
image: nodedc/bim-converter:local
|
||||||
|
container_name: NodeDcBimConverter
|
||||||
|
platform: linux/amd64
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
NODEDC_BIM_CONVERTER_UPLOADS_DIR: /beam/uploads
|
||||||
|
NODEDC_BIM_CONVERTER_INTERVAL_SECONDS: "10"
|
||||||
|
NODEDC_BIM_CONVERTER_MAX_ATTEMPTS: "3"
|
||||||
|
NODEDC_BIM_CONVERTER_TIMEOUT_SECONDS: "300"
|
||||||
|
NODEDC_BIM_CONVERTER_GLB_DRACO_ENABLED: "1"
|
||||||
|
NODEDC_BIM_CONVERTER_GLB_DRACO_TIMEOUT_SECONDS: "900"
|
||||||
|
NODEDC_BIM_CONVERTER_XCAF_TIMEOUT_SECONDS: "1200"
|
||||||
|
NODEDC_BIM_CONVERTER_CADQUERY_TIMEOUT_SECONDS: "1800"
|
||||||
|
volumes:
|
||||||
|
- ./server/data/uploads:/beam/uploads
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
|
|
@ -0,0 +1,13 @@
|
||||||
|
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<style>
|
||||||
|
.icon-fav-01 { fill: #333334; } /* Тёмный цвет для светлого таб-бара */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
.icon-fav-01 { fill: #FEFEFE; } /* Светлый цвет для тёмного таб-бара */
|
||||||
|
}
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
.icon-fav-01 { fill: #000000; } /* Тёмный цвет для светлого таб-бара (для явности) */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<path class="icon-fav-01" d="M17.8738 15.9159L16.0002 18.9718L14.1267 15.9159H17.8738ZM23.6307 12.7864H8.36914L15.9999 25.2308L23.6307 12.7864Z"/>
|
||||||
|
<path class="icon-fav-01" d="M10.9793 19.4872L6.67269 11.5918H25.5344L21.2281 19.4872H25.0581L31.2614 8H0.738281L7.16244 19.4872H10.9793Z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 852 B |
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"theme_color": "#eeeff4",
|
||||||
|
"background_color": "#eeeff4",
|
||||||
|
"display": "browser",
|
||||||
|
"scope": "/",
|
||||||
|
"start_url": "/",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "icon-adaptive.svg",
|
||||||
|
"type": "image/svg+xml",
|
||||||
|
"sizes": "any"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "icon-192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "icon-512.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "512x512"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "apple-touch-icon.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "180x180"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
4921
frontend/dcViewer.js
4921
frontend/dcViewer.js
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
|
|
@ -4,38 +4,181 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>BIM DC Viewer</title>
|
<title>BIM DC Viewer</title>
|
||||||
<link rel="icon" href="./assets/logo.svg">
|
<link rel="icon" type="image/svg+xml" href="/assets/favicon/icon-adaptive.svg">
|
||||||
<style id="preload-hidden">body{opacity:0;}</style>
|
<link rel="alternate icon" href="/assets/favicon/favicon.ico">
|
||||||
|
<link rel="apple-touch-icon" href="/assets/favicon/apple-touch-icon.png">
|
||||||
|
<link rel="manifest" href="/assets/favicon/manifest.webmanifest.json">
|
||||||
|
<style id="preload-hidden">
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
background: #1c1c1c;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.app-starting header,
|
||||||
|
body.app-starting #dropZone,
|
||||||
|
body.app-starting #status,
|
||||||
|
body.app-starting #bottomToolbar,
|
||||||
|
body.app-starting #sectionToolbar,
|
||||||
|
body.app-starting #navCube,
|
||||||
|
body.app-starting .side-panel,
|
||||||
|
body.app-starting .comments-panel,
|
||||||
|
body.app-starting .templates-panel,
|
||||||
|
body.app-starting .settings-panel {
|
||||||
|
opacity: 0 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.app-starting #loader {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap">
|
||||||
<script src="./theme.js"></script>
|
<script src="/theme.js?v=3"></script>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
if (/^\/share\/[^/]+\/?$/.test(window.location.pathname || "")) {
|
||||||
|
document.documentElement.dataset.shareStartup = "pending";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var params = new URLSearchParams(window.location.search || "");
|
||||||
|
var embeddedParam = params.get("embed") || params.get("embedded") || params.get("iframe");
|
||||||
|
var explicitEmbedded = embeddedParam !== null && !/^(0|false|no|standalone)$/i.test(embeddedParam);
|
||||||
|
var framed = false;
|
||||||
|
try {
|
||||||
|
framed = window.self !== window.top;
|
||||||
|
} catch (e) {
|
||||||
|
framed = true;
|
||||||
|
}
|
||||||
|
if (explicitEmbedded || framed) {
|
||||||
|
document.documentElement.classList.add("is-embedded-viewer");
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
</script>
|
||||||
<script>
|
<script>
|
||||||
// Apply persisted theme ASAP to avoid initial flash of defaults
|
// Apply persisted theme ASAP to avoid initial flash of defaults
|
||||||
(function () {
|
(function () {
|
||||||
const STORAGE_KEY = "bimdc-settings-v3";
|
const STORAGE_KEY = "bimdc-settings-v3";
|
||||||
const LEGACY_KEYS = ["bimdc-settings", "bimdc-settings-v2"];
|
const LEGACY_KEYS = ["bimdc-settings", "bimdc-settings-v2"];
|
||||||
try {
|
try {
|
||||||
LEGACY_KEYS.forEach((k) => localStorage.removeItem(k));
|
|
||||||
|
|
||||||
const project = window.__BIMDC_THEME__ || {};
|
const project = window.__BIMDC_THEME__ || {};
|
||||||
const raw = localStorage.getItem(STORAGE_KEY);
|
const sharedViewer = /^\/share\/[^/]+\/?$/.test(window.location.pathname || "");
|
||||||
let stored = null;
|
let stored = null;
|
||||||
try {
|
if (!sharedViewer) {
|
||||||
stored = raw ? JSON.parse(raw) : null;
|
LEGACY_KEYS.forEach((k) => localStorage.removeItem(k));
|
||||||
} catch (e) {
|
const raw = localStorage.getItem(STORAGE_KEY);
|
||||||
stored = null;
|
try {
|
||||||
|
stored = raw ? JSON.parse(raw) : null;
|
||||||
|
} catch (e) {
|
||||||
|
stored = null;
|
||||||
|
}
|
||||||
|
const storedVersion = stored && stored.themeVersion;
|
||||||
|
const projectVersion = project && project.themeVersion;
|
||||||
|
if (!stored || storedVersion !== projectVersion) {
|
||||||
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(project));
|
||||||
|
stored = { ...project };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const storedVersion = stored && stored.themeVersion;
|
const s = { ...(project || {}), ...(!sharedViewer && stored ? stored : {}) };
|
||||||
const projectVersion = project && project.themeVersion;
|
|
||||||
if (!stored || storedVersion !== projectVersion) {
|
|
||||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(project));
|
|
||||||
stored = { ...project };
|
|
||||||
}
|
|
||||||
const s = { ...(project || {}), ...(stored || {}) };
|
|
||||||
if (!Object.keys(s).length) return;
|
if (!Object.keys(s).length) return;
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
const set = (k, v) => v !== undefined && root.style.setProperty(k, v);
|
const set = (k, v) => v !== undefined && root.style.setProperty(k, v);
|
||||||
|
const parseColor = (value) => {
|
||||||
|
if (typeof value !== "string") return null;
|
||||||
|
const color = value.trim();
|
||||||
|
const hex = color.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
|
||||||
|
if (hex) {
|
||||||
|
const raw = hex[1].length === 3
|
||||||
|
? hex[1].split("").map((c) => c + c).join("")
|
||||||
|
: hex[1];
|
||||||
|
return [
|
||||||
|
parseInt(raw.slice(0, 2), 16),
|
||||||
|
parseInt(raw.slice(2, 4), 16),
|
||||||
|
parseInt(raw.slice(4, 6), 16),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const rgb = color.match(/^rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)/i);
|
||||||
|
if (!rgb) return null;
|
||||||
|
return rgb.slice(1, 4).map((channel) => Math.max(0, Math.min(255, Number(channel))));
|
||||||
|
};
|
||||||
|
const readableTextColor = (value) => {
|
||||||
|
const rgb = parseColor(value);
|
||||||
|
if (!rgb || rgb.some((channel) => !Number.isFinite(channel))) return "#15170f";
|
||||||
|
const toLinear = (channel) => {
|
||||||
|
const value = channel / 255;
|
||||||
|
return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
||||||
|
};
|
||||||
|
const lum = 0.2126 * toLinear(rgb[0]) + 0.7152 * toLinear(rgb[1]) + 0.0722 * toLinear(rgb[2]);
|
||||||
|
return (lum + 0.05) / 0.05 >= 1.05 / (lum + 0.05) ? "#15170f" : "#f5f5fa";
|
||||||
|
};
|
||||||
|
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
||||||
|
const colorParts = (value, fallback) => {
|
||||||
|
const parsed = parseColor(value);
|
||||||
|
if (parsed && parsed.every((channel) => Number.isFinite(channel))) return parsed;
|
||||||
|
const parsedFallback = parseColor(fallback);
|
||||||
|
if (parsedFallback && parsedFallback.every((channel) => Number.isFinite(channel))) return parsedFallback;
|
||||||
|
return [28, 28, 28];
|
||||||
|
};
|
||||||
|
const alphaValue = (value, fallback) => {
|
||||||
|
const numeric = Number(value);
|
||||||
|
return Number.isFinite(numeric) ? clamp(numeric, 0, 1) : fallback;
|
||||||
|
};
|
||||||
|
const rgba = (parts, alpha) => {
|
||||||
|
const [r, g, b] = parts.map((channel) => Math.round(clamp(channel, 0, 255)));
|
||||||
|
return `rgba(${r}, ${g}, ${b}, ${clamp(alpha, 0, 1).toFixed(3)})`;
|
||||||
|
};
|
||||||
|
const applyGlassSettings = () => {
|
||||||
|
const panelColor = colorParts(s.modalBg, "#1c1c1c");
|
||||||
|
const focusColor = colorParts(s.modalFocus, "#292929");
|
||||||
|
const controlColor = colorParts(s.modalElement, s.modalFocus || "#262626");
|
||||||
|
const outlineColor = colorParts(s.modalBorder, s.modalElementOutline || "#1c1c1c");
|
||||||
|
const controlOutlineColor = colorParts(s.modalElementOutline, s.modalBorder || "#262626");
|
||||||
|
const modalBgAlpha = alphaValue(s.modalBgAlpha, 1);
|
||||||
|
const modalFocusAlpha = alphaValue(s.modalFocusAlpha, 0.35);
|
||||||
|
const panelAlpha = clamp(0.24 + modalBgAlpha * 0.48, 0.32, 0.88);
|
||||||
|
const panelStrongAlpha = clamp(panelAlpha + 0.1, 0.42, 0.92);
|
||||||
|
const panelSoftAlpha = clamp(panelAlpha - 0.16, 0.2, 0.72);
|
||||||
|
const sectionAlpha = clamp(modalFocusAlpha * 0.6, 0.04, 0.42);
|
||||||
|
const controlAlpha = clamp(0.12 + modalFocusAlpha * 0.9, 0.16, 0.66);
|
||||||
|
const controlHoverAlpha = clamp(controlAlpha + 0.08, 0.22, 0.74);
|
||||||
|
const outlineAlpha = clamp(0.055 + modalFocusAlpha * 0.18, 0.065, 0.2);
|
||||||
|
const controlOutlineAlpha = clamp(0.045 + modalFocusAlpha * 0.12, 0.055, 0.16);
|
||||||
|
|
||||||
|
const panelBg = rgba(panelColor, panelAlpha);
|
||||||
|
const panelBgStrong = rgba(panelColor, panelStrongAlpha);
|
||||||
|
const panelBgSoft = rgba(panelColor, panelSoftAlpha);
|
||||||
|
const sectionBg = rgba(focusColor, sectionAlpha);
|
||||||
|
const outline = rgba(outlineColor, outlineAlpha);
|
||||||
|
const outlineBright = rgba(outlineColor, clamp(outlineAlpha + 0.05, 0.08, 0.26));
|
||||||
|
const outlineMid = rgba(outlineColor, clamp(outlineAlpha + 0.015, 0.07, 0.22));
|
||||||
|
const outlineDim = rgba(outlineColor, clamp(outlineAlpha * 0.62, 0.04, 0.16));
|
||||||
|
const controlBg = rgba(controlColor, controlAlpha);
|
||||||
|
const controlHover = rgba(focusColor, controlHoverAlpha);
|
||||||
|
const controlShadow = rgba(controlOutlineColor, controlOutlineAlpha);
|
||||||
|
|
||||||
|
set("--nodedc-glass-panel-bg", panelBg);
|
||||||
|
set("--nodedc-glass-panel-bg-strong", panelBgStrong);
|
||||||
|
set("--nodedc-glass-panel-bg-soft", panelBgSoft);
|
||||||
|
set("--nodedc-glass-panel-surface", `linear-gradient(180deg, rgba(255, 255, 255, 0.052) 0%, rgba(255, 255, 255, 0.014) 100%), ${panelBg}`);
|
||||||
|
set("--nodedc-glass-panel-surface-strong", `linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.016) 100%), ${panelBgStrong}`);
|
||||||
|
set("--nodedc-glass-section-bg", `linear-gradient(180deg, rgba(255, 255, 255, 0.038) 0%, rgba(255, 255, 255, 0.01) 100%), ${sectionBg}`);
|
||||||
|
set("--nodedc-glass-outline", outline);
|
||||||
|
set("--nodedc-glass-outline-gradient", `linear-gradient(180deg, ${outlineBright} 0%, ${outlineMid} 56%, ${outlineDim} 100%)`);
|
||||||
|
set("--nodedc-glass-panel-shadow", `inset 0 1px 0 ${outlineDim}, 0 22px 72px rgba(0, 0, 0, 0.42)`);
|
||||||
|
set("--nodedc-glass-control-bg", `linear-gradient(180deg, rgba(255, 255, 255, 0.052) 0%, rgba(255, 255, 255, 0.018) 100%), ${controlBg}`);
|
||||||
|
set("--nodedc-glass-control-hover", `linear-gradient(180deg, rgba(255, 255, 255, 0.075) 0%, rgba(255, 255, 255, 0.026) 100%), ${controlHover}`);
|
||||||
|
set("--nodedc-glass-control-shadow", `inset 0 1px 0 ${controlShadow}`);
|
||||||
|
set("--nodedc-header-dropdown-bg", panelBgStrong);
|
||||||
|
set("--nodedc-header-dropdown-item-bg", controlBg);
|
||||||
|
set("--nodedc-header-dropdown-item-hover-bg", controlHover);
|
||||||
|
set("--nodedc-header-dropdown-item-active-bg", s.toolbarBgActive);
|
||||||
|
set("--nodedc-header-dropdown-item-active-color", s.toolbarBgActive ? readableTextColor(s.toolbarBgActive) : undefined);
|
||||||
|
};
|
||||||
set("--bg-outer", s.bgOuter);
|
set("--bg-outer", s.bgOuter);
|
||||||
set("--canvas-top", s.canvasTop);
|
set("--canvas-top", s.canvasTop);
|
||||||
set("--canvas-bottom", s.canvasBottom);
|
set("--canvas-bottom", s.canvasBottom);
|
||||||
|
|
@ -49,18 +192,28 @@
|
||||||
set("--template-glow-strength", `${s.templateGlow}%`);
|
set("--template-glow-strength", `${s.templateGlow}%`);
|
||||||
set("--toolbar-bg", s.toolbarBg);
|
set("--toolbar-bg", s.toolbarBg);
|
||||||
set("--toolbar-bg-active", s.toolbarBgActive);
|
set("--toolbar-bg-active", s.toolbarBgActive);
|
||||||
|
set("--toolbar-bg-active-contrast", s.toolbarBgActive ? readableTextColor(s.toolbarBgActive) : undefined);
|
||||||
set("--toolbar-border", s.toolbarBorder);
|
set("--toolbar-border", s.toolbarBorder);
|
||||||
set("--toolbar-outline", s.toolbarOutline);
|
set("--toolbar-outline", s.toolbarOutline);
|
||||||
|
set("--tb-size", s.toolbarMinSize !== undefined ? `${s.toolbarMinSize}px` : undefined);
|
||||||
|
set("--tb-min-size", s.toolbarMinSize !== undefined ? `${s.toolbarMinSize}px` : undefined);
|
||||||
|
set("--tb-max-size", s.toolbarMaxSize !== undefined ? `${s.toolbarMaxSize}px` : undefined);
|
||||||
|
set("--tb-lens-count", s.toolbarLensCount);
|
||||||
|
set("--tb-autohide", s.toolbarAutoHide ? "1" : "0");
|
||||||
set("--modal-bg", s.modalBg);
|
set("--modal-bg", s.modalBg);
|
||||||
|
set("--modal-bg-alpha", s.modalBgAlpha !== undefined ? `${s.modalBgAlpha * 100}%` : undefined);
|
||||||
set("--modal-focus", s.modalFocus);
|
set("--modal-focus", s.modalFocus);
|
||||||
|
set("--modal-focus-alpha", s.modalFocusAlpha !== undefined ? `${s.modalFocusAlpha * 100}%` : undefined);
|
||||||
set("--modal-border", s.modalBorder);
|
set("--modal-border", s.modalBorder);
|
||||||
set("--modal-element", s.modalElement);
|
set("--modal-element", s.modalElement);
|
||||||
set("--modal-element-outline", s.modalElementOutline);
|
set("--modal-element-outline", s.modalElementOutline);
|
||||||
set("--modal-radius", s.modalRadius);
|
set("--modal-radius", s.modalRadius);
|
||||||
|
applyGlassSettings();
|
||||||
set("--project-btn-fill", s.projectBtnFill);
|
set("--project-btn-fill", s.projectBtnFill);
|
||||||
set("--project-btn-border", s.projectBtnBorder);
|
set("--project-btn-border", s.projectBtnBorder);
|
||||||
set("--project-btn-hover", s.projectBtnHover);
|
set("--project-btn-hover", s.projectBtnHover);
|
||||||
set("--modal-btn-primary", s.modalBtnPrimary);
|
set("--modal-btn-primary", s.modalBtnPrimary);
|
||||||
|
set("--modal-btn-primary-contrast", s.modalBtnPrimary ? readableTextColor(s.modalBtnPrimary) : undefined);
|
||||||
set("--modal-btn-secondary", s.modalBtnSecondary);
|
set("--modal-btn-secondary", s.modalBtnSecondary);
|
||||||
set("--loader-color", s.loaderColor);
|
set("--loader-color", s.loaderColor);
|
||||||
set("--border", s.border);
|
set("--border", s.border);
|
||||||
|
|
@ -79,6 +232,21 @@
|
||||||
set("--measure-label", s.measureLabel);
|
set("--measure-label", s.measureLabel);
|
||||||
set("--measure-label-text", s.measureLabelText);
|
set("--measure-label-text", s.measureLabelText);
|
||||||
set("--measure-dot", s.measureDot);
|
set("--measure-dot", s.measureDot);
|
||||||
|
set("--section-axis-x", s.sectionAxisX);
|
||||||
|
set("--section-axis-y", s.sectionAxisY);
|
||||||
|
set("--section-axis-z", s.sectionAxisZ);
|
||||||
|
set("--section-gizmo-diameter", s.sectionGizmoDiameter);
|
||||||
|
set("--section-gizmo-thickness", s.sectionGizmoThickness);
|
||||||
|
set("--section-plane-fill", s.sectionPlaneFill);
|
||||||
|
set("--section-plane-alpha", s.sectionPlaneAlpha);
|
||||||
|
set("--section-plane-edge", s.sectionPlaneEdge);
|
||||||
|
set("--section-plane-edge-alpha", s.sectionPlaneEdgeAlpha);
|
||||||
|
set("--comment-target-active", s.commentTargetActiveColor);
|
||||||
|
set("--comment-target-active-alpha", s.commentTargetActiveAlpha);
|
||||||
|
set("--comment-target-active-size", s.commentTargetActiveSize !== undefined ? `${s.commentTargetActiveSize}px` : undefined);
|
||||||
|
set("--comment-target-passive", s.commentTargetPassiveColor);
|
||||||
|
set("--comment-target-passive-alpha", s.commentTargetPassiveAlpha);
|
||||||
|
set("--comment-target-passive-size", s.commentTargetPassiveSize !== undefined ? `${s.commentTargetPassiveSize}px` : undefined);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ignore corrupted settings
|
// ignore corrupted settings
|
||||||
}
|
}
|
||||||
|
|
@ -87,11 +255,11 @@
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="./dcViewer.css?v=3">
|
<link rel="stylesheet" href="/dcViewer.css?v=42">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="app-starting">
|
||||||
<header>
|
<header>
|
||||||
<button class="logo-btn" id="homeButton" title="Вернуться к старту"></button>
|
<button class="logo-btn" id="homeButton" type="button" title="Открыть NODE.DC Hub"></button>
|
||||||
<div class="toolbar"></div>
|
<div class="toolbar"></div>
|
||||||
<div class="hidden-controls" style="display:none">
|
<div class="hidden-controls" style="display:none">
|
||||||
<input type="checkbox" id="toggleEdges" checked>
|
<input type="checkbox" id="toggleEdges" checked>
|
||||||
|
|
@ -124,69 +292,300 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<aside class="side-panel">
|
<aside class="side-panel" id="viewerInspector">
|
||||||
<div class="panel-section">
|
<div class="inspector-panel-header">
|
||||||
<h3>Инспектор</h3>
|
<h3>Инспектор</h3>
|
||||||
<div id="treeContainer" class="tree"></div>
|
<button
|
||||||
|
class="inspector-collapse-btn"
|
||||||
|
id="inspectorCollapseButton"
|
||||||
|
type="button"
|
||||||
|
title="Свернуть инспектор"
|
||||||
|
aria-label="Свернуть инспектор"
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-section" id="projectNameSection">
|
<div class="inspector-panel-body">
|
||||||
<h3>Название проекта</h3>
|
<div class="panel-section inspector-main-section">
|
||||||
<input type="text" id="projectNameInput" class="project-name-input" placeholder="Проект" autocomplete="off">
|
<div id="treeContainer" class="tree"></div>
|
||||||
<div class="error-text inline-error" id="projectNameError"></div>
|
<div class="inspector-controls">
|
||||||
</div>
|
<div class="inspector-control-row inspector-control-row--full hidden" id="modelVersionControl">
|
||||||
<div class="panel-section">
|
<div class="inspector-version-heading">
|
||||||
<h3>Глобальные координаты</h3>
|
<div class="inspector-control-label">Версия модели</div>
|
||||||
<div class="muted" style="margin-bottom:6px;">Центр выделения (мировые)</div>
|
<div class="inspector-version-actions">
|
||||||
<div class="transform-grid">
|
<button class="inspector-icon-btn" id="modelVersionHistoryButton" type="button" title="История версий" aria-label="История версий">
|
||||||
<label>X <input type="text" id="globalX"></label>
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
||||||
<label>Y <input type="text" id="globalY"></label>
|
<path d="M3.2 3.4v3.3h3.3"></path>
|
||||||
<label>Z <input type="text" id="globalZ"></label>
|
<path d="M3.7 6.7A4.7 4.7 0 1 0 5.1 3"></path>
|
||||||
|
<path d="M8 5.1v3.2l2.1 1.2"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="inspector-icon-btn" id="modelVersionUploadButton" type="button" title="Добавить версию" aria-label="Добавить версию">
|
||||||
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M8 11.4V3.6"></path>
|
||||||
|
<path d="M5.1 6.4 8 3.5l2.9 2.9"></path>
|
||||||
|
<path d="M3.2 11.8v1.4h9.6v-1.4"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="inspector-select-host" id="modelVersionSelect"></div>
|
||||||
|
<input id="modelVersionFileInput" class="hidden" type="file" accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl,.step,.stp">
|
||||||
|
</div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--full hidden" id="modelLodControl">
|
||||||
|
<div class="inspector-control-label">Уровни LOD</div>
|
||||||
|
<button class="primary-btn model-lod-generate-btn" id="modelLodGenerateButton" type="button">Сгенерировать LOD</button>
|
||||||
|
<div class="inspector-select-host hidden" id="modelLodSelect"></div>
|
||||||
|
</div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--half" id="displayModeControl">
|
||||||
|
<div class="inspector-control-label">Режим отображения</div>
|
||||||
|
<div class="inspector-select-host" id="displayModeSelect"></div>
|
||||||
|
</div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--half hidden" id="customDisplayColorRow">
|
||||||
|
<div class="inspector-control-label">Цвет</div>
|
||||||
|
<div class="inspector-color-host" id="customDisplayColorControl"></div>
|
||||||
|
</div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--half" id="lightingModeControl">
|
||||||
|
<div class="inspector-control-label">Свет</div>
|
||||||
|
<div class="inspector-select-host" id="lightingModeSelect"></div>
|
||||||
|
</div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--full inspector-control-row--slider hidden" id="customDisplaySaturationControl"></div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--full" id="navigationAxisControl">
|
||||||
|
<div class="inspector-control-label">Ось навигации</div>
|
||||||
|
<div class="inspector-select-host" id="navigationAxisSelect"></div>
|
||||||
|
</div>
|
||||||
|
<div class="inspector-control-row inspector-control-row--full inspector-control-row--slider" id="zoomSpeedControl"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="panel-section" id="projectNameSection">
|
||||||
<div class="panel-section">
|
<h3>Название проекта</h3>
|
||||||
<h3>Трансформации</h3>
|
<input type="text" id="projectNameInput" class="project-name-input" placeholder="Проект" autocomplete="off">
|
||||||
<div class="muted" style="margin-bottom:6px;">Перемещение</div>
|
<div class="error-text inline-error" id="projectNameError"></div>
|
||||||
<div class="transform-grid">
|
|
||||||
<label>X <input type="text" id="posX"></label>
|
|
||||||
<label>Y <input type="text" id="posY"></label>
|
|
||||||
<label>Z <input type="text" id="posZ"></label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="muted" style="margin:8px 0 6px;">Вращение (deg)</div>
|
<div class="panel-section">
|
||||||
<div class="transform-grid">
|
<h3>Глобальные координаты</h3>
|
||||||
<label>X <input type="text" id="rotX"></label>
|
<div class="muted" style="margin-bottom:6px;">Центр выделения (мировые)</div>
|
||||||
<label>Y <input type="text" id="rotY"></label>
|
<div class="transform-grid">
|
||||||
<label>Z <input type="text" id="rotZ"></label>
|
<label>X <input type="text" id="globalX"></label>
|
||||||
|
<label>Y <input type="text" id="globalY"></label>
|
||||||
|
<label>Z <input type="text" id="globalZ"></label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="muted" style="margin:8px 0 6px;">Масштаб</div>
|
<div class="panel-section">
|
||||||
<div class="transform-grid">
|
<h3>Трансформации</h3>
|
||||||
<label>X <input type="text" id="scaleX"></label>
|
<div class="muted" style="margin-bottom:6px;">Перемещение</div>
|
||||||
<label>Y <input type="text" id="scaleY"></label>
|
<div class="transform-grid">
|
||||||
<label>Z <input type="text" id="scaleZ"></label>
|
<label>X <input type="text" id="posX"></label>
|
||||||
|
<label>Y <input type="text" id="posY"></label>
|
||||||
|
<label>Z <input type="text" id="posZ"></label>
|
||||||
|
</div>
|
||||||
|
<div class="muted" style="margin:8px 0 6px;">Вращение (deg)</div>
|
||||||
|
<div class="transform-grid">
|
||||||
|
<label>X <input type="text" id="rotX"></label>
|
||||||
|
<label>Y <input type="text" id="rotY"></label>
|
||||||
|
<label>Z <input type="text" id="rotZ"></label>
|
||||||
|
</div>
|
||||||
|
<div class="muted" style="margin:8px 0 6px;">Масштаб</div>
|
||||||
|
<div class="transform-grid">
|
||||||
|
<label>X <input type="text" id="scaleX"></label>
|
||||||
|
<label>Y <input type="text" id="scaleY"></label>
|
||||||
|
<label>Z <input type="text" id="scaleZ"></label>
|
||||||
|
</div>
|
||||||
|
<small id="transformHint" class="muted">Выберите объект в инспекторе или сцене, чтобы редактировать.</small>
|
||||||
|
</div>
|
||||||
|
<div class="panel-section">
|
||||||
|
<h3>Журнал</h3>
|
||||||
|
<div id="logList" class="log"></div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-section" id="saveProjectSection">
|
||||||
|
<button class="secondary-btn model-settings-btn" id="saveModelSettingsButton" type="button">Сохранить настройки</button>
|
||||||
|
<button class="primary-btn" id="saveProjectButton" type="button">Сохранить проект</button>
|
||||||
|
<button class="secondary-btn danger-btn" id="deleteProjectButton" type="button">Удалить проект</button>
|
||||||
</div>
|
</div>
|
||||||
<small id="transformHint" class="muted">Выберите объект в инспекторе или сцене, чтобы редактировать.</small>
|
|
||||||
</div>
|
|
||||||
<div class="panel-section">
|
|
||||||
<h3>Журнал</h3>
|
|
||||||
<div id="logList" class="log"></div>
|
|
||||||
</div>
|
|
||||||
<div class="panel-section" id="saveProjectSection">
|
|
||||||
<button class="primary-btn" id="saveProjectButton" type="button">Сохранить проект</button>
|
|
||||||
<button class="secondary-btn danger-btn" id="deleteProjectButton" type="button">Удалить проект</button>
|
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
<div class="inspector-restore-tray" id="inspectorRestoreTray" hidden>
|
||||||
|
<button class="inspector-restore-button" id="inspectorRestoreButton" type="button">Инспектор</button>
|
||||||
|
</div>
|
||||||
|
<aside class="comments-panel hidden" id="commentsPanel">
|
||||||
|
<div class="comments-panel-header" id="commentsPanelHeader">
|
||||||
|
<h3>Комментарии</h3>
|
||||||
|
<button
|
||||||
|
class="inspector-collapse-btn"
|
||||||
|
id="commentsCollapseButton"
|
||||||
|
type="button"
|
||||||
|
title="Опустить комментарии"
|
||||||
|
aria-label="Опустить комментарии"
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4 6.25 8 10.25 12 6.25" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="comments-panel-body">
|
||||||
|
<div id="commentsList" class="comments-list"></div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="comments-restore-tray" id="commentsRestoreTray" hidden>
|
||||||
|
<button class="inspector-restore-button" id="commentsRestoreButton" type="button">Комментарии</button>
|
||||||
|
</div>
|
||||||
|
<div id="commentTargetsLayer" class="comment-targets-layer hidden"></div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div id="templatesPanel" class="templates-panel hidden"></div>
|
<div id="templatesPanel" class="templates-panel hidden"></div>
|
||||||
<div id="settingsPanel" class="settings-panel hidden"></div>
|
<div id="settingsPanel" class="settings-panel hidden"></div>
|
||||||
|
<div id="commentContextMenu" class="nodedc-dropdown-surface bim-context-menu hidden" role="menu" aria-label="Действия по модели">
|
||||||
|
<button class="nodedc-dropdown-option bim-context-menu__item" data-comment-menu-action="create" type="button" role="menuitem">
|
||||||
|
<span>Комментарий</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div id="measureModalBackdrop" class="modal-backdrop hidden"></div>
|
<div id="measureModalBackdrop" class="modal-backdrop hidden"></div>
|
||||||
<div id="measureModal" class="templates-panel measurement-modal hidden"></div>
|
<div id="measureModal" class="templates-panel measurement-modal hidden"></div>
|
||||||
<div id="objectModalBackdrop" class="modal-backdrop hidden"></div>
|
<div id="objectModalBackdrop" class="modal-backdrop hidden"></div>
|
||||||
<div id="objectModal" class="templates-panel measurement-modal hidden"></div>
|
<div id="objectModal" class="templates-panel measurement-modal hidden"></div>
|
||||||
|
<div id="commentModalBackdrop" class="modal-backdrop hidden"></div>
|
||||||
|
<div id="commentModal" class="comment-card-modal ops-comment-detail hidden" role="dialog" aria-modal="true" aria-label="Комментарий к модели">
|
||||||
|
<div class="comment-card-modal__header" id="commentModalHeader">
|
||||||
|
<div class="ops-detail-actions">
|
||||||
|
<button class="ops-detail-icon-btn" type="button" aria-label="Уведомления" title="Уведомления">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9"></path>
|
||||||
|
<path d="M10 21h4"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="ops-detail-icon-btn" id="commentModalExpandButton" type="button" aria-label="Развернуть" title="Развернуть">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M14 5h5v5M19 5l-7 7M10 19H5v-5M5 19l7-7"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="ops-detail-icon-btn modal-close" id="commentModalClose" type="button" aria-label="Закрыть" title="Закрыть">
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="comment-card-modal__body">
|
||||||
|
<section class="ops-detail-hero">
|
||||||
|
<div class="comment-card-modal__subtitle" id="commentModalSubtitle" hidden></div>
|
||||||
|
<input class="ops-detail-title-input" type="text" id="commentTitleInput" autocomplete="off" placeholder="Новый комментарий">
|
||||||
|
<textarea class="ops-detail-description-input" id="commentBodyInput" rows="2" placeholder="Нажмите, чтобы добавить описание"></textarea>
|
||||||
|
<div class="ops-detail-meta-row">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M3 12a9 9 0 1 0 3-6.7M3 4v6h6"></path>
|
||||||
|
<path d="M12 7v5l3 2"></path>
|
||||||
|
</svg>
|
||||||
|
<span id="commentModalEditedMeta">Последнее редактирование: только что</span>
|
||||||
|
</div>
|
||||||
|
<div class="ops-detail-pills">
|
||||||
|
<button class="ops-detail-pill" id="commentAddSubitemButton" type="button">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M12 3 4 7l8 4 8-4-8-4ZM4 12l8 4 8-4M4 17l8 4 8-4"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Добавить подэлемент</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="commentSubitemMenu" class="nodedc-dropdown-surface bim-subitem-menu hidden" role="menu" aria-label="Тип подэлемента">
|
||||||
|
<button class="nodedc-dropdown-option" data-comment-subitem-kind="text" type="button" role="menuitem">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M4 6h16M4 12h10M4 18h12"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Создать текстовый блок</span>
|
||||||
|
</button>
|
||||||
|
<button class="nodedc-dropdown-option" data-comment-subitem-kind="checker" type="button" role="menuitem">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M9 11l2 2 4-5"></path>
|
||||||
|
<path d="M4 5h16M4 12h3M4 19h16"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Создать чекер</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="ops-comment-subitems hidden" id="commentSubitemsSection">
|
||||||
|
<div class="ops-detail-section-title">Подэлементы</div>
|
||||||
|
<div class="ops-comment-subitems__list" id="commentSubitemsList"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="comment-attachments ops-detail-dropzone" id="commentDropzone">
|
||||||
|
<div class="ops-detail-dropzone__icon">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M12 16V7"></path>
|
||||||
|
<path d="m8 11 4-4 4 4"></path>
|
||||||
|
<path d="M20 16.5a4.5 4.5 0 0 0-8.7-1.6A3.5 3.5 0 1 0 6.5 19H18a2 2 0 0 0 2-2.5Z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div class="ops-detail-dropzone__copy">
|
||||||
|
<strong>Перетащите файлы сюда или нажмите для выбора</strong>
|
||||||
|
<span>Любой формат, несколько файлов за раз, до 50 МБ на файл</span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="comment-attach-button" id="commentAttachButton">Выбрать</button>
|
||||||
|
<input type="file" id="commentAttachmentInput" multiple hidden>
|
||||||
|
<div class="comment-attachment-grid" id="commentAttachmentGrid"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="comment-thread ops-detail-activity">
|
||||||
|
<div class="ops-detail-section-head">
|
||||||
|
<div class="comment-thread__title">Активность</div>
|
||||||
|
<div class="ops-detail-section-actions">
|
||||||
|
<button class="ops-detail-mini-btn" type="button" aria-label="Сортировка" title="Сортировка">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M4 6h12M4 12h8M4 18h4M18 8v10M15 15l3 3 3-3"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="ops-detail-mini-btn" type="button" aria-label="Фильтр" title="Фильтр">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M4 6h16M7 12h10M10 18h4"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label class="ops-activity-composer">
|
||||||
|
<span>Добавить комментарий</span>
|
||||||
|
<textarea id="commentReplyInput" rows="5" placeholder="Добавить комментарий"></textarea>
|
||||||
|
<div class="ops-activity-composer__toolbar">
|
||||||
|
<button type="button" class="ops-detail-mini-btn" id="commentReplyAttachButton" aria-label="Прикрепить файл" title="Прикрепить файл">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="m21.4 11.6-8.5 8.5a6 6 0 0 1-8.5-8.5l8.5-8.5a4 4 0 0 1 5.7 5.7l-8.5 8.5a2 2 0 0 1-2.8-2.8l7.8-7.8"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="ops-detail-mini-btn" aria-label="Реакция" title="Реакция">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18Z"></path>
|
||||||
|
<path d="M8 14s1.5 2 4 2 4-2 4-2M9 9h.01M15 9h.01"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="ops-activity-send" id="commentApplyInlineButton" aria-label="Отправить комментарий" title="Отправить комментарий">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M12 19V5"></path>
|
||||||
|
<path d="m5 12 7-7 7 7"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<input type="file" id="commentReplyAttachmentInput" multiple hidden>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<div class="comment-attachment-grid comment-attachment-grid--reply" id="commentReplyAttachmentGrid"></div>
|
||||||
|
<div class="comment-thread__list" id="commentThreadList"></div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div class="comment-card-modal__footer">
|
||||||
|
<div class="error-text comment-card-modal__footer-error" id="commentModalError" hidden></div>
|
||||||
|
<button class="secondary-btn" id="commentCancelButton" type="button">Отменить</button>
|
||||||
|
<button class="primary-btn" id="commentApplyButton" type="button">Применить</button>
|
||||||
|
<button class="primary-btn" id="commentSaveButton" type="button">Сохранить</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="saveProjectBackdrop" class="modal-backdrop hidden"></div>
|
<div id="saveProjectBackdrop" class="modal-backdrop hidden"></div>
|
||||||
<div id="saveProjectModal" class="save-project-modal hidden">
|
<div id="saveProjectModal" class="save-project-modal hidden">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">Сохранить проект</div>
|
<div class="modal-title">Сохранить проект</div>
|
||||||
<button class="modal-close" id="saveProjectClose" aria-label="Закрыть">×</button>
|
<button class="modal-close inspector-collapse-btn" id="saveProjectClose" aria-label="Закрыть">
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<label for="saveProjectName" class="input-label">Имя проекта</label>
|
<label for="saveProjectName" class="input-label">Имя проекта</label>
|
||||||
<input type="text" id="saveProjectName" placeholder="Новый проект" autocomplete="off">
|
<input type="text" id="saveProjectName" placeholder="Новый проект" autocomplete="off">
|
||||||
|
|
@ -202,7 +601,11 @@
|
||||||
<div id="deleteProjectModal" class="save-project-modal hidden">
|
<div id="deleteProjectModal" class="save-project-modal hidden">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<div class="modal-title">Удалить проект</div>
|
<div class="modal-title">Удалить проект</div>
|
||||||
<button class="modal-close" id="deleteProjectClose" aria-label="Закрыть">×</button>
|
<button class="modal-close inspector-collapse-btn" id="deleteProjectClose" aria-label="Закрыть">
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-hint">Вы уверены, что хотите удалить проект?</div>
|
<div class="input-hint">Вы уверены, что хотите удалить проект?</div>
|
||||||
<div class="modal-actions">
|
<div class="modal-actions">
|
||||||
|
|
@ -211,18 +614,118 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="error-text" id="deleteProjectError"></div>
|
<div class="error-text" id="deleteProjectError"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="shareModalBackdrop" class="modal-backdrop hidden"></div>
|
||||||
|
<div id="shareModal" class="save-project-modal hidden">
|
||||||
|
<div class="modal-header">
|
||||||
|
<div class="modal-title">Ссылка на модель</div>
|
||||||
|
<button class="modal-close inspector-collapse-btn" id="shareModalClose" aria-label="Закрыть">
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<input type="text" id="shareLinkInput" readonly autocomplete="off">
|
||||||
|
<div class="modal-actions">
|
||||||
|
<button class="secondary-btn" id="shareModalCancel" type="button">Закрыть</button>
|
||||||
|
<button class="primary-btn" id="shareCopyButton" type="button" disabled>Скопировать</button>
|
||||||
|
</div>
|
||||||
|
<div class="error-text" id="shareError"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="bottomToolbar" class="bottom-toolbar">
|
<div id="bottomToolbar" class="bottom-toolbar">
|
||||||
<button class="tb-btn" data-action="settings" title="Настройки">⚙</button>
|
<button class="tb-btn" data-action="settings" title="Настройки" aria-label="Настройки">
|
||||||
<button class="tb-btn" data-action="templates" title="Примеры">📂</button>
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<button class="tb-btn" data-action="measure" title="Линейка">📏</button>
|
<path d="M12 15.5A3.5 3.5 0 1 0 12 8a3.5 3.5 0 0 0 0 7.5Z"></path>
|
||||||
|
<path d="M19.4 15a1.7 1.7 0 0 0 .34 1.88l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06A1.7 1.7 0 0 0 15 19.37a1.7 1.7 0 0 0-1 .56V20a2 2 0 0 1-4 0v-.08a1.7 1.7 0 0 0-1-.56 1.7 1.7 0 0 0-1.88.34l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.7 1.7 0 0 0 4.63 15a1.7 1.7 0 0 0-.56-1H4a2 2 0 0 1 0-4h.08a1.7 1.7 0 0 0 .56-1 1.7 1.7 0 0 0-.34-1.88l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.7 1.7 0 0 0 9 4.63a1.7 1.7 0 0 0 1-.56V4a2 2 0 0 1 4 0v.08a1.7 1.7 0 0 0 1 .56 1.7 1.7 0 0 0 1.88-.34l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.7 1.7 0 0 0 19.37 9c.18.38.38.73.56 1H20a2 2 0 0 1 0 4h-.08c-.18.27-.37.62-.52 1Z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="tb-btn" data-action="templates" title="Примеры" aria-label="Примеры">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M3.5 6.5h6l2 2h9v8.75a2.25 2.25 0 0 1-2.25 2.25H5.75A2.25 2.25 0 0 1 3.5 17.25V6.5Z"></path>
|
||||||
|
<path d="M3.5 10h17"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="tb-btn" data-action="measure" title="Линейка" aria-label="Линейка">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M4.5 15.5 15.5 4.5l4 4-11 11-4-4Z"></path>
|
||||||
|
<path d="m8 12 2 2"></path>
|
||||||
|
<path d="m10.5 9.5 1.5 1.5"></path>
|
||||||
|
<path d="m13 7 2 2"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="tb-btn" data-action="section" title="Разрез" aria-label="Разрез">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M4.5 7.25 12 3.5l7.5 3.75L12 11 4.5 7.25Z"></path>
|
||||||
|
<path d="M4.5 16.75 12 20.5l7.5-3.75"></path>
|
||||||
|
<path d="M12 11v9.5"></path>
|
||||||
|
<path d="M6.25 4.5 17.75 19.5"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="tb-btn" data-action="comments" title="Комментарии" aria-label="Комментарии">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M6.5 5.5h11a2.5 2.5 0 0 1 2.5 2.5v6.25a2.5 2.5 0 0 1-2.5 2.5H12l-4.3 3.1v-3.1H6.5A2.5 2.5 0 0 1 4 14.25V8a2.5 2.5 0 0 1 2.5-2.5Z"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<button class="tb-btn" data-action="projection" title="Перспектива / аксонометрия">A</button>
|
<button class="tb-btn" data-action="projection" title="Перспектива / аксонометрия">A</button>
|
||||||
<button class="tb-btn" data-action="add" title="Добавить файл">+</button>
|
<button class="tb-btn" data-action="share" title="Поделиться моделью" aria-label="Поделиться моделью">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M12 14.5V4.75"></path>
|
||||||
|
<path d="m8.25 8.5 3.75-3.75 3.75 3.75"></path>
|
||||||
|
<path d="M7.25 11.25H6.5a2 2 0 0 0-2 2v4.25a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2v-4.25a2 2 0 0 0-2-2h-.75"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="tb-btn" data-action="add" title="Добавить файл" aria-label="Добавить файл">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path d="M12 5v14"></path>
|
||||||
|
<path d="M5 12h14"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="sectionToolbar" class="section-toolbar hidden" aria-label="Управление разрезом">
|
||||||
|
<canvas id="sectionPlanesOverview" class="section-overview" width="80" height="80"></canvas>
|
||||||
|
<button class="section-tool-btn" data-section-action="camera" type="button" title="По камере" aria-label="По камере">
|
||||||
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M1.7 8s2.35-4 6.3-4 6.3 4 6.3 4-2.35 4-6.3 4-6.3-4-6.3-4Z"></path>
|
||||||
|
<circle cx="8" cy="8" r="2.15"></circle>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="section-tool-btn section-axis-btn" data-section-action="x" type="button" title="Ось X" aria-label="Ось X">
|
||||||
|
<svg class="section-letter-icon" viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<text x="8" y="8" text-anchor="middle" dominant-baseline="central">X</text>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="section-tool-btn section-axis-btn" data-section-action="y" type="button" title="Ось Y" aria-label="Ось Y">
|
||||||
|
<svg class="section-letter-icon" viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<text x="8" y="8" text-anchor="middle" dominant-baseline="central">Y</text>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="section-tool-btn section-axis-btn" data-section-action="z" type="button" title="Ось Z" aria-label="Ось Z">
|
||||||
|
<svg class="section-letter-icon" viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<text x="8" y="8" text-anchor="middle" dominant-baseline="central">Z</text>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="section-tool-btn" data-section-action="flip" type="button" title="Инвертировать" aria-label="Инвертировать">
|
||||||
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M5.5 4.7h4.4a3.05 3.05 0 0 1 0 6.1H5.6"></path>
|
||||||
|
<path d="M6.7 2.9 4.9 4.7l1.8 1.8"></path>
|
||||||
|
<path d="m9.3 13.1 1.8-1.8-1.8-1.8"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<button class="section-tool-btn" data-section-action="clear" type="button" title="Удалить разрез" aria-label="Удалить разрез">
|
||||||
|
<svg viewBox="0 0 16 16" aria-hidden="true">
|
||||||
|
<path d="M3.2 4.5h9.6"></path>
|
||||||
|
<path d="M6.2 4.5V3.1h3.6v1.4"></path>
|
||||||
|
<path d="m4.4 4.5.55 8.4h6.1l.55-8.4"></path>
|
||||||
|
<path d="M6.65 6.5v4.3"></path>
|
||||||
|
<path d="M9.35 6.5v4.3"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input id="fileInput" class="hidden" type="file"
|
<input id="fileInput" class="hidden" type="file"
|
||||||
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
|
accept=".xkt,.glb,.gltf,.bim,.las,.laz,.obj,.stl">
|
||||||
|
|
||||||
<script type="module" src="./dcViewer.js"></script>
|
<script type="module" src="/dcViewer.js?v=64"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -123676,7 +123676,12 @@ function parseGLTF(plugin, src, gltf, metaModelJSON, options, sceneModel, ok, er
|
||||||
const spinner = plugin.viewer.scene.canvas.spinner;
|
const spinner = plugin.viewer.scene.canvas.spinner;
|
||||||
spinner.processes++;
|
spinner.processes++;
|
||||||
parse$3(gltf, GLTFLoader, {
|
parse$3(gltf, GLTFLoader, {
|
||||||
baseUri: options.basePath
|
baseUri: options.basePath,
|
||||||
|
modules: {
|
||||||
|
"draco_wasm_wrapper.js": "/lib/draco/draco_wasm_wrapper.js",
|
||||||
|
"draco_decoder.wasm": "/lib/draco/draco_decoder.wasm",
|
||||||
|
"draco_decoder.js": "/lib/draco/draco_decoder.js"
|
||||||
|
}
|
||||||
}).then((gltfData) => {
|
}).then((gltfData) => {
|
||||||
const processedGLTF = postProcessGLTF(gltfData);
|
const processedGLTF = postProcessGLTF(gltfData);
|
||||||
const ctx = {
|
const ctx = {
|
||||||
|
|
@ -126073,6 +126078,10 @@ function loadMTLs(modelNode, state, ok) {
|
||||||
var basePath = state.basePath;
|
var basePath = state.basePath;
|
||||||
var srcList = Object.keys(state.materialLibraries);
|
var srcList = Object.keys(state.materialLibraries);
|
||||||
var numToLoad = srcList.length;
|
var numToLoad = srcList.length;
|
||||||
|
if (numToLoad === 0) {
|
||||||
|
ok();
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (var i = 0, len = numToLoad; i < len; i++) {
|
for (var i = 0, len = numToLoad; i < len; i++) {
|
||||||
loadMTL(modelNode, basePath, basePath + srcList[i], function () {
|
loadMTL(modelNode, basePath, basePath + srcList[i], function () {
|
||||||
if (--numToLoad === 0) {
|
if (--numToLoad === 0) {
|
||||||
|
|
@ -126510,6 +126519,9 @@ class TransformControl {
|
||||||
scale: [5, 5, 5],
|
scale: [5, 5, 5],
|
||||||
isObject: false
|
isObject: false
|
||||||
});
|
});
|
||||||
|
this._rootNode = rootNode;
|
||||||
|
this._styleScale = 1;
|
||||||
|
this._baseRootScale = 5;
|
||||||
|
|
||||||
const pos = math.vec3();
|
const pos = math.vec3();
|
||||||
this._setPosition = (function() {
|
this._setPosition = (function() {
|
||||||
|
|
@ -126565,6 +126577,45 @@ class TransformControl {
|
||||||
axisHandle: tubeGeometry(handleRadius, arrowLength, 20)
|
axisHandle: tubeGeometry(handleRadius, arrowLength, 20)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateGeometryPositions = (geometry, cfg) => {
|
||||||
|
if (geometry?.positions && cfg?.positions && geometry.positions.length === cfg.positions.length) {
|
||||||
|
geometry.positions = cfg.positions;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this._guideThicknessScale = 1;
|
||||||
|
this._setGuideThickness = (scale = 1) => {
|
||||||
|
const nextScale = Math.max(0.5, Math.min(2.5, Number(scale) || 1));
|
||||||
|
if (nextScale === this._guideThicknessScale) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._guideThicknessScale = nextScale;
|
||||||
|
const guideTube = tubeRadius * nextScale;
|
||||||
|
updateGeometryPositions(shapes.curve, buildTorusGeometry({
|
||||||
|
radius: arrowLength - 0.2,
|
||||||
|
tube: guideTube,
|
||||||
|
radialSegments: 64,
|
||||||
|
tubeSegments: 14,
|
||||||
|
arc: (Math.PI * 2.0) * 0.25
|
||||||
|
}));
|
||||||
|
updateGeometryPositions(shapes.hoop, buildTorusGeometry({
|
||||||
|
radius: arrowLength - 0.2,
|
||||||
|
tube: guideTube,
|
||||||
|
radialSegments: 64,
|
||||||
|
tubeSegments: 8,
|
||||||
|
arc: Math.PI * 2.0
|
||||||
|
}));
|
||||||
|
updateGeometryPositions(shapes.axis, buildCylinderGeometry({
|
||||||
|
radiusTop: guideTube,
|
||||||
|
radiusBottom: guideTube,
|
||||||
|
radialSegments: 20,
|
||||||
|
heightSegments: 1,
|
||||||
|
height: arrowLength,
|
||||||
|
openEnded: false
|
||||||
|
}));
|
||||||
|
rootNode.scene?.glRedraw?.();
|
||||||
|
};
|
||||||
|
|
||||||
const colorMaterial = (rgb) => new PhongMaterial(rootNode, {
|
const colorMaterial = (rgb) => new PhongMaterial(rootNode, {
|
||||||
diffuse: rgb,
|
diffuse: rgb,
|
||||||
emissive: rgb,
|
emissive: rgb,
|
||||||
|
|
@ -126831,6 +126882,16 @@ class TransformControl {
|
||||||
return {
|
return {
|
||||||
setPositionActive: (a) => { positionActive = a; updatePositionHandle(); },
|
setPositionActive: (a) => { positionActive = a; updatePositionHandle(); },
|
||||||
setRotationActive: (a) => { rotationActive = a; updateRotationHandle(); },
|
setRotationActive: (a) => { rotationActive = a; updateRotationHandle(); },
|
||||||
|
setColor: (color) => {
|
||||||
|
if (!color) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
material.diffuse = color;
|
||||||
|
material.emissive = color;
|
||||||
|
if (hoop.highlightMaterial) {
|
||||||
|
hoop.highlightMaterial.fillColor = color;
|
||||||
|
}
|
||||||
|
},
|
||||||
set visible(v) {
|
set visible(v) {
|
||||||
visible = v;
|
visible = v;
|
||||||
updatePositionHandle();
|
updatePositionHandle();
|
||||||
|
|
@ -126868,13 +126929,16 @@ class TransformControl {
|
||||||
{ // Keep gizmo screen size constant
|
{ // Keep gizmo screen size constant
|
||||||
let lastDist = -1;
|
let lastDist = -1;
|
||||||
const setRootNodeScale = size => {
|
const setRootNodeScale = size => {
|
||||||
if (rootNode.scale[0] !== size) {
|
this._baseRootScale = size;
|
||||||
rootNode.scale = [size, size, size];
|
const styledSize = size * (this._styleScale || 1);
|
||||||
|
if (rootNode.scale[0] !== styledSize) {
|
||||||
|
rootNode.scale = [styledSize, styledSize, styledSize];
|
||||||
if (this._handlers && this._handlers.onScreenScale) {
|
if (this._handlers && this._handlers.onScreenScale) {
|
||||||
this._handlers.onScreenScale(rootNode.scale);
|
this._handlers.onScreenScale(rootNode.scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
this._applyRootScale = () => setRootNodeScale(this._baseRootScale || rootNode.scale[0] || 5);
|
||||||
const onSceneTick = scene.on("tick", () => {
|
const onSceneTick = scene.on("tick", () => {
|
||||||
const camera = scene.camera;
|
const camera = scene.camera;
|
||||||
const dist = Math.abs(math.distVec3(camera.eye, pos));
|
const dist = Math.abs(math.distVec3(camera.eye, pos));
|
||||||
|
|
@ -127030,6 +127094,22 @@ class TransformControl {
|
||||||
this.__destroy();
|
this.__destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setStyle(style = {}) {
|
||||||
|
if (style.gizmoDiameter !== undefined) {
|
||||||
|
this._styleScale = style.gizmoDiameter;
|
||||||
|
this._applyRootScale?.();
|
||||||
|
}
|
||||||
|
if (style.gizmoThickness !== undefined) {
|
||||||
|
this._setGuideThickness?.(style.gizmoThickness);
|
||||||
|
}
|
||||||
|
if (style.axes) {
|
||||||
|
this._displayMeshes.x?.setColor?.(style.axes.x);
|
||||||
|
this._displayMeshes.y?.setColor?.(style.axes.y);
|
||||||
|
this._displayMeshes.z?.setColor?.(style.axes.z);
|
||||||
|
}
|
||||||
|
this._rootNode?.scene?.glRedraw?.();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called to assign this Control to Handlers.
|
* Called to assign this Control to Handlers.
|
||||||
* Call with a null or undefined value to disconnect the Control from whatever Handlers it was assigned to.
|
* Call with a null or undefined value to disconnect the Control from whatever Handlers it was assigned to.
|
||||||
|
|
@ -127703,7 +127783,7 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
const planeRoot = (function() {
|
const planeRoot = (function() {
|
||||||
const rootNode = new Node$1(scene, { isObject: false });
|
const rootNode = new Node$1(scene, { isObject: false });
|
||||||
|
|
||||||
rootNode.addChild(new Mesh(rootNode, { // plane
|
const planeMesh = rootNode.addChild(new Mesh(rootNode, { // plane
|
||||||
geometry: new ReadableGeometry(rootNode, {
|
geometry: new ReadableGeometry(rootNode, {
|
||||||
primitive: "triangles",
|
primitive: "triangles",
|
||||||
positions: [
|
positions: [
|
||||||
|
|
@ -127737,7 +127817,7 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
isObject: false
|
isObject: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
rootNode.addChild(new Mesh(rootNode, { // Visible frame
|
const frameMesh = rootNode.addChild(new Mesh(rootNode, { // Visible frame
|
||||||
geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
|
geometry: new ReadableGeometry(rootNode, buildTorusGeometry({
|
||||||
center: [0, 0, 0],
|
center: [0, 0, 0],
|
||||||
radius: 1.7,
|
radius: 1.7,
|
||||||
|
|
@ -127769,6 +127849,38 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
isObject: false
|
isObject: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const setPhongMaterial = (material, color, alpha) => {
|
||||||
|
if (!material) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (color) {
|
||||||
|
material.diffuse = color;
|
||||||
|
material.emissive = color;
|
||||||
|
}
|
||||||
|
if (alpha !== undefined) {
|
||||||
|
material.alpha = alpha;
|
||||||
|
material.alphaMode = alpha < 1 ? "blend" : "opaque";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setEmphasisMaterial = (material, fillColor, fillAlpha, edgeColor, edgeAlpha) => {
|
||||||
|
if (!material) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fillColor) {
|
||||||
|
material.fillColor = fillColor;
|
||||||
|
}
|
||||||
|
if (fillAlpha !== undefined) {
|
||||||
|
material.fillAlpha = fillAlpha;
|
||||||
|
}
|
||||||
|
if (edgeColor) {
|
||||||
|
material.edgeColor = edgeColor;
|
||||||
|
}
|
||||||
|
if (edgeAlpha !== undefined) {
|
||||||
|
material.edgeAlpha = edgeAlpha;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setPosition: (function() {
|
setPosition: (function() {
|
||||||
const origin = math.vec3();
|
const origin = math.vec3();
|
||||||
|
|
@ -127781,7 +127893,26 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
})(),
|
})(),
|
||||||
setQuaternion: q => { rootNode.quaternion = q; },
|
setQuaternion: q => { rootNode.quaternion = q; },
|
||||||
setScale: s => { rootNode.scale = s; },
|
setScale: s => { rootNode.scale = s; },
|
||||||
setVisible: v => { rootNode.visible = v; }
|
setVisible: v => { rootNode.visible = v; },
|
||||||
|
setStyle: (style = {}) => {
|
||||||
|
setPhongMaterial(planeMesh.material, style.planeFillColor, style.planeFillAlpha);
|
||||||
|
setEmphasisMaterial(
|
||||||
|
planeMesh.ghostMaterial,
|
||||||
|
style.planeFillColor,
|
||||||
|
style.planeFillAlpha,
|
||||||
|
style.planeEdgeColor,
|
||||||
|
style.planeEdgeAlpha
|
||||||
|
);
|
||||||
|
planeMesh.opacity = style.planeFillAlpha;
|
||||||
|
setPhongMaterial(frameMesh.material, style.planeEdgeColor, style.planeEdgeAlpha);
|
||||||
|
setEmphasisMaterial(
|
||||||
|
frameMesh.highlightMaterial,
|
||||||
|
style.planeEdgeColor,
|
||||||
|
style.planeEdgeAlpha,
|
||||||
|
style.planeEdgeColor,
|
||||||
|
style.planeEdgeAlpha
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
let unbindSectionPlane = () => { };
|
let unbindSectionPlane = () => { };
|
||||||
|
|
@ -127803,6 +127934,10 @@ class SectionPlanesPlugin extends Plugin {
|
||||||
},
|
},
|
||||||
setCulled: c => { culled = c; updateVisible(); },
|
setCulled: c => { culled = c; updateVisible(); },
|
||||||
setVisible: v => { visible = v; updateVisible(); },
|
setVisible: v => { visible = v; updateVisible(); },
|
||||||
|
setStyle: style => {
|
||||||
|
planeRoot.setStyle?.(style);
|
||||||
|
ctrl.setStyle?.(style);
|
||||||
|
},
|
||||||
_setSectionPlane: sectionPlane => {
|
_setSectionPlane: sectionPlane => {
|
||||||
unbindSectionPlane();
|
unbindSectionPlane();
|
||||||
if (sectionPlane) {
|
if (sectionPlane) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
loaders.gl is licensed under the MIT license
|
||||||
|
|
||||||
|
Copyright (c) vis.gl contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Copyright (c) 2015 Uber Technologies, Inc.
|
||||||
|
|
||||||
|
loaders.gl includes certain files from Cesium (https://github.com/AnalyticalGraphicsInc/cesium)
|
||||||
|
under the Apache 2 License (found in the submodule: modules/3d-tiles):)
|
||||||
|
|
||||||
|
Copyright 2011-2018 CesiumJS Contributors
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
Local Draco decoder assets:
|
||||||
|
|
||||||
|
- draco_wasm_wrapper.js and draco_decoder.wasm are copied from @loaders.gl/draco 4.3.4.
|
||||||
|
License: MIT. See LICENSE.loaders-gl-draco.
|
||||||
|
|
||||||
|
- draco_decoder.js is copied from draco3d 1.5.7 as the local JS fallback decoder.
|
||||||
|
Package license: Apache-2.0.
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(k){var n=0;return function(){return n<k.length?{done:!1,value:k[n++]}:{done:!0}}};$jscomp.arrayIterator=function(k){return{next:$jscomp.arrayIteratorImpl(k)}};$jscomp.makeIterator=function(k){var n="undefined"!=typeof Symbol&&Symbol.iterator&&k[Symbol.iterator];return n?n.call(k):$jscomp.arrayIterator(k)};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;
|
||||||
|
$jscomp.ISOLATE_POLYFILLS=!1;$jscomp.FORCE_POLYFILL_PROMISE=!1;$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION=!1;$jscomp.getGlobal=function(k){k=["object"==typeof globalThis&&globalThis,k,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var n=0;n<k.length;++n){var l=k[n];if(l&&l.Math==Math)return l}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);
|
||||||
|
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(k,n,l){if(k==Array.prototype||k==Object.prototype)return k;k[n]=l.value;return k};$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";
|
||||||
|
var $jscomp$lookupPolyfilledValue=function(k,n){var l=$jscomp.propertyToPolyfillSymbol[n];if(null==l)return k[n];l=k[l];return void 0!==l?l:k[n]};$jscomp.polyfill=function(k,n,l,p){n&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(k,n,l,p):$jscomp.polyfillUnisolated(k,n,l,p))};
|
||||||
|
$jscomp.polyfillUnisolated=function(k,n,l,p){l=$jscomp.global;k=k.split(".");for(p=0;p<k.length-1;p++){var h=k[p];if(!(h in l))return;l=l[h]}k=k[k.length-1];p=l[k];n=n(p);n!=p&&null!=n&&$jscomp.defineProperty(l,k,{configurable:!0,writable:!0,value:n})};
|
||||||
|
$jscomp.polyfillIsolated=function(k,n,l,p){var h=k.split(".");k=1===h.length;p=h[0];p=!k&&p in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var A=0;A<h.length-1;A++){var f=h[A];if(!(f in p))return;p=p[f]}h=h[h.length-1];l=$jscomp.IS_SYMBOL_NATIVE&&"es6"===l?p[h]:null;n=n(l);null!=n&&(k?$jscomp.defineProperty($jscomp.polyfills,h,{configurable:!0,writable:!0,value:n}):n!==l&&(void 0===$jscomp.propertyToPolyfillSymbol[h]&&(l=1E9*Math.random()>>>0,$jscomp.propertyToPolyfillSymbol[h]=$jscomp.IS_SYMBOL_NATIVE?
|
||||||
|
$jscomp.global.Symbol(h):$jscomp.POLYFILL_PREFIX+l+"$"+h),$jscomp.defineProperty(p,$jscomp.propertyToPolyfillSymbol[h],{configurable:!0,writable:!0,value:n})))};
|
||||||
|
$jscomp.polyfill("Promise",function(k){function n(){this.batch_=null}function l(f){return f instanceof h?f:new h(function(q,v){q(f)})}if(k&&(!($jscomp.FORCE_POLYFILL_PROMISE||$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION&&"undefined"===typeof $jscomp.global.PromiseRejectionEvent)||!$jscomp.global.Promise||-1===$jscomp.global.Promise.toString().indexOf("[native code]")))return k;n.prototype.asyncExecute=function(f){if(null==this.batch_){this.batch_=[];var q=this;this.asyncExecuteFunction(function(){q.executeBatch_()})}this.batch_.push(f)};
|
||||||
|
var p=$jscomp.global.setTimeout;n.prototype.asyncExecuteFunction=function(f){p(f,0)};n.prototype.executeBatch_=function(){for(;this.batch_&&this.batch_.length;){var f=this.batch_;this.batch_=[];for(var q=0;q<f.length;++q){var v=f[q];f[q]=null;try{v()}catch(z){this.asyncThrow_(z)}}}this.batch_=null};n.prototype.asyncThrow_=function(f){this.asyncExecuteFunction(function(){throw f;})};var h=function(f){this.state_=0;this.result_=void 0;this.onSettledCallbacks_=[];this.isRejectionHandled_=!1;var q=this.createResolveAndReject_();
|
||||||
|
try{f(q.resolve,q.reject)}catch(v){q.reject(v)}};h.prototype.createResolveAndReject_=function(){function f(z){return function(O){v||(v=!0,z.call(q,O))}}var q=this,v=!1;return{resolve:f(this.resolveTo_),reject:f(this.reject_)}};h.prototype.resolveTo_=function(f){if(f===this)this.reject_(new TypeError("A Promise cannot resolve to itself"));else if(f instanceof h)this.settleSameAsPromise_(f);else{a:switch(typeof f){case "object":var q=null!=f;break a;case "function":q=!0;break a;default:q=!1}q?this.resolveToNonPromiseObj_(f):
|
||||||
|
this.fulfill_(f)}};h.prototype.resolveToNonPromiseObj_=function(f){var q=void 0;try{q=f.then}catch(v){this.reject_(v);return}"function"==typeof q?this.settleSameAsThenable_(q,f):this.fulfill_(f)};h.prototype.reject_=function(f){this.settle_(2,f)};h.prototype.fulfill_=function(f){this.settle_(1,f)};h.prototype.settle_=function(f,q){if(0!=this.state_)throw Error("Cannot settle("+f+", "+q+"): Promise already settled in state"+this.state_);this.state_=f;this.result_=q;2===this.state_&&this.scheduleUnhandledRejectionCheck_();
|
||||||
|
this.executeOnSettledCallbacks_()};h.prototype.scheduleUnhandledRejectionCheck_=function(){var f=this;p(function(){if(f.notifyUnhandledRejection_()){var q=$jscomp.global.console;"undefined"!==typeof q&&q.error(f.result_)}},1)};h.prototype.notifyUnhandledRejection_=function(){if(this.isRejectionHandled_)return!1;var f=$jscomp.global.CustomEvent,q=$jscomp.global.Event,v=$jscomp.global.dispatchEvent;if("undefined"===typeof v)return!0;"function"===typeof f?f=new f("unhandledrejection",{cancelable:!0}):
|
||||||
|
"function"===typeof q?f=new q("unhandledrejection",{cancelable:!0}):(f=$jscomp.global.document.createEvent("CustomEvent"),f.initCustomEvent("unhandledrejection",!1,!0,f));f.promise=this;f.reason=this.result_;return v(f)};h.prototype.executeOnSettledCallbacks_=function(){if(null!=this.onSettledCallbacks_){for(var f=0;f<this.onSettledCallbacks_.length;++f)A.asyncExecute(this.onSettledCallbacks_[f]);this.onSettledCallbacks_=null}};var A=new n;h.prototype.settleSameAsPromise_=function(f){var q=this.createResolveAndReject_();
|
||||||
|
f.callWhenSettled_(q.resolve,q.reject)};h.prototype.settleSameAsThenable_=function(f,q){var v=this.createResolveAndReject_();try{f.call(q,v.resolve,v.reject)}catch(z){v.reject(z)}};h.prototype.then=function(f,q){function v(t,x){return"function"==typeof t?function(D){try{z(t(D))}catch(R){O(R)}}:x}var z,O,ba=new h(function(t,x){z=t;O=x});this.callWhenSettled_(v(f,z),v(q,O));return ba};h.prototype.catch=function(f){return this.then(void 0,f)};h.prototype.callWhenSettled_=function(f,q){function v(){switch(z.state_){case 1:f(z.result_);
|
||||||
|
break;case 2:q(z.result_);break;default:throw Error("Unexpected state: "+z.state_);}}var z=this;null==this.onSettledCallbacks_?A.asyncExecute(v):this.onSettledCallbacks_.push(v);this.isRejectionHandled_=!0};h.resolve=l;h.reject=function(f){return new h(function(q,v){v(f)})};h.race=function(f){return new h(function(q,v){for(var z=$jscomp.makeIterator(f),O=z.next();!O.done;O=z.next())l(O.value).callWhenSettled_(q,v)})};h.all=function(f){var q=$jscomp.makeIterator(f),v=q.next();return v.done?l([]):new h(function(z,
|
||||||
|
O){function ba(D){return function(R){t[D]=R;x--;0==x&&z(t)}}var t=[],x=0;do t.push(void 0),x++,l(v.value).callWhenSettled_(ba(t.length-1),O),v=q.next();while(!v.done)})};return h},"es6","es3");$jscomp.owns=function(k,n){return Object.prototype.hasOwnProperty.call(k,n)};$jscomp.assign=$jscomp.TRUST_ES6_POLYFILLS&&"function"==typeof Object.assign?Object.assign:function(k,n){for(var l=1;l<arguments.length;l++){var p=arguments[l];if(p)for(var h in p)$jscomp.owns(p,h)&&(k[h]=p[h])}return k};
|
||||||
|
$jscomp.polyfill("Object.assign",function(k){return k||$jscomp.assign},"es6","es3");$jscomp.checkStringArgs=function(k,n,l){if(null==k)throw new TypeError("The 'this' value for String.prototype."+l+" must not be null or undefined");if(n instanceof RegExp)throw new TypeError("First argument to String.prototype."+l+" must not be a regular expression");return k+""};
|
||||||
|
$jscomp.polyfill("String.prototype.startsWith",function(k){return k?k:function(n,l){var p=$jscomp.checkStringArgs(this,n,"startsWith");n+="";var h=p.length,A=n.length;l=Math.max(0,Math.min(l|0,p.length));for(var f=0;f<A&&l<h;)if(p[l++]!=n[f++])return!1;return f>=A}},"es6","es3");
|
||||||
|
$jscomp.polyfill("Array.prototype.copyWithin",function(k){function n(l){l=Number(l);return Infinity===l||-Infinity===l?l:l|0}return k?k:function(l,p,h){var A=this.length;l=n(l);p=n(p);h=void 0===h?A:n(h);l=0>l?Math.max(A+l,0):Math.min(l,A);p=0>p?Math.max(A+p,0):Math.min(p,A);h=0>h?Math.max(A+h,0):Math.min(h,A);if(l<p)for(;p<h;)p in this?this[l++]=this[p++]:(delete this[l++],p++);else for(h=Math.min(h,A+p-l),l+=h-p;h>p;)--h in this?this[--l]=this[h]:delete this[--l];return this}},"es6","es3");
|
||||||
|
$jscomp.typedArrayCopyWithin=function(k){return k?k:Array.prototype.copyWithin};$jscomp.polyfill("Int8Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint8Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint8ClampedArray.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Int16Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");
|
||||||
|
$jscomp.polyfill("Uint16Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Int32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Float32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Float64Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");
|
||||||
|
var DracoDecoderModule=function(){var k="undefined"!==typeof document&&document.currentScript?document.currentScript.src:void 0;"undefined"!==typeof __filename&&(k=k||__filename);return function(n){function l(e){return a.locateFile?a.locateFile(e,U):U+e}function p(e,b,c){var d=b+c;for(c=b;e[c]&&!(c>=d);)++c;if(16<c-b&&e.buffer&&va)return va.decode(e.subarray(b,c));for(d="";b<c;){var g=e[b++];if(g&128){var u=e[b++]&63;if(192==(g&224))d+=String.fromCharCode((g&31)<<6|u);else{var X=e[b++]&63;g=224==
|
||||||
|
(g&240)?(g&15)<<12|u<<6|X:(g&7)<<18|u<<12|X<<6|e[b++]&63;65536>g?d+=String.fromCharCode(g):(g-=65536,d+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else d+=String.fromCharCode(g)}return d}function h(e,b){return e?p(ea,e,b):""}function A(){var e=ja.buffer;a.HEAP8=Y=new Int8Array(e);a.HEAP16=new Int16Array(e);a.HEAP32=ca=new Int32Array(e);a.HEAPU8=ea=new Uint8Array(e);a.HEAPU16=new Uint16Array(e);a.HEAPU32=V=new Uint32Array(e);a.HEAPF32=new Float32Array(e);a.HEAPF64=new Float64Array(e)}function f(e){if(a.onAbort)a.onAbort(e);
|
||||||
|
e="Aborted("+e+")";da(e);wa=!0;e=new WebAssembly.RuntimeError(e+". Build with -sASSERTIONS for more info.");ka(e);throw e;}function q(e){try{if(e==P&&fa)return new Uint8Array(fa);if(ma)return ma(e);throw"both async and sync fetching of the wasm failed";}catch(b){f(b)}}function v(){if(!fa&&(xa||ha)){if("function"==typeof fetch&&!P.startsWith("file://"))return fetch(P,{credentials:"same-origin"}).then(function(e){if(!e.ok)throw"failed to load wasm binary file at '"+P+"'";return e.arrayBuffer()}).catch(function(){return q(P)});
|
||||||
|
if(na)return new Promise(function(e,b){na(P,function(c){e(new Uint8Array(c))},b)})}return Promise.resolve().then(function(){return q(P)})}function z(e){for(;0<e.length;)e.shift()(a)}function O(e){this.excPtr=e;this.ptr=e-24;this.set_type=function(b){V[this.ptr+4>>2]=b};this.get_type=function(){return V[this.ptr+4>>2]};this.set_destructor=function(b){V[this.ptr+8>>2]=b};this.get_destructor=function(){return V[this.ptr+8>>2]};this.set_refcount=function(b){ca[this.ptr>>2]=b};this.set_caught=function(b){Y[this.ptr+
|
||||||
|
12>>0]=b?1:0};this.get_caught=function(){return 0!=Y[this.ptr+12>>0]};this.set_rethrown=function(b){Y[this.ptr+13>>0]=b?1:0};this.get_rethrown=function(){return 0!=Y[this.ptr+13>>0]};this.init=function(b,c){this.set_adjusted_ptr(0);this.set_type(b);this.set_destructor(c);this.set_refcount(0);this.set_caught(!1);this.set_rethrown(!1)};this.add_ref=function(){ca[this.ptr>>2]+=1};this.release_ref=function(){var b=ca[this.ptr>>2];ca[this.ptr>>2]=b-1;return 1===b};this.set_adjusted_ptr=function(b){V[this.ptr+
|
||||||
|
16>>2]=b};this.get_adjusted_ptr=function(){return V[this.ptr+16>>2]};this.get_exception_ptr=function(){if(ya(this.get_type()))return V[this.excPtr>>2];var b=this.get_adjusted_ptr();return 0!==b?b:this.excPtr}}function ba(){function e(){if(!la&&(la=!0,a.calledRun=!0,!wa)){za=!0;z(oa);Aa(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;)Ba.unshift(a.postRun.shift());z(Ba)}}if(!(0<aa)){if(a.preRun)for("function"==
|
||||||
|
typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)Ca.unshift(a.preRun.shift());z(Ca);0<aa||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);e()},1)):e())}}function t(){}function x(e){return(e||t).__cache__}function D(e,b){var c=x(b),d=c[e];if(d)return d;d=Object.create((b||t).prototype);d.ptr=e;return c[e]=d}function R(e){if("string"===typeof e){for(var b=0,c=0;c<e.length;++c){var d=e.charCodeAt(c);127>=d?b++:2047>=d?b+=2:55296<=d&&57343>=
|
||||||
|
d?(b+=4,++c):b+=3}b=Array(b+1);c=0;d=b.length;if(0<d){d=c+d-1;for(var g=0;g<e.length;++g){var u=e.charCodeAt(g);if(55296<=u&&57343>=u){var X=e.charCodeAt(++g);u=65536+((u&1023)<<10)|X&1023}if(127>=u){if(c>=d)break;b[c++]=u}else{if(2047>=u){if(c+1>=d)break;b[c++]=192|u>>6}else{if(65535>=u){if(c+2>=d)break;b[c++]=224|u>>12}else{if(c+3>=d)break;b[c++]=240|u>>18;b[c++]=128|u>>12&63}b[c++]=128|u>>6&63}b[c++]=128|u&63}}b[c]=0}e=r.alloc(b,Y);r.copy(b,Y,e);return e}return e}function pa(e){if("object"===typeof e){var b=
|
||||||
|
r.alloc(e,Y);r.copy(e,Y,b);return b}return e}function Z(){throw"cannot construct a VoidPtr, no constructor in IDL";}function S(){this.ptr=Da();x(S)[this.ptr]=this}function Q(){this.ptr=Ea();x(Q)[this.ptr]=this}function W(){this.ptr=Fa();x(W)[this.ptr]=this}function w(){this.ptr=Ga();x(w)[this.ptr]=this}function C(){this.ptr=Ha();x(C)[this.ptr]=this}function F(){this.ptr=Ia();x(F)[this.ptr]=this}function G(){this.ptr=Ja();x(G)[this.ptr]=this}function E(){this.ptr=Ka();x(E)[this.ptr]=this}function T(){this.ptr=
|
||||||
|
La();x(T)[this.ptr]=this}function B(){throw"cannot construct a Status, no constructor in IDL";}function H(){this.ptr=Ma();x(H)[this.ptr]=this}function I(){this.ptr=Na();x(I)[this.ptr]=this}function J(){this.ptr=Oa();x(J)[this.ptr]=this}function K(){this.ptr=Pa();x(K)[this.ptr]=this}function L(){this.ptr=Qa();x(L)[this.ptr]=this}function M(){this.ptr=Ra();x(M)[this.ptr]=this}function N(){this.ptr=Sa();x(N)[this.ptr]=this}function y(){this.ptr=Ta();x(y)[this.ptr]=this}function m(){this.ptr=Ua();x(m)[this.ptr]=
|
||||||
|
this}n=void 0===n?{}:n;var a="undefined"!=typeof n?n:{},Aa,ka;a.ready=new Promise(function(e,b){Aa=e;ka=b});var Va=!1,Wa=!1;a.onRuntimeInitialized=function(){Va=!0;if(Wa&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.onModuleParsed=function(){Wa=!0;if(Va&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.isVersionSupported=function(e){if("string"!==typeof e)return!1;e=e.split(".");return 2>e.length||3<e.length?!1:1==e[0]&&0<=e[1]&&5>=e[1]?!0:0!=e[0]||10<e[1]?!1:!0};var Xa=
|
||||||
|
Object.assign({},a),xa="object"==typeof window,ha="function"==typeof importScripts,Ya="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,U="";if(Ya){var Za=require("fs"),qa=require("path");U=ha?qa.dirname(U)+"/":__dirname+"/";var $a=function(e,b){e=e.startsWith("file://")?new URL(e):qa.normalize(e);return Za.readFileSync(e,b?void 0:"utf8")};var ma=function(e){e=$a(e,!0);e.buffer||(e=new Uint8Array(e));return e};var na=function(e,b,c){e=e.startsWith("file://")?
|
||||||
|
new URL(e):qa.normalize(e);Za.readFile(e,function(d,g){d?c(d):b(g.buffer)})};1<process.argv.length&&process.argv[1].replace(/\\/g,"/");process.argv.slice(2);a.inspect=function(){return"[Emscripten Module object]"}}else if(xa||ha)ha?U=self.location.href:"undefined"!=typeof document&&document.currentScript&&(U=document.currentScript.src),k&&(U=k),U=0!==U.indexOf("blob:")?U.substr(0,U.replace(/[?#].*/,"").lastIndexOf("/")+1):"",$a=function(e){var b=new XMLHttpRequest;b.open("GET",e,!1);b.send(null);
|
||||||
|
return b.responseText},ha&&(ma=function(e){var b=new XMLHttpRequest;b.open("GET",e,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),na=function(e,b,c){var d=new XMLHttpRequest;d.open("GET",e,!0);d.responseType="arraybuffer";d.onload=function(){200==d.status||0==d.status&&d.response?b(d.response):c()};d.onerror=c;d.send(null)};var ud=a.print||console.log.bind(console),da=a.printErr||console.warn.bind(console);Object.assign(a,Xa);Xa=null;var fa;a.wasmBinary&&(fa=a.wasmBinary);
|
||||||
|
"object"!=typeof WebAssembly&&f("no native wasm support detected");var ja,wa=!1,va="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0,Y,ea,ca,V,Ca=[],oa=[],Ba=[],za=!1,aa=0,ra=null,ia=null;var P="draco_decoder.wasm";P.startsWith("data:application/octet-stream;base64,")||(P=l(P));var vd=0,wd=[null,[],[]],xd={b:function(e,b,c){(new O(e)).init(b,c);vd++;throw e;},a:function(){f("")},g:function(e,b,c){ea.copyWithin(e,b,b+c)},e:function(e){var b=ea.length;e>>>=0;if(2147483648<e)return!1;for(var c=
|
||||||
|
1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,e+100663296);var g=Math;d=Math.max(e,d);g=g.min.call(g,2147483648,d+(65536-d%65536)%65536);a:{d=ja.buffer;try{ja.grow(g-d.byteLength+65535>>>16);A();var u=1;break a}catch(X){}u=void 0}if(u)return!0}return!1},f:function(e){return 52},d:function(e,b,c,d,g){return 70},c:function(e,b,c,d){for(var g=0,u=0;u<c;u++){var X=V[b>>2],ab=V[b+4>>2];b+=8;for(var sa=0;sa<ab;sa++){var ta=ea[X+sa],ua=wd[e];0===ta||10===ta?((1===e?ud:da)(p(ua,0)),ua.length=0):ua.push(ta)}g+=
|
||||||
|
ab}V[d>>2]=g;return 0}};(function(){function e(g,u){a.asm=g.exports;ja=a.asm.h;A();oa.unshift(a.asm.i);aa--;a.monitorRunDependencies&&a.monitorRunDependencies(aa);0==aa&&(null!==ra&&(clearInterval(ra),ra=null),ia&&(g=ia,ia=null,g()))}function b(g){e(g.instance)}function c(g){return v().then(function(u){return WebAssembly.instantiate(u,d)}).then(function(u){return u}).then(g,function(u){da("failed to asynchronously prepare wasm: "+u);f(u)})}var d={a:xd};aa++;a.monitorRunDependencies&&a.monitorRunDependencies(aa);
|
||||||
|
if(a.instantiateWasm)try{return a.instantiateWasm(d,e)}catch(g){da("Module.instantiateWasm callback failed with error: "+g),ka(g)}(function(){return fa||"function"!=typeof WebAssembly.instantiateStreaming||P.startsWith("data:application/octet-stream;base64,")||P.startsWith("file://")||Ya||"function"!=typeof fetch?c(b):fetch(P,{credentials:"same-origin"}).then(function(g){return WebAssembly.instantiateStreaming(g,d).then(b,function(u){da("wasm streaming compile failed: "+u);da("falling back to ArrayBuffer instantiation");
|
||||||
|
return c(b)})})})().catch(ka);return{}})();var bb=a._emscripten_bind_VoidPtr___destroy___0=function(){return(bb=a._emscripten_bind_VoidPtr___destroy___0=a.asm.k).apply(null,arguments)},Da=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=function(){return(Da=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=a.asm.l).apply(null,arguments)},cb=a._emscripten_bind_DecoderBuffer_Init_2=function(){return(cb=a._emscripten_bind_DecoderBuffer_Init_2=a.asm.m).apply(null,arguments)},db=a._emscripten_bind_DecoderBuffer___destroy___0=
|
||||||
|
function(){return(db=a._emscripten_bind_DecoderBuffer___destroy___0=a.asm.n).apply(null,arguments)},Ea=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=function(){return(Ea=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=a.asm.o).apply(null,arguments)},eb=a._emscripten_bind_AttributeTransformData_transform_type_0=function(){return(eb=a._emscripten_bind_AttributeTransformData_transform_type_0=a.asm.p).apply(null,arguments)},fb=a._emscripten_bind_AttributeTransformData___destroy___0=
|
||||||
|
function(){return(fb=a._emscripten_bind_AttributeTransformData___destroy___0=a.asm.q).apply(null,arguments)},Fa=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=function(){return(Fa=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=a.asm.r).apply(null,arguments)},gb=a._emscripten_bind_GeometryAttribute___destroy___0=function(){return(gb=a._emscripten_bind_GeometryAttribute___destroy___0=a.asm.s).apply(null,arguments)},Ga=a._emscripten_bind_PointAttribute_PointAttribute_0=function(){return(Ga=
|
||||||
|
a._emscripten_bind_PointAttribute_PointAttribute_0=a.asm.t).apply(null,arguments)},hb=a._emscripten_bind_PointAttribute_size_0=function(){return(hb=a._emscripten_bind_PointAttribute_size_0=a.asm.u).apply(null,arguments)},ib=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=function(){return(ib=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=a.asm.v).apply(null,arguments)},jb=a._emscripten_bind_PointAttribute_attribute_type_0=function(){return(jb=a._emscripten_bind_PointAttribute_attribute_type_0=
|
||||||
|
a.asm.w).apply(null,arguments)},kb=a._emscripten_bind_PointAttribute_data_type_0=function(){return(kb=a._emscripten_bind_PointAttribute_data_type_0=a.asm.x).apply(null,arguments)},lb=a._emscripten_bind_PointAttribute_num_components_0=function(){return(lb=a._emscripten_bind_PointAttribute_num_components_0=a.asm.y).apply(null,arguments)},mb=a._emscripten_bind_PointAttribute_normalized_0=function(){return(mb=a._emscripten_bind_PointAttribute_normalized_0=a.asm.z).apply(null,arguments)},nb=a._emscripten_bind_PointAttribute_byte_stride_0=
|
||||||
|
function(){return(nb=a._emscripten_bind_PointAttribute_byte_stride_0=a.asm.A).apply(null,arguments)},ob=a._emscripten_bind_PointAttribute_byte_offset_0=function(){return(ob=a._emscripten_bind_PointAttribute_byte_offset_0=a.asm.B).apply(null,arguments)},pb=a._emscripten_bind_PointAttribute_unique_id_0=function(){return(pb=a._emscripten_bind_PointAttribute_unique_id_0=a.asm.C).apply(null,arguments)},qb=a._emscripten_bind_PointAttribute___destroy___0=function(){return(qb=a._emscripten_bind_PointAttribute___destroy___0=
|
||||||
|
a.asm.D).apply(null,arguments)},Ha=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0=function(){return(Ha=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0=a.asm.E).apply(null,arguments)},rb=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=function(){return(rb=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=a.asm.F).apply(null,arguments)},sb=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=
|
||||||
|
function(){return(sb=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=a.asm.G).apply(null,arguments)},tb=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=function(){return(tb=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=a.asm.H).apply(null,arguments)},ub=a._emscripten_bind_AttributeQuantizationTransform_range_0=function(){return(ub=a._emscripten_bind_AttributeQuantizationTransform_range_0=a.asm.I).apply(null,arguments)},vb=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=
|
||||||
|
function(){return(vb=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=a.asm.J).apply(null,arguments)},Ia=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=function(){return(Ia=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=a.asm.K).apply(null,arguments)},wb=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=function(){return(wb=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=a.asm.L).apply(null,
|
||||||
|
arguments)},xb=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=function(){return(xb=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=a.asm.M).apply(null,arguments)},yb=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=function(){return(yb=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=a.asm.N).apply(null,arguments)},Ja=a._emscripten_bind_PointCloud_PointCloud_0=function(){return(Ja=a._emscripten_bind_PointCloud_PointCloud_0=a.asm.O).apply(null,
|
||||||
|
arguments)},zb=a._emscripten_bind_PointCloud_num_attributes_0=function(){return(zb=a._emscripten_bind_PointCloud_num_attributes_0=a.asm.P).apply(null,arguments)},Ab=a._emscripten_bind_PointCloud_num_points_0=function(){return(Ab=a._emscripten_bind_PointCloud_num_points_0=a.asm.Q).apply(null,arguments)},Bb=a._emscripten_bind_PointCloud___destroy___0=function(){return(Bb=a._emscripten_bind_PointCloud___destroy___0=a.asm.R).apply(null,arguments)},Ka=a._emscripten_bind_Mesh_Mesh_0=function(){return(Ka=
|
||||||
|
a._emscripten_bind_Mesh_Mesh_0=a.asm.S).apply(null,arguments)},Cb=a._emscripten_bind_Mesh_num_faces_0=function(){return(Cb=a._emscripten_bind_Mesh_num_faces_0=a.asm.T).apply(null,arguments)},Db=a._emscripten_bind_Mesh_num_attributes_0=function(){return(Db=a._emscripten_bind_Mesh_num_attributes_0=a.asm.U).apply(null,arguments)},Eb=a._emscripten_bind_Mesh_num_points_0=function(){return(Eb=a._emscripten_bind_Mesh_num_points_0=a.asm.V).apply(null,arguments)},Fb=a._emscripten_bind_Mesh___destroy___0=function(){return(Fb=
|
||||||
|
a._emscripten_bind_Mesh___destroy___0=a.asm.W).apply(null,arguments)},La=a._emscripten_bind_Metadata_Metadata_0=function(){return(La=a._emscripten_bind_Metadata_Metadata_0=a.asm.X).apply(null,arguments)},Gb=a._emscripten_bind_Metadata___destroy___0=function(){return(Gb=a._emscripten_bind_Metadata___destroy___0=a.asm.Y).apply(null,arguments)},Hb=a._emscripten_bind_Status_code_0=function(){return(Hb=a._emscripten_bind_Status_code_0=a.asm.Z).apply(null,arguments)},Ib=a._emscripten_bind_Status_ok_0=function(){return(Ib=
|
||||||
|
a._emscripten_bind_Status_ok_0=a.asm._).apply(null,arguments)},Jb=a._emscripten_bind_Status_error_msg_0=function(){return(Jb=a._emscripten_bind_Status_error_msg_0=a.asm.$).apply(null,arguments)},Kb=a._emscripten_bind_Status___destroy___0=function(){return(Kb=a._emscripten_bind_Status___destroy___0=a.asm.aa).apply(null,arguments)},Ma=a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=function(){return(Ma=a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=a.asm.ba).apply(null,arguments)},
|
||||||
|
Lb=a._emscripten_bind_DracoFloat32Array_GetValue_1=function(){return(Lb=a._emscripten_bind_DracoFloat32Array_GetValue_1=a.asm.ca).apply(null,arguments)},Mb=a._emscripten_bind_DracoFloat32Array_size_0=function(){return(Mb=a._emscripten_bind_DracoFloat32Array_size_0=a.asm.da).apply(null,arguments)},Nb=a._emscripten_bind_DracoFloat32Array___destroy___0=function(){return(Nb=a._emscripten_bind_DracoFloat32Array___destroy___0=a.asm.ea).apply(null,arguments)},Na=a._emscripten_bind_DracoInt8Array_DracoInt8Array_0=
|
||||||
|
function(){return(Na=a._emscripten_bind_DracoInt8Array_DracoInt8Array_0=a.asm.fa).apply(null,arguments)},Ob=a._emscripten_bind_DracoInt8Array_GetValue_1=function(){return(Ob=a._emscripten_bind_DracoInt8Array_GetValue_1=a.asm.ga).apply(null,arguments)},Pb=a._emscripten_bind_DracoInt8Array_size_0=function(){return(Pb=a._emscripten_bind_DracoInt8Array_size_0=a.asm.ha).apply(null,arguments)},Qb=a._emscripten_bind_DracoInt8Array___destroy___0=function(){return(Qb=a._emscripten_bind_DracoInt8Array___destroy___0=
|
||||||
|
a.asm.ia).apply(null,arguments)},Oa=a._emscripten_bind_DracoUInt8Array_DracoUInt8Array_0=function(){return(Oa=a._emscripten_bind_DracoUInt8Array_DracoUInt8Array_0=a.asm.ja).apply(null,arguments)},Rb=a._emscripten_bind_DracoUInt8Array_GetValue_1=function(){return(Rb=a._emscripten_bind_DracoUInt8Array_GetValue_1=a.asm.ka).apply(null,arguments)},Sb=a._emscripten_bind_DracoUInt8Array_size_0=function(){return(Sb=a._emscripten_bind_DracoUInt8Array_size_0=a.asm.la).apply(null,arguments)},Tb=a._emscripten_bind_DracoUInt8Array___destroy___0=
|
||||||
|
function(){return(Tb=a._emscripten_bind_DracoUInt8Array___destroy___0=a.asm.ma).apply(null,arguments)},Pa=a._emscripten_bind_DracoInt16Array_DracoInt16Array_0=function(){return(Pa=a._emscripten_bind_DracoInt16Array_DracoInt16Array_0=a.asm.na).apply(null,arguments)},Ub=a._emscripten_bind_DracoInt16Array_GetValue_1=function(){return(Ub=a._emscripten_bind_DracoInt16Array_GetValue_1=a.asm.oa).apply(null,arguments)},Vb=a._emscripten_bind_DracoInt16Array_size_0=function(){return(Vb=a._emscripten_bind_DracoInt16Array_size_0=
|
||||||
|
a.asm.pa).apply(null,arguments)},Wb=a._emscripten_bind_DracoInt16Array___destroy___0=function(){return(Wb=a._emscripten_bind_DracoInt16Array___destroy___0=a.asm.qa).apply(null,arguments)},Qa=a._emscripten_bind_DracoUInt16Array_DracoUInt16Array_0=function(){return(Qa=a._emscripten_bind_DracoUInt16Array_DracoUInt16Array_0=a.asm.ra).apply(null,arguments)},Xb=a._emscripten_bind_DracoUInt16Array_GetValue_1=function(){return(Xb=a._emscripten_bind_DracoUInt16Array_GetValue_1=a.asm.sa).apply(null,arguments)},
|
||||||
|
Yb=a._emscripten_bind_DracoUInt16Array_size_0=function(){return(Yb=a._emscripten_bind_DracoUInt16Array_size_0=a.asm.ta).apply(null,arguments)},Zb=a._emscripten_bind_DracoUInt16Array___destroy___0=function(){return(Zb=a._emscripten_bind_DracoUInt16Array___destroy___0=a.asm.ua).apply(null,arguments)},Ra=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=function(){return(Ra=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=a.asm.va).apply(null,arguments)},$b=a._emscripten_bind_DracoInt32Array_GetValue_1=
|
||||||
|
function(){return($b=a._emscripten_bind_DracoInt32Array_GetValue_1=a.asm.wa).apply(null,arguments)},ac=a._emscripten_bind_DracoInt32Array_size_0=function(){return(ac=a._emscripten_bind_DracoInt32Array_size_0=a.asm.xa).apply(null,arguments)},bc=a._emscripten_bind_DracoInt32Array___destroy___0=function(){return(bc=a._emscripten_bind_DracoInt32Array___destroy___0=a.asm.ya).apply(null,arguments)},Sa=a._emscripten_bind_DracoUInt32Array_DracoUInt32Array_0=function(){return(Sa=a._emscripten_bind_DracoUInt32Array_DracoUInt32Array_0=
|
||||||
|
a.asm.za).apply(null,arguments)},cc=a._emscripten_bind_DracoUInt32Array_GetValue_1=function(){return(cc=a._emscripten_bind_DracoUInt32Array_GetValue_1=a.asm.Aa).apply(null,arguments)},dc=a._emscripten_bind_DracoUInt32Array_size_0=function(){return(dc=a._emscripten_bind_DracoUInt32Array_size_0=a.asm.Ba).apply(null,arguments)},ec=a._emscripten_bind_DracoUInt32Array___destroy___0=function(){return(ec=a._emscripten_bind_DracoUInt32Array___destroy___0=a.asm.Ca).apply(null,arguments)},Ta=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=
|
||||||
|
function(){return(Ta=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=a.asm.Da).apply(null,arguments)},fc=a._emscripten_bind_MetadataQuerier_HasEntry_2=function(){return(fc=a._emscripten_bind_MetadataQuerier_HasEntry_2=a.asm.Ea).apply(null,arguments)},gc=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=function(){return(gc=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=a.asm.Fa).apply(null,arguments)},hc=a._emscripten_bind_MetadataQuerier_GetIntEntryArray_3=function(){return(hc=a._emscripten_bind_MetadataQuerier_GetIntEntryArray_3=
|
||||||
|
a.asm.Ga).apply(null,arguments)},ic=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=function(){return(ic=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=a.asm.Ha).apply(null,arguments)},jc=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=function(){return(jc=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=a.asm.Ia).apply(null,arguments)},kc=a._emscripten_bind_MetadataQuerier_NumEntries_1=function(){return(kc=a._emscripten_bind_MetadataQuerier_NumEntries_1=a.asm.Ja).apply(null,arguments)},
|
||||||
|
lc=a._emscripten_bind_MetadataQuerier_GetEntryName_2=function(){return(lc=a._emscripten_bind_MetadataQuerier_GetEntryName_2=a.asm.Ka).apply(null,arguments)},mc=a._emscripten_bind_MetadataQuerier___destroy___0=function(){return(mc=a._emscripten_bind_MetadataQuerier___destroy___0=a.asm.La).apply(null,arguments)},Ua=a._emscripten_bind_Decoder_Decoder_0=function(){return(Ua=a._emscripten_bind_Decoder_Decoder_0=a.asm.Ma).apply(null,arguments)},nc=a._emscripten_bind_Decoder_DecodeArrayToPointCloud_3=function(){return(nc=
|
||||||
|
a._emscripten_bind_Decoder_DecodeArrayToPointCloud_3=a.asm.Na).apply(null,arguments)},oc=a._emscripten_bind_Decoder_DecodeArrayToMesh_3=function(){return(oc=a._emscripten_bind_Decoder_DecodeArrayToMesh_3=a.asm.Oa).apply(null,arguments)},pc=a._emscripten_bind_Decoder_GetAttributeId_2=function(){return(pc=a._emscripten_bind_Decoder_GetAttributeId_2=a.asm.Pa).apply(null,arguments)},qc=a._emscripten_bind_Decoder_GetAttributeIdByName_2=function(){return(qc=a._emscripten_bind_Decoder_GetAttributeIdByName_2=
|
||||||
|
a.asm.Qa).apply(null,arguments)},rc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=function(){return(rc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=a.asm.Ra).apply(null,arguments)},sc=a._emscripten_bind_Decoder_GetAttribute_2=function(){return(sc=a._emscripten_bind_Decoder_GetAttribute_2=a.asm.Sa).apply(null,arguments)},tc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2=function(){return(tc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2=a.asm.Ta).apply(null,arguments)},
|
||||||
|
uc=a._emscripten_bind_Decoder_GetMetadata_1=function(){return(uc=a._emscripten_bind_Decoder_GetMetadata_1=a.asm.Ua).apply(null,arguments)},vc=a._emscripten_bind_Decoder_GetAttributeMetadata_2=function(){return(vc=a._emscripten_bind_Decoder_GetAttributeMetadata_2=a.asm.Va).apply(null,arguments)},wc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=function(){return(wc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=a.asm.Wa).apply(null,arguments)},xc=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=
|
||||||
|
function(){return(xc=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=a.asm.Xa).apply(null,arguments)},yc=a._emscripten_bind_Decoder_GetTrianglesUInt16Array_3=function(){return(yc=a._emscripten_bind_Decoder_GetTrianglesUInt16Array_3=a.asm.Ya).apply(null,arguments)},zc=a._emscripten_bind_Decoder_GetTrianglesUInt32Array_3=function(){return(zc=a._emscripten_bind_Decoder_GetTrianglesUInt32Array_3=a.asm.Za).apply(null,arguments)},Ac=a._emscripten_bind_Decoder_GetAttributeFloat_3=function(){return(Ac=
|
||||||
|
a._emscripten_bind_Decoder_GetAttributeFloat_3=a.asm._a).apply(null,arguments)},Bc=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=function(){return(Bc=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=a.asm.$a).apply(null,arguments)},Cc=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=function(){return(Cc=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=a.asm.ab).apply(null,arguments)},Dc=a._emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3=function(){return(Dc=
|
||||||
|
a._emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3=a.asm.bb).apply(null,arguments)},Ec=a._emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3=function(){return(Ec=a._emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3=a.asm.cb).apply(null,arguments)},Fc=a._emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3=function(){return(Fc=a._emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3=a.asm.db).apply(null,arguments)},Gc=a._emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3=
|
||||||
|
function(){return(Gc=a._emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3=a.asm.eb).apply(null,arguments)},Hc=a._emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3=function(){return(Hc=a._emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3=a.asm.fb).apply(null,arguments)},Ic=a._emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3=function(){return(Ic=a._emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3=a.asm.gb).apply(null,arguments)},Jc=a._emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5=
|
||||||
|
function(){return(Jc=a._emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5=a.asm.hb).apply(null,arguments)},Kc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=function(){return(Kc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=a.asm.ib).apply(null,arguments)},Lc=a._emscripten_bind_Decoder_GetEncodedGeometryType_Deprecated_1=function(){return(Lc=a._emscripten_bind_Decoder_GetEncodedGeometryType_Deprecated_1=a.asm.jb).apply(null,arguments)},Mc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=
|
||||||
|
function(){return(Mc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=a.asm.kb).apply(null,arguments)},Nc=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=function(){return(Nc=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=a.asm.lb).apply(null,arguments)},Oc=a._emscripten_bind_Decoder___destroy___0=function(){return(Oc=a._emscripten_bind_Decoder___destroy___0=a.asm.mb).apply(null,arguments)},Pc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=function(){return(Pc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=
|
||||||
|
a.asm.nb).apply(null,arguments)},Qc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=function(){return(Qc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=a.asm.ob).apply(null,arguments)},Rc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=function(){return(Rc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=a.asm.pb).apply(null,arguments)},Sc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=
|
||||||
|
function(){return(Sc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=a.asm.qb).apply(null,arguments)},Tc=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=function(){return(Tc=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=a.asm.rb).apply(null,arguments)},Uc=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=function(){return(Uc=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=a.asm.sb).apply(null,arguments)},Vc=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=
|
||||||
|
function(){return(Vc=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=a.asm.tb).apply(null,arguments)},Wc=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR=function(){return(Wc=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR=a.asm.ub).apply(null,arguments)},Xc=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=function(){return(Xc=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=a.asm.vb).apply(null,arguments)},Yc=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=
|
||||||
|
function(){return(Yc=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=a.asm.wb).apply(null,arguments)},Zc=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=function(){return(Zc=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=a.asm.xb).apply(null,arguments)},$c=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=function(){return($c=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=a.asm.yb).apply(null,arguments)},ad=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=
|
||||||
|
function(){return(ad=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=a.asm.zb).apply(null,arguments)},bd=a._emscripten_enum_draco_DataType_DT_INVALID=function(){return(bd=a._emscripten_enum_draco_DataType_DT_INVALID=a.asm.Ab).apply(null,arguments)},cd=a._emscripten_enum_draco_DataType_DT_INT8=function(){return(cd=a._emscripten_enum_draco_DataType_DT_INT8=a.asm.Bb).apply(null,arguments)},dd=a._emscripten_enum_draco_DataType_DT_UINT8=function(){return(dd=a._emscripten_enum_draco_DataType_DT_UINT8=
|
||||||
|
a.asm.Cb).apply(null,arguments)},ed=a._emscripten_enum_draco_DataType_DT_INT16=function(){return(ed=a._emscripten_enum_draco_DataType_DT_INT16=a.asm.Db).apply(null,arguments)},fd=a._emscripten_enum_draco_DataType_DT_UINT16=function(){return(fd=a._emscripten_enum_draco_DataType_DT_UINT16=a.asm.Eb).apply(null,arguments)},gd=a._emscripten_enum_draco_DataType_DT_INT32=function(){return(gd=a._emscripten_enum_draco_DataType_DT_INT32=a.asm.Fb).apply(null,arguments)},hd=a._emscripten_enum_draco_DataType_DT_UINT32=
|
||||||
|
function(){return(hd=a._emscripten_enum_draco_DataType_DT_UINT32=a.asm.Gb).apply(null,arguments)},id=a._emscripten_enum_draco_DataType_DT_INT64=function(){return(id=a._emscripten_enum_draco_DataType_DT_INT64=a.asm.Hb).apply(null,arguments)},jd=a._emscripten_enum_draco_DataType_DT_UINT64=function(){return(jd=a._emscripten_enum_draco_DataType_DT_UINT64=a.asm.Ib).apply(null,arguments)},kd=a._emscripten_enum_draco_DataType_DT_FLOAT32=function(){return(kd=a._emscripten_enum_draco_DataType_DT_FLOAT32=a.asm.Jb).apply(null,
|
||||||
|
arguments)},ld=a._emscripten_enum_draco_DataType_DT_FLOAT64=function(){return(ld=a._emscripten_enum_draco_DataType_DT_FLOAT64=a.asm.Kb).apply(null,arguments)},md=a._emscripten_enum_draco_DataType_DT_BOOL=function(){return(md=a._emscripten_enum_draco_DataType_DT_BOOL=a.asm.Lb).apply(null,arguments)},nd=a._emscripten_enum_draco_DataType_DT_TYPES_COUNT=function(){return(nd=a._emscripten_enum_draco_DataType_DT_TYPES_COUNT=a.asm.Mb).apply(null,arguments)},od=a._emscripten_enum_draco_StatusCode_OK=function(){return(od=
|
||||||
|
a._emscripten_enum_draco_StatusCode_OK=a.asm.Nb).apply(null,arguments)},pd=a._emscripten_enum_draco_StatusCode_DRACO_ERROR=function(){return(pd=a._emscripten_enum_draco_StatusCode_DRACO_ERROR=a.asm.Ob).apply(null,arguments)},qd=a._emscripten_enum_draco_StatusCode_IO_ERROR=function(){return(qd=a._emscripten_enum_draco_StatusCode_IO_ERROR=a.asm.Pb).apply(null,arguments)},rd=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=function(){return(rd=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=
|
||||||
|
a.asm.Qb).apply(null,arguments)},sd=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=function(){return(sd=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=a.asm.Rb).apply(null,arguments)},td=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=function(){return(td=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=a.asm.Sb).apply(null,arguments)};a._malloc=function(){return(a._malloc=a.asm.Tb).apply(null,arguments)};a._free=function(){return(a._free=a.asm.Ub).apply(null,arguments)};
|
||||||
|
var ya=function(){return(ya=a.asm.Vb).apply(null,arguments)};a.___start_em_js=15856;a.___stop_em_js=15954;var la;ia=function b(){la||ba();la||(ia=b)};if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();ba();t.prototype=Object.create(t.prototype);t.prototype.constructor=t;t.prototype.__class__=t;t.__cache__={};a.WrapperObject=t;a.getCache=x;a.wrapPointer=D;a.castObject=function(b,c){return D(b.ptr,c)};a.NULL=D(0);a.destroy=function(b){if(!b.__destroy__)throw"Error: Cannot destroy object. (Did you create it yourself?)";
|
||||||
|
b.__destroy__();delete x(b.__class__)[b.ptr]};a.compare=function(b,c){return b.ptr===c.ptr};a.getPointer=function(b){return b.ptr};a.getClass=function(b){return b.__class__};var r={buffer:0,size:0,pos:0,temps:[],needed:0,prepare:function(){if(r.needed){for(var b=0;b<r.temps.length;b++)a._free(r.temps[b]);r.temps.length=0;a._free(r.buffer);r.buffer=0;r.size+=r.needed;r.needed=0}r.buffer||(r.size+=128,r.buffer=a._malloc(r.size),r.buffer||f(void 0));r.pos=0},alloc:function(b,c){r.buffer||f(void 0);b=
|
||||||
|
b.length*c.BYTES_PER_ELEMENT;b=b+7&-8;r.pos+b>=r.size?(0<b||f(void 0),r.needed+=b,c=a._malloc(b),r.temps.push(c)):(c=r.buffer+r.pos,r.pos+=b);return c},copy:function(b,c,d){d>>>=0;switch(c.BYTES_PER_ELEMENT){case 2:d>>>=1;break;case 4:d>>>=2;break;case 8:d>>>=3}for(var g=0;g<b.length;g++)c[d+g]=b[g]}};Z.prototype=Object.create(t.prototype);Z.prototype.constructor=Z;Z.prototype.__class__=Z;Z.__cache__={};a.VoidPtr=Z;Z.prototype.__destroy__=Z.prototype.__destroy__=function(){bb(this.ptr)};S.prototype=
|
||||||
|
Object.create(t.prototype);S.prototype.constructor=S;S.prototype.__class__=S;S.__cache__={};a.DecoderBuffer=S;S.prototype.Init=S.prototype.Init=function(b,c){var d=this.ptr;r.prepare();"object"==typeof b&&(b=pa(b));c&&"object"===typeof c&&(c=c.ptr);cb(d,b,c)};S.prototype.__destroy__=S.prototype.__destroy__=function(){db(this.ptr)};Q.prototype=Object.create(t.prototype);Q.prototype.constructor=Q;Q.prototype.__class__=Q;Q.__cache__={};a.AttributeTransformData=Q;Q.prototype.transform_type=Q.prototype.transform_type=
|
||||||
|
function(){return eb(this.ptr)};Q.prototype.__destroy__=Q.prototype.__destroy__=function(){fb(this.ptr)};W.prototype=Object.create(t.prototype);W.prototype.constructor=W;W.prototype.__class__=W;W.__cache__={};a.GeometryAttribute=W;W.prototype.__destroy__=W.prototype.__destroy__=function(){gb(this.ptr)};w.prototype=Object.create(t.prototype);w.prototype.constructor=w;w.prototype.__class__=w;w.__cache__={};a.PointAttribute=w;w.prototype.size=w.prototype.size=function(){return hb(this.ptr)};w.prototype.GetAttributeTransformData=
|
||||||
|
w.prototype.GetAttributeTransformData=function(){return D(ib(this.ptr),Q)};w.prototype.attribute_type=w.prototype.attribute_type=function(){return jb(this.ptr)};w.prototype.data_type=w.prototype.data_type=function(){return kb(this.ptr)};w.prototype.num_components=w.prototype.num_components=function(){return lb(this.ptr)};w.prototype.normalized=w.prototype.normalized=function(){return!!mb(this.ptr)};w.prototype.byte_stride=w.prototype.byte_stride=function(){return nb(this.ptr)};w.prototype.byte_offset=
|
||||||
|
w.prototype.byte_offset=function(){return ob(this.ptr)};w.prototype.unique_id=w.prototype.unique_id=function(){return pb(this.ptr)};w.prototype.__destroy__=w.prototype.__destroy__=function(){qb(this.ptr)};C.prototype=Object.create(t.prototype);C.prototype.constructor=C;C.prototype.__class__=C;C.__cache__={};a.AttributeQuantizationTransform=C;C.prototype.InitFromAttribute=C.prototype.InitFromAttribute=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return!!rb(c,b)};C.prototype.quantization_bits=
|
||||||
|
C.prototype.quantization_bits=function(){return sb(this.ptr)};C.prototype.min_value=C.prototype.min_value=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return tb(c,b)};C.prototype.range=C.prototype.range=function(){return ub(this.ptr)};C.prototype.__destroy__=C.prototype.__destroy__=function(){vb(this.ptr)};F.prototype=Object.create(t.prototype);F.prototype.constructor=F;F.prototype.__class__=F;F.__cache__={};a.AttributeOctahedronTransform=F;F.prototype.InitFromAttribute=F.prototype.InitFromAttribute=
|
||||||
|
function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return!!wb(c,b)};F.prototype.quantization_bits=F.prototype.quantization_bits=function(){return xb(this.ptr)};F.prototype.__destroy__=F.prototype.__destroy__=function(){yb(this.ptr)};G.prototype=Object.create(t.prototype);G.prototype.constructor=G;G.prototype.__class__=G;G.__cache__={};a.PointCloud=G;G.prototype.num_attributes=G.prototype.num_attributes=function(){return zb(this.ptr)};G.prototype.num_points=G.prototype.num_points=function(){return Ab(this.ptr)};
|
||||||
|
G.prototype.__destroy__=G.prototype.__destroy__=function(){Bb(this.ptr)};E.prototype=Object.create(t.prototype);E.prototype.constructor=E;E.prototype.__class__=E;E.__cache__={};a.Mesh=E;E.prototype.num_faces=E.prototype.num_faces=function(){return Cb(this.ptr)};E.prototype.num_attributes=E.prototype.num_attributes=function(){return Db(this.ptr)};E.prototype.num_points=E.prototype.num_points=function(){return Eb(this.ptr)};E.prototype.__destroy__=E.prototype.__destroy__=function(){Fb(this.ptr)};T.prototype=
|
||||||
|
Object.create(t.prototype);T.prototype.constructor=T;T.prototype.__class__=T;T.__cache__={};a.Metadata=T;T.prototype.__destroy__=T.prototype.__destroy__=function(){Gb(this.ptr)};B.prototype=Object.create(t.prototype);B.prototype.constructor=B;B.prototype.__class__=B;B.__cache__={};a.Status=B;B.prototype.code=B.prototype.code=function(){return Hb(this.ptr)};B.prototype.ok=B.prototype.ok=function(){return!!Ib(this.ptr)};B.prototype.error_msg=B.prototype.error_msg=function(){return h(Jb(this.ptr))};
|
||||||
|
B.prototype.__destroy__=B.prototype.__destroy__=function(){Kb(this.ptr)};H.prototype=Object.create(t.prototype);H.prototype.constructor=H;H.prototype.__class__=H;H.__cache__={};a.DracoFloat32Array=H;H.prototype.GetValue=H.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Lb(c,b)};H.prototype.size=H.prototype.size=function(){return Mb(this.ptr)};H.prototype.__destroy__=H.prototype.__destroy__=function(){Nb(this.ptr)};I.prototype=Object.create(t.prototype);I.prototype.constructor=
|
||||||
|
I;I.prototype.__class__=I;I.__cache__={};a.DracoInt8Array=I;I.prototype.GetValue=I.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Ob(c,b)};I.prototype.size=I.prototype.size=function(){return Pb(this.ptr)};I.prototype.__destroy__=I.prototype.__destroy__=function(){Qb(this.ptr)};J.prototype=Object.create(t.prototype);J.prototype.constructor=J;J.prototype.__class__=J;J.__cache__={};a.DracoUInt8Array=J;J.prototype.GetValue=J.prototype.GetValue=function(b){var c=
|
||||||
|
this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Rb(c,b)};J.prototype.size=J.prototype.size=function(){return Sb(this.ptr)};J.prototype.__destroy__=J.prototype.__destroy__=function(){Tb(this.ptr)};K.prototype=Object.create(t.prototype);K.prototype.constructor=K;K.prototype.__class__=K;K.__cache__={};a.DracoInt16Array=K;K.prototype.GetValue=K.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Ub(c,b)};K.prototype.size=K.prototype.size=function(){return Vb(this.ptr)};
|
||||||
|
K.prototype.__destroy__=K.prototype.__destroy__=function(){Wb(this.ptr)};L.prototype=Object.create(t.prototype);L.prototype.constructor=L;L.prototype.__class__=L;L.__cache__={};a.DracoUInt16Array=L;L.prototype.GetValue=L.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Xb(c,b)};L.prototype.size=L.prototype.size=function(){return Yb(this.ptr)};L.prototype.__destroy__=L.prototype.__destroy__=function(){Zb(this.ptr)};M.prototype=Object.create(t.prototype);M.prototype.constructor=
|
||||||
|
M;M.prototype.__class__=M;M.__cache__={};a.DracoInt32Array=M;M.prototype.GetValue=M.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return $b(c,b)};M.prototype.size=M.prototype.size=function(){return ac(this.ptr)};M.prototype.__destroy__=M.prototype.__destroy__=function(){bc(this.ptr)};N.prototype=Object.create(t.prototype);N.prototype.constructor=N;N.prototype.__class__=N;N.__cache__={};a.DracoUInt32Array=N;N.prototype.GetValue=N.prototype.GetValue=function(b){var c=
|
||||||
|
this.ptr;b&&"object"===typeof b&&(b=b.ptr);return cc(c,b)};N.prototype.size=N.prototype.size=function(){return dc(this.ptr)};N.prototype.__destroy__=N.prototype.__destroy__=function(){ec(this.ptr)};y.prototype=Object.create(t.prototype);y.prototype.constructor=y;y.prototype.__class__=y;y.__cache__={};a.MetadataQuerier=y;y.prototype.HasEntry=y.prototype.HasEntry=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return!!fc(d,b,c)};y.prototype.GetIntEntry=
|
||||||
|
y.prototype.GetIntEntry=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return gc(d,b,c)};y.prototype.GetIntEntryArray=y.prototype.GetIntEntryArray=function(b,c,d){var g=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);d&&"object"===typeof d&&(d=d.ptr);hc(g,b,c,d)};y.prototype.GetDoubleEntry=y.prototype.GetDoubleEntry=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=
|
||||||
|
c&&"object"===typeof c?c.ptr:R(c);return ic(d,b,c)};y.prototype.GetStringEntry=y.prototype.GetStringEntry=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return h(jc(d,b,c))};y.prototype.NumEntries=y.prototype.NumEntries=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return kc(c,b)};y.prototype.GetEntryName=y.prototype.GetEntryName=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=
|
||||||
|
c.ptr);return h(lc(d,b,c))};y.prototype.__destroy__=y.prototype.__destroy__=function(){mc(this.ptr)};m.prototype=Object.create(t.prototype);m.prototype.constructor=m;m.prototype.__class__=m;m.__cache__={};a.Decoder=m;m.prototype.DecodeArrayToPointCloud=m.prototype.DecodeArrayToPointCloud=function(b,c,d){var g=this.ptr;r.prepare();"object"==typeof b&&(b=pa(b));c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return D(nc(g,b,c,d),B)};m.prototype.DecodeArrayToMesh=m.prototype.DecodeArrayToMesh=
|
||||||
|
function(b,c,d){var g=this.ptr;r.prepare();"object"==typeof b&&(b=pa(b));c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return D(oc(g,b,c,d),B)};m.prototype.GetAttributeId=m.prototype.GetAttributeId=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return pc(d,b,c)};m.prototype.GetAttributeIdByName=m.prototype.GetAttributeIdByName=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?
|
||||||
|
c.ptr:R(c);return qc(d,b,c)};m.prototype.GetAttributeIdByMetadataEntry=m.prototype.GetAttributeIdByMetadataEntry=function(b,c,d){var g=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);d=d&&"object"===typeof d?d.ptr:R(d);return rc(g,b,c,d)};m.prototype.GetAttribute=m.prototype.GetAttribute=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(sc(d,b,c),w)};m.prototype.GetAttributeByUniqueId=m.prototype.GetAttributeByUniqueId=
|
||||||
|
function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(tc(d,b,c),w)};m.prototype.GetMetadata=m.prototype.GetMetadata=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return D(uc(c,b),T)};m.prototype.GetAttributeMetadata=m.prototype.GetAttributeMetadata=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(vc(d,b,c),T)};m.prototype.GetFaceFromMesh=m.prototype.GetFaceFromMesh=function(b,
|
||||||
|
c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!wc(g,b,c,d)};m.prototype.GetTriangleStripsFromMesh=m.prototype.GetTriangleStripsFromMesh=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return xc(d,b,c)};m.prototype.GetTrianglesUInt16Array=m.prototype.GetTrianglesUInt16Array=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);
|
||||||
|
d&&"object"===typeof d&&(d=d.ptr);return!!yc(g,b,c,d)};m.prototype.GetTrianglesUInt32Array=m.prototype.GetTrianglesUInt32Array=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!zc(g,b,c,d)};m.prototype.GetAttributeFloat=m.prototype.GetAttributeFloat=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Ac(g,b,c,d)};m.prototype.GetAttributeFloatForAllPoints=
|
||||||
|
m.prototype.GetAttributeFloatForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Bc(g,b,c,d)};m.prototype.GetAttributeIntForAllPoints=m.prototype.GetAttributeIntForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Cc(g,b,c,d)};m.prototype.GetAttributeInt8ForAllPoints=m.prototype.GetAttributeInt8ForAllPoints=
|
||||||
|
function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Dc(g,b,c,d)};m.prototype.GetAttributeUInt8ForAllPoints=m.prototype.GetAttributeUInt8ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Ec(g,b,c,d)};m.prototype.GetAttributeInt16ForAllPoints=m.prototype.GetAttributeInt16ForAllPoints=function(b,c,d){var g=this.ptr;
|
||||||
|
b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Fc(g,b,c,d)};m.prototype.GetAttributeUInt16ForAllPoints=m.prototype.GetAttributeUInt16ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Gc(g,b,c,d)};m.prototype.GetAttributeInt32ForAllPoints=m.prototype.GetAttributeInt32ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&
|
||||||
|
(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Hc(g,b,c,d)};m.prototype.GetAttributeUInt32ForAllPoints=m.prototype.GetAttributeUInt32ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Ic(g,b,c,d)};m.prototype.GetAttributeDataArrayForAllPoints=m.prototype.GetAttributeDataArrayForAllPoints=function(b,c,d,g,u){var X=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&
|
||||||
|
"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);g&&"object"===typeof g&&(g=g.ptr);u&&"object"===typeof u&&(u=u.ptr);return!!Jc(X,b,c,d,g,u)};m.prototype.SkipAttributeTransform=m.prototype.SkipAttributeTransform=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);Kc(c,b)};m.prototype.GetEncodedGeometryType_Deprecated=m.prototype.GetEncodedGeometryType_Deprecated=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Lc(c,b)};m.prototype.DecodeBufferToPointCloud=
|
||||||
|
m.prototype.DecodeBufferToPointCloud=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(Mc(d,b,c),B)};m.prototype.DecodeBufferToMesh=m.prototype.DecodeBufferToMesh=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(Nc(d,b,c),B)};m.prototype.__destroy__=m.prototype.__destroy__=function(){Oc(this.ptr)};(function(){function b(){a.ATTRIBUTE_INVALID_TRANSFORM=Pc();a.ATTRIBUTE_NO_TRANSFORM=Qc();
|
||||||
|
a.ATTRIBUTE_QUANTIZATION_TRANSFORM=Rc();a.ATTRIBUTE_OCTAHEDRON_TRANSFORM=Sc();a.INVALID=Tc();a.POSITION=Uc();a.NORMAL=Vc();a.COLOR=Wc();a.TEX_COORD=Xc();a.GENERIC=Yc();a.INVALID_GEOMETRY_TYPE=Zc();a.POINT_CLOUD=$c();a.TRIANGULAR_MESH=ad();a.DT_INVALID=bd();a.DT_INT8=cd();a.DT_UINT8=dd();a.DT_INT16=ed();a.DT_UINT16=fd();a.DT_INT32=gd();a.DT_UINT32=hd();a.DT_INT64=id();a.DT_UINT64=jd();a.DT_FLOAT32=kd();a.DT_FLOAT64=ld();a.DT_BOOL=md();a.DT_TYPES_COUNT=nd();a.OK=od();a.DRACO_ERROR=pd();a.IO_ERROR=qd();
|
||||||
|
a.INVALID_PARAMETER=rd();a.UNSUPPORTED_VERSION=sd();a.UNKNOWN_VERSION=td()}za?b():oa.unshift(b)})();if("function"===typeof a.onModuleParsed)a.onModuleParsed();a.Decoder.prototype.GetEncodedGeometryType=function(b){if(b.__class__&&b.__class__===a.DecoderBuffer)return a.Decoder.prototype.GetEncodedGeometryType_Deprecated(b);if(8>b.byteLength)return a.INVALID_GEOMETRY_TYPE;switch(b[7]){case 0:return a.POINT_CLOUD;case 1:return a.TRIANGULAR_MESH;default:return a.INVALID_GEOMETRY_TYPE}};return n.ready}}();
|
||||||
|
"object"===typeof exports&&"object"===typeof module?module.exports=DracoDecoderModule:"function"===typeof define&&define.amd?define([],function(){return DracoDecoderModule}):"object"===typeof exports&&(exports.DracoDecoderModule=DracoDecoderModule);
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,117 @@
|
||||||
|
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.arrayIteratorImpl=function(k){var n=0;return function(){return n<k.length?{done:!1,value:k[n++]}:{done:!0}}};$jscomp.arrayIterator=function(k){return{next:$jscomp.arrayIteratorImpl(k)}};$jscomp.makeIterator=function(k){var n="undefined"!=typeof Symbol&&Symbol.iterator&&k[Symbol.iterator];return n?n.call(k):$jscomp.arrayIterator(k)};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;
|
||||||
|
$jscomp.ISOLATE_POLYFILLS=!1;$jscomp.FORCE_POLYFILL_PROMISE=!1;$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION=!1;$jscomp.getGlobal=function(k){k=["object"==typeof globalThis&&globalThis,k,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var n=0;n<k.length;++n){var l=k[n];if(l&&l.Math==Math)return l}throw Error("Cannot find global object");};$jscomp.global=$jscomp.getGlobal(this);
|
||||||
|
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(k,n,l){if(k==Array.prototype||k==Object.prototype)return k;k[n]=l.value;return k};$jscomp.IS_SYMBOL_NATIVE="function"===typeof Symbol&&"symbol"===typeof Symbol("x");$jscomp.TRUST_ES6_POLYFILLS=!$jscomp.ISOLATE_POLYFILLS||$jscomp.IS_SYMBOL_NATIVE;$jscomp.polyfills={};$jscomp.propertyToPolyfillSymbol={};$jscomp.POLYFILL_PREFIX="$jscp$";
|
||||||
|
var $jscomp$lookupPolyfilledValue=function(k,n){var l=$jscomp.propertyToPolyfillSymbol[n];if(null==l)return k[n];l=k[l];return void 0!==l?l:k[n]};$jscomp.polyfill=function(k,n,l,p){n&&($jscomp.ISOLATE_POLYFILLS?$jscomp.polyfillIsolated(k,n,l,p):$jscomp.polyfillUnisolated(k,n,l,p))};
|
||||||
|
$jscomp.polyfillUnisolated=function(k,n,l,p){l=$jscomp.global;k=k.split(".");for(p=0;p<k.length-1;p++){var h=k[p];if(!(h in l))return;l=l[h]}k=k[k.length-1];p=l[k];n=n(p);n!=p&&null!=n&&$jscomp.defineProperty(l,k,{configurable:!0,writable:!0,value:n})};
|
||||||
|
$jscomp.polyfillIsolated=function(k,n,l,p){var h=k.split(".");k=1===h.length;p=h[0];p=!k&&p in $jscomp.polyfills?$jscomp.polyfills:$jscomp.global;for(var A=0;A<h.length-1;A++){var f=h[A];if(!(f in p))return;p=p[f]}h=h[h.length-1];l=$jscomp.IS_SYMBOL_NATIVE&&"es6"===l?p[h]:null;n=n(l);null!=n&&(k?$jscomp.defineProperty($jscomp.polyfills,h,{configurable:!0,writable:!0,value:n}):n!==l&&(void 0===$jscomp.propertyToPolyfillSymbol[h]&&(l=1E9*Math.random()>>>0,$jscomp.propertyToPolyfillSymbol[h]=$jscomp.IS_SYMBOL_NATIVE?
|
||||||
|
$jscomp.global.Symbol(h):$jscomp.POLYFILL_PREFIX+l+"$"+h),$jscomp.defineProperty(p,$jscomp.propertyToPolyfillSymbol[h],{configurable:!0,writable:!0,value:n})))};
|
||||||
|
$jscomp.polyfill("Promise",function(k){function n(){this.batch_=null}function l(f){return f instanceof h?f:new h(function(q,v){q(f)})}if(k&&(!($jscomp.FORCE_POLYFILL_PROMISE||$jscomp.FORCE_POLYFILL_PROMISE_WHEN_NO_UNHANDLED_REJECTION&&"undefined"===typeof $jscomp.global.PromiseRejectionEvent)||!$jscomp.global.Promise||-1===$jscomp.global.Promise.toString().indexOf("[native code]")))return k;n.prototype.asyncExecute=function(f){if(null==this.batch_){this.batch_=[];var q=this;this.asyncExecuteFunction(function(){q.executeBatch_()})}this.batch_.push(f)};
|
||||||
|
var p=$jscomp.global.setTimeout;n.prototype.asyncExecuteFunction=function(f){p(f,0)};n.prototype.executeBatch_=function(){for(;this.batch_&&this.batch_.length;){var f=this.batch_;this.batch_=[];for(var q=0;q<f.length;++q){var v=f[q];f[q]=null;try{v()}catch(z){this.asyncThrow_(z)}}}this.batch_=null};n.prototype.asyncThrow_=function(f){this.asyncExecuteFunction(function(){throw f;})};var h=function(f){this.state_=0;this.result_=void 0;this.onSettledCallbacks_=[];this.isRejectionHandled_=!1;var q=this.createResolveAndReject_();
|
||||||
|
try{f(q.resolve,q.reject)}catch(v){q.reject(v)}};h.prototype.createResolveAndReject_=function(){function f(z){return function(O){v||(v=!0,z.call(q,O))}}var q=this,v=!1;return{resolve:f(this.resolveTo_),reject:f(this.reject_)}};h.prototype.resolveTo_=function(f){if(f===this)this.reject_(new TypeError("A Promise cannot resolve to itself"));else if(f instanceof h)this.settleSameAsPromise_(f);else{a:switch(typeof f){case "object":var q=null!=f;break a;case "function":q=!0;break a;default:q=!1}q?this.resolveToNonPromiseObj_(f):
|
||||||
|
this.fulfill_(f)}};h.prototype.resolveToNonPromiseObj_=function(f){var q=void 0;try{q=f.then}catch(v){this.reject_(v);return}"function"==typeof q?this.settleSameAsThenable_(q,f):this.fulfill_(f)};h.prototype.reject_=function(f){this.settle_(2,f)};h.prototype.fulfill_=function(f){this.settle_(1,f)};h.prototype.settle_=function(f,q){if(0!=this.state_)throw Error("Cannot settle("+f+", "+q+"): Promise already settled in state"+this.state_);this.state_=f;this.result_=q;2===this.state_&&this.scheduleUnhandledRejectionCheck_();
|
||||||
|
this.executeOnSettledCallbacks_()};h.prototype.scheduleUnhandledRejectionCheck_=function(){var f=this;p(function(){if(f.notifyUnhandledRejection_()){var q=$jscomp.global.console;"undefined"!==typeof q&&q.error(f.result_)}},1)};h.prototype.notifyUnhandledRejection_=function(){if(this.isRejectionHandled_)return!1;var f=$jscomp.global.CustomEvent,q=$jscomp.global.Event,v=$jscomp.global.dispatchEvent;if("undefined"===typeof v)return!0;"function"===typeof f?f=new f("unhandledrejection",{cancelable:!0}):
|
||||||
|
"function"===typeof q?f=new q("unhandledrejection",{cancelable:!0}):(f=$jscomp.global.document.createEvent("CustomEvent"),f.initCustomEvent("unhandledrejection",!1,!0,f));f.promise=this;f.reason=this.result_;return v(f)};h.prototype.executeOnSettledCallbacks_=function(){if(null!=this.onSettledCallbacks_){for(var f=0;f<this.onSettledCallbacks_.length;++f)A.asyncExecute(this.onSettledCallbacks_[f]);this.onSettledCallbacks_=null}};var A=new n;h.prototype.settleSameAsPromise_=function(f){var q=this.createResolveAndReject_();
|
||||||
|
f.callWhenSettled_(q.resolve,q.reject)};h.prototype.settleSameAsThenable_=function(f,q){var v=this.createResolveAndReject_();try{f.call(q,v.resolve,v.reject)}catch(z){v.reject(z)}};h.prototype.then=function(f,q){function v(t,x){return"function"==typeof t?function(D){try{z(t(D))}catch(R){O(R)}}:x}var z,O,ba=new h(function(t,x){z=t;O=x});this.callWhenSettled_(v(f,z),v(q,O));return ba};h.prototype.catch=function(f){return this.then(void 0,f)};h.prototype.callWhenSettled_=function(f,q){function v(){switch(z.state_){case 1:f(z.result_);
|
||||||
|
break;case 2:q(z.result_);break;default:throw Error("Unexpected state: "+z.state_);}}var z=this;null==this.onSettledCallbacks_?A.asyncExecute(v):this.onSettledCallbacks_.push(v);this.isRejectionHandled_=!0};h.resolve=l;h.reject=function(f){return new h(function(q,v){v(f)})};h.race=function(f){return new h(function(q,v){for(var z=$jscomp.makeIterator(f),O=z.next();!O.done;O=z.next())l(O.value).callWhenSettled_(q,v)})};h.all=function(f){var q=$jscomp.makeIterator(f),v=q.next();return v.done?l([]):new h(function(z,
|
||||||
|
O){function ba(D){return function(R){t[D]=R;x--;0==x&&z(t)}}var t=[],x=0;do t.push(void 0),x++,l(v.value).callWhenSettled_(ba(t.length-1),O),v=q.next();while(!v.done)})};return h},"es6","es3");$jscomp.owns=function(k,n){return Object.prototype.hasOwnProperty.call(k,n)};$jscomp.assign=$jscomp.TRUST_ES6_POLYFILLS&&"function"==typeof Object.assign?Object.assign:function(k,n){for(var l=1;l<arguments.length;l++){var p=arguments[l];if(p)for(var h in p)$jscomp.owns(p,h)&&(k[h]=p[h])}return k};
|
||||||
|
$jscomp.polyfill("Object.assign",function(k){return k||$jscomp.assign},"es6","es3");$jscomp.checkStringArgs=function(k,n,l){if(null==k)throw new TypeError("The 'this' value for String.prototype."+l+" must not be null or undefined");if(n instanceof RegExp)throw new TypeError("First argument to String.prototype."+l+" must not be a regular expression");return k+""};
|
||||||
|
$jscomp.polyfill("String.prototype.startsWith",function(k){return k?k:function(n,l){var p=$jscomp.checkStringArgs(this,n,"startsWith");n+="";var h=p.length,A=n.length;l=Math.max(0,Math.min(l|0,p.length));for(var f=0;f<A&&l<h;)if(p[l++]!=n[f++])return!1;return f>=A}},"es6","es3");
|
||||||
|
$jscomp.polyfill("Array.prototype.copyWithin",function(k){function n(l){l=Number(l);return Infinity===l||-Infinity===l?l:l|0}return k?k:function(l,p,h){var A=this.length;l=n(l);p=n(p);h=void 0===h?A:n(h);l=0>l?Math.max(A+l,0):Math.min(l,A);p=0>p?Math.max(A+p,0):Math.min(p,A);h=0>h?Math.max(A+h,0):Math.min(h,A);if(l<p)for(;p<h;)p in this?this[l++]=this[p++]:(delete this[l++],p++);else for(h=Math.min(h,A+p-l),l+=h-p;h>p;)--h in this?this[--l]=this[h]:delete this[--l];return this}},"es6","es3");
|
||||||
|
$jscomp.typedArrayCopyWithin=function(k){return k?k:Array.prototype.copyWithin};$jscomp.polyfill("Int8Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint8Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint8ClampedArray.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Int16Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");
|
||||||
|
$jscomp.polyfill("Uint16Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Int32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Uint32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Float32Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");$jscomp.polyfill("Float64Array.prototype.copyWithin",$jscomp.typedArrayCopyWithin,"es6","es5");
|
||||||
|
var DracoDecoderModule=function(){var k="undefined"!==typeof document&&document.currentScript?document.currentScript.src:void 0;"undefined"!==typeof __filename&&(k=k||__filename);return function(n){function l(e){return a.locateFile?a.locateFile(e,U):U+e}function p(e,b,c){var d=b+c;for(c=b;e[c]&&!(c>=d);)++c;if(16<c-b&&e.buffer&&ua)return ua.decode(e.subarray(b,c));for(d="";b<c;){var g=e[b++];if(g&128){var u=e[b++]&63;if(192==(g&224))d+=String.fromCharCode((g&31)<<6|u);else{var X=e[b++]&63;g=224==
|
||||||
|
(g&240)?(g&15)<<12|u<<6|X:(g&7)<<18|u<<12|X<<6|e[b++]&63;65536>g?d+=String.fromCharCode(g):(g-=65536,d+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else d+=String.fromCharCode(g)}return d}function h(e,b){return e?p(ea,e,b):""}function A(e){va=e;a.HEAP8=Y=new Int8Array(e);a.HEAP16=new Int16Array(e);a.HEAP32=ca=new Int32Array(e);a.HEAPU8=ea=new Uint8Array(e);a.HEAPU16=new Uint16Array(e);a.HEAPU32=V=new Uint32Array(e);a.HEAPF32=new Float32Array(e);a.HEAPF64=new Float64Array(e)}function f(e){if(a.onAbort)a.onAbort(e);
|
||||||
|
e="Aborted("+e+")";da(e);wa=!0;e=new WebAssembly.RuntimeError(e+". Build with -sASSERTIONS for more info.");ja(e);throw e;}function q(e){try{if(e==P&&fa)return new Uint8Array(fa);if(ma)return ma(e);throw"both async and sync fetching of the wasm failed";}catch(b){f(b)}}function v(){if(!fa&&(xa||ha)){if("function"==typeof fetch&&!P.startsWith("file://"))return fetch(P,{credentials:"same-origin"}).then(function(e){if(!e.ok)throw"failed to load wasm binary file at '"+P+"'";return e.arrayBuffer()}).catch(function(){return q(P)});
|
||||||
|
if(na)return new Promise(function(e,b){na(P,function(c){e(new Uint8Array(c))},b)})}return Promise.resolve().then(function(){return q(P)})}function z(e){for(;0<e.length;)e.shift()(a)}function O(e){this.excPtr=e;this.ptr=e-24;this.set_type=function(b){V[this.ptr+4>>2]=b};this.get_type=function(){return V[this.ptr+4>>2]};this.set_destructor=function(b){V[this.ptr+8>>2]=b};this.get_destructor=function(){return V[this.ptr+8>>2]};this.set_refcount=function(b){ca[this.ptr>>2]=b};this.set_caught=function(b){Y[this.ptr+
|
||||||
|
12>>0]=b?1:0};this.get_caught=function(){return 0!=Y[this.ptr+12>>0]};this.set_rethrown=function(b){Y[this.ptr+13>>0]=b?1:0};this.get_rethrown=function(){return 0!=Y[this.ptr+13>>0]};this.init=function(b,c){this.set_adjusted_ptr(0);this.set_type(b);this.set_destructor(c);this.set_refcount(0);this.set_caught(!1);this.set_rethrown(!1)};this.add_ref=function(){ca[this.ptr>>2]+=1};this.release_ref=function(){var b=ca[this.ptr>>2];ca[this.ptr>>2]=b-1;return 1===b};this.set_adjusted_ptr=function(b){V[this.ptr+
|
||||||
|
16>>2]=b};this.get_adjusted_ptr=function(){return V[this.ptr+16>>2]};this.get_exception_ptr=function(){if(ya(this.get_type()))return V[this.excPtr>>2];var b=this.get_adjusted_ptr();return 0!==b?b:this.excPtr}}function ba(e){function b(){if(!ka&&(ka=!0,a.calledRun=!0,!wa)){za=!0;z(oa);Aa(a);if(a.onRuntimeInitialized)a.onRuntimeInitialized();if(a.postRun)for("function"==typeof a.postRun&&(a.postRun=[a.postRun]);a.postRun.length;)Ba.unshift(a.postRun.shift());z(Ba)}}if(!(0<aa)){if(a.preRun)for("function"==
|
||||||
|
typeof a.preRun&&(a.preRun=[a.preRun]);a.preRun.length;)Ca.unshift(a.preRun.shift());z(Ca);0<aa||(a.setStatus?(a.setStatus("Running..."),setTimeout(function(){setTimeout(function(){a.setStatus("")},1);b()},1)):b())}}function t(){}function x(e){return(e||t).__cache__}function D(e,b){var c=x(b),d=c[e];if(d)return d;d=Object.create((b||t).prototype);d.ptr=e;return c[e]=d}function R(e){if("string"===typeof e){for(var b=0,c=0;c<e.length;++c){var d=e.charCodeAt(c);127>=d?b++:2047>=d?b+=2:55296<=d&&57343>=
|
||||||
|
d?(b+=4,++c):b+=3}b=Array(b+1);c=0;d=b.length;if(0<d){d=c+d-1;for(var g=0;g<e.length;++g){var u=e.charCodeAt(g);if(55296<=u&&57343>=u){var X=e.charCodeAt(++g);u=65536+((u&1023)<<10)|X&1023}if(127>=u){if(c>=d)break;b[c++]=u}else{if(2047>=u){if(c+1>=d)break;b[c++]=192|u>>6}else{if(65535>=u){if(c+2>=d)break;b[c++]=224|u>>12}else{if(c+3>=d)break;b[c++]=240|u>>18;b[c++]=128|u>>12&63}b[c++]=128|u>>6&63}b[c++]=128|u&63}}b[c]=0}e=r.alloc(b,Y);r.copy(b,Y,e);return e}return e}function pa(e){if("object"===typeof e){var b=
|
||||||
|
r.alloc(e,Y);r.copy(e,Y,b);return b}return e}function Z(){throw"cannot construct a VoidPtr, no constructor in IDL";}function S(){this.ptr=Da();x(S)[this.ptr]=this}function Q(){this.ptr=Ea();x(Q)[this.ptr]=this}function W(){this.ptr=Fa();x(W)[this.ptr]=this}function w(){this.ptr=Ga();x(w)[this.ptr]=this}function C(){this.ptr=Ha();x(C)[this.ptr]=this}function F(){this.ptr=Ia();x(F)[this.ptr]=this}function G(){this.ptr=Ja();x(G)[this.ptr]=this}function E(){this.ptr=Ka();x(E)[this.ptr]=this}function T(){this.ptr=
|
||||||
|
La();x(T)[this.ptr]=this}function B(){throw"cannot construct a Status, no constructor in IDL";}function H(){this.ptr=Ma();x(H)[this.ptr]=this}function I(){this.ptr=Na();x(I)[this.ptr]=this}function J(){this.ptr=Oa();x(J)[this.ptr]=this}function K(){this.ptr=Pa();x(K)[this.ptr]=this}function L(){this.ptr=Qa();x(L)[this.ptr]=this}function M(){this.ptr=Ra();x(M)[this.ptr]=this}function N(){this.ptr=Sa();x(N)[this.ptr]=this}function y(){this.ptr=Ta();x(y)[this.ptr]=this}function m(){this.ptr=Ua();x(m)[this.ptr]=
|
||||||
|
this}n=n||{};var a="undefined"!=typeof n?n:{},Aa,ja;a.ready=new Promise(function(e,b){Aa=e;ja=b});var Va=!1,Wa=!1;a.onRuntimeInitialized=function(){Va=!0;if(Wa&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.onModuleParsed=function(){Wa=!0;if(Va&&"function"===typeof a.onModuleLoaded)a.onModuleLoaded(a)};a.isVersionSupported=function(e){if("string"!==typeof e)return!1;e=e.split(".");return 2>e.length||3<e.length?!1:1==e[0]&&0<=e[1]&&5>=e[1]?!0:0!=e[0]||10<e[1]?!1:!0};var Xa=Object.assign({},
|
||||||
|
a),xa="object"==typeof window,ha="function"==typeof importScripts,Ya="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,U="";if(Ya){U=ha?require("path").dirname(U)+"/":__dirname+"/";if("function"===typeof require){var Za=require("fs");var $a=require("path")}var ab=function(e,b){e=$a.normalize(e);return Za.readFileSync(e,b?void 0:"utf8")};var ma=function(e){e=ab(e,!0);e.buffer||(e=new Uint8Array(e));return e};var na=function(e,b,c){e=$a.normalize(e);
|
||||||
|
Za.readFile(e,function(d,g){d?c(d):b(g.buffer)})};1<process.argv.length&&process.argv[1].replace(/\\/g,"/");process.argv.slice(2);a.inspect=function(){return"[Emscripten Module object]"}}else if(xa||ha)ha?U=self.location.href:"undefined"!=typeof document&&document.currentScript&&(U=document.currentScript.src),k&&(U=k),U=0!==U.indexOf("blob:")?U.substr(0,U.replace(/[?#].*/,"").lastIndexOf("/")+1):"",ab=function(e){var b=new XMLHttpRequest;b.open("GET",e,!1);b.send(null);return b.responseText},ha&&
|
||||||
|
(ma=function(e){var b=new XMLHttpRequest;b.open("GET",e,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),na=function(e,b,c){var d=new XMLHttpRequest;d.open("GET",e,!0);d.responseType="arraybuffer";d.onload=function(){200==d.status||0==d.status&&d.response?b(d.response):c()};d.onerror=c;d.send(null)};var wd=a.print||console.log.bind(console),da=a.printErr||console.warn.bind(console);Object.assign(a,Xa);Xa=null;var fa;a.wasmBinary&&(fa=a.wasmBinary);"object"!=typeof WebAssembly&&
|
||||||
|
f("no native wasm support detected");var la,wa=!1,ua="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0,va,Y,ea,ca,V,Ca=[],oa=[],Ba=[],za=!1,aa=0,qa=null,ia=null;var P="draco_decoder.wasm";P.startsWith("data:application/octet-stream;base64,")||(P=l(P));var xd=0,yd=[null,[],[]],zd={c:function(e){return bb(e+24)+24},b:function(e,b,c){(new O(e)).init(b,c);xd++;throw e;},a:function(){f("")},h:function(e,b,c){ea.copyWithin(e,b,b+c)},f:function(e){var b=ea.length;e>>>=0;if(2147483648<e)return!1;
|
||||||
|
for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,e+100663296);var g=Math;d=Math.max(e,d);g=g.min.call(g,2147483648,d+(65536-d%65536)%65536);a:{try{la.grow(g-va.byteLength+65535>>>16);A(la.buffer);var u=1;break a}catch(X){}u=void 0}if(u)return!0}return!1},g:function(e){return 52},e:function(e,b,c,d,g){return 70},d:function(e,b,c,d){for(var g=0,u=0;u<c;u++){var X=V[b>>2],cb=V[b+4>>2];b+=8;for(var ra=0;ra<cb;ra++){var sa=ea[X+ra],ta=yd[e];0===sa||10===sa?((1===e?wd:da)(p(ta,0)),ta.length=0):ta.push(sa)}g+=
|
||||||
|
cb}V[d>>2]=g;return 0}};(function(){function e(g,u){a.asm=g.exports;la=a.asm.i;A(la.buffer);oa.unshift(a.asm.j);aa--;a.monitorRunDependencies&&a.monitorRunDependencies(aa);0==aa&&(null!==qa&&(clearInterval(qa),qa=null),ia&&(g=ia,ia=null,g()))}function b(g){e(g.instance)}function c(g){return v().then(function(u){return WebAssembly.instantiate(u,d)}).then(function(u){return u}).then(g,function(u){da("failed to asynchronously prepare wasm: "+u);f(u)})}var d={a:zd};aa++;a.monitorRunDependencies&&a.monitorRunDependencies(aa);
|
||||||
|
if(a.instantiateWasm)try{return a.instantiateWasm(d,e)}catch(g){da("Module.instantiateWasm callback failed with error: "+g),ja(g)}(function(){return fa||"function"!=typeof WebAssembly.instantiateStreaming||P.startsWith("data:application/octet-stream;base64,")||P.startsWith("file://")||Ya||"function"!=typeof fetch?c(b):fetch(P,{credentials:"same-origin"}).then(function(g){return WebAssembly.instantiateStreaming(g,d).then(b,function(u){da("wasm streaming compile failed: "+u);da("falling back to ArrayBuffer instantiation");
|
||||||
|
return c(b)})})})().catch(ja);return{}})();a.___wasm_call_ctors=function(){return(a.___wasm_call_ctors=a.asm.j).apply(null,arguments)};var db=a._emscripten_bind_VoidPtr___destroy___0=function(){return(db=a._emscripten_bind_VoidPtr___destroy___0=a.asm.l).apply(null,arguments)},Da=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=function(){return(Da=a._emscripten_bind_DecoderBuffer_DecoderBuffer_0=a.asm.m).apply(null,arguments)},eb=a._emscripten_bind_DecoderBuffer_Init_2=function(){return(eb=a._emscripten_bind_DecoderBuffer_Init_2=
|
||||||
|
a.asm.n).apply(null,arguments)},fb=a._emscripten_bind_DecoderBuffer___destroy___0=function(){return(fb=a._emscripten_bind_DecoderBuffer___destroy___0=a.asm.o).apply(null,arguments)},Ea=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=function(){return(Ea=a._emscripten_bind_AttributeTransformData_AttributeTransformData_0=a.asm.p).apply(null,arguments)},gb=a._emscripten_bind_AttributeTransformData_transform_type_0=function(){return(gb=a._emscripten_bind_AttributeTransformData_transform_type_0=
|
||||||
|
a.asm.q).apply(null,arguments)},hb=a._emscripten_bind_AttributeTransformData___destroy___0=function(){return(hb=a._emscripten_bind_AttributeTransformData___destroy___0=a.asm.r).apply(null,arguments)},Fa=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=function(){return(Fa=a._emscripten_bind_GeometryAttribute_GeometryAttribute_0=a.asm.s).apply(null,arguments)},ib=a._emscripten_bind_GeometryAttribute___destroy___0=function(){return(ib=a._emscripten_bind_GeometryAttribute___destroy___0=a.asm.t).apply(null,
|
||||||
|
arguments)},Ga=a._emscripten_bind_PointAttribute_PointAttribute_0=function(){return(Ga=a._emscripten_bind_PointAttribute_PointAttribute_0=a.asm.u).apply(null,arguments)},jb=a._emscripten_bind_PointAttribute_size_0=function(){return(jb=a._emscripten_bind_PointAttribute_size_0=a.asm.v).apply(null,arguments)},kb=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=function(){return(kb=a._emscripten_bind_PointAttribute_GetAttributeTransformData_0=a.asm.w).apply(null,arguments)},lb=a._emscripten_bind_PointAttribute_attribute_type_0=
|
||||||
|
function(){return(lb=a._emscripten_bind_PointAttribute_attribute_type_0=a.asm.x).apply(null,arguments)},mb=a._emscripten_bind_PointAttribute_data_type_0=function(){return(mb=a._emscripten_bind_PointAttribute_data_type_0=a.asm.y).apply(null,arguments)},nb=a._emscripten_bind_PointAttribute_num_components_0=function(){return(nb=a._emscripten_bind_PointAttribute_num_components_0=a.asm.z).apply(null,arguments)},ob=a._emscripten_bind_PointAttribute_normalized_0=function(){return(ob=a._emscripten_bind_PointAttribute_normalized_0=
|
||||||
|
a.asm.A).apply(null,arguments)},pb=a._emscripten_bind_PointAttribute_byte_stride_0=function(){return(pb=a._emscripten_bind_PointAttribute_byte_stride_0=a.asm.B).apply(null,arguments)},qb=a._emscripten_bind_PointAttribute_byte_offset_0=function(){return(qb=a._emscripten_bind_PointAttribute_byte_offset_0=a.asm.C).apply(null,arguments)},rb=a._emscripten_bind_PointAttribute_unique_id_0=function(){return(rb=a._emscripten_bind_PointAttribute_unique_id_0=a.asm.D).apply(null,arguments)},sb=a._emscripten_bind_PointAttribute___destroy___0=
|
||||||
|
function(){return(sb=a._emscripten_bind_PointAttribute___destroy___0=a.asm.E).apply(null,arguments)},Ha=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0=function(){return(Ha=a._emscripten_bind_AttributeQuantizationTransform_AttributeQuantizationTransform_0=a.asm.F).apply(null,arguments)},tb=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=function(){return(tb=a._emscripten_bind_AttributeQuantizationTransform_InitFromAttribute_1=a.asm.G).apply(null,
|
||||||
|
arguments)},ub=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=function(){return(ub=a._emscripten_bind_AttributeQuantizationTransform_quantization_bits_0=a.asm.H).apply(null,arguments)},vb=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=function(){return(vb=a._emscripten_bind_AttributeQuantizationTransform_min_value_1=a.asm.I).apply(null,arguments)},wb=a._emscripten_bind_AttributeQuantizationTransform_range_0=function(){return(wb=a._emscripten_bind_AttributeQuantizationTransform_range_0=
|
||||||
|
a.asm.J).apply(null,arguments)},xb=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=function(){return(xb=a._emscripten_bind_AttributeQuantizationTransform___destroy___0=a.asm.K).apply(null,arguments)},Ia=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=function(){return(Ia=a._emscripten_bind_AttributeOctahedronTransform_AttributeOctahedronTransform_0=a.asm.L).apply(null,arguments)},yb=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=
|
||||||
|
function(){return(yb=a._emscripten_bind_AttributeOctahedronTransform_InitFromAttribute_1=a.asm.M).apply(null,arguments)},zb=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=function(){return(zb=a._emscripten_bind_AttributeOctahedronTransform_quantization_bits_0=a.asm.N).apply(null,arguments)},Ab=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=function(){return(Ab=a._emscripten_bind_AttributeOctahedronTransform___destroy___0=a.asm.O).apply(null,arguments)},Ja=a._emscripten_bind_PointCloud_PointCloud_0=
|
||||||
|
function(){return(Ja=a._emscripten_bind_PointCloud_PointCloud_0=a.asm.P).apply(null,arguments)},Bb=a._emscripten_bind_PointCloud_num_attributes_0=function(){return(Bb=a._emscripten_bind_PointCloud_num_attributes_0=a.asm.Q).apply(null,arguments)},Cb=a._emscripten_bind_PointCloud_num_points_0=function(){return(Cb=a._emscripten_bind_PointCloud_num_points_0=a.asm.R).apply(null,arguments)},Db=a._emscripten_bind_PointCloud___destroy___0=function(){return(Db=a._emscripten_bind_PointCloud___destroy___0=a.asm.S).apply(null,
|
||||||
|
arguments)},Ka=a._emscripten_bind_Mesh_Mesh_0=function(){return(Ka=a._emscripten_bind_Mesh_Mesh_0=a.asm.T).apply(null,arguments)},Eb=a._emscripten_bind_Mesh_num_faces_0=function(){return(Eb=a._emscripten_bind_Mesh_num_faces_0=a.asm.U).apply(null,arguments)},Fb=a._emscripten_bind_Mesh_num_attributes_0=function(){return(Fb=a._emscripten_bind_Mesh_num_attributes_0=a.asm.V).apply(null,arguments)},Gb=a._emscripten_bind_Mesh_num_points_0=function(){return(Gb=a._emscripten_bind_Mesh_num_points_0=a.asm.W).apply(null,
|
||||||
|
arguments)},Hb=a._emscripten_bind_Mesh___destroy___0=function(){return(Hb=a._emscripten_bind_Mesh___destroy___0=a.asm.X).apply(null,arguments)},La=a._emscripten_bind_Metadata_Metadata_0=function(){return(La=a._emscripten_bind_Metadata_Metadata_0=a.asm.Y).apply(null,arguments)},Ib=a._emscripten_bind_Metadata___destroy___0=function(){return(Ib=a._emscripten_bind_Metadata___destroy___0=a.asm.Z).apply(null,arguments)},Jb=a._emscripten_bind_Status_code_0=function(){return(Jb=a._emscripten_bind_Status_code_0=
|
||||||
|
a.asm._).apply(null,arguments)},Kb=a._emscripten_bind_Status_ok_0=function(){return(Kb=a._emscripten_bind_Status_ok_0=a.asm.$).apply(null,arguments)},Lb=a._emscripten_bind_Status_error_msg_0=function(){return(Lb=a._emscripten_bind_Status_error_msg_0=a.asm.aa).apply(null,arguments)},Mb=a._emscripten_bind_Status___destroy___0=function(){return(Mb=a._emscripten_bind_Status___destroy___0=a.asm.ba).apply(null,arguments)},Ma=a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=function(){return(Ma=
|
||||||
|
a._emscripten_bind_DracoFloat32Array_DracoFloat32Array_0=a.asm.ca).apply(null,arguments)},Nb=a._emscripten_bind_DracoFloat32Array_GetValue_1=function(){return(Nb=a._emscripten_bind_DracoFloat32Array_GetValue_1=a.asm.da).apply(null,arguments)},Ob=a._emscripten_bind_DracoFloat32Array_size_0=function(){return(Ob=a._emscripten_bind_DracoFloat32Array_size_0=a.asm.ea).apply(null,arguments)},Pb=a._emscripten_bind_DracoFloat32Array___destroy___0=function(){return(Pb=a._emscripten_bind_DracoFloat32Array___destroy___0=
|
||||||
|
a.asm.fa).apply(null,arguments)},Na=a._emscripten_bind_DracoInt8Array_DracoInt8Array_0=function(){return(Na=a._emscripten_bind_DracoInt8Array_DracoInt8Array_0=a.asm.ga).apply(null,arguments)},Qb=a._emscripten_bind_DracoInt8Array_GetValue_1=function(){return(Qb=a._emscripten_bind_DracoInt8Array_GetValue_1=a.asm.ha).apply(null,arguments)},Rb=a._emscripten_bind_DracoInt8Array_size_0=function(){return(Rb=a._emscripten_bind_DracoInt8Array_size_0=a.asm.ia).apply(null,arguments)},Sb=a._emscripten_bind_DracoInt8Array___destroy___0=
|
||||||
|
function(){return(Sb=a._emscripten_bind_DracoInt8Array___destroy___0=a.asm.ja).apply(null,arguments)},Oa=a._emscripten_bind_DracoUInt8Array_DracoUInt8Array_0=function(){return(Oa=a._emscripten_bind_DracoUInt8Array_DracoUInt8Array_0=a.asm.ka).apply(null,arguments)},Tb=a._emscripten_bind_DracoUInt8Array_GetValue_1=function(){return(Tb=a._emscripten_bind_DracoUInt8Array_GetValue_1=a.asm.la).apply(null,arguments)},Ub=a._emscripten_bind_DracoUInt8Array_size_0=function(){return(Ub=a._emscripten_bind_DracoUInt8Array_size_0=
|
||||||
|
a.asm.ma).apply(null,arguments)},Vb=a._emscripten_bind_DracoUInt8Array___destroy___0=function(){return(Vb=a._emscripten_bind_DracoUInt8Array___destroy___0=a.asm.na).apply(null,arguments)},Pa=a._emscripten_bind_DracoInt16Array_DracoInt16Array_0=function(){return(Pa=a._emscripten_bind_DracoInt16Array_DracoInt16Array_0=a.asm.oa).apply(null,arguments)},Wb=a._emscripten_bind_DracoInt16Array_GetValue_1=function(){return(Wb=a._emscripten_bind_DracoInt16Array_GetValue_1=a.asm.pa).apply(null,arguments)},Xb=
|
||||||
|
a._emscripten_bind_DracoInt16Array_size_0=function(){return(Xb=a._emscripten_bind_DracoInt16Array_size_0=a.asm.qa).apply(null,arguments)},Yb=a._emscripten_bind_DracoInt16Array___destroy___0=function(){return(Yb=a._emscripten_bind_DracoInt16Array___destroy___0=a.asm.ra).apply(null,arguments)},Qa=a._emscripten_bind_DracoUInt16Array_DracoUInt16Array_0=function(){return(Qa=a._emscripten_bind_DracoUInt16Array_DracoUInt16Array_0=a.asm.sa).apply(null,arguments)},Zb=a._emscripten_bind_DracoUInt16Array_GetValue_1=
|
||||||
|
function(){return(Zb=a._emscripten_bind_DracoUInt16Array_GetValue_1=a.asm.ta).apply(null,arguments)},$b=a._emscripten_bind_DracoUInt16Array_size_0=function(){return($b=a._emscripten_bind_DracoUInt16Array_size_0=a.asm.ua).apply(null,arguments)},ac=a._emscripten_bind_DracoUInt16Array___destroy___0=function(){return(ac=a._emscripten_bind_DracoUInt16Array___destroy___0=a.asm.va).apply(null,arguments)},Ra=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=function(){return(Ra=a._emscripten_bind_DracoInt32Array_DracoInt32Array_0=
|
||||||
|
a.asm.wa).apply(null,arguments)},bc=a._emscripten_bind_DracoInt32Array_GetValue_1=function(){return(bc=a._emscripten_bind_DracoInt32Array_GetValue_1=a.asm.xa).apply(null,arguments)},cc=a._emscripten_bind_DracoInt32Array_size_0=function(){return(cc=a._emscripten_bind_DracoInt32Array_size_0=a.asm.ya).apply(null,arguments)},dc=a._emscripten_bind_DracoInt32Array___destroy___0=function(){return(dc=a._emscripten_bind_DracoInt32Array___destroy___0=a.asm.za).apply(null,arguments)},Sa=a._emscripten_bind_DracoUInt32Array_DracoUInt32Array_0=
|
||||||
|
function(){return(Sa=a._emscripten_bind_DracoUInt32Array_DracoUInt32Array_0=a.asm.Aa).apply(null,arguments)},ec=a._emscripten_bind_DracoUInt32Array_GetValue_1=function(){return(ec=a._emscripten_bind_DracoUInt32Array_GetValue_1=a.asm.Ba).apply(null,arguments)},fc=a._emscripten_bind_DracoUInt32Array_size_0=function(){return(fc=a._emscripten_bind_DracoUInt32Array_size_0=a.asm.Ca).apply(null,arguments)},gc=a._emscripten_bind_DracoUInt32Array___destroy___0=function(){return(gc=a._emscripten_bind_DracoUInt32Array___destroy___0=
|
||||||
|
a.asm.Da).apply(null,arguments)},Ta=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=function(){return(Ta=a._emscripten_bind_MetadataQuerier_MetadataQuerier_0=a.asm.Ea).apply(null,arguments)},hc=a._emscripten_bind_MetadataQuerier_HasEntry_2=function(){return(hc=a._emscripten_bind_MetadataQuerier_HasEntry_2=a.asm.Fa).apply(null,arguments)},ic=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=function(){return(ic=a._emscripten_bind_MetadataQuerier_GetIntEntry_2=a.asm.Ga).apply(null,arguments)},jc=
|
||||||
|
a._emscripten_bind_MetadataQuerier_GetIntEntryArray_3=function(){return(jc=a._emscripten_bind_MetadataQuerier_GetIntEntryArray_3=a.asm.Ha).apply(null,arguments)},kc=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=function(){return(kc=a._emscripten_bind_MetadataQuerier_GetDoubleEntry_2=a.asm.Ia).apply(null,arguments)},lc=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=function(){return(lc=a._emscripten_bind_MetadataQuerier_GetStringEntry_2=a.asm.Ja).apply(null,arguments)},mc=a._emscripten_bind_MetadataQuerier_NumEntries_1=
|
||||||
|
function(){return(mc=a._emscripten_bind_MetadataQuerier_NumEntries_1=a.asm.Ka).apply(null,arguments)},nc=a._emscripten_bind_MetadataQuerier_GetEntryName_2=function(){return(nc=a._emscripten_bind_MetadataQuerier_GetEntryName_2=a.asm.La).apply(null,arguments)},oc=a._emscripten_bind_MetadataQuerier___destroy___0=function(){return(oc=a._emscripten_bind_MetadataQuerier___destroy___0=a.asm.Ma).apply(null,arguments)},Ua=a._emscripten_bind_Decoder_Decoder_0=function(){return(Ua=a._emscripten_bind_Decoder_Decoder_0=
|
||||||
|
a.asm.Na).apply(null,arguments)},pc=a._emscripten_bind_Decoder_DecodeArrayToPointCloud_3=function(){return(pc=a._emscripten_bind_Decoder_DecodeArrayToPointCloud_3=a.asm.Oa).apply(null,arguments)},qc=a._emscripten_bind_Decoder_DecodeArrayToMesh_3=function(){return(qc=a._emscripten_bind_Decoder_DecodeArrayToMesh_3=a.asm.Pa).apply(null,arguments)},rc=a._emscripten_bind_Decoder_GetAttributeId_2=function(){return(rc=a._emscripten_bind_Decoder_GetAttributeId_2=a.asm.Qa).apply(null,arguments)},sc=a._emscripten_bind_Decoder_GetAttributeIdByName_2=
|
||||||
|
function(){return(sc=a._emscripten_bind_Decoder_GetAttributeIdByName_2=a.asm.Ra).apply(null,arguments)},tc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=function(){return(tc=a._emscripten_bind_Decoder_GetAttributeIdByMetadataEntry_3=a.asm.Sa).apply(null,arguments)},uc=a._emscripten_bind_Decoder_GetAttribute_2=function(){return(uc=a._emscripten_bind_Decoder_GetAttribute_2=a.asm.Ta).apply(null,arguments)},vc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2=function(){return(vc=a._emscripten_bind_Decoder_GetAttributeByUniqueId_2=
|
||||||
|
a.asm.Ua).apply(null,arguments)},wc=a._emscripten_bind_Decoder_GetMetadata_1=function(){return(wc=a._emscripten_bind_Decoder_GetMetadata_1=a.asm.Va).apply(null,arguments)},xc=a._emscripten_bind_Decoder_GetAttributeMetadata_2=function(){return(xc=a._emscripten_bind_Decoder_GetAttributeMetadata_2=a.asm.Wa).apply(null,arguments)},yc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=function(){return(yc=a._emscripten_bind_Decoder_GetFaceFromMesh_3=a.asm.Xa).apply(null,arguments)},zc=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=
|
||||||
|
function(){return(zc=a._emscripten_bind_Decoder_GetTriangleStripsFromMesh_2=a.asm.Ya).apply(null,arguments)},Ac=a._emscripten_bind_Decoder_GetTrianglesUInt16Array_3=function(){return(Ac=a._emscripten_bind_Decoder_GetTrianglesUInt16Array_3=a.asm.Za).apply(null,arguments)},Bc=a._emscripten_bind_Decoder_GetTrianglesUInt32Array_3=function(){return(Bc=a._emscripten_bind_Decoder_GetTrianglesUInt32Array_3=a.asm._a).apply(null,arguments)},Cc=a._emscripten_bind_Decoder_GetAttributeFloat_3=function(){return(Cc=
|
||||||
|
a._emscripten_bind_Decoder_GetAttributeFloat_3=a.asm.$a).apply(null,arguments)},Dc=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=function(){return(Dc=a._emscripten_bind_Decoder_GetAttributeFloatForAllPoints_3=a.asm.ab).apply(null,arguments)},Ec=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=function(){return(Ec=a._emscripten_bind_Decoder_GetAttributeIntForAllPoints_3=a.asm.bb).apply(null,arguments)},Fc=a._emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3=function(){return(Fc=
|
||||||
|
a._emscripten_bind_Decoder_GetAttributeInt8ForAllPoints_3=a.asm.cb).apply(null,arguments)},Gc=a._emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3=function(){return(Gc=a._emscripten_bind_Decoder_GetAttributeUInt8ForAllPoints_3=a.asm.db).apply(null,arguments)},Hc=a._emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3=function(){return(Hc=a._emscripten_bind_Decoder_GetAttributeInt16ForAllPoints_3=a.asm.eb).apply(null,arguments)},Ic=a._emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3=
|
||||||
|
function(){return(Ic=a._emscripten_bind_Decoder_GetAttributeUInt16ForAllPoints_3=a.asm.fb).apply(null,arguments)},Jc=a._emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3=function(){return(Jc=a._emscripten_bind_Decoder_GetAttributeInt32ForAllPoints_3=a.asm.gb).apply(null,arguments)},Kc=a._emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3=function(){return(Kc=a._emscripten_bind_Decoder_GetAttributeUInt32ForAllPoints_3=a.asm.hb).apply(null,arguments)},Lc=a._emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5=
|
||||||
|
function(){return(Lc=a._emscripten_bind_Decoder_GetAttributeDataArrayForAllPoints_5=a.asm.ib).apply(null,arguments)},Mc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=function(){return(Mc=a._emscripten_bind_Decoder_SkipAttributeTransform_1=a.asm.jb).apply(null,arguments)},Nc=a._emscripten_bind_Decoder_GetEncodedGeometryType_Deprecated_1=function(){return(Nc=a._emscripten_bind_Decoder_GetEncodedGeometryType_Deprecated_1=a.asm.kb).apply(null,arguments)},Oc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=
|
||||||
|
function(){return(Oc=a._emscripten_bind_Decoder_DecodeBufferToPointCloud_2=a.asm.lb).apply(null,arguments)},Pc=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=function(){return(Pc=a._emscripten_bind_Decoder_DecodeBufferToMesh_2=a.asm.mb).apply(null,arguments)},Qc=a._emscripten_bind_Decoder___destroy___0=function(){return(Qc=a._emscripten_bind_Decoder___destroy___0=a.asm.nb).apply(null,arguments)},Rc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=function(){return(Rc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_INVALID_TRANSFORM=
|
||||||
|
a.asm.ob).apply(null,arguments)},Sc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=function(){return(Sc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_NO_TRANSFORM=a.asm.pb).apply(null,arguments)},Tc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=function(){return(Tc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_QUANTIZATION_TRANSFORM=a.asm.qb).apply(null,arguments)},Uc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=
|
||||||
|
function(){return(Uc=a._emscripten_enum_draco_AttributeTransformType_ATTRIBUTE_OCTAHEDRON_TRANSFORM=a.asm.rb).apply(null,arguments)},Vc=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=function(){return(Vc=a._emscripten_enum_draco_GeometryAttribute_Type_INVALID=a.asm.sb).apply(null,arguments)},Wc=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=function(){return(Wc=a._emscripten_enum_draco_GeometryAttribute_Type_POSITION=a.asm.tb).apply(null,arguments)},Xc=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=
|
||||||
|
function(){return(Xc=a._emscripten_enum_draco_GeometryAttribute_Type_NORMAL=a.asm.ub).apply(null,arguments)},Yc=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR=function(){return(Yc=a._emscripten_enum_draco_GeometryAttribute_Type_COLOR=a.asm.vb).apply(null,arguments)},Zc=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=function(){return(Zc=a._emscripten_enum_draco_GeometryAttribute_Type_TEX_COORD=a.asm.wb).apply(null,arguments)},$c=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=
|
||||||
|
function(){return($c=a._emscripten_enum_draco_GeometryAttribute_Type_GENERIC=a.asm.xb).apply(null,arguments)},ad=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=function(){return(ad=a._emscripten_enum_draco_EncodedGeometryType_INVALID_GEOMETRY_TYPE=a.asm.yb).apply(null,arguments)},bd=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=function(){return(bd=a._emscripten_enum_draco_EncodedGeometryType_POINT_CLOUD=a.asm.zb).apply(null,arguments)},cd=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=
|
||||||
|
function(){return(cd=a._emscripten_enum_draco_EncodedGeometryType_TRIANGULAR_MESH=a.asm.Ab).apply(null,arguments)},dd=a._emscripten_enum_draco_DataType_DT_INVALID=function(){return(dd=a._emscripten_enum_draco_DataType_DT_INVALID=a.asm.Bb).apply(null,arguments)},ed=a._emscripten_enum_draco_DataType_DT_INT8=function(){return(ed=a._emscripten_enum_draco_DataType_DT_INT8=a.asm.Cb).apply(null,arguments)},fd=a._emscripten_enum_draco_DataType_DT_UINT8=function(){return(fd=a._emscripten_enum_draco_DataType_DT_UINT8=
|
||||||
|
a.asm.Db).apply(null,arguments)},gd=a._emscripten_enum_draco_DataType_DT_INT16=function(){return(gd=a._emscripten_enum_draco_DataType_DT_INT16=a.asm.Eb).apply(null,arguments)},hd=a._emscripten_enum_draco_DataType_DT_UINT16=function(){return(hd=a._emscripten_enum_draco_DataType_DT_UINT16=a.asm.Fb).apply(null,arguments)},id=a._emscripten_enum_draco_DataType_DT_INT32=function(){return(id=a._emscripten_enum_draco_DataType_DT_INT32=a.asm.Gb).apply(null,arguments)},jd=a._emscripten_enum_draco_DataType_DT_UINT32=
|
||||||
|
function(){return(jd=a._emscripten_enum_draco_DataType_DT_UINT32=a.asm.Hb).apply(null,arguments)},kd=a._emscripten_enum_draco_DataType_DT_INT64=function(){return(kd=a._emscripten_enum_draco_DataType_DT_INT64=a.asm.Ib).apply(null,arguments)},ld=a._emscripten_enum_draco_DataType_DT_UINT64=function(){return(ld=a._emscripten_enum_draco_DataType_DT_UINT64=a.asm.Jb).apply(null,arguments)},md=a._emscripten_enum_draco_DataType_DT_FLOAT32=function(){return(md=a._emscripten_enum_draco_DataType_DT_FLOAT32=a.asm.Kb).apply(null,
|
||||||
|
arguments)},nd=a._emscripten_enum_draco_DataType_DT_FLOAT64=function(){return(nd=a._emscripten_enum_draco_DataType_DT_FLOAT64=a.asm.Lb).apply(null,arguments)},od=a._emscripten_enum_draco_DataType_DT_BOOL=function(){return(od=a._emscripten_enum_draco_DataType_DT_BOOL=a.asm.Mb).apply(null,arguments)},pd=a._emscripten_enum_draco_DataType_DT_TYPES_COUNT=function(){return(pd=a._emscripten_enum_draco_DataType_DT_TYPES_COUNT=a.asm.Nb).apply(null,arguments)},qd=a._emscripten_enum_draco_StatusCode_OK=function(){return(qd=
|
||||||
|
a._emscripten_enum_draco_StatusCode_OK=a.asm.Ob).apply(null,arguments)},rd=a._emscripten_enum_draco_StatusCode_DRACO_ERROR=function(){return(rd=a._emscripten_enum_draco_StatusCode_DRACO_ERROR=a.asm.Pb).apply(null,arguments)},sd=a._emscripten_enum_draco_StatusCode_IO_ERROR=function(){return(sd=a._emscripten_enum_draco_StatusCode_IO_ERROR=a.asm.Qb).apply(null,arguments)},td=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=function(){return(td=a._emscripten_enum_draco_StatusCode_INVALID_PARAMETER=
|
||||||
|
a.asm.Rb).apply(null,arguments)},ud=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=function(){return(ud=a._emscripten_enum_draco_StatusCode_UNSUPPORTED_VERSION=a.asm.Sb).apply(null,arguments)},vd=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=function(){return(vd=a._emscripten_enum_draco_StatusCode_UNKNOWN_VERSION=a.asm.Tb).apply(null,arguments)},bb=a._malloc=function(){return(bb=a._malloc=a.asm.Ub).apply(null,arguments)};a._free=function(){return(a._free=a.asm.Vb).apply(null,arguments)};
|
||||||
|
var ya=a.___cxa_is_pointer_type=function(){return(ya=a.___cxa_is_pointer_type=a.asm.Wb).apply(null,arguments)};a.___start_em_js=15856;a.___stop_em_js=15954;var ka;ia=function b(){ka||ba();ka||(ia=b)};if(a.preInit)for("function"==typeof a.preInit&&(a.preInit=[a.preInit]);0<a.preInit.length;)a.preInit.pop()();ba();t.prototype=Object.create(t.prototype);t.prototype.constructor=t;t.prototype.__class__=t;t.__cache__={};a.WrapperObject=t;a.getCache=x;a.wrapPointer=D;a.castObject=function(b,c){return D(b.ptr,
|
||||||
|
c)};a.NULL=D(0);a.destroy=function(b){if(!b.__destroy__)throw"Error: Cannot destroy object. (Did you create it yourself?)";b.__destroy__();delete x(b.__class__)[b.ptr]};a.compare=function(b,c){return b.ptr===c.ptr};a.getPointer=function(b){return b.ptr};a.getClass=function(b){return b.__class__};var r={buffer:0,size:0,pos:0,temps:[],needed:0,prepare:function(){if(r.needed){for(var b=0;b<r.temps.length;b++)a._free(r.temps[b]);r.temps.length=0;a._free(r.buffer);r.buffer=0;r.size+=r.needed;r.needed=
|
||||||
|
0}r.buffer||(r.size+=128,r.buffer=a._malloc(r.size),r.buffer||f(void 0));r.pos=0},alloc:function(b,c){r.buffer||f(void 0);b=b.length*c.BYTES_PER_ELEMENT;b=b+7&-8;r.pos+b>=r.size?(0<b||f(void 0),r.needed+=b,c=a._malloc(b),r.temps.push(c)):(c=r.buffer+r.pos,r.pos+=b);return c},copy:function(b,c,d){d>>>=0;switch(c.BYTES_PER_ELEMENT){case 2:d>>>=1;break;case 4:d>>>=2;break;case 8:d>>>=3}for(var g=0;g<b.length;g++)c[d+g]=b[g]}};Z.prototype=Object.create(t.prototype);Z.prototype.constructor=Z;Z.prototype.__class__=
|
||||||
|
Z;Z.__cache__={};a.VoidPtr=Z;Z.prototype.__destroy__=Z.prototype.__destroy__=function(){db(this.ptr)};S.prototype=Object.create(t.prototype);S.prototype.constructor=S;S.prototype.__class__=S;S.__cache__={};a.DecoderBuffer=S;S.prototype.Init=S.prototype.Init=function(b,c){var d=this.ptr;r.prepare();"object"==typeof b&&(b=pa(b));c&&"object"===typeof c&&(c=c.ptr);eb(d,b,c)};S.prototype.__destroy__=S.prototype.__destroy__=function(){fb(this.ptr)};Q.prototype=Object.create(t.prototype);Q.prototype.constructor=
|
||||||
|
Q;Q.prototype.__class__=Q;Q.__cache__={};a.AttributeTransformData=Q;Q.prototype.transform_type=Q.prototype.transform_type=function(){return gb(this.ptr)};Q.prototype.__destroy__=Q.prototype.__destroy__=function(){hb(this.ptr)};W.prototype=Object.create(t.prototype);W.prototype.constructor=W;W.prototype.__class__=W;W.__cache__={};a.GeometryAttribute=W;W.prototype.__destroy__=W.prototype.__destroy__=function(){ib(this.ptr)};w.prototype=Object.create(t.prototype);w.prototype.constructor=w;w.prototype.__class__=
|
||||||
|
w;w.__cache__={};a.PointAttribute=w;w.prototype.size=w.prototype.size=function(){return jb(this.ptr)};w.prototype.GetAttributeTransformData=w.prototype.GetAttributeTransformData=function(){return D(kb(this.ptr),Q)};w.prototype.attribute_type=w.prototype.attribute_type=function(){return lb(this.ptr)};w.prototype.data_type=w.prototype.data_type=function(){return mb(this.ptr)};w.prototype.num_components=w.prototype.num_components=function(){return nb(this.ptr)};w.prototype.normalized=w.prototype.normalized=
|
||||||
|
function(){return!!ob(this.ptr)};w.prototype.byte_stride=w.prototype.byte_stride=function(){return pb(this.ptr)};w.prototype.byte_offset=w.prototype.byte_offset=function(){return qb(this.ptr)};w.prototype.unique_id=w.prototype.unique_id=function(){return rb(this.ptr)};w.prototype.__destroy__=w.prototype.__destroy__=function(){sb(this.ptr)};C.prototype=Object.create(t.prototype);C.prototype.constructor=C;C.prototype.__class__=C;C.__cache__={};a.AttributeQuantizationTransform=C;C.prototype.InitFromAttribute=
|
||||||
|
C.prototype.InitFromAttribute=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return!!tb(c,b)};C.prototype.quantization_bits=C.prototype.quantization_bits=function(){return ub(this.ptr)};C.prototype.min_value=C.prototype.min_value=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return vb(c,b)};C.prototype.range=C.prototype.range=function(){return wb(this.ptr)};C.prototype.__destroy__=C.prototype.__destroy__=function(){xb(this.ptr)};F.prototype=Object.create(t.prototype);
|
||||||
|
F.prototype.constructor=F;F.prototype.__class__=F;F.__cache__={};a.AttributeOctahedronTransform=F;F.prototype.InitFromAttribute=F.prototype.InitFromAttribute=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return!!yb(c,b)};F.prototype.quantization_bits=F.prototype.quantization_bits=function(){return zb(this.ptr)};F.prototype.__destroy__=F.prototype.__destroy__=function(){Ab(this.ptr)};G.prototype=Object.create(t.prototype);G.prototype.constructor=G;G.prototype.__class__=G;G.__cache__=
|
||||||
|
{};a.PointCloud=G;G.prototype.num_attributes=G.prototype.num_attributes=function(){return Bb(this.ptr)};G.prototype.num_points=G.prototype.num_points=function(){return Cb(this.ptr)};G.prototype.__destroy__=G.prototype.__destroy__=function(){Db(this.ptr)};E.prototype=Object.create(t.prototype);E.prototype.constructor=E;E.prototype.__class__=E;E.__cache__={};a.Mesh=E;E.prototype.num_faces=E.prototype.num_faces=function(){return Eb(this.ptr)};E.prototype.num_attributes=E.prototype.num_attributes=function(){return Fb(this.ptr)};
|
||||||
|
E.prototype.num_points=E.prototype.num_points=function(){return Gb(this.ptr)};E.prototype.__destroy__=E.prototype.__destroy__=function(){Hb(this.ptr)};T.prototype=Object.create(t.prototype);T.prototype.constructor=T;T.prototype.__class__=T;T.__cache__={};a.Metadata=T;T.prototype.__destroy__=T.prototype.__destroy__=function(){Ib(this.ptr)};B.prototype=Object.create(t.prototype);B.prototype.constructor=B;B.prototype.__class__=B;B.__cache__={};a.Status=B;B.prototype.code=B.prototype.code=function(){return Jb(this.ptr)};
|
||||||
|
B.prototype.ok=B.prototype.ok=function(){return!!Kb(this.ptr)};B.prototype.error_msg=B.prototype.error_msg=function(){return h(Lb(this.ptr))};B.prototype.__destroy__=B.prototype.__destroy__=function(){Mb(this.ptr)};H.prototype=Object.create(t.prototype);H.prototype.constructor=H;H.prototype.__class__=H;H.__cache__={};a.DracoFloat32Array=H;H.prototype.GetValue=H.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Nb(c,b)};H.prototype.size=H.prototype.size=function(){return Ob(this.ptr)};
|
||||||
|
H.prototype.__destroy__=H.prototype.__destroy__=function(){Pb(this.ptr)};I.prototype=Object.create(t.prototype);I.prototype.constructor=I;I.prototype.__class__=I;I.__cache__={};a.DracoInt8Array=I;I.prototype.GetValue=I.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Qb(c,b)};I.prototype.size=I.prototype.size=function(){return Rb(this.ptr)};I.prototype.__destroy__=I.prototype.__destroy__=function(){Sb(this.ptr)};J.prototype=Object.create(t.prototype);J.prototype.constructor=
|
||||||
|
J;J.prototype.__class__=J;J.__cache__={};a.DracoUInt8Array=J;J.prototype.GetValue=J.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Tb(c,b)};J.prototype.size=J.prototype.size=function(){return Ub(this.ptr)};J.prototype.__destroy__=J.prototype.__destroy__=function(){Vb(this.ptr)};K.prototype=Object.create(t.prototype);K.prototype.constructor=K;K.prototype.__class__=K;K.__cache__={};a.DracoInt16Array=K;K.prototype.GetValue=K.prototype.GetValue=function(b){var c=
|
||||||
|
this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Wb(c,b)};K.prototype.size=K.prototype.size=function(){return Xb(this.ptr)};K.prototype.__destroy__=K.prototype.__destroy__=function(){Yb(this.ptr)};L.prototype=Object.create(t.prototype);L.prototype.constructor=L;L.prototype.__class__=L;L.__cache__={};a.DracoUInt16Array=L;L.prototype.GetValue=L.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Zb(c,b)};L.prototype.size=L.prototype.size=function(){return $b(this.ptr)};
|
||||||
|
L.prototype.__destroy__=L.prototype.__destroy__=function(){ac(this.ptr)};M.prototype=Object.create(t.prototype);M.prototype.constructor=M;M.prototype.__class__=M;M.__cache__={};a.DracoInt32Array=M;M.prototype.GetValue=M.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return bc(c,b)};M.prototype.size=M.prototype.size=function(){return cc(this.ptr)};M.prototype.__destroy__=M.prototype.__destroy__=function(){dc(this.ptr)};N.prototype=Object.create(t.prototype);N.prototype.constructor=
|
||||||
|
N;N.prototype.__class__=N;N.__cache__={};a.DracoUInt32Array=N;N.prototype.GetValue=N.prototype.GetValue=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return ec(c,b)};N.prototype.size=N.prototype.size=function(){return fc(this.ptr)};N.prototype.__destroy__=N.prototype.__destroy__=function(){gc(this.ptr)};y.prototype=Object.create(t.prototype);y.prototype.constructor=y;y.prototype.__class__=y;y.__cache__={};a.MetadataQuerier=y;y.prototype.HasEntry=y.prototype.HasEntry=function(b,c){var d=
|
||||||
|
this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return!!hc(d,b,c)};y.prototype.GetIntEntry=y.prototype.GetIntEntry=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return ic(d,b,c)};y.prototype.GetIntEntryArray=y.prototype.GetIntEntryArray=function(b,c,d){var g=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);d&&"object"===typeof d&&(d=d.ptr);jc(g,b,c,
|
||||||
|
d)};y.prototype.GetDoubleEntry=y.prototype.GetDoubleEntry=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return kc(d,b,c)};y.prototype.GetStringEntry=y.prototype.GetStringEntry=function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return h(lc(d,b,c))};y.prototype.NumEntries=y.prototype.NumEntries=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return mc(c,b)};y.prototype.GetEntryName=
|
||||||
|
y.prototype.GetEntryName=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return h(nc(d,b,c))};y.prototype.__destroy__=y.prototype.__destroy__=function(){oc(this.ptr)};m.prototype=Object.create(t.prototype);m.prototype.constructor=m;m.prototype.__class__=m;m.__cache__={};a.Decoder=m;m.prototype.DecodeArrayToPointCloud=m.prototype.DecodeArrayToPointCloud=function(b,c,d){var g=this.ptr;r.prepare();"object"==typeof b&&(b=pa(b));c&&"object"===typeof c&&
|
||||||
|
(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return D(pc(g,b,c,d),B)};m.prototype.DecodeArrayToMesh=m.prototype.DecodeArrayToMesh=function(b,c,d){var g=this.ptr;r.prepare();"object"==typeof b&&(b=pa(b));c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return D(qc(g,b,c,d),B)};m.prototype.GetAttributeId=m.prototype.GetAttributeId=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return rc(d,b,c)};m.prototype.GetAttributeIdByName=m.prototype.GetAttributeIdByName=
|
||||||
|
function(b,c){var d=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);return sc(d,b,c)};m.prototype.GetAttributeIdByMetadataEntry=m.prototype.GetAttributeIdByMetadataEntry=function(b,c,d){var g=this.ptr;r.prepare();b&&"object"===typeof b&&(b=b.ptr);c=c&&"object"===typeof c?c.ptr:R(c);d=d&&"object"===typeof d?d.ptr:R(d);return tc(g,b,c,d)};m.prototype.GetAttribute=m.prototype.GetAttribute=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===
|
||||||
|
typeof c&&(c=c.ptr);return D(uc(d,b,c),w)};m.prototype.GetAttributeByUniqueId=m.prototype.GetAttributeByUniqueId=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(vc(d,b,c),w)};m.prototype.GetMetadata=m.prototype.GetMetadata=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return D(wc(c,b),T)};m.prototype.GetAttributeMetadata=m.prototype.GetAttributeMetadata=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===
|
||||||
|
typeof c&&(c=c.ptr);return D(xc(d,b,c),T)};m.prototype.GetFaceFromMesh=m.prototype.GetFaceFromMesh=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!yc(g,b,c,d)};m.prototype.GetTriangleStripsFromMesh=m.prototype.GetTriangleStripsFromMesh=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return zc(d,b,c)};m.prototype.GetTrianglesUInt16Array=m.prototype.GetTrianglesUInt16Array=
|
||||||
|
function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Ac(g,b,c,d)};m.prototype.GetTrianglesUInt32Array=m.prototype.GetTrianglesUInt32Array=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Bc(g,b,c,d)};m.prototype.GetAttributeFloat=m.prototype.GetAttributeFloat=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);
|
||||||
|
c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Cc(g,b,c,d)};m.prototype.GetAttributeFloatForAllPoints=m.prototype.GetAttributeFloatForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Dc(g,b,c,d)};m.prototype.GetAttributeIntForAllPoints=m.prototype.GetAttributeIntForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);
|
||||||
|
d&&"object"===typeof d&&(d=d.ptr);return!!Ec(g,b,c,d)};m.prototype.GetAttributeInt8ForAllPoints=m.prototype.GetAttributeInt8ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Fc(g,b,c,d)};m.prototype.GetAttributeUInt8ForAllPoints=m.prototype.GetAttributeUInt8ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=
|
||||||
|
d.ptr);return!!Gc(g,b,c,d)};m.prototype.GetAttributeInt16ForAllPoints=m.prototype.GetAttributeInt16ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Hc(g,b,c,d)};m.prototype.GetAttributeUInt16ForAllPoints=m.prototype.GetAttributeUInt16ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Ic(g,b,c,
|
||||||
|
d)};m.prototype.GetAttributeInt32ForAllPoints=m.prototype.GetAttributeInt32ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Jc(g,b,c,d)};m.prototype.GetAttributeUInt32ForAllPoints=m.prototype.GetAttributeUInt32ForAllPoints=function(b,c,d){var g=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);return!!Kc(g,b,c,d)};m.prototype.GetAttributeDataArrayForAllPoints=
|
||||||
|
m.prototype.GetAttributeDataArrayForAllPoints=function(b,c,d,g,u){var X=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);d&&"object"===typeof d&&(d=d.ptr);g&&"object"===typeof g&&(g=g.ptr);u&&"object"===typeof u&&(u=u.ptr);return!!Lc(X,b,c,d,g,u)};m.prototype.SkipAttributeTransform=m.prototype.SkipAttributeTransform=function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);Mc(c,b)};m.prototype.GetEncodedGeometryType_Deprecated=m.prototype.GetEncodedGeometryType_Deprecated=
|
||||||
|
function(b){var c=this.ptr;b&&"object"===typeof b&&(b=b.ptr);return Nc(c,b)};m.prototype.DecodeBufferToPointCloud=m.prototype.DecodeBufferToPointCloud=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(Oc(d,b,c),B)};m.prototype.DecodeBufferToMesh=m.prototype.DecodeBufferToMesh=function(b,c){var d=this.ptr;b&&"object"===typeof b&&(b=b.ptr);c&&"object"===typeof c&&(c=c.ptr);return D(Pc(d,b,c),B)};m.prototype.__destroy__=m.prototype.__destroy__=
|
||||||
|
function(){Qc(this.ptr)};(function(){function b(){a.ATTRIBUTE_INVALID_TRANSFORM=Rc();a.ATTRIBUTE_NO_TRANSFORM=Sc();a.ATTRIBUTE_QUANTIZATION_TRANSFORM=Tc();a.ATTRIBUTE_OCTAHEDRON_TRANSFORM=Uc();a.INVALID=Vc();a.POSITION=Wc();a.NORMAL=Xc();a.COLOR=Yc();a.TEX_COORD=Zc();a.GENERIC=$c();a.INVALID_GEOMETRY_TYPE=ad();a.POINT_CLOUD=bd();a.TRIANGULAR_MESH=cd();a.DT_INVALID=dd();a.DT_INT8=ed();a.DT_UINT8=fd();a.DT_INT16=gd();a.DT_UINT16=hd();a.DT_INT32=id();a.DT_UINT32=jd();a.DT_INT64=kd();a.DT_UINT64=ld();
|
||||||
|
a.DT_FLOAT32=md();a.DT_FLOAT64=nd();a.DT_BOOL=od();a.DT_TYPES_COUNT=pd();a.OK=qd();a.DRACO_ERROR=rd();a.IO_ERROR=sd();a.INVALID_PARAMETER=td();a.UNSUPPORTED_VERSION=ud();a.UNKNOWN_VERSION=vd()}za?b():oa.unshift(b)})();if("function"===typeof a.onModuleParsed)a.onModuleParsed();a.Decoder.prototype.GetEncodedGeometryType=function(b){if(b.__class__&&b.__class__===a.DecoderBuffer)return a.Decoder.prototype.GetEncodedGeometryType_Deprecated(b);if(8>b.byteLength)return a.INVALID_GEOMETRY_TYPE;switch(b[7]){case 0:return a.POINT_CLOUD;
|
||||||
|
case 1:return a.TRIANGULAR_MESH;default:return a.INVALID_GEOMETRY_TYPE}};return n.ready}}();"object"===typeof exports&&"object"===typeof module?module.exports=DracoDecoderModule:"function"===typeof define&&define.amd?define([],function(){return DracoDecoderModule}):"object"===typeof exports&&(exports.DracoDecoderModule=DracoDecoderModule);
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
const isHexColor = (value) => /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(String(value || "").trim());
|
||||||
|
|
||||||
|
export function createColorControl({
|
||||||
|
value = "#ffffff",
|
||||||
|
previewValue = value,
|
||||||
|
ariaLabel = "Выбрать цвет",
|
||||||
|
valueLabel = "Значение цвета",
|
||||||
|
onChange,
|
||||||
|
}) {
|
||||||
|
const root = document.createElement("div");
|
||||||
|
root.className = "env-color-field";
|
||||||
|
|
||||||
|
const swatch = document.createElement("label");
|
||||||
|
swatch.className = "env-color-field__swatch";
|
||||||
|
|
||||||
|
const preview = document.createElement("span");
|
||||||
|
preview.className = "env-color-field__preview";
|
||||||
|
|
||||||
|
const picker = document.createElement("input");
|
||||||
|
picker.type = "color";
|
||||||
|
picker.setAttribute("aria-label", ariaLabel);
|
||||||
|
|
||||||
|
const valueWrap = document.createElement("div");
|
||||||
|
valueWrap.className = "env-color-field__value";
|
||||||
|
|
||||||
|
const valueInput = document.createElement("input");
|
||||||
|
valueInput.type = "text";
|
||||||
|
valueInput.setAttribute("aria-label", valueLabel);
|
||||||
|
valueWrap.appendChild(valueInput);
|
||||||
|
|
||||||
|
const update = (nextValue, { emit = false } = {}) => {
|
||||||
|
const safeValue = String(nextValue ?? "");
|
||||||
|
const safePreview = isHexColor(safeValue)
|
||||||
|
? safeValue
|
||||||
|
: (isHexColor(previewValue) ? previewValue : "#000000");
|
||||||
|
|
||||||
|
valueInput.value = safeValue;
|
||||||
|
picker.value = isHexColor(safeValue) ? safeValue : safePreview;
|
||||||
|
preview.style.background = safePreview;
|
||||||
|
|
||||||
|
if (emit && typeof onChange === "function") {
|
||||||
|
onChange(safeValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
picker.addEventListener("input", () => update(picker.value, { emit: true }));
|
||||||
|
valueInput.addEventListener("change", () => update(valueInput.value, { emit: true }));
|
||||||
|
|
||||||
|
swatch.appendChild(preview);
|
||||||
|
swatch.appendChild(picker);
|
||||||
|
root.appendChild(swatch);
|
||||||
|
root.appendChild(valueWrap);
|
||||||
|
|
||||||
|
update(value);
|
||||||
|
|
||||||
|
root.setValue = (nextValue) => update(nextValue);
|
||||||
|
root.getValue = () => valueInput.value;
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,16 @@
|
||||||
export function createSliderControl({ label = "", value = 0, min = 0, max = 100, step = 1, onChange }) {
|
export function createSliderControl({
|
||||||
|
label = "",
|
||||||
|
value = 0,
|
||||||
|
min = 0,
|
||||||
|
max = 100,
|
||||||
|
step = 1,
|
||||||
|
className = "",
|
||||||
|
showValue = false,
|
||||||
|
formatValue = (val) => String(val),
|
||||||
|
onChange
|
||||||
|
}) {
|
||||||
const row = document.createElement("div");
|
const row = document.createElement("div");
|
||||||
row.className = "slider-row";
|
row.className = ["slider-row", className].filter(Boolean).join(" ");
|
||||||
|
|
||||||
const lbl = document.createElement("label");
|
const lbl = document.createElement("label");
|
||||||
lbl.textContent = label;
|
lbl.textContent = label;
|
||||||
|
|
@ -14,9 +24,34 @@ export function createSliderControl({ label = "", value = 0, min = 0, max = 100,
|
||||||
input.step = step;
|
input.step = step;
|
||||||
input.value = value;
|
input.value = value;
|
||||||
|
|
||||||
|
const valueEl = document.createElement("div");
|
||||||
|
valueEl.className = "slider-value";
|
||||||
|
|
||||||
|
const fillText = document.createElement("span");
|
||||||
|
fillText.className = "slider-fill-text";
|
||||||
|
fillText.setAttribute("aria-hidden", "true");
|
||||||
|
|
||||||
|
const fillLabel = document.createElement("span");
|
||||||
|
fillLabel.textContent = label;
|
||||||
|
fillLabel.className = "slider-label";
|
||||||
|
|
||||||
|
const fillValue = document.createElement("span");
|
||||||
|
fillValue.className = "slider-value";
|
||||||
|
fillText.appendChild(fillLabel);
|
||||||
|
fillText.appendChild(fillValue);
|
||||||
|
|
||||||
const updateFill = () => {
|
const updateFill = () => {
|
||||||
const percent = ((input.value - input.min) / (input.max - input.min)) * 100;
|
const range = Number(input.max) - Number(input.min);
|
||||||
|
const percent = range
|
||||||
|
? Math.max(0, Math.min(100, ((Number(input.value) - Number(input.min)) / range) * 100))
|
||||||
|
: 0;
|
||||||
|
row.style.setProperty("--slider-percent", `${percent}%`);
|
||||||
input.style.setProperty("--slider-percent", `${percent}%`);
|
input.style.setProperty("--slider-percent", `${percent}%`);
|
||||||
|
if (showValue) {
|
||||||
|
const formattedValue = formatValue(Number(input.value));
|
||||||
|
valueEl.textContent = formattedValue;
|
||||||
|
fillValue.textContent = formattedValue;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
input.addEventListener("input", () => {
|
input.addEventListener("input", () => {
|
||||||
|
|
@ -25,9 +60,69 @@ export function createSliderControl({ label = "", value = 0, min = 0, max = 100,
|
||||||
onChange?.(v);
|
onChange?.(v);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const clampValue = (next) => Math.min(Number(input.max), Math.max(Number(input.min), next));
|
||||||
|
|
||||||
|
const valueFromClientX = (clientX) => {
|
||||||
|
const rect = input.getBoundingClientRect();
|
||||||
|
const minValue = Number(input.min);
|
||||||
|
const maxValue = Number(input.max);
|
||||||
|
const range = maxValue - minValue;
|
||||||
|
if (!rect.width || !range) return Number(input.value);
|
||||||
|
const ratio = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
|
||||||
|
const raw = minValue + (ratio * range);
|
||||||
|
if (input.step === "any") return clampValue(raw);
|
||||||
|
const stepValue = Number(input.step) || 1;
|
||||||
|
return clampValue(minValue + (Math.round((raw - minValue) / stepValue) * stepValue));
|
||||||
|
};
|
||||||
|
|
||||||
|
const commitValue = (nextValue) => {
|
||||||
|
input.value = nextValue;
|
||||||
|
updateFill();
|
||||||
|
onChange?.(Number(input.value));
|
||||||
|
};
|
||||||
|
|
||||||
|
let activeTouchPointerId = null;
|
||||||
|
|
||||||
|
const isTouchLikePointer = (event) => event.pointerType === "touch" || event.pointerType === "pen";
|
||||||
|
|
||||||
|
row.addEventListener("pointerdown", (event) => {
|
||||||
|
if (!isTouchLikePointer(event) || (event.button !== undefined && event.button !== 0)) return;
|
||||||
|
activeTouchPointerId = event.pointerId;
|
||||||
|
event.preventDefault();
|
||||||
|
row.setPointerCapture?.(event.pointerId);
|
||||||
|
input.focus?.({ preventScroll: true });
|
||||||
|
commitValue(valueFromClientX(event.clientX));
|
||||||
|
});
|
||||||
|
|
||||||
|
row.addEventListener("pointermove", (event) => {
|
||||||
|
if (activeTouchPointerId !== event.pointerId) return;
|
||||||
|
event.preventDefault();
|
||||||
|
commitValue(valueFromClientX(event.clientX));
|
||||||
|
});
|
||||||
|
|
||||||
|
const finishTouchPointer = (event) => {
|
||||||
|
if (activeTouchPointerId !== event.pointerId) return;
|
||||||
|
activeTouchPointerId = null;
|
||||||
|
if (row.hasPointerCapture?.(event.pointerId)) {
|
||||||
|
row.releasePointerCapture?.(event.pointerId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
row.addEventListener("pointerup", finishTouchPointer);
|
||||||
|
row.addEventListener("pointercancel", finishTouchPointer);
|
||||||
|
|
||||||
updateFill();
|
updateFill();
|
||||||
|
|
||||||
row.appendChild(lbl);
|
row.appendChild(lbl);
|
||||||
row.appendChild(input);
|
row.appendChild(input);
|
||||||
|
if (showValue) {
|
||||||
|
row.appendChild(valueEl);
|
||||||
|
row.appendChild(fillText);
|
||||||
|
}
|
||||||
|
row.setValue = (nextValue) => {
|
||||||
|
input.value = nextValue;
|
||||||
|
updateFill();
|
||||||
|
};
|
||||||
|
row.getValue = () => Number(input.value);
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
const closeEventName = "nodedc-select-open";
|
||||||
|
|
||||||
|
const makeSelectId = () => `ndc-select-${Math.random().toString(16).slice(2)}`;
|
||||||
|
|
||||||
|
export function createGlassSelect({
|
||||||
|
host,
|
||||||
|
value,
|
||||||
|
options = [],
|
||||||
|
ariaLabel = "Выбрать",
|
||||||
|
disabled = false,
|
||||||
|
onChange = null,
|
||||||
|
}) {
|
||||||
|
if (!host) return null;
|
||||||
|
|
||||||
|
const selectId = makeSelectId();
|
||||||
|
let currentValue = value;
|
||||||
|
let currentOptions = [...options];
|
||||||
|
let open = false;
|
||||||
|
let menu = null;
|
||||||
|
let menuRect = { top: 0, left: 0, width: 0 };
|
||||||
|
|
||||||
|
host.innerHTML = "";
|
||||||
|
|
||||||
|
const root = document.createElement("div");
|
||||||
|
root.className = "nodedc-select";
|
||||||
|
|
||||||
|
const control = document.createElement("div");
|
||||||
|
control.className = "nodedc-select__control";
|
||||||
|
|
||||||
|
const valueEl = document.createElement("div");
|
||||||
|
valueEl.className = "nodedc-select__value";
|
||||||
|
|
||||||
|
const toggle = document.createElement("button");
|
||||||
|
toggle.type = "button";
|
||||||
|
toggle.className = "nodedc-select__toggle";
|
||||||
|
toggle.setAttribute("aria-label", ariaLabel);
|
||||||
|
toggle.setAttribute("aria-haspopup", "listbox");
|
||||||
|
toggle.disabled = !!disabled;
|
||||||
|
|
||||||
|
const chevron = document.createElement("span");
|
||||||
|
chevron.className = "nodedc-select__chevron";
|
||||||
|
chevron.setAttribute("aria-hidden", "true");
|
||||||
|
toggle.appendChild(chevron);
|
||||||
|
|
||||||
|
control.appendChild(valueEl);
|
||||||
|
control.appendChild(toggle);
|
||||||
|
root.appendChild(control);
|
||||||
|
host.appendChild(root);
|
||||||
|
|
||||||
|
const selectedOption = () => (
|
||||||
|
currentOptions.find((option) => option.value === currentValue) ||
|
||||||
|
currentOptions[0] ||
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateValue = () => {
|
||||||
|
const selected = selectedOption();
|
||||||
|
valueEl.textContent = selected?.label || "";
|
||||||
|
toggle.setAttribute("aria-expanded", open ? "true" : "false");
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateMenuRect = () => {
|
||||||
|
const rect = root.getBoundingClientRect();
|
||||||
|
const toggleWidth = 42;
|
||||||
|
const gap = 8;
|
||||||
|
const menuMaxHeight = 232;
|
||||||
|
const bottomTop = rect.bottom + 6;
|
||||||
|
const top = bottomTop + menuMaxHeight > window.innerHeight - 12
|
||||||
|
? Math.max(12, rect.top - menuMaxHeight - 6)
|
||||||
|
: bottomTop;
|
||||||
|
|
||||||
|
menuRect = {
|
||||||
|
top,
|
||||||
|
left: rect.left,
|
||||||
|
width: Math.max(180, rect.width - toggleWidth - gap),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (menu) {
|
||||||
|
menu.style.top = `${menuRect.top}px`;
|
||||||
|
menu.style.left = `${menuRect.left}px`;
|
||||||
|
menu.style.width = `${menuRect.width}px`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderMenuOptions = () => {
|
||||||
|
if (!menu) return;
|
||||||
|
menu.innerHTML = "";
|
||||||
|
currentOptions.forEach((option) => {
|
||||||
|
const item = document.createElement("button");
|
||||||
|
item.type = "button";
|
||||||
|
item.className = "nodedc-dropdown-option nodedc-select__option";
|
||||||
|
item.dataset.value = option.value;
|
||||||
|
if (option.value === currentValue) {
|
||||||
|
item.dataset.selected = "true";
|
||||||
|
}
|
||||||
|
item.setAttribute("role", "option");
|
||||||
|
item.setAttribute("aria-selected", option.value === currentValue ? "true" : "false");
|
||||||
|
item.textContent = option.label;
|
||||||
|
item.addEventListener("click", () => {
|
||||||
|
setValue(option.value, { emit: true });
|
||||||
|
closeMenu();
|
||||||
|
});
|
||||||
|
menu.appendChild(item);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const openMenu = () => {
|
||||||
|
if (toggle.disabled || open) return;
|
||||||
|
open = true;
|
||||||
|
updateValue();
|
||||||
|
updateMenuRect();
|
||||||
|
window.dispatchEvent(new CustomEvent(closeEventName, { detail: { id: selectId } }));
|
||||||
|
|
||||||
|
menu = document.createElement("div");
|
||||||
|
menu.className = "nodedc-dropdown-surface nodedc-select__menu";
|
||||||
|
menu.setAttribute("role", "listbox");
|
||||||
|
menu.style.position = "fixed";
|
||||||
|
menu.style.top = `${menuRect.top}px`;
|
||||||
|
menu.style.left = `${menuRect.left}px`;
|
||||||
|
menu.style.width = `${menuRect.width}px`;
|
||||||
|
renderMenuOptions();
|
||||||
|
document.body.appendChild(menu);
|
||||||
|
|
||||||
|
document.addEventListener("mousedown", handleDocumentPointerDown);
|
||||||
|
document.addEventListener("keydown", handleKeyDown);
|
||||||
|
window.addEventListener(closeEventName, handleOtherSelectOpen);
|
||||||
|
window.addEventListener("resize", updateMenuRect);
|
||||||
|
window.addEventListener("scroll", updateMenuRect, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
function closeMenu() {
|
||||||
|
if (!open) return;
|
||||||
|
open = false;
|
||||||
|
updateValue();
|
||||||
|
if (menu) {
|
||||||
|
menu.remove();
|
||||||
|
menu = null;
|
||||||
|
}
|
||||||
|
document.removeEventListener("mousedown", handleDocumentPointerDown);
|
||||||
|
document.removeEventListener("keydown", handleKeyDown);
|
||||||
|
window.removeEventListener(closeEventName, handleOtherSelectOpen);
|
||||||
|
window.removeEventListener("resize", updateMenuRect);
|
||||||
|
window.removeEventListener("scroll", updateMenuRect, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDocumentPointerDown(event) {
|
||||||
|
const target = event.target;
|
||||||
|
if (
|
||||||
|
target instanceof Node &&
|
||||||
|
!root.contains(target) &&
|
||||||
|
(!menu || !menu.contains(target))
|
||||||
|
) {
|
||||||
|
closeMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeyDown(event) {
|
||||||
|
if (event.key === "Escape") closeMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleOtherSelectOpen(event) {
|
||||||
|
if (event?.detail?.id !== selectId) closeMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setValue(nextValue, { emit = false } = {}) {
|
||||||
|
const nextOption = currentOptions.find((option) => option.value === nextValue);
|
||||||
|
if (!nextOption) return;
|
||||||
|
const changed = currentValue !== nextValue;
|
||||||
|
currentValue = nextValue;
|
||||||
|
updateValue();
|
||||||
|
renderMenuOptions();
|
||||||
|
if (emit && changed && typeof onChange === "function") {
|
||||||
|
onChange(nextValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setOptions = (nextOptions = [], nextValue = currentValue) => {
|
||||||
|
currentOptions = [...nextOptions];
|
||||||
|
currentValue = currentOptions.some((option) => option.value === nextValue)
|
||||||
|
? nextValue
|
||||||
|
: currentOptions[0]?.value;
|
||||||
|
updateValue();
|
||||||
|
renderMenuOptions();
|
||||||
|
};
|
||||||
|
|
||||||
|
const setDisabled = (nextDisabled) => {
|
||||||
|
toggle.disabled = !!nextDisabled;
|
||||||
|
if (toggle.disabled) closeMenu();
|
||||||
|
};
|
||||||
|
|
||||||
|
const destroy = () => {
|
||||||
|
closeMenu();
|
||||||
|
root.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
toggle.addEventListener("click", () => {
|
||||||
|
if (open) {
|
||||||
|
closeMenu();
|
||||||
|
} else {
|
||||||
|
openMenu();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
valueEl.addEventListener("click", openMenu);
|
||||||
|
|
||||||
|
updateValue();
|
||||||
|
|
||||||
|
return {
|
||||||
|
root,
|
||||||
|
setValue,
|
||||||
|
setOptions,
|
||||||
|
setDisabled,
|
||||||
|
close: closeMenu,
|
||||||
|
destroy,
|
||||||
|
getValue: () => currentValue,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@ export function createLogo({
|
||||||
aspect = 4, // соотношение width / height контейнера
|
aspect = 4, // соотношение width / height контейнера
|
||||||
offsetY = 0,
|
offsetY = 0,
|
||||||
paddingX = 0,
|
paddingX = 0,
|
||||||
imageUrl = "./assets/logo.svg",
|
imageUrl = "/assets/logo.svg",
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const wrapper = document.createElement("div");
|
const wrapper = document.createElement("div");
|
||||||
wrapper.className = "ue-logo";
|
wrapper.className = "ue-logo";
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import { createSliderControl } from "./controls/slider.js";
|
import { createSliderControl } from "./controls/slider.js";
|
||||||
|
import { createColorControl } from "./controls/color.js";
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
themeVersion: "v3-yellow",
|
themeVersion: "v7-toolbar-hub-icon",
|
||||||
bgOuter: "#0f0f0f",
|
bgOuter: "#0f0f0f",
|
||||||
canvasTop: "#1c1c1c",
|
canvasTop: "#1c1c1c",
|
||||||
canvasBottom: "#1c1c1c",
|
canvasBottom: "#1c1c1c",
|
||||||
|
|
@ -9,53 +10,199 @@ const defaultSettings = {
|
||||||
loadingBottom: "#1c1c1c",
|
loadingBottom: "#1c1c1c",
|
||||||
accent: "#ffea00",
|
accent: "#ffea00",
|
||||||
accent2: "#ffea00",
|
accent2: "#ffea00",
|
||||||
templateFill: "#1c1c1c",
|
templateFill: "#292929",
|
||||||
templateOutline: "#233044",
|
templateOutline: "#292929",
|
||||||
templateOutlineHover: "rgba(255,234,0,0.7)",
|
templateOutlineHover: "#1c1c1c",
|
||||||
projectBtnFill: "#1c1c1c",
|
projectBtnFill: "#292929",
|
||||||
projectBtnBorder: "#233044",
|
projectBtnBorder: "#292929",
|
||||||
projectBtnHover: "rgba(255,234,0,0.7)",
|
projectBtnHover: "#1c1c1c",
|
||||||
modalBtnPrimary: "#ffea00",
|
modalBtnPrimary: "#c4ff67",
|
||||||
modalBtnSecondary: "#292929",
|
modalBtnSecondary: "#292929",
|
||||||
loaderColor: "#ffea00",
|
loaderColor: "#c4ff67",
|
||||||
templateGlow: 80,
|
templateGlow: 80,
|
||||||
toolbarBg: "#1c1c1c",
|
toolbarBg: "#292929",
|
||||||
toolbarBgActive: "#ffea00",
|
toolbarBgActive: "#c4ff67",
|
||||||
toolbarBorder: "#233044",
|
toolbarBorder: "#292929",
|
||||||
toolbarOutline: "#ffea00",
|
toolbarOutline: "#292929",
|
||||||
|
toolbarMinSize: 25,
|
||||||
|
toolbarMaxSize: 87,
|
||||||
|
toolbarLensCount: 5,
|
||||||
|
toolbarAutoHide: false,
|
||||||
modalBg: "#1c1c1c",
|
modalBg: "#1c1c1c",
|
||||||
modalBgAlpha: 1,
|
modalBgAlpha: 1,
|
||||||
modalFocus: "#292929",
|
modalFocus: "#292929",
|
||||||
modalFocusAlpha: 1,
|
modalFocusAlpha: 0.35,
|
||||||
modalBorder: "#292929",
|
modalBorder: "#1c1c1c",
|
||||||
modalElement: "#292929",
|
modalElement: "#262626",
|
||||||
modalElementOutline: "#2b2b2b",
|
modalElementOutline: "#262626",
|
||||||
modalRadius: "14px",
|
modalRadius: "14px",
|
||||||
border: "#233044",
|
border: "#233044",
|
||||||
text: "#e6edf3",
|
text: "#e6edf3",
|
||||||
panel: "#1c1c1c",
|
panel: "#1c1c1c",
|
||||||
panel2: "#292929",
|
panel2: "#292929",
|
||||||
highlight: "#ffea00",
|
highlight: "#c4ff67",
|
||||||
cubeText: "#242424",
|
cubeText: "#242424",
|
||||||
cubeEdges: "#e0e7ff",
|
cubeEdges: "#e0e7ff",
|
||||||
plus: "#ffea00",
|
plus: "#c4ff67",
|
||||||
navCubeBase: "#ffea00",
|
navCubeBase: "#ffffff",
|
||||||
navCubeHover: "#ffffff",
|
navCubeHover: "#ffffff",
|
||||||
navCubeText: "#242424",
|
navCubeText: "#242424",
|
||||||
navCubeEdge: "#e0e7ff",
|
navCubeEdge: "#e0e7ff",
|
||||||
navCubeEdgeAlpha: 0.6,
|
navCubeEdgeAlpha: 0.6,
|
||||||
measureLine: "#ffea00",
|
measureLine: "#c4ff67",
|
||||||
measureLabel: "#ffea00",
|
measureLabel: "#c4ff67",
|
||||||
measureLabelText: "#292929",
|
measureLabelText: "#292929",
|
||||||
measureDot: "#ffea00",
|
measureDot: "#c4ff67",
|
||||||
|
sectionAxisX: "#ff2b2b",
|
||||||
|
sectionAxisY: "#35ff4f",
|
||||||
|
sectionAxisZ: "#285bff",
|
||||||
|
sectionGizmoDiameter: 1,
|
||||||
|
sectionGizmoThickness: 1,
|
||||||
|
sectionPlaneFill: "#606060",
|
||||||
|
sectionPlaneAlpha: 0.32,
|
||||||
|
sectionPlaneEdge: "#0d0d0d",
|
||||||
|
sectionPlaneEdgeAlpha: 0.8,
|
||||||
|
commentTargetActiveColor: "#c4ff67",
|
||||||
|
commentTargetActiveAlpha: 1,
|
||||||
|
commentTargetActiveSize: 30,
|
||||||
|
commentTargetPassiveColor: "#f5f5fa",
|
||||||
|
commentTargetPassiveAlpha: 0.58,
|
||||||
|
commentTargetPassiveSize: 22,
|
||||||
};
|
};
|
||||||
|
|
||||||
const STORAGE_KEY = "bimdc-settings-v3";
|
const STORAGE_KEY = "bimdc-settings-v3";
|
||||||
const LEGACY_KEYS = ["bimdc-settings", "bimdc-settings-v2"];
|
const LEGACY_KEYS = ["bimdc-settings", "bimdc-settings-v2"];
|
||||||
|
const isSharedViewerPath = () => (
|
||||||
|
typeof window !== "undefined" &&
|
||||||
|
/^\/share\/[^/]+\/?$/.test(window.location.pathname || "")
|
||||||
|
);
|
||||||
|
const isReadonlySettingsContext = () => {
|
||||||
|
if (typeof document !== "undefined") {
|
||||||
|
const mode = document.body?.dataset?.viewerMode;
|
||||||
|
if (mode) return mode === "guest";
|
||||||
|
}
|
||||||
|
return isSharedViewerPath();
|
||||||
|
};
|
||||||
const projectSettings = typeof window !== "undefined" && window.__BIMDC_THEME__
|
const projectSettings = typeof window !== "undefined" && window.__BIMDC_THEME__
|
||||||
? { ...defaultSettings, ...window.__BIMDC_THEME__ }
|
? { ...defaultSettings, ...window.__BIMDC_THEME__ }
|
||||||
: { ...defaultSettings };
|
: { ...defaultSettings };
|
||||||
|
|
||||||
|
const parseColor = (value) => {
|
||||||
|
if (typeof value !== "string") return null;
|
||||||
|
const color = value.trim();
|
||||||
|
const hex = color.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
|
||||||
|
if (hex) {
|
||||||
|
const raw = hex[1].length === 3
|
||||||
|
? hex[1].split("").map((c) => c + c).join("")
|
||||||
|
: hex[1];
|
||||||
|
return [
|
||||||
|
parseInt(raw.slice(0, 2), 16),
|
||||||
|
parseInt(raw.slice(2, 4), 16),
|
||||||
|
parseInt(raw.slice(4, 6), 16),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const rgb = color.match(/^rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)/i);
|
||||||
|
if (!rgb) return null;
|
||||||
|
return rgb.slice(1, 4).map((channel) => Math.max(0, Math.min(255, Number(channel))));
|
||||||
|
};
|
||||||
|
|
||||||
|
const readableTextColor = (value) => {
|
||||||
|
const rgb = parseColor(value);
|
||||||
|
if (!rgb || rgb.some((channel) => !Number.isFinite(channel))) return "#15170f";
|
||||||
|
const toLinear = (channel) => {
|
||||||
|
const value = channel / 255;
|
||||||
|
return value <= 0.03928 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
||||||
|
};
|
||||||
|
const lum = 0.2126 * toLinear(rgb[0]) + 0.7152 * toLinear(rgb[1]) + 0.0722 * toLinear(rgb[2]);
|
||||||
|
return (lum + 0.05) / 0.05 >= 1.05 / (lum + 0.05) ? "#15170f" : "#f5f5fa";
|
||||||
|
};
|
||||||
|
|
||||||
|
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
||||||
|
|
||||||
|
const colorParts = (value, fallback) => {
|
||||||
|
const parsed = parseColor(value);
|
||||||
|
if (parsed && parsed.every((channel) => Number.isFinite(channel))) return parsed;
|
||||||
|
const parsedFallback = parseColor(fallback);
|
||||||
|
if (parsedFallback && parsedFallback.every((channel) => Number.isFinite(channel))) return parsedFallback;
|
||||||
|
return [28, 28, 28];
|
||||||
|
};
|
||||||
|
|
||||||
|
const alphaValue = (value, fallback) => {
|
||||||
|
const numeric = Number(value);
|
||||||
|
return Number.isFinite(numeric) ? clamp(numeric, 0, 1) : fallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rgba = (parts, alpha) => {
|
||||||
|
const [r, g, b] = parts.map((channel) => Math.round(clamp(channel, 0, 255)));
|
||||||
|
return `rgba(${r}, ${g}, ${b}, ${clamp(alpha, 0, 1).toFixed(3)})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyGlassSettings = (root, s) => {
|
||||||
|
const panelColor = colorParts(s.modalBg, defaultSettings.modalBg);
|
||||||
|
const focusColor = colorParts(s.modalFocus, defaultSettings.modalFocus);
|
||||||
|
const controlColor = colorParts(s.modalElement, s.modalFocus || defaultSettings.modalElement);
|
||||||
|
const outlineColor = colorParts(s.modalBorder, s.modalElementOutline || defaultSettings.modalBorder);
|
||||||
|
const controlOutlineColor = colorParts(s.modalElementOutline, s.modalBorder || defaultSettings.modalElementOutline);
|
||||||
|
const modalBgAlpha = alphaValue(s.modalBgAlpha, defaultSettings.modalBgAlpha);
|
||||||
|
const modalFocusAlpha = alphaValue(s.modalFocusAlpha, defaultSettings.modalFocusAlpha);
|
||||||
|
const panelAlpha = clamp(0.24 + modalBgAlpha * 0.48, 0.32, 0.88);
|
||||||
|
const panelStrongAlpha = clamp(panelAlpha + 0.1, 0.42, 0.92);
|
||||||
|
const panelSoftAlpha = clamp(panelAlpha - 0.16, 0.2, 0.72);
|
||||||
|
const sectionAlpha = clamp(modalFocusAlpha * 0.6, 0.04, 0.42);
|
||||||
|
const controlAlpha = clamp(0.12 + modalFocusAlpha * 0.9, 0.16, 0.66);
|
||||||
|
const controlHoverAlpha = clamp(controlAlpha + 0.08, 0.22, 0.74);
|
||||||
|
const outlineAlpha = clamp(0.055 + modalFocusAlpha * 0.18, 0.065, 0.2);
|
||||||
|
const controlOutlineAlpha = clamp(0.045 + modalFocusAlpha * 0.12, 0.055, 0.16);
|
||||||
|
|
||||||
|
const panelBg = rgba(panelColor, panelAlpha);
|
||||||
|
const panelBgStrong = rgba(panelColor, panelStrongAlpha);
|
||||||
|
const panelBgSoft = rgba(panelColor, panelSoftAlpha);
|
||||||
|
const sectionBg = rgba(focusColor, sectionAlpha);
|
||||||
|
const outline = rgba(outlineColor, outlineAlpha);
|
||||||
|
const outlineBright = rgba(outlineColor, clamp(outlineAlpha + 0.05, 0.08, 0.26));
|
||||||
|
const outlineMid = rgba(outlineColor, clamp(outlineAlpha + 0.015, 0.07, 0.22));
|
||||||
|
const outlineDim = rgba(outlineColor, clamp(outlineAlpha * 0.62, 0.04, 0.16));
|
||||||
|
const controlBg = rgba(controlColor, controlAlpha);
|
||||||
|
const controlHover = rgba(focusColor, controlHoverAlpha);
|
||||||
|
const controlShadow = rgba(controlOutlineColor, controlOutlineAlpha);
|
||||||
|
|
||||||
|
root.style.setProperty("--nodedc-glass-panel-bg", panelBg);
|
||||||
|
root.style.setProperty("--nodedc-glass-panel-bg-strong", panelBgStrong);
|
||||||
|
root.style.setProperty("--nodedc-glass-panel-bg-soft", panelBgSoft);
|
||||||
|
root.style.setProperty(
|
||||||
|
"--nodedc-glass-panel-surface",
|
||||||
|
`linear-gradient(180deg, rgba(255, 255, 255, 0.052) 0%, rgba(255, 255, 255, 0.014) 100%), ${panelBg}`
|
||||||
|
);
|
||||||
|
root.style.setProperty(
|
||||||
|
"--nodedc-glass-panel-surface-strong",
|
||||||
|
`linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.016) 100%), ${panelBgStrong}`
|
||||||
|
);
|
||||||
|
root.style.setProperty(
|
||||||
|
"--nodedc-glass-section-bg",
|
||||||
|
`linear-gradient(180deg, rgba(255, 255, 255, 0.038) 0%, rgba(255, 255, 255, 0.01) 100%), ${sectionBg}`
|
||||||
|
);
|
||||||
|
root.style.setProperty("--nodedc-glass-outline", outline);
|
||||||
|
root.style.setProperty(
|
||||||
|
"--nodedc-glass-outline-gradient",
|
||||||
|
`linear-gradient(180deg, ${outlineBright} 0%, ${outlineMid} 56%, ${outlineDim} 100%)`
|
||||||
|
);
|
||||||
|
root.style.setProperty("--nodedc-glass-panel-shadow", `inset 0 1px 0 ${outlineDim}, 0 22px 72px rgba(0, 0, 0, 0.42)`);
|
||||||
|
root.style.setProperty(
|
||||||
|
"--nodedc-glass-control-bg",
|
||||||
|
`linear-gradient(180deg, rgba(255, 255, 255, 0.052) 0%, rgba(255, 255, 255, 0.018) 100%), ${controlBg}`
|
||||||
|
);
|
||||||
|
root.style.setProperty(
|
||||||
|
"--nodedc-glass-control-hover",
|
||||||
|
`linear-gradient(180deg, rgba(255, 255, 255, 0.075) 0%, rgba(255, 255, 255, 0.026) 100%), ${controlHover}`
|
||||||
|
);
|
||||||
|
root.style.setProperty("--nodedc-glass-control-shadow", `inset 0 1px 0 ${controlShadow}`);
|
||||||
|
root.style.setProperty("--nodedc-header-dropdown-bg", panelBgStrong);
|
||||||
|
root.style.setProperty("--nodedc-header-dropdown-item-bg", controlBg);
|
||||||
|
root.style.setProperty("--nodedc-header-dropdown-item-hover-bg", controlHover);
|
||||||
|
root.style.setProperty("--nodedc-header-dropdown-item-active-bg", s.toolbarBgActive);
|
||||||
|
root.style.setProperty("--nodedc-header-dropdown-item-active-color", readableTextColor(s.toolbarBgActive));
|
||||||
|
};
|
||||||
|
|
||||||
const applySettings = (s) => {
|
const applySettings = (s) => {
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
root.style.setProperty("--bg-outer", s.bgOuter);
|
root.style.setProperty("--bg-outer", s.bgOuter);
|
||||||
|
|
@ -72,13 +219,26 @@ const applySettings = (s) => {
|
||||||
root.style.setProperty("--project-btn-border", s.projectBtnBorder);
|
root.style.setProperty("--project-btn-border", s.projectBtnBorder);
|
||||||
root.style.setProperty("--project-btn-hover", s.projectBtnHover);
|
root.style.setProperty("--project-btn-hover", s.projectBtnHover);
|
||||||
root.style.setProperty("--modal-btn-primary", s.modalBtnPrimary);
|
root.style.setProperty("--modal-btn-primary", s.modalBtnPrimary);
|
||||||
|
root.style.setProperty("--modal-btn-primary-contrast", readableTextColor(s.modalBtnPrimary));
|
||||||
root.style.setProperty("--modal-btn-secondary", s.modalBtnSecondary);
|
root.style.setProperty("--modal-btn-secondary", s.modalBtnSecondary);
|
||||||
root.style.setProperty("--loader-color", s.loaderColor);
|
root.style.setProperty("--loader-color", s.loaderColor);
|
||||||
root.style.setProperty("--template-glow-strength", `${s.templateGlow}%`);
|
root.style.setProperty("--template-glow-strength", `${s.templateGlow}%`);
|
||||||
root.style.setProperty("--toolbar-bg", s.toolbarBg);
|
root.style.setProperty("--toolbar-bg", s.toolbarBg);
|
||||||
root.style.setProperty("--toolbar-bg-active", s.toolbarBgActive);
|
root.style.setProperty("--toolbar-bg-active", s.toolbarBgActive);
|
||||||
|
root.style.setProperty("--toolbar-bg-active-contrast", readableTextColor(s.toolbarBgActive));
|
||||||
root.style.setProperty("--toolbar-border", s.toolbarBorder);
|
root.style.setProperty("--toolbar-border", s.toolbarBorder);
|
||||||
root.style.setProperty("--toolbar-outline", s.toolbarOutline);
|
root.style.setProperty("--toolbar-outline", s.toolbarOutline);
|
||||||
|
const toolbarMinRaw = Number(s.toolbarMinSize ?? defaultSettings.toolbarMinSize);
|
||||||
|
const toolbarMaxRaw = Number(s.toolbarMaxSize ?? defaultSettings.toolbarMaxSize);
|
||||||
|
const toolbarLensRaw = Number(s.toolbarLensCount ?? defaultSettings.toolbarLensCount);
|
||||||
|
const toolbarMinSize = clamp(Number.isFinite(toolbarMinRaw) ? toolbarMinRaw : defaultSettings.toolbarMinSize, 18, 88);
|
||||||
|
const toolbarMaxSize = Math.max(toolbarMinSize, clamp(Number.isFinite(toolbarMaxRaw) ? toolbarMaxRaw : defaultSettings.toolbarMaxSize, 18, 96));
|
||||||
|
const toolbarLensCount = Math.max(1, Math.min(15, Math.round(Number.isFinite(toolbarLensRaw) ? toolbarLensRaw : defaultSettings.toolbarLensCount)));
|
||||||
|
root.style.setProperty("--tb-size", `${toolbarMinSize}px`);
|
||||||
|
root.style.setProperty("--tb-min-size", `${toolbarMinSize}px`);
|
||||||
|
root.style.setProperty("--tb-max-size", `${toolbarMaxSize}px`);
|
||||||
|
root.style.setProperty("--tb-lens-count", `${toolbarLensCount % 2 === 0 ? toolbarLensCount + 1 : toolbarLensCount}`);
|
||||||
|
root.style.setProperty("--tb-autohide", s.toolbarAutoHide ? "1" : "0");
|
||||||
const bgAlphaPct = `${(s.modalBgAlpha ?? 1) * 100}%`;
|
const bgAlphaPct = `${(s.modalBgAlpha ?? 1) * 100}%`;
|
||||||
const focusAlphaPct = `${(s.modalFocusAlpha ?? 1) * 100}%`;
|
const focusAlphaPct = `${(s.modalFocusAlpha ?? 1) * 100}%`;
|
||||||
root.style.setProperty("--modal-bg", s.modalBg);
|
root.style.setProperty("--modal-bg", s.modalBg);
|
||||||
|
|
@ -89,6 +249,7 @@ const applySettings = (s) => {
|
||||||
root.style.setProperty("--modal-element", s.modalElement);
|
root.style.setProperty("--modal-element", s.modalElement);
|
||||||
root.style.setProperty("--modal-element-outline", s.modalElementOutline);
|
root.style.setProperty("--modal-element-outline", s.modalElementOutline);
|
||||||
root.style.setProperty("--modal-radius", s.modalRadius);
|
root.style.setProperty("--modal-radius", s.modalRadius);
|
||||||
|
applyGlassSettings(root, s);
|
||||||
root.style.setProperty("--border", s.border);
|
root.style.setProperty("--border", s.border);
|
||||||
root.style.setProperty("--text", s.text);
|
root.style.setProperty("--text", s.text);
|
||||||
root.style.setProperty("--panel", s.panel);
|
root.style.setProperty("--panel", s.panel);
|
||||||
|
|
@ -108,11 +269,27 @@ const applySettings = (s) => {
|
||||||
root.style.setProperty("--measure-label", s.measureLabel);
|
root.style.setProperty("--measure-label", s.measureLabel);
|
||||||
root.style.setProperty("--measure-label-text", s.measureLabelText);
|
root.style.setProperty("--measure-label-text", s.measureLabelText);
|
||||||
root.style.setProperty("--measure-dot", s.measureDot);
|
root.style.setProperty("--measure-dot", s.measureDot);
|
||||||
|
root.style.setProperty("--section-axis-x", s.sectionAxisX);
|
||||||
|
root.style.setProperty("--section-axis-y", s.sectionAxisY);
|
||||||
|
root.style.setProperty("--section-axis-z", s.sectionAxisZ);
|
||||||
|
root.style.setProperty("--section-gizmo-diameter", s.sectionGizmoDiameter);
|
||||||
|
root.style.setProperty("--section-gizmo-thickness", s.sectionGizmoThickness);
|
||||||
|
root.style.setProperty("--section-plane-fill", s.sectionPlaneFill);
|
||||||
|
root.style.setProperty("--section-plane-alpha", s.sectionPlaneAlpha);
|
||||||
|
root.style.setProperty("--section-plane-edge", s.sectionPlaneEdge);
|
||||||
|
root.style.setProperty("--section-plane-edge-alpha", s.sectionPlaneEdgeAlpha);
|
||||||
|
root.style.setProperty("--comment-target-active", s.commentTargetActiveColor);
|
||||||
|
root.style.setProperty("--comment-target-active-alpha", s.commentTargetActiveAlpha);
|
||||||
|
root.style.setProperty("--comment-target-active-size", `${s.commentTargetActiveSize}px`);
|
||||||
|
root.style.setProperty("--comment-target-passive", s.commentTargetPassiveColor);
|
||||||
|
root.style.setProperty("--comment-target-passive-alpha", s.commentTargetPassiveAlpha);
|
||||||
|
root.style.setProperty("--comment-target-passive-size", `${s.commentTargetPassiveSize}px`);
|
||||||
// подсветка объектов
|
// подсветка объектов
|
||||||
root.style.setProperty("--highlight-color", s.highlight);
|
root.style.setProperty("--highlight-color", s.highlight);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveSettings = (s) => {
|
const saveSettings = (s) => {
|
||||||
|
if (isReadonlySettingsContext()) return;
|
||||||
try {
|
try {
|
||||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(s));
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(s));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -121,6 +298,9 @@ const saveSettings = (s) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadSettings = () => {
|
const loadSettings = () => {
|
||||||
|
if (isReadonlySettingsContext()) {
|
||||||
|
return { ...projectSettings };
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// purge legacy keys so старые палитры не мешали
|
// purge legacy keys so старые палитры не мешали
|
||||||
LEGACY_KEYS.forEach((k) => localStorage.removeItem(k));
|
LEGACY_KEYS.forEach((k) => localStorage.removeItem(k));
|
||||||
|
|
@ -186,11 +366,20 @@ export function createSettingsMenu({ panel, controls = {}, onChange = null, onSh
|
||||||
header.innerHTML = `<span class="settings-title">Настройки</span>`;
|
header.innerHTML = `<span class="settings-title">Настройки</span>`;
|
||||||
const closeBtn = document.createElement("button");
|
const closeBtn = document.createElement("button");
|
||||||
closeBtn.className = "settings-close";
|
closeBtn.className = "settings-close";
|
||||||
closeBtn.textContent = "—";
|
closeBtn.setAttribute("aria-label", "Закрыть настройки");
|
||||||
|
closeBtn.innerHTML = `
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
closeBtn.addEventListener("click", hide);
|
closeBtn.addEventListener("click", hide);
|
||||||
header.appendChild(closeBtn);
|
header.appendChild(closeBtn);
|
||||||
panel.appendChild(header);
|
panel.appendChild(header);
|
||||||
|
|
||||||
|
const body = document.createElement("div");
|
||||||
|
body.className = "settings-panel-body";
|
||||||
|
panel.appendChild(body);
|
||||||
|
|
||||||
const section = (title) => {
|
const section = (title) => {
|
||||||
const box = document.createElement("div");
|
const box = document.createElement("div");
|
||||||
box.className = "settings-section";
|
box.className = "settings-section";
|
||||||
|
|
@ -202,29 +391,103 @@ export function createSettingsMenu({ panel, controls = {}, onChange = null, onSh
|
||||||
};
|
};
|
||||||
|
|
||||||
const addColor = (parent, label, key) => {
|
const addColor = (parent, label, key) => {
|
||||||
const isHex = (val) => /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test((val || "").trim());
|
|
||||||
const row = document.createElement("div");
|
const row = document.createElement("div");
|
||||||
row.className = "color-row";
|
row.className = "color-row";
|
||||||
const lbl = document.createElement("label");
|
const lbl = document.createElement("div");
|
||||||
|
lbl.textContent = label;
|
||||||
|
const control = createColorControl({
|
||||||
|
value: state[key],
|
||||||
|
onChange: (nextValue) => {
|
||||||
|
setVal(key, nextValue);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
row.appendChild(lbl);
|
||||||
|
row.appendChild(control);
|
||||||
|
parent.appendChild(row);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addSettingsSlider = ({
|
||||||
|
parent,
|
||||||
|
label,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
min = 0,
|
||||||
|
max = 100,
|
||||||
|
step = 1,
|
||||||
|
formatValue = (nextValue) => String(nextValue),
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
|
const slider = createSliderControl({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
step,
|
||||||
|
className: "env-range-control",
|
||||||
|
showValue: true,
|
||||||
|
formatValue,
|
||||||
|
onChange: (nextValue) => {
|
||||||
|
if (typeof onChange === "function") {
|
||||||
|
onChange(nextValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setVal(key, nextValue);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
parent.appendChild(slider);
|
||||||
|
return slider;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addNumber = ({
|
||||||
|
parent,
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
min = 0,
|
||||||
|
max,
|
||||||
|
step = 1,
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
|
const row = document.createElement("div");
|
||||||
|
row.className = "color-row";
|
||||||
|
const lbl = document.createElement("div");
|
||||||
lbl.textContent = label;
|
lbl.textContent = label;
|
||||||
const input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.type = "color";
|
input.className = "env-number-field";
|
||||||
input.value = isHex(state[key]) ? state[key] : "#ffffff";
|
input.type = "number";
|
||||||
const hex = document.createElement("input");
|
input.value = value;
|
||||||
hex.type = "text";
|
input.min = min;
|
||||||
hex.value = state[key];
|
input.step = step;
|
||||||
input.addEventListener("change", (e) => {
|
if (max !== undefined) {
|
||||||
hex.value = e.target.value;
|
input.max = max;
|
||||||
setVal(key, e.target.value);
|
}
|
||||||
});
|
input.addEventListener("input", () => {
|
||||||
hex.addEventListener("change", (e) => {
|
const nextValue = Number(input.value);
|
||||||
input.value = e.target.value;
|
if (Number.isFinite(nextValue)) {
|
||||||
setVal(key, e.target.value);
|
onChange?.(nextValue);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
row.appendChild(lbl);
|
row.appendChild(lbl);
|
||||||
row.appendChild(input);
|
row.appendChild(input);
|
||||||
row.appendChild(hex);
|
|
||||||
parent.appendChild(row);
|
parent.appendChild(row);
|
||||||
|
return input;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addBoolean = (parent, label, key) => {
|
||||||
|
const row = document.createElement("label");
|
||||||
|
row.className = "checkbox-row";
|
||||||
|
const text = document.createElement("span");
|
||||||
|
text.className = "checkbox-row__label";
|
||||||
|
text.textContent = label;
|
||||||
|
const chk = document.createElement("input");
|
||||||
|
chk.type = "checkbox";
|
||||||
|
chk.checked = !!state[key];
|
||||||
|
chk.addEventListener("change", () => {
|
||||||
|
setVal(key, chk.checked);
|
||||||
|
});
|
||||||
|
row.appendChild(text);
|
||||||
|
row.appendChild(chk);
|
||||||
|
parent.appendChild(row);
|
||||||
|
return chk;
|
||||||
};
|
};
|
||||||
|
|
||||||
const font = section("Фон");
|
const font = section("Фон");
|
||||||
|
|
@ -233,157 +496,302 @@ export function createSettingsMenu({ panel, controls = {}, onChange = null, onSh
|
||||||
addColor(font, "Фон холста низ", "canvasBottom");
|
addColor(font, "Фон холста низ", "canvasBottom");
|
||||||
addColor(font, "Фон загрузки верх", "loadingTop");
|
addColor(font, "Фон загрузки верх", "loadingTop");
|
||||||
addColor(font, "Фон загрузки низ", "loadingBottom");
|
addColor(font, "Фон загрузки низ", "loadingBottom");
|
||||||
panel.appendChild(font);
|
body.appendChild(font);
|
||||||
|
|
||||||
const buttons = section("Кнопки");
|
const buttons = section("Кнопки");
|
||||||
addColor(buttons, "Плюс", "plus");
|
addColor(buttons, "Плюс", "plus");
|
||||||
addColor(buttons, "Кнопки (заливка)", "templateFill");
|
addColor(buttons, "Кнопки (заливка)", "templateFill");
|
||||||
addColor(buttons, "Кнопки (бордер)", "templateOutline");
|
addColor(buttons, "Кнопки (бордер)", "templateOutline");
|
||||||
addColor(buttons, "Кнопки (outline hover)", "templateOutlineHover");
|
addColor(buttons, "Кнопки (outline hover)", "templateOutlineHover");
|
||||||
const brightnessSlider = createSliderControl({
|
addSettingsSlider({
|
||||||
label: "Яркость подсветки",
|
parent: buttons,
|
||||||
value: Number(state.templateGlow ?? 80),
|
label: "Яркость подсветки",
|
||||||
min: 0,
|
key: "templateGlow",
|
||||||
max: 100,
|
value: Number(state.templateGlow ?? 80),
|
||||||
step: 1,
|
min: 0,
|
||||||
onChange: (val) => setVal("templateGlow", val),
|
max: 100,
|
||||||
});
|
step: 1,
|
||||||
buttons.appendChild(brightnessSlider);
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
panel.appendChild(buttons);
|
});
|
||||||
|
body.appendChild(buttons);
|
||||||
|
|
||||||
const projectButtons = section("Кнопки проектов");
|
const projectButtons = section("Кнопки проектов");
|
||||||
addColor(projectButtons, "Проекты (заливка)", "projectBtnFill");
|
addColor(projectButtons, "Проекты (заливка)", "projectBtnFill");
|
||||||
addColor(projectButtons, "Проекты (бордер)", "projectBtnBorder");
|
addColor(projectButtons, "Проекты (бордер)", "projectBtnBorder");
|
||||||
addColor(projectButtons, "Проекты (hover)", "projectBtnHover");
|
addColor(projectButtons, "Проекты (hover)", "projectBtnHover");
|
||||||
panel.appendChild(projectButtons);
|
body.appendChild(projectButtons);
|
||||||
|
|
||||||
const modalButtons = section("Кнопки модалок");
|
const modalButtons = section("Кнопки модалок");
|
||||||
addColor(modalButtons, "Модальная primary", "modalBtnPrimary");
|
addColor(modalButtons, "Модальная primary", "modalBtnPrimary");
|
||||||
addColor(modalButtons, "Модальная secondary", "modalBtnSecondary");
|
addColor(modalButtons, "Модальная secondary", "modalBtnSecondary");
|
||||||
addColor(modalButtons, "Лоудер", "loaderColor");
|
addColor(modalButtons, "Лоудер", "loaderColor");
|
||||||
panel.appendChild(modalButtons);
|
body.appendChild(modalButtons);
|
||||||
|
|
||||||
const toolbar = section("Toolbar");
|
const toolbar = section("Toolbar");
|
||||||
addColor(toolbar, "Фон", "toolbarBg");
|
addColor(toolbar, "Фон", "toolbarBg");
|
||||||
addColor(toolbar, "Актив", "toolbarBgActive");
|
addColor(toolbar, "Актив", "toolbarBgActive");
|
||||||
addColor(toolbar, "Бордер", "toolbarBorder");
|
addColor(toolbar, "Бордер", "toolbarBorder");
|
||||||
addColor(toolbar, "Outline", "toolbarOutline");
|
addColor(toolbar, "Outline", "toolbarOutline");
|
||||||
panel.appendChild(toolbar);
|
addSettingsSlider({
|
||||||
|
parent: toolbar,
|
||||||
|
label: "Минимальный размер",
|
||||||
|
value: Math.max(18, Math.min(42, Number(state.toolbarMinSize ?? defaultSettings.toolbarMinSize))),
|
||||||
|
min: 18,
|
||||||
|
max: 42,
|
||||||
|
step: 1,
|
||||||
|
formatValue: (val) => `${Math.round(val)}px`,
|
||||||
|
onChange: (val) => {
|
||||||
|
const next = Math.max(18, Math.min(42, Math.round(Number(val))));
|
||||||
|
setVal("toolbarMinSize", next);
|
||||||
|
if (Number(state.toolbarMaxSize) < next) {
|
||||||
|
setVal("toolbarMaxSize", next);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: toolbar,
|
||||||
|
label: "Максимальный размер",
|
||||||
|
value: Math.max(28, Math.min(88, Number(state.toolbarMaxSize ?? defaultSettings.toolbarMaxSize))),
|
||||||
|
min: 28,
|
||||||
|
max: 88,
|
||||||
|
step: 1,
|
||||||
|
formatValue: (val) => `${Math.round(val)}px`,
|
||||||
|
onChange: (val) => {
|
||||||
|
const minSize = Math.max(18, Math.min(42, Number(state.toolbarMinSize ?? defaultSettings.toolbarMinSize)));
|
||||||
|
setVal("toolbarMaxSize", Math.max(minSize, Math.min(88, Math.round(Number(val)))));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: toolbar,
|
||||||
|
label: "Линза",
|
||||||
|
value: Math.max(1, Math.min(13, Number(state.toolbarLensCount ?? defaultSettings.toolbarLensCount))),
|
||||||
|
min: 1,
|
||||||
|
max: 13,
|
||||||
|
step: 2,
|
||||||
|
formatValue: (val) => `${Math.round(val)} иконок`,
|
||||||
|
onChange: (val) => {
|
||||||
|
const next = Math.max(1, Math.min(13, Math.round(Number(val))));
|
||||||
|
setVal("toolbarLensCount", next % 2 === 0 ? next + 1 : next);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addBoolean(toolbar, "Автоскрытие", "toolbarAutoHide");
|
||||||
|
body.appendChild(toolbar);
|
||||||
|
|
||||||
const navCube = section("NavCube");
|
const navCube = section("NavCube");
|
||||||
addColor(navCube, "Грани", "navCubeBase");
|
addColor(navCube, "Грани", "navCubeBase");
|
||||||
addColor(navCube, "Hover", "navCubeHover");
|
addColor(navCube, "Hover", "navCubeHover");
|
||||||
addColor(navCube, "Текст", "navCubeText");
|
addColor(navCube, "Текст", "navCubeText");
|
||||||
addColor(navCube, "Рёбра", "navCubeEdge");
|
addColor(navCube, "Рёбра", "navCubeEdge");
|
||||||
const edgeAlphaRow = document.createElement("div");
|
addSettingsSlider({
|
||||||
edgeAlphaRow.className = "color-row";
|
parent: navCube,
|
||||||
const edgeAlphaLbl = document.createElement("label");
|
label: "Прозрачность рёбер",
|
||||||
edgeAlphaLbl.textContent = "Прозрачность рёбер (0-1)";
|
value: Math.round(Math.max(0, Math.min(1, Number(state.navCubeEdgeAlpha ?? 0.6))) * 100),
|
||||||
const edgeAlphaInput = document.createElement("input");
|
min: 0,
|
||||||
edgeAlphaInput.type = "number";
|
max: 100,
|
||||||
edgeAlphaInput.step = "0.05";
|
step: 5,
|
||||||
edgeAlphaInput.min = "0";
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
edgeAlphaInput.max = "1";
|
onChange: (val) => {
|
||||||
edgeAlphaInput.value = state.navCubeEdgeAlpha;
|
setVal("navCubeEdgeAlpha", Math.max(0, Math.min(1, Number(val) / 100)));
|
||||||
edgeAlphaInput.addEventListener("change", () => {
|
},
|
||||||
const v = Math.min(1, Math.max(0, parseFloat(edgeAlphaInput.value) || 0));
|
|
||||||
edgeAlphaInput.value = v;
|
|
||||||
setVal("navCubeEdgeAlpha", v);
|
|
||||||
});
|
});
|
||||||
edgeAlphaRow.appendChild(edgeAlphaLbl);
|
body.appendChild(navCube);
|
||||||
edgeAlphaRow.appendChild(edgeAlphaInput);
|
|
||||||
edgeAlphaRow.appendChild(document.createElement("div"));
|
const sectionCut = section("Разрез / сечение");
|
||||||
navCube.appendChild(edgeAlphaRow);
|
addColor(sectionCut, "Ось X", "sectionAxisX");
|
||||||
panel.appendChild(navCube);
|
addColor(sectionCut, "Ось Y", "sectionAxisY");
|
||||||
|
addColor(sectionCut, "Ось Z", "sectionAxisZ");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: sectionCut,
|
||||||
|
label: "Диаметр гизмо",
|
||||||
|
value: Math.round(Math.max(0.5, Math.min(1.8, Number(state.sectionGizmoDiameter ?? 1))) * 100),
|
||||||
|
min: 50,
|
||||||
|
max: 180,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("sectionGizmoDiameter", Math.max(0.5, Math.min(1.8, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: sectionCut,
|
||||||
|
label: "Толщина гизмо",
|
||||||
|
value: Math.round(Math.max(0.5, Math.min(2.5, Number(state.sectionGizmoThickness ?? 1))) * 100),
|
||||||
|
min: 50,
|
||||||
|
max: 250,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("sectionGizmoThickness", Math.max(0.5, Math.min(2.5, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addColor(sectionCut, "Плоскость", "sectionPlaneFill");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: sectionCut,
|
||||||
|
label: "Прозрачность плоскости",
|
||||||
|
value: Math.round(Math.max(0, Math.min(1, Number(state.sectionPlaneAlpha ?? 0.32))) * 100),
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("sectionPlaneAlpha", Math.max(0, Math.min(1, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addColor(sectionCut, "Обводка", "sectionPlaneEdge");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: sectionCut,
|
||||||
|
label: "Прозрачность обводки",
|
||||||
|
value: Math.round(Math.max(0, Math.min(1, Number(state.sectionPlaneEdgeAlpha ?? 0.8))) * 100),
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("sectionPlaneEdgeAlpha", Math.max(0, Math.min(1, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
body.appendChild(sectionCut);
|
||||||
|
|
||||||
|
const commentTargets = section("Таргеты комментариев");
|
||||||
|
addColor(commentTargets, "Активный: цвет", "commentTargetActiveColor");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: commentTargets,
|
||||||
|
label: "Активный: прозрачность",
|
||||||
|
value: Math.round(Math.max(0, Math.min(1, Number(state.commentTargetActiveAlpha ?? 1))) * 100),
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("commentTargetActiveAlpha", Math.max(0, Math.min(1, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: commentTargets,
|
||||||
|
label: "Активный: размер",
|
||||||
|
value: Math.max(14, Math.min(64, Number(state.commentTargetActiveSize ?? 30))),
|
||||||
|
min: 14,
|
||||||
|
max: 64,
|
||||||
|
step: 1,
|
||||||
|
formatValue: (val) => `${Math.round(val)}px`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("commentTargetActiveSize", Math.max(14, Math.min(64, Math.round(Number(val)))));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addColor(commentTargets, "Пассивный: цвет", "commentTargetPassiveColor");
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: commentTargets,
|
||||||
|
label: "Пассивный: прозрачность",
|
||||||
|
value: Math.round(Math.max(0, Math.min(1, Number(state.commentTargetPassiveAlpha ?? 0.58))) * 100),
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 5,
|
||||||
|
formatValue: (val) => `${Math.round(val)}%`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("commentTargetPassiveAlpha", Math.max(0, Math.min(1, Number(val) / 100)));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
addSettingsSlider({
|
||||||
|
parent: commentTargets,
|
||||||
|
label: "Пассивный: размер",
|
||||||
|
value: Math.max(12, Math.min(48, Number(state.commentTargetPassiveSize ?? 22))),
|
||||||
|
min: 12,
|
||||||
|
max: 48,
|
||||||
|
step: 1,
|
||||||
|
formatValue: (val) => `${Math.round(val)}px`,
|
||||||
|
onChange: (val) => {
|
||||||
|
setVal("commentTargetPassiveSize", Math.max(12, Math.min(48, Math.round(Number(val)))));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
body.appendChild(commentTargets);
|
||||||
|
|
||||||
const measure = section("Линейка");
|
const measure = section("Линейка");
|
||||||
addColor(measure, "Линия/бордер", "measureLine");
|
addColor(measure, "Линия/бордер", "measureLine");
|
||||||
addColor(measure, "Плашка", "measureLabel");
|
addColor(measure, "Плашка", "measureLabel");
|
||||||
addColor(measure, "Текст плашки", "measureLabelText");
|
addColor(measure, "Текст плашки", "measureLabelText");
|
||||||
addColor(measure, "Кружок", "measureDot");
|
addColor(measure, "Кружок", "measureDot");
|
||||||
panel.appendChild(measure);
|
body.appendChild(measure);
|
||||||
|
|
||||||
const viewport = section("Viewport");
|
const viewport = section("Viewport");
|
||||||
const addCheck = (label, checked, handler) => {
|
const addCheck = (label, checked, handler) => {
|
||||||
const row = document.createElement("div");
|
const row = document.createElement("label");
|
||||||
row.className = "checkbox-row";
|
row.className = "checkbox-row";
|
||||||
|
const text = document.createElement("span");
|
||||||
|
text.className = "checkbox-row__label";
|
||||||
|
text.textContent = label;
|
||||||
const chk = document.createElement("input");
|
const chk = document.createElement("input");
|
||||||
chk.type = "checkbox";
|
chk.type = "checkbox";
|
||||||
chk.checked = checked;
|
chk.checked = checked;
|
||||||
chk.addEventListener("change", () => handler(chk.checked));
|
chk.addEventListener("change", () => handler(chk.checked));
|
||||||
const lbl = document.createElement("label");
|
row.appendChild(text);
|
||||||
lbl.textContent = label;
|
|
||||||
row.appendChild(chk);
|
row.appendChild(chk);
|
||||||
row.appendChild(lbl);
|
|
||||||
viewport.appendChild(row);
|
viewport.appendChild(row);
|
||||||
};
|
};
|
||||||
if (controls.toggleEdges) addCheck("Рёбра", controls.toggleEdges.checked, (v) => { controls.toggleEdges.checked = v; controls.toggleEdges.dispatchEvent(new Event("change")); });
|
if (controls.toggleEdges) addCheck("Рёбра", controls.toggleEdges.checked, (v) => { controls.toggleEdges.checked = v; controls.toggleEdges.dispatchEvent(new Event("change")); });
|
||||||
if (controls.toggleTransparent) addCheck("Прозрачный фон", controls.toggleTransparent.checked, (v) => { controls.toggleTransparent.checked = v; controls.toggleTransparent.dispatchEvent(new Event("change")); });
|
if (controls.toggleTransparent) addCheck("Прозрачный фон", controls.toggleTransparent.checked, (v) => { controls.toggleTransparent.checked = v; controls.toggleTransparent.dispatchEvent(new Event("change")); });
|
||||||
if (controls.addMode) addCheck("Добавлять в сцену", controls.addMode.checked, (v) => { controls.addMode.checked = v; });
|
if (controls.addMode) addCheck("Добавлять в сцену", controls.addMode.checked, (v) => { controls.addMode.checked = v; });
|
||||||
panel.appendChild(viewport);
|
body.appendChild(viewport);
|
||||||
|
|
||||||
const modals = section("Модальные окна");
|
const modals = section("Модальные окна");
|
||||||
addColor(modals, "Основной фон", "modalBg");
|
addColor(modals, "Основной фон", "modalBg");
|
||||||
addColor(modals, "Фокусный фон", "modalFocus");
|
addColor(modals, "Фокусный фон", "modalFocus");
|
||||||
const modalBgAlphaRow = createSliderControl({
|
addSettingsSlider({
|
||||||
|
parent: modals,
|
||||||
label: "Прозрачность основного фона",
|
label: "Прозрачность основного фона",
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1,
|
max: 1,
|
||||||
step: 0.05,
|
step: 0.05,
|
||||||
value: parseFloat(state.modalBgAlpha ?? 1),
|
value: parseFloat(state.modalBgAlpha ?? 1),
|
||||||
|
formatValue: (val) => `${Math.round(Number(val) * 100)}%`,
|
||||||
onChange: (val) => {
|
onChange: (val) => {
|
||||||
const num = Math.max(0, Math.min(1, parseFloat(val)));
|
const num = Math.max(0, Math.min(1, parseFloat(val)));
|
||||||
setVal("modalBgAlpha", num);
|
setVal("modalBgAlpha", num);
|
||||||
document.documentElement.style.setProperty("--modal-bg-alpha", `${num * 100}%`);
|
document.documentElement.style.setProperty("--modal-bg-alpha", `${num * 100}%`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
modals.appendChild(modalBgAlphaRow);
|
|
||||||
|
|
||||||
const modalFocusAlphaRow = createSliderControl({
|
addSettingsSlider({
|
||||||
|
parent: modals,
|
||||||
label: "Прозрачность фокусного фона",
|
label: "Прозрачность фокусного фона",
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1,
|
max: 1,
|
||||||
step: 0.05,
|
step: 0.05,
|
||||||
value: parseFloat(state.modalFocusAlpha ?? 1),
|
value: parseFloat(state.modalFocusAlpha ?? 1),
|
||||||
|
formatValue: (val) => `${Math.round(Number(val) * 100)}%`,
|
||||||
onChange: (val) => {
|
onChange: (val) => {
|
||||||
const num = Math.max(0, Math.min(1, parseFloat(val)));
|
const num = Math.max(0, Math.min(1, parseFloat(val)));
|
||||||
setVal("modalFocusAlpha", num);
|
setVal("modalFocusAlpha", num);
|
||||||
document.documentElement.style.setProperty("--modal-focus-alpha", `${num * 100}%`);
|
document.documentElement.style.setProperty("--modal-focus-alpha", `${num * 100}%`);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
modals.appendChild(modalFocusAlphaRow);
|
|
||||||
|
|
||||||
addColor(modals, "Аутлайн", "modalBorder");
|
addColor(modals, "Аутлайн", "modalBorder");
|
||||||
addColor(modals, "Фон элемента", "modalElement");
|
addColor(modals, "Контролы", "modalElement");
|
||||||
addColor(modals, "Аутлайн элемента", "modalElementOutline");
|
addColor(modals, "Аутлайн элемента", "modalElementOutline");
|
||||||
const radiusRow = document.createElement("div");
|
addNumber({
|
||||||
radiusRow.className = "color-row";
|
parent: modals,
|
||||||
const radiusLbl = document.createElement("label");
|
label: "Радиус",
|
||||||
radiusLbl.textContent = "Радиус";
|
value: parseInt(getComputedStyle(document.documentElement).getPropertyValue("--modal-radius")) || 14,
|
||||||
const radiusInput = document.createElement("input");
|
min: 0,
|
||||||
radiusInput.type = "number";
|
max: 48,
|
||||||
radiusInput.value = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--modal-radius")) || 14;
|
step: 1,
|
||||||
radiusInput.addEventListener("change", () => {
|
onChange: (nextValue) => {
|
||||||
const val = `${radiusInput.value}px`;
|
const val = `${Math.max(0, Math.min(48, Math.round(nextValue)))}px`;
|
||||||
document.documentElement.style.setProperty("--modal-radius", val);
|
setVal("modalRadius", val);
|
||||||
setVal("modalRadius", val);
|
},
|
||||||
});
|
});
|
||||||
radiusRow.appendChild(radiusLbl);
|
body.appendChild(modals);
|
||||||
radiusRow.appendChild(radiusInput);
|
|
||||||
radiusRow.appendChild(document.createElement("div"));
|
|
||||||
modals.appendChild(radiusRow);
|
|
||||||
panel.appendChild(modals);
|
|
||||||
|
|
||||||
const cube = section("Выделение объектов");
|
const cube = section("Выделение объектов");
|
||||||
addColor(cube, "Подсветка объектов", "highlight");
|
addColor(cube, "Подсветка объектов", "highlight");
|
||||||
panel.appendChild(cube);
|
body.appendChild(cube);
|
||||||
};
|
};
|
||||||
|
|
||||||
const show = () => {
|
const show = () => {
|
||||||
render();
|
render();
|
||||||
if (panel) {
|
if (panel) {
|
||||||
panel.classList.remove("hidden");
|
panel.classList.remove("hidden");
|
||||||
panel.style.display = "grid";
|
panel.style.display = "flex";
|
||||||
}
|
}
|
||||||
onShow?.();
|
onShow?.();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -62,27 +62,42 @@ export function createTemplatesMenu({ panel, fetchProjects, openProject, onShow,
|
||||||
header.className = "templates-header";
|
header.className = "templates-header";
|
||||||
header.innerHTML = `<span class="templates-title">Проекты и шаблоны</span>`;
|
header.innerHTML = `<span class="templates-title">Проекты и шаблоны</span>`;
|
||||||
const actions = document.createElement("div");
|
const actions = document.createElement("div");
|
||||||
actions.style.display = "flex";
|
actions.className = "templates-actions";
|
||||||
actions.style.gap = "6px";
|
|
||||||
const refresh = document.createElement("button");
|
const refresh = document.createElement("button");
|
||||||
refresh.className = "templates-close";
|
refresh.className = "templates-close";
|
||||||
|
refresh.type = "button";
|
||||||
refresh.title = "Обновить список";
|
refresh.title = "Обновить список";
|
||||||
refresh.textContent = "↻";
|
refresh.setAttribute("aria-label", "Обновить список");
|
||||||
|
refresh.innerHTML = `
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M12.2 5.3A4.4 4.4 0 0 0 4.7 3.4L3.6 4.5M3.7 2.1v2.4h2.4M3.8 10.7a4.4 4.4 0 0 0 7.5 1.9l1.1-1.1M12.3 13.9v-2.4H9.9" fill="none" stroke="currentColor" stroke-width="1.35" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
refresh.addEventListener("click", () => load());
|
refresh.addEventListener("click", () => load());
|
||||||
const closeBtn = document.createElement("button");
|
const closeBtn = document.createElement("button");
|
||||||
closeBtn.className = "templates-close";
|
closeBtn.className = "templates-close";
|
||||||
closeBtn.textContent = "×";
|
closeBtn.type = "button";
|
||||||
|
closeBtn.setAttribute("aria-label", "Закрыть проекты и шаблоны");
|
||||||
|
closeBtn.innerHTML = `
|
||||||
|
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
|
||||||
|
<path d="M4.25 4.25 11.75 11.75M11.75 4.25 4.25 11.75" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"></path>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
closeBtn.addEventListener("click", hide);
|
closeBtn.addEventListener("click", hide);
|
||||||
actions.appendChild(refresh);
|
actions.appendChild(refresh);
|
||||||
actions.appendChild(closeBtn);
|
actions.appendChild(closeBtn);
|
||||||
header.appendChild(actions);
|
header.appendChild(actions);
|
||||||
panel.appendChild(header);
|
panel.appendChild(header);
|
||||||
|
|
||||||
|
const body = document.createElement("div");
|
||||||
|
body.className = "templates-panel-body";
|
||||||
|
panel.appendChild(body);
|
||||||
|
|
||||||
if (state.loading) {
|
if (state.loading) {
|
||||||
const loadingEl = document.createElement("div");
|
const loadingEl = document.createElement("div");
|
||||||
loadingEl.className = "templates-empty";
|
loadingEl.className = "templates-empty";
|
||||||
loadingEl.textContent = "Загрузка списка проектов...";
|
loadingEl.textContent = "Загрузка списка проектов...";
|
||||||
panel.appendChild(loadingEl);
|
body.appendChild(loadingEl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,11 +106,11 @@ export function createTemplatesMenu({ panel, fetchProjects, openProject, onShow,
|
||||||
errorEl.className = "templates-empty";
|
errorEl.className = "templates-empty";
|
||||||
errorEl.style.color = "var(--error)";
|
errorEl.style.color = "var(--error)";
|
||||||
errorEl.textContent = state.error;
|
errorEl.textContent = state.error;
|
||||||
panel.appendChild(errorEl);
|
body.appendChild(errorEl);
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.appendChild(renderSection("Шаблоны", state.templates, "Нет шаблонов"));
|
body.appendChild(renderSection("Шаблоны", state.templates, "Нет шаблонов"));
|
||||||
panel.appendChild(renderSection("Мои проекты", state.projects, "Нет сохранённых проектов"));
|
body.appendChild(renderSection("Мои проекты", state.projects, "Нет сохранённых проектов"));
|
||||||
};
|
};
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
|
|
@ -126,7 +141,7 @@ export function createTemplatesMenu({ panel, fetchProjects, openProject, onShow,
|
||||||
render();
|
render();
|
||||||
if (panel) {
|
if (panel) {
|
||||||
panel.classList.remove("hidden");
|
panel.classList.remove("hidden");
|
||||||
panel.style.display = "grid";
|
panel.style.display = "flex";
|
||||||
}
|
}
|
||||||
load();
|
load();
|
||||||
onShow?.();
|
onShow?.();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
const toolbarConfig = {
|
const toolbarConfig = {
|
||||||
|
minSize: 25,
|
||||||
|
maxSize: 87,
|
||||||
|
lensCount: 5,
|
||||||
|
autoHide: false,
|
||||||
size: 25,
|
size: 25,
|
||||||
gap: 10,
|
gap: 10,
|
||||||
radius: 7,
|
radius: 7,
|
||||||
|
|
@ -7,9 +11,22 @@ const toolbarConfig = {
|
||||||
iconSize: 13,
|
iconSize: 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
const applyToolbarVars = () => {
|
const numericSetting = (settings, key, fallback) => {
|
||||||
|
const value = Number(settings?.[key]);
|
||||||
|
return Number.isFinite(value) ? value : fallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyToolbarVars = (settings = {}) => {
|
||||||
const root = document.documentElement;
|
const root = document.documentElement;
|
||||||
root.style.setProperty("--tb-size", `${toolbarConfig.size}px`);
|
const minSize = numericSetting(settings, "toolbarMinSize", toolbarConfig.minSize);
|
||||||
|
const maxSize = Math.max(minSize, numericSetting(settings, "toolbarMaxSize", toolbarConfig.maxSize));
|
||||||
|
const lensCount = Math.max(1, Math.round(numericSetting(settings, "toolbarLensCount", toolbarConfig.lensCount)));
|
||||||
|
const autoHide = settings?.toolbarAutoHide ?? toolbarConfig.autoHide;
|
||||||
|
root.style.setProperty("--tb-size", `${minSize}px`);
|
||||||
|
root.style.setProperty("--tb-min-size", `${minSize}px`);
|
||||||
|
root.style.setProperty("--tb-max-size", `${maxSize}px`);
|
||||||
|
root.style.setProperty("--tb-lens-count", `${lensCount}`);
|
||||||
|
root.style.setProperty("--tb-autohide", autoHide ? "1" : "0");
|
||||||
root.style.setProperty("--tb-gap", `${toolbarConfig.gap}px`);
|
root.style.setProperty("--tb-gap", `${toolbarConfig.gap}px`);
|
||||||
root.style.setProperty("--tb-radius", `${toolbarConfig.radius}px`);
|
root.style.setProperty("--tb-radius", `${toolbarConfig.radius}px`);
|
||||||
root.style.setProperty("--tb-pad-y", `${toolbarConfig.paddingY}px`);
|
root.style.setProperty("--tb-pad-y", `${toolbarConfig.paddingY}px`);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Базовые цвета/настройки проекта. При очистке localStorage эти значения остаются.
|
// Базовые цвета/настройки проекта. При очистке localStorage эти значения остаются.
|
||||||
// Чтобы изменить палитру по умолчанию — правь этот объект и закоммить изменения.
|
// Чтобы изменить палитру по умолчанию — правь этот объект и закоммить изменения.
|
||||||
const PROJECT_THEME = {
|
const PROJECT_THEME = {
|
||||||
themeVersion: "v3-yellow",
|
themeVersion: "v7-toolbar-hub-icon",
|
||||||
bgOuter: "#0f0f0f",
|
bgOuter: "#0f0f0f",
|
||||||
canvasTop: "#1c1c1c",
|
canvasTop: "#1c1c1c",
|
||||||
canvasBottom: "#1c1c1c",
|
canvasBottom: "#1c1c1c",
|
||||||
|
|
@ -9,44 +9,64 @@ const PROJECT_THEME = {
|
||||||
loadingBottom: "#1c1c1c",
|
loadingBottom: "#1c1c1c",
|
||||||
accent: "#ffea00",
|
accent: "#ffea00",
|
||||||
accent2: "#ffea00",
|
accent2: "#ffea00",
|
||||||
templateFill: "#1c1c1c",
|
templateFill: "#292929",
|
||||||
templateOutline: "#233044",
|
templateOutline: "#292929",
|
||||||
templateOutlineHover: "rgba(255,234,0,0.7)",
|
templateOutlineHover: "#1c1c1c",
|
||||||
templateGlow: 80,
|
templateGlow: 80,
|
||||||
toolbarBg: "#1c1c1c",
|
toolbarBg: "#292929",
|
||||||
toolbarBgActive: "#ffea00",
|
toolbarBgActive: "#c4ff67",
|
||||||
toolbarBorder: "#233044",
|
toolbarBorder: "#292929",
|
||||||
toolbarOutline: "#ffea00",
|
toolbarOutline: "#292929",
|
||||||
|
toolbarMinSize: 25,
|
||||||
|
toolbarMaxSize: 87,
|
||||||
|
toolbarLensCount: 5,
|
||||||
|
toolbarAutoHide: false,
|
||||||
modalBg: "#1c1c1c",
|
modalBg: "#1c1c1c",
|
||||||
modalBgAlpha: 1,
|
modalBgAlpha: 1,
|
||||||
modalFocus: "#292929",
|
modalFocus: "#292929",
|
||||||
modalFocusAlpha: 1,
|
modalFocusAlpha: 0.35,
|
||||||
modalBorder: "#292929",
|
modalBorder: "#1c1c1c",
|
||||||
modalElement: "#292929",
|
modalElement: "#262626",
|
||||||
modalElementOutline: "#2b2b2b",
|
modalElementOutline: "#262626",
|
||||||
modalRadius: "14px",
|
modalRadius: "14px",
|
||||||
projectBtnFill: "#1c1c1c",
|
projectBtnFill: "#292929",
|
||||||
projectBtnBorder: "#233044",
|
projectBtnBorder: "#292929",
|
||||||
projectBtnHover: "rgba(255,234,0,0.7)",
|
projectBtnHover: "#1c1c1c",
|
||||||
modalBtnPrimary: "#ffea00",
|
modalBtnPrimary: "#c4ff67",
|
||||||
modalBtnSecondary: "#292929",
|
modalBtnSecondary: "#292929",
|
||||||
|
loaderColor: "#c4ff67",
|
||||||
border: "#233044",
|
border: "#233044",
|
||||||
text: "#e6edf3",
|
text: "#e6edf3",
|
||||||
panel: "#1c1c1c",
|
panel: "#1c1c1c",
|
||||||
panel2: "#292929",
|
panel2: "#292929",
|
||||||
highlight: "#ffea00",
|
highlight: "#c4ff67",
|
||||||
cubeText: "#242424",
|
cubeText: "#242424",
|
||||||
cubeEdges: "#e0e7ff",
|
cubeEdges: "#e0e7ff",
|
||||||
plus: "#ffea00",
|
plus: "#c4ff67",
|
||||||
navCubeBase: "#ffea00",
|
navCubeBase: "#ffffff",
|
||||||
navCubeHover: "#ffffff",
|
navCubeHover: "#ffffff",
|
||||||
navCubeText: "#242424",
|
navCubeText: "#242424",
|
||||||
navCubeEdge: "#e0e7ff",
|
navCubeEdge: "#e0e7ff",
|
||||||
navCubeEdgeAlpha: 0.6,
|
navCubeEdgeAlpha: 0.6,
|
||||||
measureLine: "#ffea00",
|
measureLine: "#c4ff67",
|
||||||
measureLabel: "#ffea00",
|
measureLabel: "#c4ff67",
|
||||||
measureLabelText: "#292929",
|
measureLabelText: "#292929",
|
||||||
measureDot: "#ffea00",
|
measureDot: "#c4ff67",
|
||||||
|
sectionAxisX: "#ff2b2b",
|
||||||
|
sectionAxisY: "#35ff4f",
|
||||||
|
sectionAxisZ: "#285bff",
|
||||||
|
sectionGizmoDiameter: 1,
|
||||||
|
sectionGizmoThickness: 1,
|
||||||
|
sectionPlaneFill: "#606060",
|
||||||
|
sectionPlaneAlpha: 0.32,
|
||||||
|
sectionPlaneEdge: "#0d0d0d",
|
||||||
|
sectionPlaneEdgeAlpha: 0.8,
|
||||||
|
commentTargetActiveColor: "#c4ff67",
|
||||||
|
commentTargetActiveAlpha: 1,
|
||||||
|
commentTargetActiveSize: 30,
|
||||||
|
commentTargetPassiveColor: "#f5f5fa",
|
||||||
|
commentTargetPassiveAlpha: 0.58,
|
||||||
|
commentTargetPassiveSize: 22,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,13 @@ export class TransformGizmo {
|
||||||
this._bindTree();
|
this._bindTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isPointCloudTarget(model, objectId = null) {
|
||||||
|
const entity = objectId ? this.scene.objects[objectId] : null;
|
||||||
|
const firstObject = entity || Object.values(model?.objects || {})[0];
|
||||||
|
const firstMesh = firstObject?.meshes?.[0] || model?.meshes?.[0];
|
||||||
|
return firstMesh?._geometry?._state?.primitiveName === "points";
|
||||||
|
}
|
||||||
|
|
||||||
setMode(next) {
|
setMode(next) {
|
||||||
if (!["translate", "rotate", "scale"].includes(next)) return;
|
if (!["translate", "rotate", "scale"].includes(next)) return;
|
||||||
this.mode = next;
|
this.mode = next;
|
||||||
|
|
@ -66,7 +73,9 @@ export class TransformGizmo {
|
||||||
scale: model.scale ? [...model.scale] : [1, 1, 1],
|
scale: model.scale ? [...model.scale] : [1, 1, 1],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.scene.setObjectsHighlighted([objectId], true);
|
if (!this._isPointCloudTarget(model, objectId)) {
|
||||||
|
this.scene.setObjectsHighlighted([objectId], true);
|
||||||
|
}
|
||||||
this.target = { modelId, objectId };
|
this.target = { modelId, objectId };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +83,7 @@ export class TransformGizmo {
|
||||||
|
|
||||||
// Если objectId нет, работаем всей моделью
|
// Если objectId нет, работаем всей моделью
|
||||||
const ids = Object.keys(model.objects || {});
|
const ids = Object.keys(model.objects || {});
|
||||||
if (ids.length) {
|
if (ids.length && !this._isPointCloudTarget(model)) {
|
||||||
this.scene.setObjectsHighlighted(ids, true);
|
this.scene.setObjectsHighlighted(ids, true);
|
||||||
}
|
}
|
||||||
this.onTargetChange?.({
|
this.onTargetChange?.({
|
||||||
|
|
@ -101,7 +110,9 @@ export class TransformGizmo {
|
||||||
if (model) {
|
if (model) {
|
||||||
const ids = Object.keys(model.objects || {});
|
const ids = Object.keys(model.objects || {});
|
||||||
this.scene.setObjectsHighlighted(this.scene.highlightedObjectIds || [], false);
|
this.scene.setObjectsHighlighted(this.scene.highlightedObjectIds || [], false);
|
||||||
this.scene.setObjectsHighlighted(ids, true);
|
if (!this._isPointCloudTarget(model)) {
|
||||||
|
this.scene.setObjectsHighlighted(ids, true);
|
||||||
|
}
|
||||||
this.target = { modelId, objectId: null };
|
this.target = { modelId, objectId: null };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build": "rollup --config rollup.config.js && rollup --config rollup.dev.config.js && copyfiles -f locales/messages.js ./dist && copyfiles -f xeokit-bim-viewer.css ./dist",
|
"build": "rollup --config rollup.config.js && rollup --config rollup.dev.config.js && copyfiles -f locales/messages.js ./dist && copyfiles -f xeokit-bim-viewer.css ./dist",
|
||||||
"docs": "./node_modules/.bin/esdoc",
|
"docs": "./node_modules/.bin/esdoc",
|
||||||
"serve": "http-server . -p 8080 ",
|
"serve": "npm --prefix server start",
|
||||||
|
"serve:static": "http-server . -p 8080 ",
|
||||||
|
"serve:frontend": "http-server frontend -p 9001",
|
||||||
|
"serve:beam": "docker compose -f docker-compose.beam.yml up ndc-beam-viewer nodedc-bim-converter",
|
||||||
"changelog": "auto-changelog --commit-limit false --package --template changelog-template.hbs"
|
"changelog": "auto-changelog --commit-limit false --package --template changelog-template.hbs"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,50 @@
|
||||||
Лёгкий файловый backend без внешних зависимостей.
|
Лёгкий файловый backend без внешних зависимостей.
|
||||||
|
|
||||||
Быстрый старт
|
Быстрый старт
|
||||||
- Сервер: `npm --prefix server start` (PORT=8080 по умолчанию). Если порт занят, сервер попробует 8081/8082/8083 автоматически.
|
- Полный локальный viewer с backend/API: `npm run serve` или `npm --prefix server start` (PORT=8080 по умолчанию). Если порт занят, сервер попробует 8081/8082/8083 автоматически.
|
||||||
- Ручной выбор порта: `PORT=8088 npm --prefix server start`
|
- Ручной выбор порта: `PORT=8088 npm --prefix server start`
|
||||||
- Клиент отдельно (только статика, без API): `npx http-server frontend -p 9001` и открыть http://localhost:9001
|
- Клиент отдельно (только статика, без API): `npm run serve:frontend` или `npx http-server frontend -p 9001` и открыть http://localhost:9001
|
||||||
|
- Старый статический корень без backend оставлен как `npm run serve:static`; для проверки upload/comments/share/LOD его не использовать.
|
||||||
|
|
||||||
Статика: раздаётся из `../frontend/dist`, при отсутствии сборки — из `../frontend`.
|
Статика: раздаётся из `../frontend/dist`, при отсутствии сборки — из `../frontend`.
|
||||||
|
|
||||||
Хранилище: `server/data/projects/index.json` (список) + `server/data/projects/proj_<id>.json` (полный проект). При старте создаются при необходимости.
|
Хранилище: `server/data/projects/index.json` (список) + `server/data/projects/proj_<id>.json` (полный проект).
|
||||||
|
Upload-артефакты лежат в `server/data/uploads`, публичные share-ссылки — в `server/data/shares/index.json`,
|
||||||
|
а пользовательские ссылки/ref-count моделей — в `server/data/models/registry.json`. При старте директории и индексы создаются при необходимости.
|
||||||
|
|
||||||
API:
|
API:
|
||||||
- `GET /api/projects[?type=project|template]` — укороченный список из `index.json`.
|
- `GET /api/projects[?type=project|template]` — укороченный список из `index.json`.
|
||||||
- `GET /api/projects/:id` — полный JSON проекта.
|
- `GET /api/projects/:id` — полный JSON проекта.
|
||||||
- `POST /api/projects` — создать проект, генерируется `id`, `createdAt`, `updatedAt`, сохраняется файл и обновляется индекс.
|
- `POST /api/projects` — создать проект, генерируется `id`, `createdAt`, `updatedAt`, сохраняется файл и обновляется индекс.
|
||||||
|
- `POST /api/uploads?filename=<name>&projectId=<id>` — сохранить оригинальный файл модели в `server/data/uploads`.
|
||||||
|
- `DELETE /api/uploads/asset` — снять ссылку текущего пользователя на модель и физически удалить asset только если больше нет user/share refs.
|
||||||
|
- `DELETE /api/uploads/version` — удалить версию, если на неё нет чужих refs или публичных share-ссылок.
|
||||||
|
- `GET /api/conversions/status?src=<uploads/...>` — получить статус подготовки viewer-артефакта.
|
||||||
|
Для `.step/.stp` ответ помечается `conversion.status=conversion_required`: оригинал уже доступен для скачивания,
|
||||||
|
а preview должен появиться после работы `NodeDcBimConverter`, который готовит GLB и metadata/tree.
|
||||||
|
|
||||||
|
Локальный Beam compose:
|
||||||
|
- `docker compose -f docker-compose.beam.yml up ndc-beam-viewer`
|
||||||
|
- `docker compose -f docker-compose.beam.yml up nodedc-bim-converter`
|
||||||
|
|
||||||
|
Synology Beam compose:
|
||||||
|
- скопировать `.env.synology.example` в `.env` рядом с `docker-compose.beam.yml`;
|
||||||
|
- заполнить `NODEDC_INTERNAL_ACCESS_TOKEN` тем же значением, что и в platform `.env.synology`;
|
||||||
|
- запустить `docker compose -f docker-compose.beam.yml up -d ndc-beam-viewer nodedc-bim-converter`.
|
||||||
|
|
||||||
Поле `ownerId` пока всегда `null`, но оставлено для будущих пользователей/шаринга.
|
Поле `ownerId` пока всегда `null`, но оставлено для будущих пользователей/шаринга.
|
||||||
|
|
||||||
|
NODE.DC auth/share:
|
||||||
|
- `NODEDC_BIM_AUTH_REQUIRED=1` включает вход через Launcher handoff.
|
||||||
|
- `NODEDC_BIM_SERVICE_SLUG=bim-viewer` должен совпадать со slug сервиса в Launcher.
|
||||||
|
- `NODEDC_INTERNAL_ACCESS_TOKEN` должен совпадать с Launcher internal token.
|
||||||
|
- `NODEDC_LAUNCHER_BASE_URL` — публичный Launcher URL для редиректа на login/launch.
|
||||||
|
- `NODEDC_LAUNCHER_INTERNAL_URL` — внутренний URL Launcher для `/api/internal/handoff/consume`.
|
||||||
|
- `NODEDC_BIM_PUBLIC_URL` — публичный URL viewer-а для share-ссылок, на проде `https://bim.nodedc.tech`.
|
||||||
|
- `NODEDC_BIM_HOST_PORT` — host-port для `docker-compose.beam.yml`; на Synology BIM публикуется как `18100:8080`.
|
||||||
|
- `NODEDC_BIM_COOKIE_SAMESITE=None` и `NODEDC_BIM_COOKIE_SECURE=1` нужны для BIM в iframe на `ops.nodedc.ru`.
|
||||||
|
- `NODEDC_BIM_DATA_ROOT` — опциональный корень файлового storage вместо `server/data`.
|
||||||
|
- `POST /api/shares` создаёт публичную read-only ссылку на upload artifact; `/share/<token>` открывает viewer в guest mode.
|
||||||
|
- `GET /api/models` возвращает личные активные модели текущего пользователя.
|
||||||
|
- `POST /api/models/refs` сохраняет существующий upload artifact в личные модели текущего пользователя.
|
||||||
|
- `DELETE /api/models/refs` снимает личную ссылку и удаляет физические файлы только при отсутствии других refs/share.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "cmt_vtqiMR-vxXQUVYlz76M",
|
||||||
|
"sourceKey": "3fd1f5a5-6073-49d8-b8a3-ee73db24fe97:legacy_32e0d0079d836057bb86",
|
||||||
|
"sourceSrc": "uploads/3fd1f5a5-6073-49d8-b8a3-ee73db24fe97/SK_LOFT.glb",
|
||||||
|
"projectId": "3fd1f5a5-6073-49d8-b8a3-ee73db24fe97",
|
||||||
|
"assetId": "legacy_32e0d0079d836057bb86",
|
||||||
|
"modelId": "model-1",
|
||||||
|
"objectId": "_loft_",
|
||||||
|
"title": "ТУТ ЕБУТЬСЯ",
|
||||||
|
"body": "",
|
||||||
|
"subitems": [],
|
||||||
|
"worldPos": [
|
||||||
|
-27.293008589464144,
|
||||||
|
19.296417387225965,
|
||||||
|
-52.16235563339727
|
||||||
|
],
|
||||||
|
"createdAt": "2026-06-23T18:20:59.108Z",
|
||||||
|
"updatedAt": "2026-06-23T18:20:59.108Z",
|
||||||
|
"createdBy": {
|
||||||
|
"id": "local-dev",
|
||||||
|
"email": null,
|
||||||
|
"name": "Local BIM user",
|
||||||
|
"subject": null,
|
||||||
|
"authentikUserId": null
|
||||||
|
},
|
||||||
|
"messages": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cmt_WugIB9w6U8jhk1qOHew",
|
||||||
|
"sourceKey": "nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2:legacy_572b02d5d4c05ce512d6",
|
||||||
|
"sourceSrc": "uploads/nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2/Final_Assembly.STEP",
|
||||||
|
"projectId": "nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2",
|
||||||
|
"assetId": "legacy_572b02d5d4c05ce512d6",
|
||||||
|
"modelId": "model",
|
||||||
|
"objectId": "407",
|
||||||
|
"title": "2",
|
||||||
|
"body": "2",
|
||||||
|
"subitems": [],
|
||||||
|
"worldPos": [
|
||||||
|
-0.016629892462037388,
|
||||||
|
0.03852343379522116,
|
||||||
|
-0.518901357060331
|
||||||
|
],
|
||||||
|
"createdAt": "2026-06-20T16:16:16.607Z",
|
||||||
|
"updatedAt": "2026-06-20T16:16:16.607Z",
|
||||||
|
"createdBy": {
|
||||||
|
"id": "local-dev",
|
||||||
|
"email": null,
|
||||||
|
"name": "Local BIM user",
|
||||||
|
"subject": null,
|
||||||
|
"authentikUserId": null
|
||||||
|
},
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"id": "msg_d5ioR6S1xqv2lg",
|
||||||
|
"body": "2",
|
||||||
|
"attachments": [],
|
||||||
|
"createdAt": "2026-06-20T16:16:16.607Z",
|
||||||
|
"updatedAt": "2026-06-20T16:16:16.607Z",
|
||||||
|
"createdBy": {
|
||||||
|
"id": "local-dev",
|
||||||
|
"email": null,
|
||||||
|
"name": "Local BIM user",
|
||||||
|
"subject": null,
|
||||||
|
"authentikUserId": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "cmt_y_t1tTNgNa1SJA43-No",
|
||||||
|
"sourceKey": "nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2:legacy_572b02d5d4c05ce512d6",
|
||||||
|
"sourceSrc": "uploads/nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2/Final_Assembly.STEP",
|
||||||
|
"projectId": "nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2",
|
||||||
|
"assetId": "legacy_572b02d5d4c05ce512d6",
|
||||||
|
"modelId": "model",
|
||||||
|
"objectId": "401",
|
||||||
|
"title": "1",
|
||||||
|
"body": "1",
|
||||||
|
"subitems": [],
|
||||||
|
"worldPos": [
|
||||||
|
-0.0010763776897612098,
|
||||||
|
-0.00014665442142014137,
|
||||||
|
-0.00001253560767433548
|
||||||
|
],
|
||||||
|
"createdAt": "2026-06-20T16:15:03.218Z",
|
||||||
|
"updatedAt": "2026-06-20T16:47:23.780Z",
|
||||||
|
"createdBy": {
|
||||||
|
"id": "local-dev",
|
||||||
|
"email": null,
|
||||||
|
"name": "Local BIM user",
|
||||||
|
"subject": null,
|
||||||
|
"authentikUserId": null
|
||||||
|
},
|
||||||
|
"messages": [
|
||||||
|
{
|
||||||
|
"id": "msg_qaFqDoGumOeJ1g",
|
||||||
|
"body": "1",
|
||||||
|
"attachments": [],
|
||||||
|
"createdAt": "2026-06-20T16:15:03.218Z",
|
||||||
|
"updatedAt": "2026-06-20T16:15:03.218Z",
|
||||||
|
"createdBy": {
|
||||||
|
"id": "local-dev",
|
||||||
|
"email": null,
|
||||||
|
"name": "Local BIM user",
|
||||||
|
"subject": null,
|
||||||
|
"authentikUserId": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "msg_aAr0GFHSrUjeQw",
|
||||||
|
"body": "пиевив",
|
||||||
|
"attachments": [],
|
||||||
|
"createdAt": "2026-06-20T16:47:23.780Z",
|
||||||
|
"updatedAt": "2026-06-20T16:47:23.780Z",
|
||||||
|
"createdBy": {
|
||||||
|
"id": "local-dev",
|
||||||
|
"email": null,
|
||||||
|
"name": "Local BIM user",
|
||||||
|
"subject": null,
|
||||||
|
"authentikUserId": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -1,4 +1,20 @@
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
"id": "proj_0a284bb5-1c82-48b1-a636-e204578a570a",
|
||||||
|
"name": "DRONE",
|
||||||
|
"type": "project",
|
||||||
|
"ownerId": null,
|
||||||
|
"createdAt": "2026-06-05T13:33:23.556Z",
|
||||||
|
"updatedAt": "2026-06-20T20:33:51.505Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "proj_0c1b26f3-020c-4ee9-926c-fedf08003304",
|
||||||
|
"name": "TrackEnsemble_6074_v11",
|
||||||
|
"type": "project",
|
||||||
|
"ownerId": null,
|
||||||
|
"createdAt": "2026-06-04T19:14:21.726Z",
|
||||||
|
"updatedAt": "2026-06-04T19:14:21.726Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "proj_e5355c03-983b-4e2f-800c-f57638e9732f",
|
"id": "proj_e5355c03-983b-4e2f-800c-f57638e9732f",
|
||||||
"name": "СКОЛКОВО - LOFT КВАРТАЛ",
|
"name": "СКОЛКОВО - LOFT КВАРТАЛ",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
{
|
||||||
|
"id": "proj_0a284bb5-1c82-48b1-a636-e204578a570a",
|
||||||
|
"name": "DRONE",
|
||||||
|
"type": "project",
|
||||||
|
"createdAt": "2026-06-05T13:33:23.556Z",
|
||||||
|
"updatedAt": "2026-06-20T20:33:51.505Z",
|
||||||
|
"ownerId": null,
|
||||||
|
"shares": [],
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"id": "model",
|
||||||
|
"type": "xkt",
|
||||||
|
"meta": {
|
||||||
|
"label": "Final Assembly.STEP",
|
||||||
|
"metadataPath": null,
|
||||||
|
"settingsSrc": "uploads/nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2/Final_Assembly.STEP",
|
||||||
|
"sourceSrc": "uploads/nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2/Final_Assembly.STEP",
|
||||||
|
"artifactSrc": "uploads/nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2/Final_Assembly.xkt"
|
||||||
|
},
|
||||||
|
"visible": true,
|
||||||
|
"src": "http://localhost:8080/uploads/nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2/Final_Assembly.xkt?v=2026-06-04T18%3A09%3A13.204700%2B00%3A00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"viewerState": {
|
||||||
|
"camera": {
|
||||||
|
"eye": [
|
||||||
|
-0.3470755265527011,
|
||||||
|
0.20168643298944608,
|
||||||
|
0.34824520869461856
|
||||||
|
],
|
||||||
|
"look": [
|
||||||
|
-0.01809624637167012,
|
||||||
|
-0.014447461123117594,
|
||||||
|
-0.15640939974292462
|
||||||
|
],
|
||||||
|
"up": [
|
||||||
|
0.18441935979386925,
|
||||||
|
0.941253080967919,
|
||||||
|
-0.28289951803002283
|
||||||
|
],
|
||||||
|
"projection": "perspective"
|
||||||
|
},
|
||||||
|
"transparent": true,
|
||||||
|
"edges": true,
|
||||||
|
"addMode": true,
|
||||||
|
"displayMode": "white",
|
||||||
|
"lightingMode": "standard",
|
||||||
|
"navigationAxis": "auto",
|
||||||
|
"zoomSpeed": 52,
|
||||||
|
"selection": {
|
||||||
|
"ids": [],
|
||||||
|
"modelId": null
|
||||||
|
},
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"id": "model",
|
||||||
|
"visible": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transforms": {
|
||||||
|
"model": {
|
||||||
|
"__model__": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"design": {
|
||||||
|
"themeVersion": "v5-drone-lime",
|
||||||
|
"bgOuter": "#0f0f0f",
|
||||||
|
"canvasTop": "#1c1c1c",
|
||||||
|
"canvasBottom": "#1c1c1c",
|
||||||
|
"loadingTop": "#1c1c1c",
|
||||||
|
"loadingBottom": "#1c1c1c",
|
||||||
|
"accent": "#ffea00",
|
||||||
|
"accent2": "#ffea00",
|
||||||
|
"templateFill": "#292929",
|
||||||
|
"templateOutline": "#292929",
|
||||||
|
"templateOutlineHover": "#1c1c1c",
|
||||||
|
"projectBtnFill": "#292929",
|
||||||
|
"projectBtnBorder": "#292929",
|
||||||
|
"projectBtnHover": "#1c1c1c",
|
||||||
|
"modalBtnPrimary": "#c4ff67",
|
||||||
|
"modalBtnSecondary": "#292929",
|
||||||
|
"loaderColor": "#c4ff67",
|
||||||
|
"templateGlow": 80,
|
||||||
|
"toolbarBg": "#292929",
|
||||||
|
"toolbarBgActive": "#c4ff67",
|
||||||
|
"toolbarBorder": "#292929",
|
||||||
|
"toolbarOutline": "#292929",
|
||||||
|
"toolbarMinSize": 24,
|
||||||
|
"toolbarMaxSize": 88,
|
||||||
|
"toolbarLensCount": 5,
|
||||||
|
"toolbarAutoHide": false,
|
||||||
|
"modalBg": "#1c1c1c",
|
||||||
|
"modalBgAlpha": 1,
|
||||||
|
"modalFocus": "#292929",
|
||||||
|
"modalFocusAlpha": 0.35,
|
||||||
|
"modalBorder": "#1c1c1c",
|
||||||
|
"modalElement": "#262626",
|
||||||
|
"modalElementOutline": "#262626",
|
||||||
|
"modalRadius": "14px",
|
||||||
|
"border": "#233044",
|
||||||
|
"text": "#e6edf3",
|
||||||
|
"panel": "#1c1c1c",
|
||||||
|
"panel2": "#292929",
|
||||||
|
"highlight": "#c4ff67",
|
||||||
|
"cubeText": "#242424",
|
||||||
|
"cubeEdges": "#e0e7ff",
|
||||||
|
"plus": "#c4ff67",
|
||||||
|
"navCubeBase": "#ffffff",
|
||||||
|
"navCubeHover": "#ffffff",
|
||||||
|
"navCubeText": "#242424",
|
||||||
|
"navCubeEdge": "#e0e7ff",
|
||||||
|
"navCubeEdgeAlpha": 0.6,
|
||||||
|
"measureLine": "#c4ff67",
|
||||||
|
"measureLabel": "#c4ff67",
|
||||||
|
"measureLabelText": "#292929",
|
||||||
|
"measureDot": "#c4ff67",
|
||||||
|
"sectionAxisX": "#ff2b2b",
|
||||||
|
"sectionAxisY": "#35ff4f",
|
||||||
|
"sectionAxisZ": "#285bff",
|
||||||
|
"sectionGizmoDiameter": 1,
|
||||||
|
"sectionGizmoThickness": 1,
|
||||||
|
"sectionPlaneFill": "#606060",
|
||||||
|
"sectionPlaneAlpha": 0.32,
|
||||||
|
"sectionPlaneEdge": "#0d0d0d",
|
||||||
|
"sectionPlaneEdgeAlpha": 0.8,
|
||||||
|
"commentTargetActiveColor": "#c4ff67",
|
||||||
|
"commentTargetActiveAlpha": 1,
|
||||||
|
"commentTargetActiveSize": 45,
|
||||||
|
"commentTargetPassiveColor": "#262626",
|
||||||
|
"commentTargetPassiveAlpha": 0.58,
|
||||||
|
"commentTargetPassiveSize": 28
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"description": "",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
{
|
||||||
|
"id": "proj_0c1b26f3-020c-4ee9-926c-fedf08003304",
|
||||||
|
"name": "TrackEnsemble_6074_v11",
|
||||||
|
"type": "project",
|
||||||
|
"createdAt": "2026-06-04T19:14:21.726Z",
|
||||||
|
"updatedAt": "2026-06-04T19:14:21.726Z",
|
||||||
|
"ownerId": null,
|
||||||
|
"shares": [],
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"id": "model",
|
||||||
|
"type": "xkt",
|
||||||
|
"meta": {
|
||||||
|
"label": "TV_ensemble complet.STEP",
|
||||||
|
"metadataPath": null
|
||||||
|
},
|
||||||
|
"visible": true,
|
||||||
|
"src": "http://localhost:8080/uploads/nodedc_c2f0a08f-3f98-446a-94e9-c7b91ee95611_32e82d59-f15f-49b1-ba36-de2f8cc9ebc2/TV_ensemble_complet.xkt?v=2026-06-04T18%3A34%3A12.613772%2B00%3A00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"viewerState": {
|
||||||
|
"camera": {
|
||||||
|
"eye": [
|
||||||
|
0.5620614003131926,
|
||||||
|
0.636732837776035,
|
||||||
|
0.5089379140596013
|
||||||
|
],
|
||||||
|
"look": [
|
||||||
|
0.26556218907312157,
|
||||||
|
0.09433375758008311,
|
||||||
|
0.05622267468342307
|
||||||
|
],
|
||||||
|
"up": [
|
||||||
|
-0.28340934910241067,
|
||||||
|
-0.5184532182367775,
|
||||||
|
0.806774690568114
|
||||||
|
],
|
||||||
|
"projection": "perspective"
|
||||||
|
},
|
||||||
|
"transparent": true,
|
||||||
|
"edges": true,
|
||||||
|
"addMode": true,
|
||||||
|
"displayMode": "white",
|
||||||
|
"lightingMode": "technical",
|
||||||
|
"navigationAxis": "z-up",
|
||||||
|
"selection": {
|
||||||
|
"ids": [
|
||||||
|
"TV_tcapot"
|
||||||
|
],
|
||||||
|
"modelId": "model"
|
||||||
|
},
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"id": "model",
|
||||||
|
"visible": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"transforms": {
|
||||||
|
"model": {
|
||||||
|
"__model__": {
|
||||||
|
"position": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"rotation": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"scale": [
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"design": {
|
||||||
|
"themeVersion": "v5-drone-lime",
|
||||||
|
"bgOuter": "#0f0f0f",
|
||||||
|
"canvasTop": "#1c1c1c",
|
||||||
|
"canvasBottom": "#1c1c1c",
|
||||||
|
"loadingTop": "#1c1c1c",
|
||||||
|
"loadingBottom": "#1c1c1c",
|
||||||
|
"accent": "#ffea00",
|
||||||
|
"accent2": "#ffea00",
|
||||||
|
"templateFill": "#292929",
|
||||||
|
"templateOutline": "#292929",
|
||||||
|
"templateOutlineHover": "#1c1c1c",
|
||||||
|
"projectBtnFill": "#292929",
|
||||||
|
"projectBtnBorder": "#292929",
|
||||||
|
"projectBtnHover": "#1c1c1c",
|
||||||
|
"modalBtnPrimary": "#c4ff67",
|
||||||
|
"modalBtnSecondary": "#292929",
|
||||||
|
"loaderColor": "#c4ff67",
|
||||||
|
"templateGlow": 80,
|
||||||
|
"toolbarBg": "#292929",
|
||||||
|
"toolbarBgActive": "#c4ff67",
|
||||||
|
"toolbarBorder": "#292929",
|
||||||
|
"toolbarOutline": "#292929",
|
||||||
|
"modalBg": "#1c1c1c",
|
||||||
|
"modalBgAlpha": 1,
|
||||||
|
"modalFocus": "#292929",
|
||||||
|
"modalFocusAlpha": 0.35,
|
||||||
|
"modalBorder": "#1c1c1c",
|
||||||
|
"modalElement": "#262626",
|
||||||
|
"modalElementOutline": "#262626",
|
||||||
|
"modalRadius": "14px",
|
||||||
|
"border": "#233044",
|
||||||
|
"text": "#e6edf3",
|
||||||
|
"panel": "#1c1c1c",
|
||||||
|
"panel2": "#292929",
|
||||||
|
"highlight": "#c4ff67",
|
||||||
|
"cubeText": "#242424",
|
||||||
|
"cubeEdges": "#e0e7ff",
|
||||||
|
"plus": "#c4ff67",
|
||||||
|
"navCubeBase": "#ffffff",
|
||||||
|
"navCubeHover": "#ffffff",
|
||||||
|
"navCubeText": "#242424",
|
||||||
|
"navCubeEdge": "#e0e7ff",
|
||||||
|
"navCubeEdgeAlpha": 0.6,
|
||||||
|
"measureLine": "#c4ff67",
|
||||||
|
"measureLabel": "#c4ff67",
|
||||||
|
"measureLabelText": "#292929",
|
||||||
|
"measureDot": "#c4ff67"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"description": "",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -802,62 +802,56 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"design": {
|
"design": {
|
||||||
"themeVersion": "v3-yellow",
|
"themeVersion": "v5-drone-lime",
|
||||||
"bgOuter": "#121319",
|
"bgOuter": "#0f0f0f",
|
||||||
"canvasTop": "#121319",
|
"canvasTop": "#1c1c1c",
|
||||||
"canvasBottom": "#121319",
|
"canvasBottom": "#1c1c1c",
|
||||||
"loadingTop": "#121319",
|
"loadingTop": "#1c1c1c",
|
||||||
"loadingBottom": "#121319",
|
"loadingBottom": "#1c1c1c",
|
||||||
"accent": "#ffea00",
|
"accent": "#ffea00",
|
||||||
"accent2": "#ffea00",
|
"accent2": "#ffea00",
|
||||||
"templateFill": "#1f1f1f",
|
"templateFill": "#292929",
|
||||||
"templateOutline": "#1c1c1c",
|
"templateOutline": "#292929",
|
||||||
"templateOutlineHover": "#2e2e2e",
|
"templateOutlineHover": "#1c1c1c",
|
||||||
"projectBtnFill": "#1c1c1c",
|
"projectBtnFill": "#292929",
|
||||||
"projectBtnBorder": "#1c1c1c",
|
"projectBtnBorder": "#292929",
|
||||||
"projectBtnHover": "#292929",
|
"projectBtnHover": "#1c1c1c",
|
||||||
"modalBtnPrimary": "#befd02",
|
"modalBtnPrimary": "#c4ff67",
|
||||||
"modalBtnSecondary": "#292929",
|
"modalBtnSecondary": "#292929",
|
||||||
"loaderColor": "#befd02",
|
"loaderColor": "#c4ff67",
|
||||||
"templateGlow": 39,
|
"templateGlow": 80,
|
||||||
"toolbarBg": "#1c1c1c",
|
"toolbarBg": "#292929",
|
||||||
"toolbarBgActive": "#befd02",
|
"toolbarBgActive": "#c4ff67",
|
||||||
"toolbarBorder": "#233044",
|
"toolbarBorder": "#292929",
|
||||||
"toolbarOutline": "#befd02",
|
"toolbarOutline": "#292929",
|
||||||
"modalBg": "#1a1a1a",
|
"modalBg": "#1c1c1c",
|
||||||
"modalBgAlpha": 0.95,
|
"modalBgAlpha": 1,
|
||||||
"modalFocus": "#141414",
|
"modalFocus": "#292929",
|
||||||
"modalFocusAlpha": 0.55,
|
"modalFocusAlpha": 0.35,
|
||||||
"modalBorder": "#141414",
|
"modalBorder": "#1c1c1c",
|
||||||
"modalElement": "#141414",
|
"modalElement": "#262626",
|
||||||
"modalElementOutline": "#141414",
|
"modalElementOutline": "#262626",
|
||||||
"modalRadius": "14px",
|
"modalRadius": "14px",
|
||||||
"border": "#233044",
|
"border": "#233044",
|
||||||
"text": "#e6edf3",
|
"text": "#e6edf3",
|
||||||
"panel": "#1c1c1c",
|
"panel": "#1c1c1c",
|
||||||
"panel2": "#292929",
|
"panel2": "#292929",
|
||||||
"highlight": "#befd02",
|
"highlight": "#c4ff67",
|
||||||
"cubeText": "#242424",
|
"cubeText": "#242424",
|
||||||
"cubeEdges": "#e0e7ff",
|
"cubeEdges": "#e0e7ff",
|
||||||
"plus": "#befd02",
|
"plus": "#c4ff67",
|
||||||
"navCubeBase": "#ffffff",
|
"navCubeBase": "#ffffff",
|
||||||
"navCubeHover": "#ffffff",
|
"navCubeHover": "#ffffff",
|
||||||
"navCubeText": "#242424",
|
"navCubeText": "#242424",
|
||||||
"navCubeEdge": "#e0e7ff",
|
"navCubeEdge": "#e0e7ff",
|
||||||
"navCubeEdgeAlpha": 0.6,
|
"navCubeEdgeAlpha": 0.6,
|
||||||
"measureLine": "#befd02",
|
"measureLine": "#c4ff67",
|
||||||
"measureLabel": "#befd02",
|
"measureLabel": "#c4ff67",
|
||||||
"measureLabelText": "#292929",
|
"measureLabelText": "#292929",
|
||||||
"measureDot": "#befd02",
|
"measureDot": "#c4ff67"
|
||||||
"clipPerspectiveNear": 0.01,
|
|
||||||
"clipPerspectiveFar": 100000,
|
|
||||||
"clipOrthoNear": 0.01,
|
|
||||||
"clipOrthoFar": 100000,
|
|
||||||
"clipPerspective": 4000,
|
|
||||||
"clipOrtho": 5000
|
|
||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"description": "",
|
"description": "",
|
||||||
"tags": []
|
"tags": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"design": {
|
"design": {
|
||||||
"themeVersion": "v3-yellow",
|
"themeVersion": "v5-drone-lime",
|
||||||
"bgOuter": "#0f0f0f",
|
"bgOuter": "#0f0f0f",
|
||||||
"canvasTop": "#1c1c1c",
|
"canvasTop": "#1c1c1c",
|
||||||
"canvasBottom": "#1c1c1c",
|
"canvasBottom": "#1c1c1c",
|
||||||
|
|
@ -81,40 +81,48 @@
|
||||||
"loadingBottom": "#1c1c1c",
|
"loadingBottom": "#1c1c1c",
|
||||||
"accent": "#ffea00",
|
"accent": "#ffea00",
|
||||||
"accent2": "#ffea00",
|
"accent2": "#ffea00",
|
||||||
"templateFill": "#1c1c1c",
|
"templateFill": "#292929",
|
||||||
"templateOutline": "#233044",
|
"templateOutline": "#292929",
|
||||||
"templateOutlineHover": "rgba(255,234,0,0.7)",
|
"templateOutlineHover": "#1c1c1c",
|
||||||
|
"projectBtnFill": "#292929",
|
||||||
|
"projectBtnBorder": "#292929",
|
||||||
|
"projectBtnHover": "#1c1c1c",
|
||||||
|
"modalBtnPrimary": "#c4ff67",
|
||||||
|
"modalBtnSecondary": "#292929",
|
||||||
|
"loaderColor": "#c4ff67",
|
||||||
"templateGlow": 80,
|
"templateGlow": 80,
|
||||||
"toolbarBg": "#1c1c1c",
|
"toolbarBg": "#292929",
|
||||||
"toolbarBgActive": "#ffea00",
|
"toolbarBgActive": "#c4ff67",
|
||||||
"toolbarBorder": "#233044",
|
"toolbarBorder": "#292929",
|
||||||
"toolbarOutline": "#ffea00",
|
"toolbarOutline": "#292929",
|
||||||
"modalBg": "#1c1c1c",
|
"modalBg": "#1c1c1c",
|
||||||
|
"modalBgAlpha": 1,
|
||||||
"modalFocus": "#292929",
|
"modalFocus": "#292929",
|
||||||
"modalBorder": "#292929",
|
"modalFocusAlpha": 0.35,
|
||||||
"modalElement": "#292929",
|
"modalBorder": "#1c1c1c",
|
||||||
"modalElementOutline": "#2b2b2b",
|
"modalElement": "#262626",
|
||||||
|
"modalElementOutline": "#262626",
|
||||||
"modalRadius": "14px",
|
"modalRadius": "14px",
|
||||||
"border": "#233044",
|
"border": "#233044",
|
||||||
"text": "#e6edf3",
|
"text": "#e6edf3",
|
||||||
"panel": "#1c1c1c",
|
"panel": "#1c1c1c",
|
||||||
"panel2": "#292929",
|
"panel2": "#292929",
|
||||||
"highlight": "#ffea00",
|
"highlight": "#c4ff67",
|
||||||
"cubeText": "#242424",
|
"cubeText": "#242424",
|
||||||
"cubeEdges": "#e0e7ff",
|
"cubeEdges": "#e0e7ff",
|
||||||
"plus": "#ffea00",
|
"plus": "#c4ff67",
|
||||||
"navCubeBase": "#ffea00",
|
"navCubeBase": "#ffffff",
|
||||||
"navCubeHover": "#ffffff",
|
"navCubeHover": "#ffffff",
|
||||||
"navCubeText": "#242424",
|
"navCubeText": "#242424",
|
||||||
"navCubeEdge": "#e0e7ff",
|
"navCubeEdge": "#e0e7ff",
|
||||||
"navCubeEdgeAlpha": 0.6,
|
"navCubeEdgeAlpha": 0.6,
|
||||||
"measureLine": "#ffea00",
|
"measureLine": "#c4ff67",
|
||||||
"measureLabel": "#ffea00",
|
"measureLabel": "#c4ff67",
|
||||||
"measureLabelText": "#292929",
|
"measureLabelText": "#292929",
|
||||||
"measureDot": "#ffea00"
|
"measureDot": "#c4ff67"
|
||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"description": "",
|
"description": "",
|
||||||
"tags": []
|
"tags": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"design": {
|
"design": {
|
||||||
"themeVersion": "v3-yellow",
|
"themeVersion": "v5-drone-lime",
|
||||||
"bgOuter": "#0f0f0f",
|
"bgOuter": "#0f0f0f",
|
||||||
"canvasTop": "#1c1c1c",
|
"canvasTop": "#1c1c1c",
|
||||||
"canvasBottom": "#1c1c1c",
|
"canvasBottom": "#1c1c1c",
|
||||||
|
|
@ -100,48 +100,48 @@
|
||||||
"loadingBottom": "#1c1c1c",
|
"loadingBottom": "#1c1c1c",
|
||||||
"accent": "#ffea00",
|
"accent": "#ffea00",
|
||||||
"accent2": "#ffea00",
|
"accent2": "#ffea00",
|
||||||
"templateFill": "#1c1c1c",
|
"templateFill": "#292929",
|
||||||
"templateOutline": "#233044",
|
"templateOutline": "#292929",
|
||||||
"templateOutlineHover": "rgba(255,234,0,0.7)",
|
"templateOutlineHover": "#1c1c1c",
|
||||||
"projectBtnFill": "#1c1c1c",
|
"projectBtnFill": "#292929",
|
||||||
"projectBtnBorder": "#1c1c1c",
|
"projectBtnBorder": "#292929",
|
||||||
"projectBtnHover": "#292929",
|
"projectBtnHover": "#1c1c1c",
|
||||||
"modalBtnPrimary": "#befd02",
|
"modalBtnPrimary": "#c4ff67",
|
||||||
"modalBtnSecondary": "#292929",
|
"modalBtnSecondary": "#292929",
|
||||||
"loaderColor": "#befd02",
|
"loaderColor": "#c4ff67",
|
||||||
"templateGlow": 80,
|
"templateGlow": 80,
|
||||||
"toolbarBg": "#1c1c1c",
|
"toolbarBg": "#292929",
|
||||||
"toolbarBgActive": "#ffea00",
|
"toolbarBgActive": "#c4ff67",
|
||||||
"toolbarBorder": "#233044",
|
"toolbarBorder": "#292929",
|
||||||
"toolbarOutline": "#ffea00",
|
"toolbarOutline": "#292929",
|
||||||
"modalBg": "#1c1c1c",
|
"modalBg": "#1c1c1c",
|
||||||
"modalBgAlpha": 0.95,
|
"modalBgAlpha": 1,
|
||||||
"modalFocus": "#292929",
|
"modalFocus": "#292929",
|
||||||
"modalFocusAlpha": 0.55,
|
"modalFocusAlpha": 0.35,
|
||||||
"modalBorder": "#292929",
|
"modalBorder": "#1c1c1c",
|
||||||
"modalElement": "#292929",
|
"modalElement": "#262626",
|
||||||
"modalElementOutline": "#2b2b2b",
|
"modalElementOutline": "#262626",
|
||||||
"modalRadius": "14px",
|
"modalRadius": "14px",
|
||||||
"border": "#233044",
|
"border": "#233044",
|
||||||
"text": "#e6edf3",
|
"text": "#e6edf3",
|
||||||
"panel": "#1c1c1c",
|
"panel": "#1c1c1c",
|
||||||
"panel2": "#292929",
|
"panel2": "#292929",
|
||||||
"highlight": "#ffea00",
|
"highlight": "#c4ff67",
|
||||||
"cubeText": "#242424",
|
"cubeText": "#242424",
|
||||||
"cubeEdges": "#e0e7ff",
|
"cubeEdges": "#e0e7ff",
|
||||||
"plus": "#ffea00",
|
"plus": "#c4ff67",
|
||||||
"navCubeBase": "#ffea00",
|
"navCubeBase": "#ffffff",
|
||||||
"navCubeHover": "#ffffff",
|
"navCubeHover": "#ffffff",
|
||||||
"navCubeText": "#242424",
|
"navCubeText": "#242424",
|
||||||
"navCubeEdge": "#e0e7ff",
|
"navCubeEdge": "#e0e7ff",
|
||||||
"navCubeEdgeAlpha": 0.6,
|
"navCubeEdgeAlpha": 0.6,
|
||||||
"measureLine": "#ffea00",
|
"measureLine": "#c4ff67",
|
||||||
"measureLabel": "#ffea00",
|
"measureLabel": "#c4ff67",
|
||||||
"measureLabelText": "#292929",
|
"measureLabelText": "#292929",
|
||||||
"measureDot": "#ffea00"
|
"measureDot": "#c4ff67"
|
||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"description": "",
|
"description": "",
|
||||||
"tags": []
|
"tags": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3471
server/index.js
3471
server/index.js
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue