mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-06 08:22:24 +01:00
chore (plugin): revamp frontend plugin
This commit is contained in:
parent
fb29c7b6c2
commit
f4a99c4ad6
45 changed files with 179 additions and 18787 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import rxjs from "../lib/rx.js";
|
import rxjs from "../lib/rx.js";
|
||||||
import ajax from "../lib/ajax.js";
|
import ajax from "../lib/ajax.js";
|
||||||
|
import { join } from "../lib/path.js";
|
||||||
|
|
||||||
let LNG = {};
|
let LNG = {};
|
||||||
|
|
||||||
|
|
@ -42,7 +43,7 @@ export async function init() {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return ajax({
|
return ajax({
|
||||||
url: "assets/locales/" + selectedLanguage + ".json",
|
url: join(import.meta.url, selectedLanguage + ".json"),
|
||||||
}).pipe(rxjs.tap(({ responseHeaders, response }) => {
|
}).pipe(rxjs.tap(({ responseHeaders, response }) => {
|
||||||
const contentType = responseHeaders["content-type"].trim();
|
const contentType = responseHeaders["content-type"].trim();
|
||||||
if (contentType === "application/json") {
|
if (contentType === "application/json") {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import ctrlError from "../ctrl_error.js";
|
||||||
import componentDownloader, { init as initDownloader } from "./application_downloader.js";
|
import componentDownloader, { init as initDownloader } from "./application_downloader.js";
|
||||||
import { renderMenubar, buttonDownload } from "./component_menubar.js";
|
import { renderMenubar, buttonDownload } from "./component_menubar.js";
|
||||||
|
|
||||||
import * as THREE from "../../../lib/vendor/three/three.module.js";
|
import * as THREE from "../../lib/vendor/three/three.module.js";
|
||||||
import setup3D from "./application_3d/init.js";
|
import setup3D from "./application_3d/init.js";
|
||||||
import withLight from "./application_3d/scene_light.js";
|
import withLight from "./application_3d/scene_light.js";
|
||||||
import withCube from "./application_3d/scene_cube.js";
|
import withCube from "./application_3d/scene_cube.js";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { createElement, onDestroy } from "../../../lib/skeleton/index.js";
|
import { createElement, onDestroy } from "../../../lib/skeleton/index.js";
|
||||||
import { OrbitControls } from "../../../../lib/vendor/three/OrbitControls.js";
|
import { OrbitControls } from "../../../lib/vendor/three/OrbitControls.js";
|
||||||
|
|
||||||
export default function({ THREE, $page, $menubar, mesh, refresh, is2D }) {
|
export default function({ THREE, $page, $menubar, mesh, refresh, is2D }) {
|
||||||
// setup the dom
|
// setup the dom
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { onDestroy } from "../../../lib/skeleton/index.js";
|
import { onDestroy } from "../../../lib/skeleton/index.js";
|
||||||
import { ViewCubeGizmo, SimpleCameraControls, ObjectPosition } from "../../../../lib/vendor/three/viewcube.js";
|
import { ViewCubeGizmo, SimpleCameraControls, ObjectPosition } from "../../../lib/vendor/three/viewcube.js";
|
||||||
|
|
||||||
export default function({ camera, renderer, refresh, controls }) {
|
export default function({ camera, renderer, refresh, controls }) {
|
||||||
const viewCubeGizmo = new ViewCubeGizmo(camera, renderer, {
|
const viewCubeGizmo = new ViewCubeGizmo(camera, renderer, {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { settings_get } from "../../../lib/settings.js";
|
import { settings_get } from "../../../lib/settings.js";
|
||||||
import * as THREE from "../../../../lib/vendor/three/three.module.js";
|
import * as THREE from "../../../lib/vendor/three/three.module.js";
|
||||||
|
|
||||||
const LIGHT_COLOR = 0xf5f5f5;
|
const LIGHT_COLOR = 0xf5f5f5;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { createElement } from "../../../lib/skeleton/index.js";
|
import { createElement } from "../../../lib/skeleton/index.js";
|
||||||
import { qs } from "../../../lib/dom.js";
|
import { qs } from "../../../lib/dom.js";
|
||||||
import * as THREE from "../../../../lib/vendor/three/three.module.js";
|
import * as THREE from "../../../lib/vendor/three/three.module.js";
|
||||||
|
|
||||||
export default function(render, { camera, controls, mesh, $menubar, $toolbar, is2D }) {
|
export default function(render, { camera, controls, mesh, $menubar, $toolbar, is2D }) {
|
||||||
if (mesh.children.length <= 1) return;
|
if (mesh.children.length <= 1) return;
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ import t from "../../locales/index.js";
|
||||||
import ctrlError from "../ctrl_error.js";
|
import ctrlError from "../ctrl_error.js";
|
||||||
|
|
||||||
import { transition } from "./common.js";
|
import { transition } from "./common.js";
|
||||||
|
import { renderMenubar } from "./component_menubar.js";
|
||||||
import "../../components/icon.js";
|
import "../../components/icon.js";
|
||||||
import "./component_menubar.js";
|
|
||||||
|
|
||||||
export default async function(render, { acl$, getFilename, getDownloadUrl, hasMenubar = true }) {
|
export default async function(render, { acl$, $menubar, getFilename, getDownloadUrl, hasMenubar = true }) {
|
||||||
const $page = createElement(`
|
const $page = createElement(`
|
||||||
<div class="component_filedownloader">
|
<div class="component_filedownloader">
|
||||||
<component-menubar filename="${getFilename()}" class="${!hasMenubar && "hidden"}"></component-menubar>
|
<component-menubar filename="${getFilename()}" class="${!hasMenubar && "hidden"}"></component-menubar>
|
||||||
|
|
@ -20,6 +20,7 @@ export default async function(render, { acl$, getFilename, getDownloadUrl, hasMe
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
render(transition($page));
|
render(transition($page));
|
||||||
|
renderMenubar(qs($page, "component-menubar"));
|
||||||
|
|
||||||
const $link = qs($page, "a");
|
const $link = qs($page, "a");
|
||||||
const $loading = qs($page, "component-icon");
|
const $loading = qs($page, "component-icon");
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import rxjs, { effect } from "../../lib/rx.js";
|
||||||
import { animate, slideXIn, opacityOut } from "../../lib/animate.js";
|
import { animate, slideXIn, opacityOut } from "../../lib/animate.js";
|
||||||
import { qs } from "../../lib/dom.js";
|
import { qs } from "../../lib/dom.js";
|
||||||
import { get as getConfig } from "../../model/config.js";
|
import { get as getConfig } from "../../model/config.js";
|
||||||
|
import { load as loadPlugin } from "../../model/plugin.js";
|
||||||
import { createLoader } from "../../components/loader.js";
|
import { createLoader } from "../../components/loader.js";
|
||||||
import { createModal, MODAL_RIGHT_BUTTON } from "../../components/modal.js";
|
import { createModal, MODAL_RIGHT_BUTTON } from "../../components/modal.js";
|
||||||
import { loadCSS, loadJS } from "../../helpers/loader.js";
|
import { loadCSS, loadJS } from "../../helpers/loader.js";
|
||||||
|
|
@ -21,7 +22,9 @@ import "../../components/icon.js";
|
||||||
|
|
||||||
const TIME_BEFORE_ABORT_EDIT = 5000;
|
const TIME_BEFORE_ABORT_EDIT = 5000;
|
||||||
|
|
||||||
export default async function(render, { acl$, getFilename, getDownloadUrl }) {
|
class IEditor {}
|
||||||
|
|
||||||
|
export default async function(render, { acl$, getFilename, getDownloadUrl, mime }) {
|
||||||
const $page = createElement(`
|
const $page = createElement(`
|
||||||
<div class="component_ide">
|
<div class="component_ide">
|
||||||
<component-menubar filename="${getFilename()}" class="hidden"></component-menubar>
|
<component-menubar filename="${getFilename()}" class="hidden"></component-menubar>
|
||||||
|
|
@ -107,6 +110,11 @@ export default async function(render, { acl$, getFilename, getDownloadUrl }) {
|
||||||
rxjs.tap((editor) => requestAnimationFrame(() => editor.refresh())),
|
rxjs.tap((editor) => requestAnimationFrame(() => editor.refresh())),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
rxjs.mergeMap(async (editor) => {
|
||||||
|
const loader = await loadPlugin(mime);
|
||||||
|
if (loader) new (await loader(IEditor, { mime, $menubar: $dom.menubar(), getFilename, getDownloadUrl }))(editor);
|
||||||
|
return editor;
|
||||||
|
}),
|
||||||
rxjs.catchError(ctrlError()),
|
rxjs.catchError(ctrlError()),
|
||||||
rxjs.share(),
|
rxjs.share(),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ export default async function(render, { mime, getDownloadUrl = nop, getFilename
|
||||||
catch (err) { componentDownloader(render, { mime, acl$, getFilename, getDownloadUrl }); }
|
catch (err) { componentDownloader(render, { mime, acl$, getFilename, getDownloadUrl }); }
|
||||||
return rxjs.EMPTY;
|
return rxjs.EMPTY;
|
||||||
}
|
}
|
||||||
const mapImpl = new (await loader(IMap))(response, {
|
const mapImpl = new (await loader(IMap, { mime, getDownloadUrl, getFilename, $menubar }))(response, {
|
||||||
map, $page, $menubar, L: window.L,
|
map, $page, L: window.L,
|
||||||
});
|
});
|
||||||
loadGeoJSON(map, await mapImpl.toGeoJSON());
|
loadGeoJSON(map, await mapImpl.toGeoJSON());
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { loadCSS } from "../../helpers/loader.js";
|
||||||
import { createLoader } from "../../components/loader.js";
|
import { createLoader } from "../../components/loader.js";
|
||||||
import ctrlError from "../ctrl_error.js";
|
import ctrlError from "../ctrl_error.js";
|
||||||
import componentDownloader, { init as initDownloader } from "./application_downloader.js";
|
import componentDownloader, { init as initDownloader } from "./application_downloader.js";
|
||||||
|
import { renderMenubar } from "./component_menubar.js";
|
||||||
|
|
||||||
export default function(render, { mime, getFilename, getDownloadUrl, acl$, hasMenubar = true }) {
|
export default function(render, { mime, getFilename, getDownloadUrl, acl$, hasMenubar = true }) {
|
||||||
const $page = createElement(`
|
const $page = createElement(`
|
||||||
|
|
@ -15,7 +16,7 @@ export default function(render, { mime, getFilename, getDownloadUrl, acl$, hasMe
|
||||||
</div>
|
</div>
|
||||||
`);
|
`);
|
||||||
render($page);
|
render($page);
|
||||||
const $menubar = qs($page, "component-menubar");
|
const $menubar = renderMenubar(qs($page, "component-menubar"));
|
||||||
const $container = qs($page, ".component_skeleton_container");
|
const $container = qs($page, ".component_skeleton_container");
|
||||||
const removeLoader = createLoader($container);
|
const removeLoader = createLoader($container);
|
||||||
effect(rxjs.from(loadPlugin(mime)).pipe(
|
effect(rxjs.from(loadPlugin(mime)).pipe(
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export default async function(render, { mime, getDownloadUrl = nop, getFilename
|
||||||
if (!loader) throw new TypeError(`unsupported mimetype "${mime}"`);
|
if (!loader) throw new TypeError(`unsupported mimetype "${mime}"`);
|
||||||
const [, url] = loader;
|
const [, url] = loader;
|
||||||
const module = await import(url);
|
const module = await import(url);
|
||||||
let table = new (await module.default(ITable))(response, { $menubar });
|
let table = new (await module.default(ITable, { $menubar }))(response);
|
||||||
if (typeof table.then === "function") table = await table;
|
if (typeof table.then === "function") table = await table;
|
||||||
STATE.header = table.getHeader();
|
STATE.header = table.getHeader();
|
||||||
STATE.body = table.getBody();
|
STATE.body = table.getBody();
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,12 @@ self.addEventListener("activate", (event) => {
|
||||||
})());
|
})());
|
||||||
});
|
});
|
||||||
|
|
||||||
self.addEventListener("fetch", (event) => {
|
self.addEventListener("fetch", async (event) => {
|
||||||
if (!event.request.url.startsWith(location.origin + "/assets/")) return;
|
if (!event.request.url.startsWith(location.origin + "/assets/")) return;
|
||||||
|
|
||||||
event.respondWith((async() => {
|
event.respondWith((async() => {
|
||||||
const cachedResponse = await caches.match(event.request);
|
const cache = await caches.open(CACHENAME);
|
||||||
|
const cachedResponse = await cache.match(event.request);
|
||||||
if (cachedResponse) return cachedResponse;
|
if (cachedResponse) return cachedResponse;
|
||||||
return fetch(event.request);
|
return fetch(event.request);
|
||||||
})());
|
})());
|
||||||
|
|
@ -55,37 +56,36 @@ self.addEventListener("message", (event) => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const handlePreloadMessage = (() => {
|
async function handlePreloadMessage(chunks, resolve, reject, id) {
|
||||||
return async(chunks, resolve, reject, id) => {
|
const cleanup = [];
|
||||||
const cleanup = [];
|
try {
|
||||||
try {
|
await caches.delete(CACHENAME);
|
||||||
caches.delete(CACHENAME);
|
const cache = await caches.open(CACHENAME);
|
||||||
const cache = await caches.open(CACHENAME);
|
await Promise.all(chunks.map((urls) => {
|
||||||
await Promise.all(chunks.map((urls) => {
|
return preload({ urls, cache, cleanup });
|
||||||
return preload({ urls, cache, cleanup });
|
}));
|
||||||
}));
|
resolve();
|
||||||
resolve();
|
} catch (err) {
|
||||||
} catch (err) {
|
console.log("ERR", err);
|
||||||
reject(err);
|
reject(err);
|
||||||
} finally {
|
} finally {
|
||||||
cleanup.forEach((fn) => fn());
|
cleanup.forEach((fn) => fn());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
|
||||||
|
|
||||||
async function preload({ urls, cache, cleanup }) {
|
async function preload({ urls, cache, cleanup }) {
|
||||||
const evtsrc = new self.EventSource("/assets/bundle?" + urls.map((url) => `url=${url}`).join("&"));
|
const evtsrc = new self.EventSource("/assets/bundle?" + urls.map((url) => `url=${url}`).join("&"));
|
||||||
cleanup.push(() => evtsrc.close());
|
cleanup.push(() => evtsrc.close());
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const messageHandler = (resolve, event, decoder) => {
|
const messageHandler = async (resolve, event, decoder) => {
|
||||||
const url = event.lastEventId;
|
const url = event.lastEventId;
|
||||||
let mime = "application/octet-stream";
|
let mime = "application/octet-stream";
|
||||||
if (url.endsWith(".css")) mime = "text/css";
|
if (url.endsWith(".css")) mime = "text/css";
|
||||||
else if (url.endsWith(".js")) mime = "application/javascript";
|
else if (url.endsWith(".js")) mime = "application/javascript";
|
||||||
|
|
||||||
i += 1;
|
i += 1;
|
||||||
cache.put(
|
await cache.put(
|
||||||
location.origin + url,
|
location.origin + url,
|
||||||
new Response(
|
new Response(
|
||||||
decoder(new Blob([Uint8Array.from(atob(event.data), (c) => c.charCodeAt(0))]).stream()),
|
decoder(new Blob([Uint8Array.from(atob(event.data), (c) => c.charCodeAt(0))]).stream()),
|
||||||
|
|
@ -111,6 +111,9 @@ async function preload({ urls, cache, cleanup }) {
|
||||||
event,
|
event,
|
||||||
(stream) => stream.pipeThrough(new DecompressionStream("gzip")),
|
(stream) => stream.pipeThrough(new DecompressionStream("gzip")),
|
||||||
));
|
));
|
||||||
evtsrc.onerror = (err) => errorHandler(reject, err);
|
evtsrc.onerror = (err) => {
|
||||||
|
if (i === urls.length) return;
|
||||||
|
errorHandler(reject, err);
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,129 +38,16 @@
|
||||||
<script type="module" src="./assets/{{ .version }}/components/notification.js" defer></script>
|
<script type="module" src="./assets/{{ .version }}/components/notification.js" defer></script>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script id="preload" type="application/json">{{ .preload }}</script>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
function boot() {
|
function boot() {
|
||||||
document.head.appendChild(document.querySelector("template#head").content);
|
document.head.appendChild(document.querySelector("template#head").content);
|
||||||
document.body.appendChild(document.querySelector("template#body").content);
|
document.body.appendChild(document.querySelector("template#body").content);
|
||||||
}
|
}
|
||||||
|
|
||||||
const URLS = [
|
|
||||||
[
|
|
||||||
"/assets/{{ .version }}/lib/vendor/rxjs/rxjs.min.js",
|
|
||||||
"/assets/{{ .version }}/lib/vendor/rxjs/rxjs-ajax.min.js",
|
|
||||||
"/assets/{{ .version }}/lib/vendor/rxjs/rxjs-shared.min.js",
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"/assets/{{ .version }}/boot/ctrl_boot_frontoffice.js",
|
|
||||||
"/assets/{{ .version }}/locales/index.js",
|
|
||||||
"/assets/{{ .version }}/css/designsystem.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_input.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_textarea.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_inputgroup.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_checkbox.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_formbuilder.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_button.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_icon.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_dropdown.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_container.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_box.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_darkmode.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_skeleton.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_utils.css",
|
|
||||||
"/assets/{{ .version }}/css/designsystem_alert.css",
|
|
||||||
"/assets/{{ .version }}/components/loader.js",
|
|
||||||
"/assets/{{ .version }}/components/modal.js",
|
|
||||||
"/assets/{{ .version }}/components/modal.css",
|
|
||||||
"/assets/{{ .version }}/components/notification.js",
|
|
||||||
"/assets/{{ .version }}/components/notification.css",
|
|
||||||
"/assets/{{ .version }}/boot/router_frontoffice.js",
|
|
||||||
"/assets/{{ .version }}/helpers/loader.js",
|
|
||||||
"/assets/{{ .version }}/lib/skeleton/index.js",
|
|
||||||
"/assets/{{ .version }}/lib/rx.js",
|
|
||||||
"/assets/{{ .version }}/lib/ajax.js",
|
|
||||||
"/assets/{{ .version }}/lib/animate.js",
|
|
||||||
"/assets/{{ .version }}/lib/assert.js",
|
|
||||||
"/assets/{{ .version }}/lib/dom.js",
|
|
||||||
"/assets/{{ .version }}/lib/skeleton/router.js",
|
|
||||||
"/assets/{{ .version }}/lib/skeleton/lifecycle.js",
|
|
||||||
"/assets/{{ .version }}/lib/error.js",
|
|
||||||
"/assets/{{ .version }}/model/config.js",
|
|
||||||
"/assets/{{ .version }}/model/plugin.js",
|
|
||||||
"/assets/{{ .version }}/model/chromecast.js",
|
|
||||||
"/assets/{{ .version }}/model/session.js",
|
|
||||||
"/assets/{{ .version }}/helpers/log.js",
|
|
||||||
"/assets/{{ .version }}/boot/common.js",
|
|
||||||
"/assets/{{ .version }}/helpers/sdk.js",
|
|
||||||
|
|
||||||
"/assets/{{ .version }}/components/breadcrumb.js",
|
|
||||||
"/assets/{{ .version }}/components/breadcrumb.css",
|
|
||||||
"/assets/{{ .version }}/components/form.js",
|
|
||||||
"/assets/{{ .version }}/components/sidebar.js",
|
|
||||||
"/assets/{{ .version }}/components/sidebar.css",
|
|
||||||
"/assets/{{ .version }}/components/dropdown.js",
|
|
||||||
"/assets/{{ .version }}/components/icon.js",
|
|
||||||
"/assets/{{ .version }}/lib/store.js",
|
|
||||||
"/assets/{{ .version }}/lib/random.js",
|
|
||||||
"/assets/{{ .version }}/lib/form.js",
|
|
||||||
"/assets/{{ .version }}/lib/path.js",
|
|
||||||
|
|
||||||
"/assets/{{ .version }}/components/decorator_shell_filemanager.js",
|
|
||||||
"/assets/{{ .version }}/components/decorator_shell_filemanager.css",
|
|
||||||
"/assets/{{ .version }}/pages/ctrl_error.js",
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"/assets/{{ .version }}/pages/ctrl_connectpage.js",
|
|
||||||
"/assets/{{ .version }}/pages/connectpage/ctrl_form.js",
|
|
||||||
"/assets/{{ .version }}/pages/connectpage/ctrl_forkme.js",
|
|
||||||
"/assets/{{ .version }}/pages/connectpage/ctrl_poweredby.js",
|
|
||||||
"/assets/{{ .version }}/lib/path.js",
|
|
||||||
"/assets/{{ .version }}/lib/form.js",
|
|
||||||
"/assets/{{ .version }}/lib/settings.js",
|
|
||||||
"/assets/{{ .version }}/components/form.js",
|
|
||||||
"/assets/{{ .version }}/model/session.js",
|
|
||||||
"/assets/{{ .version }}/pages/ctrl_error.js",
|
|
||||||
"/assets/{{ .version }}/pages/connectpage/model_backend.js",
|
|
||||||
"/assets/{{ .version }}/pages/connectpage/model_config.js",
|
|
||||||
"/assets/{{ .version }}/pages/connectpage/ctrl_form_state.js",
|
|
||||||
"/assets/{{ .version }}/lib/random.js",
|
|
||||||
"/assets/{{ .version }}/components/icon.js",
|
|
||||||
|
|
||||||
"/assets/{{ .version }}/pages/ctrl_connectpage.css",
|
|
||||||
"/assets/{{ .version }}/pages/connectpage/ctrl_form.css",
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"/assets/{{ .version }}/pages/ctrl_filespage.js",
|
|
||||||
"/assets/{{ .version }}/pages/ctrl_filespage.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_filesystem.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_submenu.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_newitem.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_upload.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/cache.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/state_config.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/thing.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/state_newthing.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/helper.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/model_files.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/model_virtual_layer.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/modal_share.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/modal_tag.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/modal_rename.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/modal_delete.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/state_selection.js",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/model_acl.js",
|
|
||||||
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_filesystem.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/thing.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/modal.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_submenu.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/modal_share.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/modal_tag.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_newitem.css",
|
|
||||||
"/assets/{{ .version }}/pages/filespage/ctrl_upload.css",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
|
const URLS = JSON.parse(document.getElementById("preload").textContent);
|
||||||
try {
|
try {
|
||||||
const register = await navigator.serviceWorker.register("sw.js");
|
const register = await navigator.serviceWorker.register("sw.js");
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ func PluginExportHandler(ctx *App, res http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
plgExports[module["mime"]] = []string{
|
plgExports[module["mime"]] = []string{
|
||||||
module["application"],
|
module["application"],
|
||||||
WithBase(JoinPath("/plugin/", filepath.Join(name, index))),
|
WithBase(JoinPath("/assets/"+BUILD_REF+"/plugin/", filepath.Join(name+".zip", index))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
|
|
@ -233,11 +234,6 @@ func ServeFile(chroot string) func(*App, http.ResponseWriter, *http.Request) {
|
||||||
)
|
)
|
||||||
head := res.Header()
|
head := res.Header()
|
||||||
|
|
||||||
if filePath == "/assets/bundle" {
|
|
||||||
ServeBundle(ctx, res, req)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// case: patch must be apply because of a "StaticPatch" plugin
|
// case: patch must be apply because of a "StaticPatch" plugin
|
||||||
if f := applyPatch(filePath); f != nil {
|
if f := applyPatch(filePath); f != nil {
|
||||||
head.Set("Content-Type", GetMimeType(filepath.Ext(filePath)))
|
head.Set("Content-Type", GetMimeType(filepath.Ext(filePath)))
|
||||||
|
|
@ -311,13 +307,13 @@ func ServeIndex(indexPath string) func(*App, http.ResponseWriter, *http.Request)
|
||||||
}
|
}
|
||||||
head.Set("Content-Type", "text/html")
|
head.Set("Content-Type", "text/html")
|
||||||
res.WriteHeader(http.StatusOK)
|
res.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
tmpl := template.Must(template.New(indexPath).Parse(string(b)))
|
tmpl := template.Must(template.New(indexPath).Parse(string(b)))
|
||||||
tmpl = template.Must(tmpl.Parse(string(TmplLoader)))
|
tmpl = template.Must(tmpl.Parse(string(TmplLoader)))
|
||||||
tmpl.Execute(res, map[string]any{
|
tmpl.Execute(res, map[string]any{
|
||||||
"base": WithBase("/"),
|
"base": WithBase("/"),
|
||||||
"version": BUILD_REF,
|
"version": BUILD_REF,
|
||||||
"license": LICENSE,
|
"license": LICENSE,
|
||||||
|
"preload": preload(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -429,3 +425,123 @@ func InitPluginList(code []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func preload() string {
|
||||||
|
out, _ := json.Marshal([][]string{
|
||||||
|
{
|
||||||
|
"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs.min.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs-ajax.min.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/vendor/rxjs/rxjs-shared.min.js",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/assets/" + BUILD_REF + "/boot/ctrl_boot_frontoffice.js",
|
||||||
|
"/assets/" + BUILD_REF + "/locales/index.js",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_input.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_textarea.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_inputgroup.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_checkbox.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_formbuilder.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_button.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_icon.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_dropdown.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_container.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_box.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_darkmode.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_skeleton.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_utils.css",
|
||||||
|
"/assets/" + BUILD_REF + "/css/designsystem_alert.css",
|
||||||
|
"/assets/" + BUILD_REF + "/components/loader.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/modal.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/modal.css",
|
||||||
|
"/assets/" + BUILD_REF + "/components/notification.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/notification.css",
|
||||||
|
"/assets/" + BUILD_REF + "/boot/router_frontoffice.js",
|
||||||
|
"/assets/" + BUILD_REF + "/helpers/loader.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/skeleton/index.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/rx.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/ajax.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/animate.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/assert.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/dom.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/skeleton/router.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/skeleton/lifecycle.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/error.js",
|
||||||
|
"/assets/" + BUILD_REF + "/model/config.js",
|
||||||
|
"/assets/" + BUILD_REF + "/model/plugin.js",
|
||||||
|
"/assets/" + BUILD_REF + "/model/chromecast.js",
|
||||||
|
"/assets/" + BUILD_REF + "/model/session.js",
|
||||||
|
"/assets/" + BUILD_REF + "/helpers/log.js",
|
||||||
|
"/assets/" + BUILD_REF + "/boot/common.js",
|
||||||
|
"/assets/" + BUILD_REF + "/helpers/sdk.js",
|
||||||
|
|
||||||
|
"/assets/" + BUILD_REF + "/components/breadcrumb.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/breadcrumb.css",
|
||||||
|
"/assets/" + BUILD_REF + "/components/form.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/sidebar.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/sidebar.css",
|
||||||
|
"/assets/" + BUILD_REF + "/components/dropdown.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/icon.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/store.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/random.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/form.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/path.js",
|
||||||
|
|
||||||
|
"/assets/" + BUILD_REF + "/components/decorator_shell_filemanager.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/decorator_shell_filemanager.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/ctrl_error.js",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/assets/" + BUILD_REF + "/pages/ctrl_connectpage.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/ctrl_connectpage.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_forkme.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_poweredby.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form.css",
|
||||||
|
|
||||||
|
"/assets/" + BUILD_REF + "/lib/path.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/form.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/settings.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/form.js",
|
||||||
|
"/assets/" + BUILD_REF + "/model/session.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/ctrl_error.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/connectpage/model_backend.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/connectpage/model_config.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/connectpage/ctrl_form_state.js",
|
||||||
|
"/assets/" + BUILD_REF + "/lib/random.js",
|
||||||
|
"/assets/" + BUILD_REF + "/components/icon.js",
|
||||||
|
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/thing.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_filesystem.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/thing.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/state_newthing.js",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"/assets/" + BUILD_REF + "/pages/ctrl_filespage.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/ctrl_filespage.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_newitem.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/cache.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/state_config.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/helper.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/model_files.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/model_virtual_layer.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/modal_share.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/modal_tag.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/modal_rename.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/modal_delete.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/state_selection.js",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/model_acl.js",
|
||||||
|
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/modal.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_submenu.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/modal_share.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/modal_tag.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_newitem.css",
|
||||||
|
"/assets/" + BUILD_REF + "/pages/filespage/ctrl_upload.css",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return string(out)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
all:
|
|
||||||
make install
|
|
||||||
|
|
||||||
install:
|
|
||||||
zip -r application_3d.zip .
|
|
||||||
mv application_3d.zip ../../../dist/data/state/plugins/application_3d.zip
|
|
||||||
|
|
||||||
deps_mesh:
|
|
||||||
[ -d vendor ] || mkdir vendor
|
|
||||||
curl https://gist.githubusercontent.com/mickael-kerjean/9a517f95112410fcacaad8563c1ba314/raw/ab483b38aebb7048832aad7b342f9161dd928e49/gistfile1.txt > vendor/MeshLoader.js
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
export default async function(I3D, { THREE }) {
|
|
||||||
const module = await import("./vendor/FBXLoader.js");
|
|
||||||
|
|
||||||
return class Impl extends I3D {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
load(url, onLoad, onProgress, onError) {
|
|
||||||
return (new module.FBXLoader()).load(url, onLoad, onProgress, onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
transform(obj) {
|
|
||||||
obj.name = "All";
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
export default async function(I3D, { THREE }) {
|
|
||||||
const module = await import("./vendor/GLTFLoader.js");
|
|
||||||
|
|
||||||
return class Impl extends I3D {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
load(url, onLoad, onProgress, onError) {
|
|
||||||
return new module.GLTFLoader().load(url, onLoad, onProgress, onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
transform(gltf) {
|
|
||||||
const mesh = gltf.scene;
|
|
||||||
mesh.animations = gltf.animations;
|
|
||||||
return mesh;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
export default async function(I3D, { THREE }) {
|
|
||||||
const module = await import("./vendor/MeshLoader.js");
|
|
||||||
|
|
||||||
return class Impl extends I3D {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
load(url, onLoad, onProgress, onError) {
|
|
||||||
return (new module.MeshLoader()).load(url, onLoad, onProgress, onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
transform(obj) {
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
import { toCreasedNormals } from "./vendor/utils/BufferGeometryUtils.js";
|
|
||||||
|
|
||||||
export default async function(I3D, { THREE }) {
|
|
||||||
const module = await import("./vendor/OBJLoader.js");
|
|
||||||
|
|
||||||
return class Impl extends I3D {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
load(url, onLoad, onProgress, onError) {
|
|
||||||
return (new module.OBJLoader()).load(url, onLoad, onProgress, onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
transform(obj) {
|
|
||||||
obj.name = "All";
|
|
||||||
obj.traverse((child) => {
|
|
||||||
if (child.isMesh) {
|
|
||||||
child.material = new THREE.MeshPhongMaterial({
|
|
||||||
color: 0x40464b,
|
|
||||||
emissive: 0x40464b,
|
|
||||||
specular: 0xf9f9fa,
|
|
||||||
shininess: 10,
|
|
||||||
transparent: true,
|
|
||||||
});
|
|
||||||
// smooth the edges: https://discourse.threejs.org/t/how-to-smooth-an-obj-with-threejs/3950/16
|
|
||||||
child.geometry = toCreasedNormals(child.geometry, (30 / 180) * Math.PI);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
import { loadJS } from "../../assets/helpers/loader.js";
|
|
||||||
|
|
||||||
await loadJS("https://cdn.jsdelivr.net", "/npm/occt-import-js@0.0.22/dist/occt-import-js.min.js");
|
|
||||||
|
|
||||||
async function LoadGeometry(url) {
|
|
||||||
const occt = await occtimportjs()
|
|
||||||
let fileUrl = "https://raw.githubusercontent.com/kovacsv/occt-import-js/main/test/testfiles/cax-if/as1_pe_203.stp"
|
|
||||||
// let response = await fetch(fileUrl)
|
|
||||||
let response = await fetch(url)
|
|
||||||
let buffer = await response.arrayBuffer()
|
|
||||||
let fileBuffer = new Uint8Array(buffer)
|
|
||||||
return occt.ReadStepFile(fileBuffer, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function(I3D, { THREE }) {
|
|
||||||
return class Impl extends I3D {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
load(url, onLoad, onProgress, onError) {
|
|
||||||
LoadGeometry(url)
|
|
||||||
.then(({ success, ...obj }) => {
|
|
||||||
if (success === false) throw new Error("NOT SUPPORTED");
|
|
||||||
onLoad(obj);
|
|
||||||
})
|
|
||||||
.catch((err) => onError(err));
|
|
||||||
}
|
|
||||||
|
|
||||||
transform({ root, meshes }) {
|
|
||||||
const group = new THREE.Group();
|
|
||||||
|
|
||||||
const recurse = ({ meshes: m, children, name}) => {
|
|
||||||
if (m.length > 0) {
|
|
||||||
const obj = new THREE.Object3D();
|
|
||||||
obj.name = name;
|
|
||||||
for (let i=0; i<m.length; i++) {
|
|
||||||
const resultMesh = meshes[m[i]];
|
|
||||||
console.log(name, resultMesh);
|
|
||||||
let geometry = new THREE.BufferGeometry()
|
|
||||||
geometry.setAttribute(
|
|
||||||
"position",
|
|
||||||
new THREE.Float32BufferAttribute(resultMesh.attributes.position.array, 3),
|
|
||||||
)
|
|
||||||
if (resultMesh.attributes.normal) geometry.setAttribute(
|
|
||||||
"normal",
|
|
||||||
new THREE.Float32BufferAttribute(resultMesh.attributes.normal.array, 3),
|
|
||||||
);
|
|
||||||
geometry.setIndex(new THREE.BufferAttribute(
|
|
||||||
Uint32Array.from(resultMesh.index.array),
|
|
||||||
1,
|
|
||||||
));
|
|
||||||
let material = null
|
|
||||||
if (resultMesh.color) material = new THREE.MeshPhongMaterial({ color: new THREE.Color(
|
|
||||||
resultMesh.color[0],
|
|
||||||
resultMesh.color[1],
|
|
||||||
resultMesh.color[2],
|
|
||||||
)});
|
|
||||||
else material = new THREE.MeshPhongMaterial({ color: 0xcccccc });
|
|
||||||
obj.add(new THREE.Mesh(geometry, material));
|
|
||||||
}
|
|
||||||
group.add(obj);
|
|
||||||
}
|
|
||||||
if (children.length > 0) children.forEach((obj) => recurse(obj));
|
|
||||||
}
|
|
||||||
root.children.forEach(recurse);
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
transformOld({ meshes, root }) {
|
|
||||||
console.log(meshes, root)
|
|
||||||
const targetObject = new THREE.Object3D();
|
|
||||||
for (let resultMesh of meshes) {
|
|
||||||
let geometry = new THREE.BufferGeometry()
|
|
||||||
geometry.setAttribute(
|
|
||||||
"position",
|
|
||||||
new THREE.Float32BufferAttribute(resultMesh.attributes.position.array, 3),
|
|
||||||
)
|
|
||||||
if (resultMesh.attributes.normal) geometry.setAttribute(
|
|
||||||
"normal",
|
|
||||||
new THREE.Float32BufferAttribute(resultMesh.attributes.normal.array, 3),
|
|
||||||
);
|
|
||||||
geometry.setIndex(new THREE.BufferAttribute(
|
|
||||||
Uint32Array.from(resultMesh.index.array),
|
|
||||||
1,
|
|
||||||
));
|
|
||||||
|
|
||||||
let material = null
|
|
||||||
if (resultMesh.color) material = new THREE.MeshPhongMaterial({ color: new THREE.Color(
|
|
||||||
resultMesh.color[0],
|
|
||||||
resultMesh.color[1],
|
|
||||||
resultMesh.color[2],
|
|
||||||
)});
|
|
||||||
else material = new THREE.MeshPhongMaterial({ color: 0xcccccc });
|
|
||||||
|
|
||||||
targetObject.add(new THREE.Mesh(geometry, material));
|
|
||||||
}
|
|
||||||
return targetObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
export default async function(I3D, { THREE }) {
|
|
||||||
const module = await import("./vendor/STLLoader.js");
|
|
||||||
|
|
||||||
return class Impl extends I3D {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
load(url, onLoad, onProgress, onError) {
|
|
||||||
return (new module.STLLoader()).load(url, onLoad, onProgress, onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
transform(geometry) {
|
|
||||||
const material = new THREE.MeshPhongMaterial({
|
|
||||||
emissive: 0x40464b,
|
|
||||||
specular: 0xf9f9fa,
|
|
||||||
shininess: 15,
|
|
||||||
transparent: true,
|
|
||||||
});
|
|
||||||
if (geometry.hasColors) material.vertexColors = true;
|
|
||||||
else material.color = material.emissive;
|
|
||||||
return new THREE.Mesh(geometry, material);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
export default async function(I3D, { THREE }) {
|
|
||||||
const module = await import("./vendor/SVGLoader.js");
|
|
||||||
|
|
||||||
const threecolor = (color) => {
|
|
||||||
if (color && color.substr && color.substr(0, 4) === "RGB(") {
|
|
||||||
function componentToHex(c) {
|
|
||||||
const hex = c.toString(16);
|
|
||||||
return hex.length === 1 ? "0" + hex : hex;
|
|
||||||
}
|
|
||||||
const [r, g, b] = color.replace(/^RGB\(/, "").replace(/\)/, "").split(",").map((i) => parseInt(i));
|
|
||||||
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
|
|
||||||
}
|
|
||||||
return color;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createMaterial = (color, opacity = 1) => new THREE.MeshBasicMaterial({
|
|
||||||
color: new THREE.Color().setStyle(color),
|
|
||||||
opacity,
|
|
||||||
transparent: true,
|
|
||||||
side: THREE.DoubleSide,
|
|
||||||
depthWrite: false,
|
|
||||||
wireframe: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
return class Impl extends I3D {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
load(url, onLoad, onProgress, onError) {
|
|
||||||
return (new module.SVGLoader()).load(url, onLoad, onProgress, onError);
|
|
||||||
}
|
|
||||||
|
|
||||||
transform(data) {
|
|
||||||
const group = new THREE.Group();
|
|
||||||
group.name = "All";
|
|
||||||
group.scale.y *= -1;
|
|
||||||
let renderOrder = 0;
|
|
||||||
for (const path of data.paths) {
|
|
||||||
const fillColor = threecolor(path.userData.style.fill);
|
|
||||||
if (fillColor !== undefined && fillColor !== "none") {
|
|
||||||
const material = createMaterial(
|
|
||||||
fillColor,
|
|
||||||
path.userData.style.fillOpacity,
|
|
||||||
);
|
|
||||||
const shapes = module.SVGLoader.createShapes(path);
|
|
||||||
for (const shape of shapes) {
|
|
||||||
const mesh = new THREE.Mesh(
|
|
||||||
new THREE.ShapeGeometry(shape),
|
|
||||||
material,
|
|
||||||
);
|
|
||||||
mesh.renderOrder = renderOrder++;
|
|
||||||
group.add(mesh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const strokeColor = threecolor(path.userData.style.stroke);
|
|
||||||
if (strokeColor !== undefined && strokeColor !== "none") {
|
|
||||||
const material = createMaterial(strokeColor);
|
|
||||||
for (const subPath of path.subPaths) {
|
|
||||||
const geometry = module.SVGLoader.pointsToStroke(subPath.getPoints(), path.userData.style);
|
|
||||||
if (geometry) {
|
|
||||||
const mesh = new THREE.Mesh(geometry, material);
|
|
||||||
mesh.renderOrder = renderOrder++;
|
|
||||||
group.add(mesh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
is2D() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
{
|
|
||||||
"author": "Filestash Pty Ltd",
|
|
||||||
"version": "v0.0",
|
|
||||||
"modules": [
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "application/fbx",
|
|
||||||
"entrypoint": "/index_fbx.js",
|
|
||||||
"application": "3d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "model/gltf-binary",
|
|
||||||
"entrypoint": "/index_gltf.js",
|
|
||||||
"application": "3d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "application/object",
|
|
||||||
"entrypoint": "/index_obj.js",
|
|
||||||
"application": "3d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "model/stl",
|
|
||||||
"entrypoint": "/index_stl.js",
|
|
||||||
"application": "3d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "image/svg+xml",
|
|
||||||
"entrypoint": "/index_svg.js",
|
|
||||||
"application": "3d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "model/step",
|
|
||||||
"entrypoint": "/index_step.js",
|
|
||||||
"application": "3d"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "model/mesh",
|
|
||||||
"entrypoint": "/index_mesh.js",
|
|
||||||
"application": "3d"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
4315
server/plugin/plg_application_3d/vendor/FBXLoader.js
vendored
4315
server/plugin/plg_application_3d/vendor/FBXLoader.js
vendored
File diff suppressed because it is too large
Load diff
4664
server/plugin/plg_application_3d/vendor/GLTFLoader.js
vendored
4664
server/plugin/plg_application_3d/vendor/GLTFLoader.js
vendored
File diff suppressed because it is too large
Load diff
906
server/plugin/plg_application_3d/vendor/OBJLoader.js
vendored
906
server/plugin/plg_application_3d/vendor/OBJLoader.js
vendored
|
|
@ -1,906 +0,0 @@
|
||||||
// @ts-nocheck
|
|
||||||
import {
|
|
||||||
BufferGeometry,
|
|
||||||
FileLoader,
|
|
||||||
Float32BufferAttribute,
|
|
||||||
Group,
|
|
||||||
LineBasicMaterial,
|
|
||||||
LineSegments,
|
|
||||||
Loader,
|
|
||||||
Material,
|
|
||||||
Mesh,
|
|
||||||
MeshPhongMaterial,
|
|
||||||
Points,
|
|
||||||
PointsMaterial,
|
|
||||||
Vector3,
|
|
||||||
Color
|
|
||||||
} from '../../../assets/lib/vendor/three/three.module.js';
|
|
||||||
|
|
||||||
// o object_name | g group_name
|
|
||||||
const _object_pattern = /^[og]\s*(.+)?/;
|
|
||||||
// mtllib file_reference
|
|
||||||
const _material_library_pattern = /^mtllib /;
|
|
||||||
// usemtl material_name
|
|
||||||
const _material_use_pattern = /^usemtl /;
|
|
||||||
// usemap map_name
|
|
||||||
const _map_use_pattern = /^usemap /;
|
|
||||||
const _face_vertex_data_separator_pattern = /\s+/;
|
|
||||||
|
|
||||||
const _vA = new Vector3();
|
|
||||||
const _vB = new Vector3();
|
|
||||||
const _vC = new Vector3();
|
|
||||||
|
|
||||||
const _ab = new Vector3();
|
|
||||||
const _cb = new Vector3();
|
|
||||||
|
|
||||||
const _color = new Color();
|
|
||||||
|
|
||||||
function ParserState() {
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
objects: [],
|
|
||||||
object: {},
|
|
||||||
|
|
||||||
vertices: [],
|
|
||||||
normals: [],
|
|
||||||
colors: [],
|
|
||||||
uvs: [],
|
|
||||||
|
|
||||||
materials: {},
|
|
||||||
materialLibraries: [],
|
|
||||||
|
|
||||||
startObject: function ( name, fromDeclaration ) {
|
|
||||||
|
|
||||||
// If the current object (initial from reset) is not from a g/o declaration in the parsed
|
|
||||||
// file. We need to use it for the first parsed g/o to keep things in sync.
|
|
||||||
if ( this.object && this.object.fromDeclaration === false ) {
|
|
||||||
|
|
||||||
this.object.name = name;
|
|
||||||
this.object.fromDeclaration = ( fromDeclaration !== false );
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );
|
|
||||||
|
|
||||||
if ( this.object && typeof this.object._finalize === 'function' ) {
|
|
||||||
|
|
||||||
this.object._finalize( true );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
this.object = {
|
|
||||||
name: name || '',
|
|
||||||
fromDeclaration: ( fromDeclaration !== false ),
|
|
||||||
|
|
||||||
geometry: {
|
|
||||||
vertices: [],
|
|
||||||
normals: [],
|
|
||||||
colors: [],
|
|
||||||
uvs: [],
|
|
||||||
hasUVIndices: false
|
|
||||||
},
|
|
||||||
materials: [],
|
|
||||||
smooth: true,
|
|
||||||
|
|
||||||
startMaterial: function ( name, libraries ) {
|
|
||||||
|
|
||||||
const previous = this._finalize( false );
|
|
||||||
|
|
||||||
// New usemtl declaration overwrites an inherited material, except if faces were declared
|
|
||||||
// after the material, then it must be preserved for proper MultiMaterial continuation.
|
|
||||||
if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
|
|
||||||
|
|
||||||
this.materials.splice( previous.index, 1 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const material = {
|
|
||||||
index: this.materials.length,
|
|
||||||
name: name || '',
|
|
||||||
mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
|
|
||||||
smooth: ( previous !== undefined ? previous.smooth : this.smooth ),
|
|
||||||
groupStart: ( previous !== undefined ? previous.groupEnd : 0 ),
|
|
||||||
groupEnd: - 1,
|
|
||||||
groupCount: - 1,
|
|
||||||
inherited: false,
|
|
||||||
|
|
||||||
clone: function ( index ) {
|
|
||||||
|
|
||||||
const cloned = {
|
|
||||||
index: ( typeof index === 'number' ? index : this.index ),
|
|
||||||
name: this.name,
|
|
||||||
mtllib: this.mtllib,
|
|
||||||
smooth: this.smooth,
|
|
||||||
groupStart: 0,
|
|
||||||
groupEnd: - 1,
|
|
||||||
groupCount: - 1,
|
|
||||||
inherited: false
|
|
||||||
};
|
|
||||||
cloned.clone = this.clone.bind( cloned );
|
|
||||||
return cloned;
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.materials.push( material );
|
|
||||||
|
|
||||||
return material;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
currentMaterial: function () {
|
|
||||||
|
|
||||||
if ( this.materials.length > 0 ) {
|
|
||||||
|
|
||||||
return this.materials[ this.materials.length - 1 ];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
_finalize: function ( end ) {
|
|
||||||
|
|
||||||
const lastMultiMaterial = this.currentMaterial();
|
|
||||||
if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
|
|
||||||
|
|
||||||
lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
|
|
||||||
lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
|
|
||||||
lastMultiMaterial.inherited = false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore objects tail materials if no face declarations followed them before a new o/g started.
|
|
||||||
if ( end && this.materials.length > 1 ) {
|
|
||||||
|
|
||||||
for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) {
|
|
||||||
|
|
||||||
if ( this.materials[ mi ].groupCount <= 0 ) {
|
|
||||||
|
|
||||||
this.materials.splice( mi, 1 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Guarantee at least one empty material, this makes the creation later more straight forward.
|
|
||||||
if ( end && this.materials.length === 0 ) {
|
|
||||||
|
|
||||||
this.materials.push( {
|
|
||||||
name: '',
|
|
||||||
smooth: this.smooth
|
|
||||||
} );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return lastMultiMaterial;
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Inherit previous objects material.
|
|
||||||
// Spec tells us that a declared material must be set to all objects until a new material is declared.
|
|
||||||
// If a usemtl declaration is encountered while this new object is being parsed, it will
|
|
||||||
// overwrite the inherited material. Exception being that there was already face declarations
|
|
||||||
// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
|
|
||||||
|
|
||||||
if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
|
|
||||||
|
|
||||||
const declared = previousMaterial.clone( 0 );
|
|
||||||
declared.inherited = true;
|
|
||||||
this.object.materials.push( declared );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
this.objects.push( this.object );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
finalize: function () {
|
|
||||||
|
|
||||||
if ( this.object && typeof this.object._finalize === 'function' ) {
|
|
||||||
|
|
||||||
this.object._finalize( true );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
parseVertexIndex: function ( value, len ) {
|
|
||||||
|
|
||||||
const index = parseInt( value, 10 );
|
|
||||||
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
parseNormalIndex: function ( value, len ) {
|
|
||||||
|
|
||||||
const index = parseInt( value, 10 );
|
|
||||||
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
parseUVIndex: function ( value, len ) {
|
|
||||||
|
|
||||||
const index = parseInt( value, 10 );
|
|
||||||
return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addVertex: function ( a, b, c ) {
|
|
||||||
|
|
||||||
const src = this.vertices;
|
|
||||||
const dst = this.object.geometry.vertices;
|
|
||||||
|
|
||||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
|
|
||||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
|
|
||||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addVertexPoint: function ( a ) {
|
|
||||||
|
|
||||||
const src = this.vertices;
|
|
||||||
const dst = this.object.geometry.vertices;
|
|
||||||
|
|
||||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addVertexLine: function ( a ) {
|
|
||||||
|
|
||||||
const src = this.vertices;
|
|
||||||
const dst = this.object.geometry.vertices;
|
|
||||||
|
|
||||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addNormal: function ( a, b, c ) {
|
|
||||||
|
|
||||||
const src = this.normals;
|
|
||||||
const dst = this.object.geometry.normals;
|
|
||||||
|
|
||||||
dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
|
|
||||||
dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
|
|
||||||
dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addFaceNormal: function ( a, b, c ) {
|
|
||||||
|
|
||||||
const src = this.vertices;
|
|
||||||
const dst = this.object.geometry.normals;
|
|
||||||
|
|
||||||
_vA.fromArray( src, a );
|
|
||||||
_vB.fromArray( src, b );
|
|
||||||
_vC.fromArray( src, c );
|
|
||||||
|
|
||||||
_cb.subVectors( _vC, _vB );
|
|
||||||
_ab.subVectors( _vA, _vB );
|
|
||||||
_cb.cross( _ab );
|
|
||||||
|
|
||||||
_cb.normalize();
|
|
||||||
|
|
||||||
dst.push( _cb.x, _cb.y, _cb.z );
|
|
||||||
dst.push( _cb.x, _cb.y, _cb.z );
|
|
||||||
dst.push( _cb.x, _cb.y, _cb.z );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addColor: function ( a, b, c ) {
|
|
||||||
|
|
||||||
const src = this.colors;
|
|
||||||
const dst = this.object.geometry.colors;
|
|
||||||
|
|
||||||
if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
|
|
||||||
if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
|
|
||||||
if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addUV: function ( a, b, c ) {
|
|
||||||
|
|
||||||
const src = this.uvs;
|
|
||||||
const dst = this.object.geometry.uvs;
|
|
||||||
|
|
||||||
dst.push( src[ a + 0 ], src[ a + 1 ] );
|
|
||||||
dst.push( src[ b + 0 ], src[ b + 1 ] );
|
|
||||||
dst.push( src[ c + 0 ], src[ c + 1 ] );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addDefaultUV: function () {
|
|
||||||
|
|
||||||
const dst = this.object.geometry.uvs;
|
|
||||||
|
|
||||||
dst.push( 0, 0 );
|
|
||||||
dst.push( 0, 0 );
|
|
||||||
dst.push( 0, 0 );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addUVLine: function ( a ) {
|
|
||||||
|
|
||||||
const src = this.uvs;
|
|
||||||
const dst = this.object.geometry.uvs;
|
|
||||||
|
|
||||||
dst.push( src[ a + 0 ], src[ a + 1 ] );
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
|
|
||||||
|
|
||||||
const vLen = this.vertices.length;
|
|
||||||
|
|
||||||
let ia = this.parseVertexIndex( a, vLen );
|
|
||||||
let ib = this.parseVertexIndex( b, vLen );
|
|
||||||
let ic = this.parseVertexIndex( c, vLen );
|
|
||||||
|
|
||||||
this.addVertex( ia, ib, ic );
|
|
||||||
this.addColor( ia, ib, ic );
|
|
||||||
|
|
||||||
// normals
|
|
||||||
|
|
||||||
if ( na !== undefined && na !== '' ) {
|
|
||||||
|
|
||||||
const nLen = this.normals.length;
|
|
||||||
|
|
||||||
ia = this.parseNormalIndex( na, nLen );
|
|
||||||
ib = this.parseNormalIndex( nb, nLen );
|
|
||||||
ic = this.parseNormalIndex( nc, nLen );
|
|
||||||
|
|
||||||
this.addNormal( ia, ib, ic );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
this.addFaceNormal( ia, ib, ic );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// uvs
|
|
||||||
|
|
||||||
if ( ua !== undefined && ua !== '' ) {
|
|
||||||
|
|
||||||
const uvLen = this.uvs.length;
|
|
||||||
|
|
||||||
ia = this.parseUVIndex( ua, uvLen );
|
|
||||||
ib = this.parseUVIndex( ub, uvLen );
|
|
||||||
ic = this.parseUVIndex( uc, uvLen );
|
|
||||||
|
|
||||||
this.addUV( ia, ib, ic );
|
|
||||||
|
|
||||||
this.object.geometry.hasUVIndices = true;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// add placeholder values (for inconsistent face definitions)
|
|
||||||
|
|
||||||
this.addDefaultUV();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addPointGeometry: function ( vertices ) {
|
|
||||||
|
|
||||||
this.object.geometry.type = 'Points';
|
|
||||||
|
|
||||||
const vLen = this.vertices.length;
|
|
||||||
|
|
||||||
for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
|
|
||||||
|
|
||||||
const index = this.parseVertexIndex( vertices[ vi ], vLen );
|
|
||||||
|
|
||||||
this.addVertexPoint( index );
|
|
||||||
this.addColor( index );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
addLineGeometry: function ( vertices, uvs ) {
|
|
||||||
|
|
||||||
this.object.geometry.type = 'Line';
|
|
||||||
|
|
||||||
const vLen = this.vertices.length;
|
|
||||||
const uvLen = this.uvs.length;
|
|
||||||
|
|
||||||
for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
|
|
||||||
|
|
||||||
this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
|
|
||||||
|
|
||||||
this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
state.startObject( '', false );
|
|
||||||
|
|
||||||
return state;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
class OBJLoader extends Loader {
|
|
||||||
|
|
||||||
constructor( manager ) {
|
|
||||||
|
|
||||||
super( manager );
|
|
||||||
|
|
||||||
this.materials = null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
load( url, onLoad, onProgress, onError ) {
|
|
||||||
|
|
||||||
const scope = this;
|
|
||||||
|
|
||||||
const loader = new FileLoader( this.manager );
|
|
||||||
loader.setPath( this.path );
|
|
||||||
loader.setRequestHeader( this.requestHeader );
|
|
||||||
loader.setWithCredentials( this.withCredentials );
|
|
||||||
loader.load( url, function ( text ) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
onLoad( scope.parse( text ) );
|
|
||||||
|
|
||||||
} catch ( e ) {
|
|
||||||
|
|
||||||
if ( onError ) {
|
|
||||||
|
|
||||||
onError( e );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
console.error( e );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.manager.itemError( url );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}, onProgress, onError );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
setMaterials( materials ) {
|
|
||||||
|
|
||||||
this.materials = materials;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
parse( text ) {
|
|
||||||
|
|
||||||
const state = new ParserState();
|
|
||||||
|
|
||||||
if ( text.indexOf( '\r\n' ) !== - 1 ) {
|
|
||||||
|
|
||||||
// This is faster than String.split with regex that splits on both
|
|
||||||
text = text.replace( /\r\n/g, '\n' );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( text.indexOf( '\\\n' ) !== - 1 ) {
|
|
||||||
|
|
||||||
// join lines separated by a line continuation character (\)
|
|
||||||
text = text.replace( /\\\n/g, '' );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const lines = text.split( '\n' );
|
|
||||||
let result = [];
|
|
||||||
|
|
||||||
for ( let i = 0, l = lines.length; i < l; i ++ ) {
|
|
||||||
|
|
||||||
const line = lines[ i ].trimStart();
|
|
||||||
|
|
||||||
if ( line.length === 0 ) continue;
|
|
||||||
|
|
||||||
const lineFirstChar = line.charAt( 0 );
|
|
||||||
|
|
||||||
// @todo invoke passed in handler if any
|
|
||||||
if ( lineFirstChar === '#' ) continue; // skip comments
|
|
||||||
|
|
||||||
if ( lineFirstChar === 'v' ) {
|
|
||||||
|
|
||||||
const data = line.split( _face_vertex_data_separator_pattern );
|
|
||||||
|
|
||||||
switch ( data[ 0 ] ) {
|
|
||||||
|
|
||||||
case 'v':
|
|
||||||
state.vertices.push(
|
|
||||||
parseFloat( data[ 1 ] ),
|
|
||||||
parseFloat( data[ 2 ] ),
|
|
||||||
parseFloat( data[ 3 ] )
|
|
||||||
);
|
|
||||||
if ( data.length >= 7 ) {
|
|
||||||
|
|
||||||
_color.setRGB(
|
|
||||||
parseFloat( data[ 4 ] ),
|
|
||||||
parseFloat( data[ 5 ] ),
|
|
||||||
parseFloat( data[ 6 ] )
|
|
||||||
).convertSRGBToLinear();
|
|
||||||
|
|
||||||
state.colors.push( _color.r, _color.g, _color.b );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// if no colors are defined, add placeholders so color and vertex indices match
|
|
||||||
|
|
||||||
state.colors.push( undefined, undefined, undefined );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 'vn':
|
|
||||||
state.normals.push(
|
|
||||||
parseFloat( data[ 1 ] ),
|
|
||||||
parseFloat( data[ 2 ] ),
|
|
||||||
parseFloat( data[ 3 ] )
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'vt':
|
|
||||||
state.uvs.push(
|
|
||||||
parseFloat( data[ 1 ] ),
|
|
||||||
parseFloat( data[ 2 ] )
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ( lineFirstChar === 'f' ) {
|
|
||||||
|
|
||||||
const lineData = line.slice( 1 ).trim();
|
|
||||||
const vertexData = lineData.split( _face_vertex_data_separator_pattern );
|
|
||||||
const faceVertices = [];
|
|
||||||
|
|
||||||
// Parse the face vertex data into an easy to work with format
|
|
||||||
|
|
||||||
for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) {
|
|
||||||
|
|
||||||
const vertex = vertexData[ j ];
|
|
||||||
|
|
||||||
if ( vertex.length > 0 ) {
|
|
||||||
|
|
||||||
const vertexParts = vertex.split( '/' );
|
|
||||||
faceVertices.push( vertexParts );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw an edge between the first vertex and all subsequent vertices to form an n-gon
|
|
||||||
|
|
||||||
const v1 = faceVertices[ 0 ];
|
|
||||||
|
|
||||||
for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
|
|
||||||
|
|
||||||
const v2 = faceVertices[ j ];
|
|
||||||
const v3 = faceVertices[ j + 1 ];
|
|
||||||
|
|
||||||
state.addFace(
|
|
||||||
v1[ 0 ], v2[ 0 ], v3[ 0 ],
|
|
||||||
v1[ 1 ], v2[ 1 ], v3[ 1 ],
|
|
||||||
v1[ 2 ], v2[ 2 ], v3[ 2 ]
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ( lineFirstChar === 'l' ) {
|
|
||||||
|
|
||||||
const lineParts = line.substring( 1 ).trim().split( ' ' );
|
|
||||||
let lineVertices = [];
|
|
||||||
const lineUVs = [];
|
|
||||||
|
|
||||||
if ( line.indexOf( '/' ) === - 1 ) {
|
|
||||||
|
|
||||||
lineVertices = lineParts;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) {
|
|
||||||
|
|
||||||
const parts = lineParts[ li ].split( '/' );
|
|
||||||
|
|
||||||
if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );
|
|
||||||
if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
state.addLineGeometry( lineVertices, lineUVs );
|
|
||||||
|
|
||||||
} else if ( lineFirstChar === 'p' ) {
|
|
||||||
|
|
||||||
const lineData = line.slice( 1 ).trim();
|
|
||||||
const pointData = lineData.split( ' ' );
|
|
||||||
|
|
||||||
state.addPointGeometry( pointData );
|
|
||||||
|
|
||||||
} else if ( ( result = _object_pattern.exec( line ) ) !== null ) {
|
|
||||||
|
|
||||||
// o object_name
|
|
||||||
// or
|
|
||||||
// g group_name
|
|
||||||
|
|
||||||
// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
|
|
||||||
// let name = result[ 0 ].slice( 1 ).trim();
|
|
||||||
const name = ( ' ' + result[ 0 ].slice( 1 ).trim() ).slice( 1 );
|
|
||||||
|
|
||||||
state.startObject( name );
|
|
||||||
|
|
||||||
} else if ( _material_use_pattern.test( line ) ) {
|
|
||||||
|
|
||||||
// material
|
|
||||||
|
|
||||||
state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
|
|
||||||
|
|
||||||
} else if ( _material_library_pattern.test( line ) ) {
|
|
||||||
|
|
||||||
// mtl file
|
|
||||||
|
|
||||||
state.materialLibraries.push( line.substring( 7 ).trim() );
|
|
||||||
|
|
||||||
} else if ( _map_use_pattern.test( line ) ) {
|
|
||||||
|
|
||||||
// the line is parsed but ignored since the loader assumes textures are defined MTL files
|
|
||||||
// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
|
|
||||||
|
|
||||||
console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
|
|
||||||
|
|
||||||
} else if ( lineFirstChar === 's' ) {
|
|
||||||
|
|
||||||
result = line.split( ' ' );
|
|
||||||
|
|
||||||
// smooth shading
|
|
||||||
|
|
||||||
// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
|
|
||||||
// but does not define a usemtl for each face set.
|
|
||||||
// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
|
|
||||||
// This requires some care to not create extra material on each smooth value for "normal" obj files.
|
|
||||||
// where explicit usemtl defines geometry groups.
|
|
||||||
// Example asset: examples/models/obj/cerberus/Cerberus.obj
|
|
||||||
|
|
||||||
/*
|
|
||||||
* http://paulbourke.net/dataformats/obj/
|
|
||||||
*
|
|
||||||
* From chapter "Grouping" Syntax explanation "s group_number":
|
|
||||||
* "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
|
|
||||||
* Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
|
|
||||||
* surfaces, smoothing groups are either turned on or off; there is no difference between values greater
|
|
||||||
* than 0."
|
|
||||||
*/
|
|
||||||
if ( result.length > 1 ) {
|
|
||||||
|
|
||||||
const value = result[ 1 ].trim().toLowerCase();
|
|
||||||
state.object.smooth = ( value !== '0' && value !== 'off' );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// ZBrush can produce "s" lines #11707
|
|
||||||
state.object.smooth = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const material = state.object.currentMaterial();
|
|
||||||
if ( material ) material.smooth = state.object.smooth;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Handle null terminated files without exception
|
|
||||||
if ( line === '\0' ) continue;
|
|
||||||
|
|
||||||
console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
state.finalize();
|
|
||||||
|
|
||||||
const container = new Group();
|
|
||||||
container.materialLibraries = [].concat( state.materialLibraries );
|
|
||||||
|
|
||||||
const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );
|
|
||||||
|
|
||||||
if ( hasPrimitives === true ) {
|
|
||||||
|
|
||||||
for ( let i = 0, l = state.objects.length; i < l; i ++ ) {
|
|
||||||
|
|
||||||
const object = state.objects[ i ];
|
|
||||||
const geometry = object.geometry;
|
|
||||||
const materials = object.materials;
|
|
||||||
const isLine = ( geometry.type === 'Line' );
|
|
||||||
const isPoints = ( geometry.type === 'Points' );
|
|
||||||
let hasVertexColors = false;
|
|
||||||
|
|
||||||
// Skip o/g line declarations that did not follow with any faces
|
|
||||||
if ( geometry.vertices.length === 0 ) continue;
|
|
||||||
|
|
||||||
const buffergeometry = new BufferGeometry();
|
|
||||||
|
|
||||||
buffergeometry.setAttribute( 'position', new Float32BufferAttribute( geometry.vertices, 3 ) );
|
|
||||||
|
|
||||||
if ( geometry.normals.length > 0 ) {
|
|
||||||
|
|
||||||
buffergeometry.setAttribute( 'normal', new Float32BufferAttribute( geometry.normals, 3 ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( geometry.colors.length > 0 ) {
|
|
||||||
|
|
||||||
hasVertexColors = true;
|
|
||||||
buffergeometry.setAttribute( 'color', new Float32BufferAttribute( geometry.colors, 3 ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( geometry.hasUVIndices === true ) {
|
|
||||||
|
|
||||||
buffergeometry.setAttribute( 'uv', new Float32BufferAttribute( geometry.uvs, 2 ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create materials
|
|
||||||
|
|
||||||
const createdMaterials = [];
|
|
||||||
|
|
||||||
for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
|
|
||||||
|
|
||||||
const sourceMaterial = materials[ mi ];
|
|
||||||
const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;
|
|
||||||
let material = state.materials[ materialHash ];
|
|
||||||
|
|
||||||
if ( this.materials !== null ) {
|
|
||||||
|
|
||||||
material = this.materials.create( sourceMaterial.name );
|
|
||||||
|
|
||||||
// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
|
|
||||||
if ( isLine && material && ! ( material instanceof LineBasicMaterial ) ) {
|
|
||||||
|
|
||||||
const materialLine = new LineBasicMaterial();
|
|
||||||
Material.prototype.copy.call( materialLine, material );
|
|
||||||
materialLine.color.copy( material.color );
|
|
||||||
material = materialLine;
|
|
||||||
|
|
||||||
} else if ( isPoints && material && ! ( material instanceof PointsMaterial ) ) {
|
|
||||||
|
|
||||||
const materialPoints = new PointsMaterial( { size: 10, sizeAttenuation: false } );
|
|
||||||
Material.prototype.copy.call( materialPoints, material );
|
|
||||||
materialPoints.color.copy( material.color );
|
|
||||||
materialPoints.map = material.map;
|
|
||||||
material = materialPoints;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( material === undefined ) {
|
|
||||||
|
|
||||||
if ( isLine ) {
|
|
||||||
|
|
||||||
material = new LineBasicMaterial();
|
|
||||||
|
|
||||||
} else if ( isPoints ) {
|
|
||||||
|
|
||||||
material = new PointsMaterial( { size: 1, sizeAttenuation: false } );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
material = new MeshPhongMaterial();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
material.name = sourceMaterial.name;
|
|
||||||
material.flatShading = sourceMaterial.smooth ? false : true;
|
|
||||||
material.vertexColors = hasVertexColors;
|
|
||||||
|
|
||||||
state.materials[ materialHash ] = material;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
createdMaterials.push( material );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create mesh
|
|
||||||
|
|
||||||
let mesh;
|
|
||||||
|
|
||||||
if ( createdMaterials.length > 1 ) {
|
|
||||||
|
|
||||||
for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
|
|
||||||
|
|
||||||
const sourceMaterial = materials[ mi ];
|
|
||||||
buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( isLine ) {
|
|
||||||
|
|
||||||
mesh = new LineSegments( buffergeometry, createdMaterials );
|
|
||||||
|
|
||||||
} else if ( isPoints ) {
|
|
||||||
|
|
||||||
mesh = new Points( buffergeometry, createdMaterials );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
mesh = new Mesh( buffergeometry, createdMaterials );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if ( isLine ) {
|
|
||||||
|
|
||||||
mesh = new LineSegments( buffergeometry, createdMaterials[ 0 ] );
|
|
||||||
|
|
||||||
} else if ( isPoints ) {
|
|
||||||
|
|
||||||
mesh = new Points( buffergeometry, createdMaterials[ 0 ] );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
mesh = new Mesh( buffergeometry, createdMaterials[ 0 ] );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
mesh.name = object.name;
|
|
||||||
|
|
||||||
container.add( mesh );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// if there is only the default parser state object with no geometry data, interpret data as point cloud
|
|
||||||
|
|
||||||
if ( state.vertices.length > 0 ) {
|
|
||||||
|
|
||||||
const material = new PointsMaterial( { size: 1, sizeAttenuation: false } );
|
|
||||||
|
|
||||||
const buffergeometry = new BufferGeometry();
|
|
||||||
|
|
||||||
buffergeometry.setAttribute( 'position', new Float32BufferAttribute( state.vertices, 3 ) );
|
|
||||||
|
|
||||||
if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {
|
|
||||||
|
|
||||||
buffergeometry.setAttribute( 'color', new Float32BufferAttribute( state.colors, 3 ) );
|
|
||||||
material.vertexColors = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const points = new Points( buffergeometry, material );
|
|
||||||
container.add( points );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return container;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export { OBJLoader };
|
|
||||||
411
server/plugin/plg_application_3d/vendor/STLLoader.js
vendored
411
server/plugin/plg_application_3d/vendor/STLLoader.js
vendored
|
|
@ -1,411 +0,0 @@
|
||||||
// @ts-nocheck
|
|
||||||
import {
|
|
||||||
BufferAttribute,
|
|
||||||
BufferGeometry,
|
|
||||||
Color,
|
|
||||||
FileLoader,
|
|
||||||
Float32BufferAttribute,
|
|
||||||
Loader,
|
|
||||||
Vector3
|
|
||||||
} from '../../../assets/lib/vendor/three/three.module.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Description: A THREE loader for STL ASCII files, as created by Solidworks and other CAD programs.
|
|
||||||
*
|
|
||||||
* Supports both binary and ASCII encoded files, with automatic detection of type.
|
|
||||||
*
|
|
||||||
* The loader returns a non-indexed buffer geometry.
|
|
||||||
*
|
|
||||||
* Limitations:
|
|
||||||
* Binary decoding supports "Magics" color format (http://en.wikipedia.org/wiki/STL_(file_format)#Color_in_binary_STL).
|
|
||||||
* There is perhaps some question as to how valid it is to always assume little-endian-ness.
|
|
||||||
* ASCII decoding assumes file is UTF-8.
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* const loader = new STLLoader();
|
|
||||||
* loader.load( './models/stl/slotted_disk.stl', function ( geometry ) {
|
|
||||||
* scene.add( new THREE.Mesh( geometry ) );
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* For binary STLs geometry might contain colors for vertices. To use it:
|
|
||||||
* // use the same code to load STL as above
|
|
||||||
* if (geometry.hasColors) {
|
|
||||||
* material = new THREE.MeshPhongMaterial({ opacity: geometry.alpha, vertexColors: true });
|
|
||||||
* } else { .... }
|
|
||||||
* const mesh = new THREE.Mesh( geometry, material );
|
|
||||||
*
|
|
||||||
* For ASCII STLs containing multiple solids, each solid is assigned to a different group.
|
|
||||||
* Groups can be used to assign a different color by defining an array of materials with the same length of
|
|
||||||
* geometry.groups and passing it to the Mesh constructor:
|
|
||||||
*
|
|
||||||
* const mesh = new THREE.Mesh( geometry, material );
|
|
||||||
*
|
|
||||||
* For example:
|
|
||||||
*
|
|
||||||
* const materials = [];
|
|
||||||
* const nGeometryGroups = geometry.groups.length;
|
|
||||||
*
|
|
||||||
* const colorMap = ...; // Some logic to index colors.
|
|
||||||
*
|
|
||||||
* for (let i = 0; i < nGeometryGroups; i++) {
|
|
||||||
*
|
|
||||||
* const material = new THREE.MeshPhongMaterial({
|
|
||||||
* color: colorMap[i],
|
|
||||||
* wireframe: false
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* materials.push(material);
|
|
||||||
* const mesh = new THREE.Mesh(geometry, materials);
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
class STLLoader extends Loader {
|
|
||||||
|
|
||||||
constructor( manager ) {
|
|
||||||
|
|
||||||
super( manager );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
load( url, onLoad, onProgress, onError ) {
|
|
||||||
|
|
||||||
const scope = this;
|
|
||||||
|
|
||||||
const loader = new FileLoader( this.manager );
|
|
||||||
loader.setPath( this.path );
|
|
||||||
loader.setResponseType( 'arraybuffer' );
|
|
||||||
loader.setRequestHeader( this.requestHeader );
|
|
||||||
loader.setWithCredentials( this.withCredentials );
|
|
||||||
|
|
||||||
loader.load( url, function ( text ) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
onLoad( scope.parse( text ) );
|
|
||||||
|
|
||||||
} catch ( e ) {
|
|
||||||
|
|
||||||
if ( onError ) {
|
|
||||||
|
|
||||||
onError( e );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
console.error( e );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
scope.manager.itemError( url );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}, onProgress, onError );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
parse( data ) {
|
|
||||||
|
|
||||||
function isBinary( data ) {
|
|
||||||
|
|
||||||
const reader = new DataView( data );
|
|
||||||
const face_size = ( 32 / 8 * 3 ) + ( ( 32 / 8 * 3 ) * 3 ) + ( 16 / 8 );
|
|
||||||
const n_faces = reader.getUint32( 80, true );
|
|
||||||
const expect = 80 + ( 32 / 8 ) + ( n_faces * face_size );
|
|
||||||
|
|
||||||
if ( expect === reader.byteLength ) {
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// An ASCII STL data must begin with 'solid ' as the first six bytes.
|
|
||||||
// However, ASCII STLs lacking the SPACE after the 'd' are known to be
|
|
||||||
// plentiful. So, check the first 5 bytes for 'solid'.
|
|
||||||
|
|
||||||
// Several encodings, such as UTF-8, precede the text with up to 5 bytes:
|
|
||||||
// https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
|
|
||||||
// Search for "solid" to start anywhere after those prefixes.
|
|
||||||
|
|
||||||
// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
|
|
||||||
|
|
||||||
const solid = [ 115, 111, 108, 105, 100 ];
|
|
||||||
|
|
||||||
for ( let off = 0; off < 5; off ++ ) {
|
|
||||||
|
|
||||||
// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
|
|
||||||
|
|
||||||
if ( matchDataViewAt( solid, reader, off ) ) return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Couldn't find "solid" text at the beginning; it is binary STL.
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function matchDataViewAt( query, reader, offset ) {
|
|
||||||
|
|
||||||
// Check if each byte in query matches the corresponding byte from the current offset
|
|
||||||
|
|
||||||
for ( let i = 0, il = query.length; i < il; i ++ ) {
|
|
||||||
|
|
||||||
if ( query[ i ] !== reader.getUint8( offset + i ) ) return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseBinary( data ) {
|
|
||||||
|
|
||||||
const reader = new DataView( data );
|
|
||||||
const faces = reader.getUint32( 80, true );
|
|
||||||
|
|
||||||
let r, g, b, hasColors = false, colors;
|
|
||||||
let defaultR, defaultG, defaultB, alpha;
|
|
||||||
|
|
||||||
// process STL header
|
|
||||||
// check for default color in header ("COLOR=rgba" sequence).
|
|
||||||
|
|
||||||
for ( let index = 0; index < 80 - 10; index ++ ) {
|
|
||||||
|
|
||||||
if ( ( reader.getUint32( index, false ) == 0x434F4C4F /*COLO*/ ) &&
|
|
||||||
( reader.getUint8( index + 4 ) == 0x52 /*'R'*/ ) &&
|
|
||||||
( reader.getUint8( index + 5 ) == 0x3D /*'='*/ ) ) {
|
|
||||||
|
|
||||||
hasColors = true;
|
|
||||||
colors = new Float32Array( faces * 3 * 3 );
|
|
||||||
|
|
||||||
defaultR = reader.getUint8( index + 6 ) / 255;
|
|
||||||
defaultG = reader.getUint8( index + 7 ) / 255;
|
|
||||||
defaultB = reader.getUint8( index + 8 ) / 255;
|
|
||||||
alpha = reader.getUint8( index + 9 ) / 255;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataOffset = 84;
|
|
||||||
const faceLength = 12 * 4 + 2;
|
|
||||||
|
|
||||||
const geometry = new BufferGeometry();
|
|
||||||
|
|
||||||
const vertices = new Float32Array( faces * 3 * 3 );
|
|
||||||
const normals = new Float32Array( faces * 3 * 3 );
|
|
||||||
|
|
||||||
const color = new Color();
|
|
||||||
|
|
||||||
for ( let face = 0; face < faces; face ++ ) {
|
|
||||||
|
|
||||||
const start = dataOffset + face * faceLength;
|
|
||||||
const normalX = reader.getFloat32( start, true );
|
|
||||||
const normalY = reader.getFloat32( start + 4, true );
|
|
||||||
const normalZ = reader.getFloat32( start + 8, true );
|
|
||||||
|
|
||||||
if ( hasColors ) {
|
|
||||||
|
|
||||||
const packedColor = reader.getUint16( start + 48, true );
|
|
||||||
|
|
||||||
if ( ( packedColor & 0x8000 ) === 0 ) {
|
|
||||||
|
|
||||||
// facet has its own unique color
|
|
||||||
|
|
||||||
r = ( packedColor & 0x1F ) / 31;
|
|
||||||
g = ( ( packedColor >> 5 ) & 0x1F ) / 31;
|
|
||||||
b = ( ( packedColor >> 10 ) & 0x1F ) / 31;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
r = defaultR;
|
|
||||||
g = defaultG;
|
|
||||||
b = defaultB;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( let i = 1; i <= 3; i ++ ) {
|
|
||||||
|
|
||||||
const vertexstart = start + i * 12;
|
|
||||||
const componentIdx = ( face * 3 * 3 ) + ( ( i - 1 ) * 3 );
|
|
||||||
|
|
||||||
vertices[ componentIdx ] = reader.getFloat32( vertexstart, true );
|
|
||||||
vertices[ componentIdx + 1 ] = reader.getFloat32( vertexstart + 4, true );
|
|
||||||
vertices[ componentIdx + 2 ] = reader.getFloat32( vertexstart + 8, true );
|
|
||||||
|
|
||||||
normals[ componentIdx ] = normalX;
|
|
||||||
normals[ componentIdx + 1 ] = normalY;
|
|
||||||
normals[ componentIdx + 2 ] = normalZ;
|
|
||||||
|
|
||||||
if ( hasColors ) {
|
|
||||||
|
|
||||||
color.set( r, g, b ).convertSRGBToLinear();
|
|
||||||
|
|
||||||
colors[ componentIdx ] = color.r;
|
|
||||||
colors[ componentIdx + 1 ] = color.g;
|
|
||||||
colors[ componentIdx + 2 ] = color.b;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
geometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) );
|
|
||||||
geometry.setAttribute( 'normal', new BufferAttribute( normals, 3 ) );
|
|
||||||
|
|
||||||
if ( hasColors ) {
|
|
||||||
|
|
||||||
geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
|
|
||||||
geometry.hasColors = true;
|
|
||||||
geometry.alpha = alpha;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return geometry;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseASCII( data ) {
|
|
||||||
|
|
||||||
const geometry = new BufferGeometry();
|
|
||||||
const patternSolid = /solid([\s\S]*?)endsolid/g;
|
|
||||||
const patternFace = /facet([\s\S]*?)endfacet/g;
|
|
||||||
const patternName = /solid\s(.+)/;
|
|
||||||
let faceCounter = 0;
|
|
||||||
|
|
||||||
const patternFloat = /[\s]+([+-]?(?:\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?)/.source;
|
|
||||||
const patternVertex = new RegExp( 'vertex' + patternFloat + patternFloat + patternFloat, 'g' );
|
|
||||||
const patternNormal = new RegExp( 'normal' + patternFloat + patternFloat + patternFloat, 'g' );
|
|
||||||
|
|
||||||
const vertices = [];
|
|
||||||
const normals = [];
|
|
||||||
const groupNames = [];
|
|
||||||
|
|
||||||
const normal = new Vector3();
|
|
||||||
|
|
||||||
let result;
|
|
||||||
|
|
||||||
let groupCount = 0;
|
|
||||||
let startVertex = 0;
|
|
||||||
let endVertex = 0;
|
|
||||||
|
|
||||||
while ( ( result = patternSolid.exec( data ) ) !== null ) {
|
|
||||||
|
|
||||||
startVertex = endVertex;
|
|
||||||
|
|
||||||
const solid = result[ 0 ];
|
|
||||||
|
|
||||||
const name = ( result = patternName.exec( solid ) ) !== null ? result[ 1 ] : '';
|
|
||||||
groupNames.push( name );
|
|
||||||
|
|
||||||
while ( ( result = patternFace.exec( solid ) ) !== null ) {
|
|
||||||
|
|
||||||
let vertexCountPerFace = 0;
|
|
||||||
let normalCountPerFace = 0;
|
|
||||||
|
|
||||||
const text = result[ 0 ];
|
|
||||||
|
|
||||||
while ( ( result = patternNormal.exec( text ) ) !== null ) {
|
|
||||||
|
|
||||||
normal.x = parseFloat( result[ 1 ] );
|
|
||||||
normal.y = parseFloat( result[ 2 ] );
|
|
||||||
normal.z = parseFloat( result[ 3 ] );
|
|
||||||
normalCountPerFace ++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( ( result = patternVertex.exec( text ) ) !== null ) {
|
|
||||||
|
|
||||||
vertices.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
|
|
||||||
normals.push( normal.x, normal.y, normal.z );
|
|
||||||
vertexCountPerFace ++;
|
|
||||||
endVertex ++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// every face have to own ONE valid normal
|
|
||||||
|
|
||||||
if ( normalCountPerFace !== 1 ) {
|
|
||||||
|
|
||||||
console.error( 'THREE.STLLoader: Something isn\'t right with the normal of face number ' + faceCounter );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// each face have to own THREE valid vertices
|
|
||||||
|
|
||||||
if ( vertexCountPerFace !== 3 ) {
|
|
||||||
|
|
||||||
console.error( 'THREE.STLLoader: Something isn\'t right with the vertices of face number ' + faceCounter );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
faceCounter ++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const start = startVertex;
|
|
||||||
const count = endVertex - startVertex;
|
|
||||||
|
|
||||||
geometry.userData.groupNames = groupNames;
|
|
||||||
|
|
||||||
geometry.addGroup( start, count, groupCount );
|
|
||||||
groupCount ++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
|
||||||
geometry.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
|
||||||
|
|
||||||
return geometry;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureString( buffer ) {
|
|
||||||
|
|
||||||
if ( typeof buffer !== 'string' ) {
|
|
||||||
|
|
||||||
return new TextDecoder().decode( buffer );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureBinary( buffer ) {
|
|
||||||
|
|
||||||
if ( typeof buffer === 'string' ) {
|
|
||||||
|
|
||||||
const array_buffer = new Uint8Array( buffer.length );
|
|
||||||
for ( let i = 0; i < buffer.length; i ++ ) {
|
|
||||||
|
|
||||||
array_buffer[ i ] = buffer.charCodeAt( i ) & 0xff; // implicitly assumes little-endian
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return array_buffer.buffer || array_buffer;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// start
|
|
||||||
|
|
||||||
const binData = ensureBinary( data );
|
|
||||||
|
|
||||||
return isBinary( binData ) ? parseBinary( binData ) : parseASCII( ensureString( data ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export { STLLoader };
|
|
||||||
3174
server/plugin/plg_application_3d/vendor/SVGLoader.js
vendored
3174
server/plugin/plg_application_3d/vendor/SVGLoader.js
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,81 +0,0 @@
|
||||||
// @ts-nocheck
|
|
||||||
import {
|
|
||||||
Curve,
|
|
||||||
Vector3,
|
|
||||||
Vector4
|
|
||||||
} from '../../../../assets/lib/vendor/three/three.module.js';
|
|
||||||
import * as NURBSUtils from './NURBSUtils.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NURBS curve object
|
|
||||||
*
|
|
||||||
* Derives from Curve, overriding getPoint and getTangent.
|
|
||||||
*
|
|
||||||
* Implementation is based on (x, y [, z=0 [, w=1]]) control points with w=weight.
|
|
||||||
*
|
|
||||||
**/
|
|
||||||
|
|
||||||
class NURBSCurve extends Curve {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
degree,
|
|
||||||
knots /* array of reals */,
|
|
||||||
controlPoints /* array of Vector(2|3|4) */,
|
|
||||||
startKnot /* index in knots */,
|
|
||||||
endKnot /* index in knots */
|
|
||||||
) {
|
|
||||||
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.degree = degree;
|
|
||||||
this.knots = knots;
|
|
||||||
this.controlPoints = [];
|
|
||||||
// Used by periodic NURBS to remove hidden spans
|
|
||||||
this.startKnot = startKnot || 0;
|
|
||||||
this.endKnot = endKnot || ( this.knots.length - 1 );
|
|
||||||
|
|
||||||
for ( let i = 0; i < controlPoints.length; ++ i ) {
|
|
||||||
|
|
||||||
// ensure Vector4 for control points
|
|
||||||
const point = controlPoints[ i ];
|
|
||||||
this.controlPoints[ i ] = new Vector4( point.x, point.y, point.z, point.w );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
getPoint( t, optionalTarget = new Vector3() ) {
|
|
||||||
|
|
||||||
const point = optionalTarget;
|
|
||||||
|
|
||||||
const u = this.knots[ this.startKnot ] + t * ( this.knots[ this.endKnot ] - this.knots[ this.startKnot ] ); // linear mapping t->u
|
|
||||||
|
|
||||||
// following results in (wx, wy, wz, w) homogeneous point
|
|
||||||
const hpoint = NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u );
|
|
||||||
|
|
||||||
if ( hpoint.w !== 1.0 ) {
|
|
||||||
|
|
||||||
// project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1)
|
|
||||||
hpoint.divideScalar( hpoint.w );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return point.set( hpoint.x, hpoint.y, hpoint.z );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
getTangent( t, optionalTarget = new Vector3() ) {
|
|
||||||
|
|
||||||
const tangent = optionalTarget;
|
|
||||||
|
|
||||||
const u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] );
|
|
||||||
const ders = NURBSUtils.calcNURBSDerivatives( this.degree, this.knots, this.controlPoints, u, 1 );
|
|
||||||
tangent.copy( ders[ 1 ] ).normalize();
|
|
||||||
|
|
||||||
return tangent;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export { NURBSCurve };
|
|
||||||
|
|
@ -1,488 +0,0 @@
|
||||||
// @ts-nocheck
|
|
||||||
import {
|
|
||||||
Vector3,
|
|
||||||
Vector4
|
|
||||||
} from '../../../../assets/lib/vendor/three/three.module.js';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* NURBS utils
|
|
||||||
*
|
|
||||||
* See NURBSCurve and NURBSSurface.
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************
|
|
||||||
* NURBS Utils
|
|
||||||
**************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Finds knot vector span.
|
|
||||||
|
|
||||||
p : degree
|
|
||||||
u : parametric value
|
|
||||||
U : knot vector
|
|
||||||
|
|
||||||
returns the span
|
|
||||||
*/
|
|
||||||
function findSpan( p, u, U ) {
|
|
||||||
|
|
||||||
const n = U.length - p - 1;
|
|
||||||
|
|
||||||
if ( u >= U[ n ] ) {
|
|
||||||
|
|
||||||
return n - 1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( u <= U[ p ] ) {
|
|
||||||
|
|
||||||
return p;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
let low = p;
|
|
||||||
let high = n;
|
|
||||||
let mid = Math.floor( ( low + high ) / 2 );
|
|
||||||
|
|
||||||
while ( u < U[ mid ] || u >= U[ mid + 1 ] ) {
|
|
||||||
|
|
||||||
if ( u < U[ mid ] ) {
|
|
||||||
|
|
||||||
high = mid;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
low = mid;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
mid = Math.floor( ( low + high ) / 2 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return mid;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate basis functions. See The NURBS Book, page 70, algorithm A2.2
|
|
||||||
|
|
||||||
span : span in which u lies
|
|
||||||
u : parametric point
|
|
||||||
p : degree
|
|
||||||
U : knot vector
|
|
||||||
|
|
||||||
returns array[p+1] with basis functions values.
|
|
||||||
*/
|
|
||||||
function calcBasisFunctions( span, u, p, U ) {
|
|
||||||
|
|
||||||
const N = [];
|
|
||||||
const left = [];
|
|
||||||
const right = [];
|
|
||||||
N[ 0 ] = 1.0;
|
|
||||||
|
|
||||||
for ( let j = 1; j <= p; ++ j ) {
|
|
||||||
|
|
||||||
left[ j ] = u - U[ span + 1 - j ];
|
|
||||||
right[ j ] = U[ span + j ] - u;
|
|
||||||
|
|
||||||
let saved = 0.0;
|
|
||||||
|
|
||||||
for ( let r = 0; r < j; ++ r ) {
|
|
||||||
|
|
||||||
const rv = right[ r + 1 ];
|
|
||||||
const lv = left[ j - r ];
|
|
||||||
const temp = N[ r ] / ( rv + lv );
|
|
||||||
N[ r ] = saved + rv * temp;
|
|
||||||
saved = lv * temp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
N[ j ] = saved;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return N;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate B-Spline curve points. See The NURBS Book, page 82, algorithm A3.1.
|
|
||||||
|
|
||||||
p : degree of B-Spline
|
|
||||||
U : knot vector
|
|
||||||
P : control points (x, y, z, w)
|
|
||||||
u : parametric point
|
|
||||||
|
|
||||||
returns point for given u
|
|
||||||
*/
|
|
||||||
function calcBSplinePoint( p, U, P, u ) {
|
|
||||||
|
|
||||||
const span = findSpan( p, u, U );
|
|
||||||
const N = calcBasisFunctions( span, u, p, U );
|
|
||||||
const C = new Vector4( 0, 0, 0, 0 );
|
|
||||||
|
|
||||||
for ( let j = 0; j <= p; ++ j ) {
|
|
||||||
|
|
||||||
const point = P[ span - p + j ];
|
|
||||||
const Nj = N[ j ];
|
|
||||||
const wNj = point.w * Nj;
|
|
||||||
C.x += point.x * wNj;
|
|
||||||
C.y += point.y * wNj;
|
|
||||||
C.z += point.z * wNj;
|
|
||||||
C.w += point.w * Nj;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return C;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate basis functions derivatives. See The NURBS Book, page 72, algorithm A2.3.
|
|
||||||
|
|
||||||
span : span in which u lies
|
|
||||||
u : parametric point
|
|
||||||
p : degree
|
|
||||||
n : number of derivatives to calculate
|
|
||||||
U : knot vector
|
|
||||||
|
|
||||||
returns array[n+1][p+1] with basis functions derivatives
|
|
||||||
*/
|
|
||||||
function calcBasisFunctionDerivatives( span, u, p, n, U ) {
|
|
||||||
|
|
||||||
const zeroArr = [];
|
|
||||||
for ( let i = 0; i <= p; ++ i )
|
|
||||||
zeroArr[ i ] = 0.0;
|
|
||||||
|
|
||||||
const ders = [];
|
|
||||||
|
|
||||||
for ( let i = 0; i <= n; ++ i )
|
|
||||||
ders[ i ] = zeroArr.slice( 0 );
|
|
||||||
|
|
||||||
const ndu = [];
|
|
||||||
|
|
||||||
for ( let i = 0; i <= p; ++ i )
|
|
||||||
ndu[ i ] = zeroArr.slice( 0 );
|
|
||||||
|
|
||||||
ndu[ 0 ][ 0 ] = 1.0;
|
|
||||||
|
|
||||||
const left = zeroArr.slice( 0 );
|
|
||||||
const right = zeroArr.slice( 0 );
|
|
||||||
|
|
||||||
for ( let j = 1; j <= p; ++ j ) {
|
|
||||||
|
|
||||||
left[ j ] = u - U[ span + 1 - j ];
|
|
||||||
right[ j ] = U[ span + j ] - u;
|
|
||||||
|
|
||||||
let saved = 0.0;
|
|
||||||
|
|
||||||
for ( let r = 0; r < j; ++ r ) {
|
|
||||||
|
|
||||||
const rv = right[ r + 1 ];
|
|
||||||
const lv = left[ j - r ];
|
|
||||||
ndu[ j ][ r ] = rv + lv;
|
|
||||||
|
|
||||||
const temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ];
|
|
||||||
ndu[ r ][ j ] = saved + rv * temp;
|
|
||||||
saved = lv * temp;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ndu[ j ][ j ] = saved;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( let j = 0; j <= p; ++ j ) {
|
|
||||||
|
|
||||||
ders[ 0 ][ j ] = ndu[ j ][ p ];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( let r = 0; r <= p; ++ r ) {
|
|
||||||
|
|
||||||
let s1 = 0;
|
|
||||||
let s2 = 1;
|
|
||||||
|
|
||||||
const a = [];
|
|
||||||
for ( let i = 0; i <= p; ++ i ) {
|
|
||||||
|
|
||||||
a[ i ] = zeroArr.slice( 0 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
a[ 0 ][ 0 ] = 1.0;
|
|
||||||
|
|
||||||
for ( let k = 1; k <= n; ++ k ) {
|
|
||||||
|
|
||||||
let d = 0.0;
|
|
||||||
const rk = r - k;
|
|
||||||
const pk = p - k;
|
|
||||||
|
|
||||||
if ( r >= k ) {
|
|
||||||
|
|
||||||
a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ];
|
|
||||||
d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const j1 = ( rk >= - 1 ) ? 1 : - rk;
|
|
||||||
const j2 = ( r - 1 <= pk ) ? k - 1 : p - r;
|
|
||||||
|
|
||||||
for ( let j = j1; j <= j2; ++ j ) {
|
|
||||||
|
|
||||||
a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ];
|
|
||||||
d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( r <= pk ) {
|
|
||||||
|
|
||||||
a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ];
|
|
||||||
d += a[ s2 ][ k ] * ndu[ r ][ pk ];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ders[ k ][ r ] = d;
|
|
||||||
|
|
||||||
const j = s1;
|
|
||||||
s1 = s2;
|
|
||||||
s2 = j;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
let r = p;
|
|
||||||
|
|
||||||
for ( let k = 1; k <= n; ++ k ) {
|
|
||||||
|
|
||||||
for ( let j = 0; j <= p; ++ j ) {
|
|
||||||
|
|
||||||
ders[ k ][ j ] *= r;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
r *= p - k;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return ders;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
|
|
||||||
|
|
||||||
p : degree
|
|
||||||
U : knot vector
|
|
||||||
P : control points
|
|
||||||
u : Parametric points
|
|
||||||
nd : number of derivatives
|
|
||||||
|
|
||||||
returns array[d+1] with derivatives
|
|
||||||
*/
|
|
||||||
function calcBSplineDerivatives( p, U, P, u, nd ) {
|
|
||||||
|
|
||||||
const du = nd < p ? nd : p;
|
|
||||||
const CK = [];
|
|
||||||
const span = findSpan( p, u, U );
|
|
||||||
const nders = calcBasisFunctionDerivatives( span, u, p, du, U );
|
|
||||||
const Pw = [];
|
|
||||||
|
|
||||||
for ( let i = 0; i < P.length; ++ i ) {
|
|
||||||
|
|
||||||
const point = P[ i ].clone();
|
|
||||||
const w = point.w;
|
|
||||||
|
|
||||||
point.x *= w;
|
|
||||||
point.y *= w;
|
|
||||||
point.z *= w;
|
|
||||||
|
|
||||||
Pw[ i ] = point;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( let k = 0; k <= du; ++ k ) {
|
|
||||||
|
|
||||||
const point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] );
|
|
||||||
|
|
||||||
for ( let j = 1; j <= p; ++ j ) {
|
|
||||||
|
|
||||||
point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CK[ k ] = point;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( let k = du + 1; k <= nd + 1; ++ k ) {
|
|
||||||
|
|
||||||
CK[ k ] = new Vector4( 0, 0, 0 );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return CK;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate "K over I"
|
|
||||||
|
|
||||||
returns k!/(i!(k-i)!)
|
|
||||||
*/
|
|
||||||
function calcKoverI( k, i ) {
|
|
||||||
|
|
||||||
let nom = 1;
|
|
||||||
|
|
||||||
for ( let j = 2; j <= k; ++ j ) {
|
|
||||||
|
|
||||||
nom *= j;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
let denom = 1;
|
|
||||||
|
|
||||||
for ( let j = 2; j <= i; ++ j ) {
|
|
||||||
|
|
||||||
denom *= j;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( let j = 2; j <= k - i; ++ j ) {
|
|
||||||
|
|
||||||
denom *= j;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return nom / denom;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate derivatives (0-nd) of rational curve. See The NURBS Book, page 127, algorithm A4.2.
|
|
||||||
|
|
||||||
Pders : result of function calcBSplineDerivatives
|
|
||||||
|
|
||||||
returns array with derivatives for rational curve.
|
|
||||||
*/
|
|
||||||
function calcRationalCurveDerivatives( Pders ) {
|
|
||||||
|
|
||||||
const nd = Pders.length;
|
|
||||||
const Aders = [];
|
|
||||||
const wders = [];
|
|
||||||
|
|
||||||
for ( let i = 0; i < nd; ++ i ) {
|
|
||||||
|
|
||||||
const point = Pders[ i ];
|
|
||||||
Aders[ i ] = new Vector3( point.x, point.y, point.z );
|
|
||||||
wders[ i ] = point.w;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const CK = [];
|
|
||||||
|
|
||||||
for ( let k = 0; k < nd; ++ k ) {
|
|
||||||
|
|
||||||
const v = Aders[ k ].clone();
|
|
||||||
|
|
||||||
for ( let i = 1; i <= k; ++ i ) {
|
|
||||||
|
|
||||||
v.sub( CK[ k - i ].clone().multiplyScalar( calcKoverI( k, i ) * wders[ i ] ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CK[ k ] = v.divideScalar( wders[ 0 ] );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return CK;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate NURBS curve derivatives. See The NURBS Book, page 127, algorithm A4.2.
|
|
||||||
|
|
||||||
p : degree
|
|
||||||
U : knot vector
|
|
||||||
P : control points in homogeneous space
|
|
||||||
u : parametric points
|
|
||||||
nd : number of derivatives
|
|
||||||
|
|
||||||
returns array with derivatives.
|
|
||||||
*/
|
|
||||||
function calcNURBSDerivatives( p, U, P, u, nd ) {
|
|
||||||
|
|
||||||
const Pders = calcBSplineDerivatives( p, U, P, u, nd );
|
|
||||||
return calcRationalCurveDerivatives( Pders );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.
|
|
||||||
|
|
||||||
p1, p2 : degrees of B-Spline surface
|
|
||||||
U1, U2 : knot vectors
|
|
||||||
P : control points (x, y, z, w)
|
|
||||||
u, v : parametric values
|
|
||||||
|
|
||||||
returns point for given (u, v)
|
|
||||||
*/
|
|
||||||
function calcSurfacePoint( p, q, U, V, P, u, v, target ) {
|
|
||||||
|
|
||||||
const uspan = findSpan( p, u, U );
|
|
||||||
const vspan = findSpan( q, v, V );
|
|
||||||
const Nu = calcBasisFunctions( uspan, u, p, U );
|
|
||||||
const Nv = calcBasisFunctions( vspan, v, q, V );
|
|
||||||
const temp = [];
|
|
||||||
|
|
||||||
for ( let l = 0; l <= q; ++ l ) {
|
|
||||||
|
|
||||||
temp[ l ] = new Vector4( 0, 0, 0, 0 );
|
|
||||||
for ( let k = 0; k <= p; ++ k ) {
|
|
||||||
|
|
||||||
const point = P[ uspan - p + k ][ vspan - q + l ].clone();
|
|
||||||
const w = point.w;
|
|
||||||
point.x *= w;
|
|
||||||
point.y *= w;
|
|
||||||
point.z *= w;
|
|
||||||
temp[ l ].add( point.multiplyScalar( Nu[ k ] ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const Sw = new Vector4( 0, 0, 0, 0 );
|
|
||||||
for ( let l = 0; l <= q; ++ l ) {
|
|
||||||
|
|
||||||
Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Sw.divideScalar( Sw.w );
|
|
||||||
target.set( Sw.x, Sw.y, Sw.z );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export {
|
|
||||||
findSpan,
|
|
||||||
calcBasisFunctions,
|
|
||||||
calcBSplinePoint,
|
|
||||||
calcBasisFunctionDerivatives,
|
|
||||||
calcBSplineDerivatives,
|
|
||||||
calcKoverI,
|
|
||||||
calcRationalCurveDerivatives,
|
|
||||||
calcNURBSDerivatives,
|
|
||||||
calcSurfacePoint,
|
|
||||||
};
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,15 +0,0 @@
|
||||||
all:
|
|
||||||
make build
|
|
||||||
make install
|
|
||||||
make clean
|
|
||||||
|
|
||||||
build:
|
|
||||||
emcc -O2 -c loader_symbol.c
|
|
||||||
emcc --no-entry loader_symbol.o -o loader_symbol.wasm
|
|
||||||
|
|
||||||
install:
|
|
||||||
zip -r application_dev.zip .
|
|
||||||
mv application_dev.zip ../../../dist/data/state/plugins/
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm *.o *.wasm
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
import assert from "../../assets/lib/assert.js";
|
|
||||||
import loadWASM, { writeFS, readFS } from "../../assets/helpers/loader_wasm.js";
|
|
||||||
|
|
||||||
export default async function(ITable) {
|
|
||||||
const { instance } = await loadWASM(import.meta.url, "./loader_symbol.wasm");
|
|
||||||
|
|
||||||
return class TableImpl extends ITable {
|
|
||||||
constructor(response) {
|
|
||||||
super();
|
|
||||||
const fdIn = writeFS(new Uint8Array(response));
|
|
||||||
const fdOut = writeFS(new Uint8Array([]));
|
|
||||||
const res = assert.truthy(instance.exports["execute"])(fdIn, fdOut);
|
|
||||||
if (res !== 0) throw new Error(`WASM exited with code=${res}`);
|
|
||||||
const buffer = readFS(fdOut);
|
|
||||||
|
|
||||||
this.header = [
|
|
||||||
{ name: "Mode", size: 3 },
|
|
||||||
{ name: "Timestamp", size: 6 },
|
|
||||||
{ name: "Size", size: 4 },
|
|
||||||
{ name: "Owner", size: 6 },
|
|
||||||
{ name: "Group", size: 6 },
|
|
||||||
{ name: "Object", size: 40 },
|
|
||||||
];
|
|
||||||
this.rows = new TextDecoder().decode(buffer).trimRight().split("\n").map((line) => {
|
|
||||||
const row = line.split(",");
|
|
||||||
return {
|
|
||||||
"Object": row[0],
|
|
||||||
"Timestamp": row[1],
|
|
||||||
"Size": row[5],
|
|
||||||
"Mode": row[4],
|
|
||||||
"Owner": row[2],
|
|
||||||
"Group": row[3],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getHeader() {
|
|
||||||
return this.header;
|
|
||||||
}
|
|
||||||
|
|
||||||
getBody() {
|
|
||||||
return this.rows;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <emscripten/emscripten.h>
|
|
||||||
|
|
||||||
#define ARMAG "!<arch>\n"
|
|
||||||
#define SARMAG sizeof(ARMAG) - 1
|
|
||||||
#define AR_HDR_SIZE 60
|
|
||||||
|
|
||||||
struct ar_hdr {
|
|
||||||
char name[16];
|
|
||||||
char timestamp[12];
|
|
||||||
char owner[6];
|
|
||||||
char group[6];
|
|
||||||
char mode[8];
|
|
||||||
char size[10];
|
|
||||||
char fmag[2];
|
|
||||||
};
|
|
||||||
|
|
||||||
EMSCRIPTEN_KEEPALIVE int execute(int fdinput, int fdoutput) {
|
|
||||||
if (fdinput == 0) {
|
|
||||||
fprintf(stderr, "ERROR - missing input %d\n", fdinput);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (fdoutput == 0) {
|
|
||||||
fprintf(stderr, "ERROR - missing input %d\n", fdoutput);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* finput = fdopen(fdinput, "rb");
|
|
||||||
if (!finput) {
|
|
||||||
fprintf(stderr, "ERROR - cannot open input file\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
FILE* foutput = fdopen(fdoutput, "wb");
|
|
||||||
if (!foutput) {
|
|
||||||
fprintf(stderr, "ERROR - cannot open output file\n");
|
|
||||||
fclose(finput);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char magic[SARMAG];
|
|
||||||
size_t c = fread(magic, 1, SARMAG, finput);
|
|
||||||
if (c == 0) {
|
|
||||||
fprintf(stderr, "ERROR count=%zu error=%d\n", c, ferror(finput));
|
|
||||||
fclose(finput);
|
|
||||||
fclose(foutput);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (strncmp(magic, ARMAG, SARMAG) != 0) {
|
|
||||||
fprintf(stderr, "ERROR bad magic value");
|
|
||||||
fclose(finput);
|
|
||||||
fclose(foutput);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ar_hdr header;
|
|
||||||
while (fread(&header, 1, AR_HDR_SIZE, finput) == AR_HDR_SIZE) {
|
|
||||||
if (strncmp(header.fmag, "`\n", 2) != 0) {
|
|
||||||
fprintf(stderr, "Invalid header format.\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
long size = strtol(header.size, NULL, 10);
|
|
||||||
char filename[17] = {0};
|
|
||||||
strncpy(filename, header.name, 16);
|
|
||||||
for (int i = strlen(filename) - 1; i >= 0; i--) {
|
|
||||||
if (filename[i] == ' ' || filename[i] == '/') {
|
|
||||||
filename[i] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strlen(filename) > 0) fprintf(
|
|
||||||
foutput,
|
|
||||||
"%.16s,%ld,%ld,%ld,%ld,%ld\n",
|
|
||||||
filename,
|
|
||||||
strtol(header.timestamp, NULL, 10),
|
|
||||||
strtol(header.owner, NULL, 10),
|
|
||||||
strtol(header.group, NULL, 10),
|
|
||||||
strtol(header.mode, NULL, 10),
|
|
||||||
size,
|
|
||||||
);
|
|
||||||
fseek(finput, (size + 1) & ~1, SEEK_CUR);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "hello world!\n");
|
|
||||||
fflush(foutput);
|
|
||||||
fclose(foutput);
|
|
||||||
fclose(finput);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"author": "Filestash Pty Ltd",
|
|
||||||
"version": "v0.0",
|
|
||||||
"modules": [
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "application/x-archive",
|
|
||||||
"application": "table"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
all:
|
|
||||||
make install
|
|
||||||
|
|
||||||
install:
|
|
||||||
zip -r application_map.zip .
|
|
||||||
mv application_map.zip ../../../dist/data/state/plugins/
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
export const PLUGINS = [
|
|
||||||
"plugin_grayscale",
|
|
||||||
];
|
|
||||||
export const DEFAULT_TILE_SERVER = "https://tile.openstreetmap.org/{z}/{x}/{y}.png";
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
import { PLUGINS, DEFAULT_TILE_SERVER } from "./constant.js";
|
|
||||||
|
|
||||||
export default async function(IMap) {
|
|
||||||
const plugins = await Promise.all(PLUGINS.map((name) => import(`./plugins/${name}.js`)));
|
|
||||||
|
|
||||||
return class MapImpl extends IMap {
|
|
||||||
constructor(response, { map, $page }) {
|
|
||||||
super();
|
|
||||||
this.response = JSON.parse(new TextDecoder().decode(response));
|
|
||||||
|
|
||||||
window.L.tileLayer(DEFAULT_TILE_SERVER, { maxZoom: 21 }).addTo(map);
|
|
||||||
plugins.forEach((plugin) => plugin.default({ map, $page }));
|
|
||||||
}
|
|
||||||
|
|
||||||
async toGeoJSON() {
|
|
||||||
return this.response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,128 +0,0 @@
|
||||||
import { PLUGINS, DEFAULT_TILE_SERVER } from "./constant.js";
|
|
||||||
|
|
||||||
export default async function(IMap) {
|
|
||||||
const plugins = await Promise.all(PLUGINS.map((name) => import(`./plugins/${name}.js`)));
|
|
||||||
|
|
||||||
return class MapImpl extends IMap {
|
|
||||||
constructor(response, { L, map, $page }) {
|
|
||||||
super();
|
|
||||||
const xmlDoc = new DOMParser().parseFromString(
|
|
||||||
new TextDecoder().decode(response),
|
|
||||||
"application/xml",
|
|
||||||
);
|
|
||||||
this.xmlDoc = xmlDoc;
|
|
||||||
L.tileLayer(DEFAULT_TILE_SERVER, { maxZoom: 21 }).addTo(map);
|
|
||||||
plugins.forEach((plugin) => plugin.default({ map, $page }));
|
|
||||||
}
|
|
||||||
|
|
||||||
async toGeoJSON() {
|
|
||||||
let geoJSON = {
|
|
||||||
type: "FeatureCollection",
|
|
||||||
features: [],
|
|
||||||
};
|
|
||||||
this.xmlDoc.querySelectorAll("wpt").forEach((wayPoint) => {
|
|
||||||
geoJSON.features.push({
|
|
||||||
type: "Feature",
|
|
||||||
geometry: {
|
|
||||||
type: "Point",
|
|
||||||
coordinates: [
|
|
||||||
Number(wayPoint.getAttribute("lon")),
|
|
||||||
Number(wayPoint.getAttribute("lat")),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
group: "waypoint",
|
|
||||||
"popup::type": "html",
|
|
||||||
"popup::content": createLegendFromXML(wayPoint),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.xmlDoc.querySelectorAll("rte").forEach((route) => {
|
|
||||||
const coordinates = [];
|
|
||||||
route.querySelectorAll("rtept").forEach((point) => {
|
|
||||||
const lon = Number(point.getAttribute("lon"));
|
|
||||||
const lat = Number(point.getAttribute("lat"));
|
|
||||||
if (!isNaN(lon) && !isNaN(lat)) {
|
|
||||||
coordinates.push([lon, lat]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (coordinates.length > 0) geoJSON.features.push({
|
|
||||||
type: "Feature",
|
|
||||||
geometry: {
|
|
||||||
type: "LineString",
|
|
||||||
coordinates: coordinates,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
group: "path",
|
|
||||||
weight: 5,
|
|
||||||
name: route.querySelector("name").textContent,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.xmlDoc.querySelectorAll("trk").forEach((track) => {
|
|
||||||
track.querySelectorAll("trkseg").forEach((segment) => {
|
|
||||||
const group = "Track: " + track.querySelector("name").textContent;
|
|
||||||
const coordinates = [];
|
|
||||||
segment.querySelectorAll("trkpt").forEach((point) => {
|
|
||||||
const lon = Number(point.getAttribute("lon"));
|
|
||||||
const lat = Number(point.getAttribute("lat"));
|
|
||||||
if (!isNaN(lon) && !isNaN(lat)) {
|
|
||||||
coordinates.push([lon, lat]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (coordinates.length > 0) {
|
|
||||||
geoJSON.features.push({
|
|
||||||
type: "Feature",
|
|
||||||
geometry: {
|
|
||||||
type: "LineString",
|
|
||||||
coordinates: coordinates,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
group,
|
|
||||||
color: "brown",
|
|
||||||
weight: 3,
|
|
||||||
name: track.querySelector("name").textContent,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
geoJSON.features.push({
|
|
||||||
type: "Feature",
|
|
||||||
geometry: {
|
|
||||||
type: "Point",
|
|
||||||
coordinates: coordinates[0],
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
group,
|
|
||||||
color: "green",
|
|
||||||
name: "Start: " + group,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
geoJSON.features.push({
|
|
||||||
type: "Feature",
|
|
||||||
geometry: {
|
|
||||||
type: "Point",
|
|
||||||
coordinates: coordinates.slice(-1)[0],
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
group,
|
|
||||||
color: "red",
|
|
||||||
name: "Arrival: " + group,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return geoJSON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function createLegendFromXML(point) {
|
|
||||||
return [...point.children]
|
|
||||||
.map((tag) => `
|
|
||||||
<div class="ellipsis" style="line-height: 1rem;">
|
|
||||||
<strong style="text-transform: capitalize;">${tag.tagName}: </strong>
|
|
||||||
${tag.textContent || "N/A"}
|
|
||||||
</div>
|
|
||||||
`)
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
import { PLUGINS, DEFAULT_TILE_SERVER } from "./constant.js";
|
|
||||||
|
|
||||||
export default async function(IMap) {
|
|
||||||
let modules = await Promise.all(PLUGINS.map((name) => import(`./plugins/${name}.js`)));
|
|
||||||
|
|
||||||
return class MapImpl extends IMap {
|
|
||||||
constructor(response, { map, $page }) {
|
|
||||||
super();
|
|
||||||
for (let i=0; i<PLUGINS.length; i++) {
|
|
||||||
modules.forEach((module) => module.default({ map, $page }));
|
|
||||||
}
|
|
||||||
const xmlDoc = new DOMParser().parseFromString(
|
|
||||||
new TextDecoder().decode(response),
|
|
||||||
"application/xml",
|
|
||||||
);
|
|
||||||
const svcURL = (function() {
|
|
||||||
const svc = xmlDoc.querySelector("Capability OnlineResource");
|
|
||||||
if (!svc) return "";
|
|
||||||
return svc.getAttribute("xlink:href");
|
|
||||||
}());
|
|
||||||
let _layer = "";
|
|
||||||
const baseLayers = {};
|
|
||||||
xmlDoc.querySelectorAll("Layer").forEach((layer) => {
|
|
||||||
_layer = layer.querySelector("Name").textContent;
|
|
||||||
baseLayers[layer.querySelector("Title").textContent] = window.L.tileLayer.wms(svcURL, {
|
|
||||||
layers: _layer,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
map.setView([0, 0], 1);
|
|
||||||
window.L.tileLayer.wms(svcURL, { layers: _layer }).addTo(map);
|
|
||||||
window.L.control.layers(baseLayers, {}).addTo(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
async toGeoJSON() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
{
|
|
||||||
"author": "Filestash Pty Ltd",
|
|
||||||
"version": "v0.0",
|
|
||||||
"modules": [
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "application/geo+json",
|
|
||||||
"entrypoint": "/index_geojson.js",
|
|
||||||
"application": "map"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "application/vnd.ogc.wms_xml",
|
|
||||||
"entrypoint": "/index_wms.js",
|
|
||||||
"application": "map"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "xdg-open",
|
|
||||||
"mime": "application/gpx+xml",
|
|
||||||
"entrypoint": "/index_gpx.js",
|
|
||||||
"application": "map"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
import { createElement } from "../../../assets/lib/skeleton/index.js";
|
|
||||||
|
|
||||||
const PERCENT = "85%";
|
|
||||||
|
|
||||||
export default async function({ $page }) {
|
|
||||||
$page.appendChild(createElement(`
|
|
||||||
<style>#map img.leaflet-tile { filter: grayscale(${PERCENT}); }</style>
|
|
||||||
`));
|
|
||||||
}
|
|
||||||
|
|
@ -87,11 +87,12 @@ func Build(r *mux.Router, a App) {
|
||||||
r.HandleFunc(WithBase("/api/plugin"), NewMiddlewareChain(PluginExportHandler, append(middlewares, PublicCORS), a)).Methods("GET", "OPTIONS")
|
r.HandleFunc(WithBase("/api/plugin"), NewMiddlewareChain(PluginExportHandler, append(middlewares, PublicCORS), a)).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc(WithBase("/api/config"), NewMiddlewareChain(PublicConfigHandler, append(middlewares, PublicCORS), a)).Methods("GET", "OPTIONS")
|
r.HandleFunc(WithBase("/api/config"), NewMiddlewareChain(PublicConfigHandler, append(middlewares, PublicCORS), a)).Methods("GET", "OPTIONS")
|
||||||
middlewares = []Middleware{StaticHeaders, SecureHeaders, PublicCORS, PluginInjector}
|
middlewares = []Middleware{StaticHeaders, SecureHeaders, PublicCORS, PluginInjector}
|
||||||
r.PathPrefix(WithBase("/assets")).Handler(http.HandlerFunc(NewMiddlewareChain(ServeFile("/"), middlewares, a))).Methods("GET", "OPTIONS")
|
r.HandleFunc(WithBase("/assets/"+BUILD_REF+"/plugin/{name}.zip/{path:.+}"), NewMiddlewareChain(PluginStaticHandler, middlewares, a)).Methods("GET", "OPTIONS")
|
||||||
|
r.HandleFunc(WithBase("/assets/"+BUILD_REF+"/plugin/{name}.zip"), NewMiddlewareChain(PluginDownloadHandler, middlewares, a)).Methods("GET")
|
||||||
|
r.PathPrefix(WithBase("/assets/"+BUILD_REF)).Handler(http.HandlerFunc(NewMiddlewareChain(ServeFile("/"), middlewares, a))).Methods("GET", "OPTIONS")
|
||||||
|
r.PathPrefix(WithBase("/assets/bundle")).Handler(http.HandlerFunc(NewMiddlewareChain(ServeBundle, middlewares, a))).Methods("GET", "OPTIONS")
|
||||||
r.HandleFunc(WithBase("/sw.js"), http.HandlerFunc(NewMiddlewareChain(ServeFile("/assets/"), middlewares, a))).Methods("GET")
|
r.HandleFunc(WithBase("/sw.js"), http.HandlerFunc(NewMiddlewareChain(ServeFile("/assets/"), middlewares, a))).Methods("GET")
|
||||||
r.HandleFunc(WithBase("/favicon.ico"), NewMiddlewareChain(ServeFavicon, middlewares, a)).Methods("GET")
|
r.HandleFunc(WithBase("/favicon.ico"), NewMiddlewareChain(ServeFavicon, middlewares, a)).Methods("GET")
|
||||||
r.HandleFunc(WithBase("/plugin/{name}/{path:.+}"), NewMiddlewareChain(PluginStaticHandler, middlewares, a)).Methods("GET")
|
|
||||||
r.HandleFunc(WithBase("/plugin/{name}.zip"), NewMiddlewareChain(PluginDownloadHandler, middlewares, a)).Methods("GET")
|
|
||||||
|
|
||||||
// Other endpoints
|
// Other endpoints
|
||||||
middlewares = []Middleware{ApiHeaders, PluginInjector, PublicCORS}
|
middlewares = []Middleware{ApiHeaders, PluginInjector, PublicCORS}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue