misc improvements

This commit is contained in:
Yeicor
2024-02-10 13:37:30 +01:00
parent dda1162953
commit f8ee906f45
11 changed files with 113 additions and 44 deletions

View File

@@ -2,33 +2,34 @@
import ModelViewer from './ModelViewer.vue'
import {ref} from "vue";
import Loading from "./Loading.vue";
let modelsOpened = ref(false)
let toolsOpened = ref(true)
// Open models by default on wide screens
let modelsOpened = ref(window.innerWidth > 600);
</script>
<
<template>
<v-layout>
<v-btn @click="modelsOpened = !modelsOpened" max-width="22px" style="position:absolute; z-index: 1">&gt;</v-btn>
<v-navigation-drawer v-model="modelsOpened">
<v-list density="compact" nav > <!-- TODO: Accordion -->
<v-list-item-title>Models <v-btn @click="modelsOpened = !modelsOpened" style="float: right" height="22px"><</v-btn></v-list-item-title>
<v-list-item prepend-icon="mdi-view-dashboard" title="Home" value="home"></v-list-item>
<v-list-item prepend-icon="mdi-forum" title="About" value="about"></v-list-item>
<v-layout full-height>
<v-btn icon="$menu" @click="modelsOpened = !modelsOpened" style="position: absolute; z-index: 1"/>
<v-navigation-drawer v-model="modelsOpened" permanent>
<v-toolbar>
<v-toolbar-title>Models</v-toolbar-title>
<v-toolbar-items>
<v-btn icon="$close" @click="modelsOpened = !modelsOpened"/>
</v-toolbar-items>
</v-toolbar>
<v-list density="compact" nav> <!-- TODO: Accordion -->
<v-list-item><Loading/></v-list-item>
</v-list>
</v-navigation-drawer>
<v-main style="height: 100vh">
<v-main >
<ModelViewer/>
</v-main>
<v-navigation-drawer location="right" v-model="toolsOpened" opa>
<v-list density="compact" nav >
<v-list-item-title>Tools</v-list-item-title>
<v-list-item prepend-icon="mdi-view-dashboard" title="Home" value="home"></v-list-item>
<v-list-item prepend-icon="mdi-forum" title="About" value="about"></v-list-item>
</v-list>
</v-navigation-drawer>
</v-layout>
</template>
<style scoped>
<style>
html, body {
height: 100%;
}
</style>

9
src/Loading.vue Normal file
View File

@@ -0,0 +1,9 @@
<template>
<v-container style="height: 100%">
<v-row justify="center" style="height: 100%">
<v-col align-self="center">
<v-progress-circular indeterminate style="display: block; margin: 0 auto;"/>
</v-col>
</v-row>
</v-container>
</template>

View File

@@ -1,11 +1,19 @@
<script setup lang="ts">
import ModelViewerWrapper from "./ModelViewerWrapper.vue";
import ModelViewerOverlay from "./ModelViewerOverlay.vue";
import Loading from "./Loading.vue";
import {defineAsyncComponent} from "vue";
// NOTE: The ModelViewer library is big, so we split it and import it asynchronously
const ModelViewerWrapper = defineAsyncComponent({
loader: () => import('./ModelViewerWrapper.vue'),
loadingComponent: Loading,
delay: 0,
});
</script>
<template>
<ModelViewerWrapper/>
<ModelViewerOverlay/>
<model-viewer-wrapper/>
<model-viewer-overlay/>
</template>
<style scoped>

View File

@@ -9,7 +9,7 @@ import {ModelScene} from "@google/model-viewer/lib/three-components/ModelScene";
let _ = ModelViewerElement // HACK: Keep the import from being removed by the bundler
const viewer = ref(null);
onMounted(() => {
// TODO: Custom gizmo component inside Tools window
// TODO: Custom gizmo component inside tools sidebar
// Gizmo installation
let scene: ModelScene = viewer.value[$scene];
let gizmo = new OrientationGizmo(scene);
@@ -28,7 +28,7 @@ onMounted(() => {
<template>
<model-viewer
ref="viewer" style="width: 100%; height: 100%" :src="settings.preloadModel" alt="The 3D model(s)" camera-controls
ref="viewer" style="width: 100%; height: 100%" :src="settings.preloadModels[0]" alt="The 3D model(s)" camera-controls
camera-orbit="30deg 75deg auto" max-camera-orbit="Infinity 180deg auto" min-camera-orbit="-Infinity 0deg auto"
:exposure="settings.exposure" :shadow-intensity="settings.shadowIntensity" interaction-prompt="none"
:autoplay="settings.autoplay" :ar="settings.arModes.length > 0" :ar-modes="settings.arModes"

View File

@@ -14,6 +14,7 @@ import App from './App.vue'
import 'vuetify/lib/styles/main.sass';
import { createVuetify } from 'vuetify';
import '@mdi/font/css/materialdesignicons.css'
// TODO: Only import the components and directives that are actually used
// @ts-ignore
@@ -31,5 +32,4 @@ const vuetify = createVuetify({
const app = createApp(App)
app.use(vuetify)
app.config.compilerOptions.isCustomElement = tag => tag === 'model-viewer'
app.mount('body')

View File

@@ -1,31 +1,48 @@
// @ts-ignore
import skyboxUrl from '../assets/st_peters_square_night_8k.jpg';
// @ts-ignore
import logo from "url:../assets/fox.glb";
// import logo from "url:../assets/fox.glb";
// These are the default values for the settings, which are overridden below
export const settings = {
// @ts-ignore
preloadModels: [new URL('../assets/fox.glb', import.meta.url).href, "ws://localhost:8080/api/updates"],
// ModelViewer settings
preloadModel: logo,
autoplay: true,
arModes: 'webxr scene-viewer quick-look',
exposure: 1,
shadowIntensity: 0,
background: skyboxUrl,
background: '',
}
const firstTimeNames = []; // Needed for array values, which clear the array when overridden
function parseSetting(name: string, value: string): any {
let arrayElem = name.endsWith(".0")
if (arrayElem) name = name.slice(0, -2);
let prevValue = settings[name];
if (prevValue === undefined) throw new Error(`Unknown setting: ${name}`);
if (Array.isArray(prevValue) && !arrayElem) {
let toExtend = []
if (!firstTimeNames.includes(name)) {
firstTimeNames.push(name);
} else {
toExtend = prevValue;
}
toExtend.push(parseSetting(name+".0", value));
return toExtend;
}
switch (typeof prevValue) {
case 'boolean':
return value === 'true';
case 'number':
return Number(value);
case 'string':
return value;
default:
throw new Error(`Unknown setting type: ${typeof prevValue}`);
}
}
// Auto-override any settings from the URL
const url = new URL(window.location.href);
url.searchParams.forEach((value, key) => {
if (key in settings) {
switch (typeof settings[key]) {
case 'boolean':
settings[key] = value === 'true';
break;
case 'number':
settings[key] = Number(value);
break;
default:
settings[key] = value;
}
}
if (key in settings) settings[key] = parseSetting(key, value);
})