wip: feat/godot

This commit is contained in:
Leon van Kammen 2025-08-22 11:30:34 +02:00
parent 24c65543cc
commit acbfed004d
11 changed files with 28221 additions and 15 deletions

View file

@ -51,7 +51,9 @@ $ manyfold/cli/manyfold run -v ./experiences:/mnt/experiences
| `APPNAME` | `manyfold` | manyfold instance name | | `APPNAME` | `manyfold` | manyfold instance name |
| `HOMEPAGE` | `/models` | show '/models' URL as homepage (use `/` for manyfold default) | | `HOMEPAGE` | `/models` | show '/models' URL as homepage (use `/` for manyfold default) |
| `THEME` | `default` | bootstrap theme | | `THEME` | `default` | bootstrap theme |
| `GODOT_VERSION` | `4.4.1-stable`| godot editor version |
| `RUNTESTS` | `0` | set to `1` to run XRForge related [/test](test) scripts | | `RUNTESTS` | `0` | set to `1` to run XRForge related [/test](test) scripts |
| `DEV` | `` | enable development mode (disables caching, sets `bin/dev` as entrypoint) |
| `NO_PUBLIC_ONLY` | `` | disable public only models | | `NO_PUBLIC_ONLY` | `` | disable public only models |
| `NO_OVERLAYFS` | `` | disable the filesystem overlay mechanism | | `NO_OVERLAYFS` | `` | disable the filesystem overlay mechanism |
| `NO_DEFAULTDB` | `` | disable the default xrforge db (activates manyfold installer) | | `NO_DEFAULTDB` | `` | disable the default xrforge db (activates manyfold installer) |
@ -60,7 +62,8 @@ $ manyfold/cli/manyfold run -v ./experiences:/mnt/experiences
| `NO_PACKAGEALL` | `` | don't package all experiences every hour to /usr/src/app/public/experiences.zip | | `NO_PACKAGEALL` | `` | don't package all experiences every hour to /usr/src/app/public/experiences.zip |
| `RCLONE_REMOTE` | `` | specify **single** rclone remote name (without semicolon) to mount (default: mount all rclone remotes)| | `RCLONE_REMOTE` | `` | specify **single** rclone remote name (without semicolon) to mount (default: mount all rclone remotes)|
| `UPLOAD_PATH` | `/mnt/experiences`| specify default library where user-files are uploaded (regular dir or mounted rclone path) | | `UPLOAD_PATH` | `/mnt/experiences`| specify default library where user-files are uploaded (regular dir or mounted rclone path) |
| `FEDERATE_DRIVE_PATH` | `/mnt/experiences`| serve path over HTTP (so other instances can add it as a remote). Specify `0` to disable | | `FEDERATE_DRIVE_HOST` | `http://localhost:3215` | host adress which other hosts can use to access the federate drive |
| `FEDERATE_DRIVE_PATH` | `/mnt` | serve path over HTTP (so other instances can add it as a remote). Specify `0` to disable |
| `FEDERATE_DRIVE_PORT` | `3215` | specify default library where user-files are uploaded (regular dir or mounted rclone path) | | `FEDERATE_DRIVE_PORT` | `3215` | specify default library where user-files are uploaded (regular dir or mounted rclone path) |
| `FEDERATE_DRIVE_USER` | `` | specify HTTP AUTH credentials (`user` e.g.) for restricted sharing | | `FEDERATE_DRIVE_USER` | `` | specify HTTP AUTH credentials (`user` e.g.) for restricted sharing |
| `FEDERATE_DRIVE_PW` | `` | specify HTTP AUTH credentials (`pass` e.g.) for restricted sharing | | `FEDERATE_DRIVE_PW` | `` | specify HTTP AUTH credentials (`pass` e.g.) for restricted sharing |
@ -171,3 +174,12 @@ In theory, federated drives can still be reacted upon, but by integrating with X
> Perhaps in the future this will also work for rclone remotes, by writing a `hourly`-script which scans them and fires `inotify_MODIFY` accordingly. > Perhaps in the future this will also work for rclone remotes, by writing a `hourly`-script which scans them and fires `inotify_MODIFY` accordingly.
# Customization
See the [manyfold](https://github.com/manyfold3d/manyfold) repository.
For a quick dev-environment run:
```
$ mkdir /dev
$ manyfold/cli/manyfold.sh run -e DEV=1
```

View file

@ -1,9 +1,10 @@
#!/bin/sh #!/bin/sh
oci=$(which podman || which docker) oci=$(which podman || which docker)
test -n "$APPNAME" || APPNAME=xrforge test -n "$APPNAME" || APPNAME=xrforge
test -n "$UPLOAD_PATH" || UPLOAD_PATH=/mnt/experiences test -n "$UPLOAD_PATH" || UPLOAD_PATH=/mnt/experiences
test -n "$THEME" || THEME=vapor # xrforge (public/assets/themes/xrforge.css gives err) test -n "$THEME" || THEME=slate
test -n "$HOMEPAGE" || HOMEPAGE=/models test -n "$HOMEPAGE" || HOMEPAGE=/models
test -n "$GODOT_VERSION" || GODOT_VERSION=4.4.1-stable
db=/config/manyfold.sqlite3 db=/config/manyfold.sqlite3
# utility funcs # utility funcs
@ -27,11 +28,13 @@ run(){
debug ${oci} run "$@" -p 8790:3214 -p 8791:3215 --name xrforge \ debug ${oci} run "$@" -p 8790:3214 -p 8791:3215 --name xrforge \
-e SECRET_KEY_BASE=lkjwljlkwejrlkjek34k234l \ -e SECRET_KEY_BASE=lkjwljlkwejrlkjek34k234l \
-e DATABASE_ADAPTER=sqlite3 \ -e DATABASE_ADAPTER=sqlite3 \
-e FEDERATE_DRIVE_HOST=http://localhost:8791 \
-e SUDO_RUN_UNSAFELY=enabled \ -e SUDO_RUN_UNSAFELY=enabled \
-e MULTIUSER=enabled \ -e MULTIUSER=enabled \
-e FEDERATION=enabled \ -e FEDERATION=enabled \
-e THEME=$THEME \ -e THEME=$THEME \
-e HOMEPAGE=$HOMEPAGE \ -e HOMEPAGE=$HOMEPAGE \
-e GODOT_VERSION=4.4.1-stable \
-e FEDERATE_DRIVE_CACHE=5s \ -e FEDERATE_DRIVE_CACHE=5s \
--cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse \ --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse \
xrforge xrforge
@ -81,7 +84,10 @@ start_hook_daemon(){
$0 infinite 86400 hook daily & $0 infinite 86400 hook daily &
$0 infinite 3600 hook hourly & $0 infinite 3600 hook hourly &
# trigger hooks when files change in /mnt/experiences # trigger hooks when files change in /mnt/experiences
inotifywait -r -m $UPLOAD_PATH | awk '$2 ~ /(CREATE|MODIFY|MOVED_TO|DELETE)/ { system("'$0' hook inotify_"$2" "$1""$3) }' & find /mnt -type d -mindepth 1 -maxdepth 1 | while read dir; do
echocolor "[$APPNAME]" "listening to inotify events in $dir"
inotifywait -r -m $dir | awk '$2 ~ /(CREATE|MODIFY|MOVED_TO|DELETE)/ { system("'$0' hook inotify_"$2" "$1""$3) }' &
done
} }
@ -119,6 +125,7 @@ mount_dir(){
find /mnt -type d -mindepth 1 -maxdepth 1 | while read dir; do find /mnt -type d -mindepth 1 -maxdepth 1 | while read dir; do
echocolor "[$APPNAME]" "mounting $dir as library" echocolor "[$APPNAME]" "mounting $dir as library"
add_lib_to_db "$dir" add_lib_to_db "$dir"
ln -s "$dir" /usr/src/app/public/.
done done
} }
@ -198,17 +205,16 @@ force_public(){
get_xrfragment_assets(){ get_xrfragment_assets(){
test -n "$NO_ASSETS" && return 0 # nothing to do here test -n "$NO_ASSETS" && return 0 # nothing to do here
test -d /mnt/assets || { test -d /mnt/asset || {
echocolor "fetching XR Fragments assets & templates" echocolor "fetching XR Fragments asset & templates"
mkdir -p /mnt/assets/xrfragment /mnt/templates/xrfragment mkdir -p /mnt/asset/xrfragment /mnt/templates/xrfragment
cd /tmp cd /tmp
timeout 50 wget "https://codeberg.org/coderofsalvation/xrfragment/archive/main.zip" timeout 50 wget "https://codeberg.org/coderofsalvation/xrfragment/archive/main.zip"
unzip main.zip unzip main.zip
cp -r xrfragment/assets/library /mnt/assets/xrfragment/\#1 cp -r xrfragment/assets/library /mnt/asset/xrfragment/\#1
cp -r xrfragment/assets/template /mnt/templates/xrfragment/\#2 cp -r xrfragment/assets/template /mnt/templates/xrfragment/\#2
rm -rf main.zip xrfragment
} }
add_lib_to_db /mnt/assets add_lib_to_db /mnt/asset
add_lib_to_db /mnt/templates add_lib_to_db /mnt/templates
} }
@ -222,15 +228,22 @@ boot(){
set_homepage set_homepage
set_theme set_theme
set_modelpath set_modelpath
mount_dir
mount_rclone mount_rclone
set_upload_path set_upload_path
start_hook_daemon
force_public force_public
get_xrfragment_assets get_xrfragment_assets
scan_libraries & scan_libraries &
mount_dir
start_hook_daemon
hook boot # emit unixy hook-event (/root/hook.d/boot/* scripts) hook boot # emit unixy hook-event (/root/hook.d/boot/* scripts)
# enable development mode (disables template caching etc)
test -n "$DEV" && {
sed -i 's|^exec.*|exec s6-setuidgid $PUID:$PGID bin/dev|g' /usr/src/app/bin/docker-entrypoint.sh
sed -i 's|config.enable_reloading = false|config.enable_reloading = true|g' /usr/src/app/config/environments/production.rb
apk add vim
}
exec "$@" # exec prevents error 's6-overlay-suexec: fatal: can only run as pid 1' exec "$@" # exec prevents error 's6-overlay-suexec: fatal: can only run as pid 1'
} }

View file

@ -0,0 +1,6 @@
#!/bin/sh
test -z "$GODOT_VERSION" && exit 0 # nothing to do
wget "https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_web_editor.zip" -O /root/godot.zip
cd /usr/src/app/public/godot
unzip /root/godot.zip
cp index.override.html index.html # make index.html autoload a manyfold zip-file (passed via HTTP query)

View file

@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
test -z "$FEDERATE_DRIVE_PATH" && FEDERATE_DRIVE_PATH=/mnt/experiences test -z "$FEDERATE_DRIVE_HOST" && FEDERATE_DRIVE_HOST=http://localhost:3215
test -z "$FEDERATE_DRIVE_PATH" && FEDERATE_DRIVE_PATH=/mnt
test -z "$FEDERATE_DRIVE_PORT" && FEDERATE_DRIVE_PORT=3215 test -z "$FEDERATE_DRIVE_PORT" && FEDERATE_DRIVE_PORT=3215
test -z "$FEDERATE_DRIVE_CACHE" && FEDERATE_DRIVE_CACHE=1m0s test -z "$FEDERATE_DRIVE_CACHE" && FEDERATE_DRIVE_CACHE=1m0s

View file

@ -0,0 +1,9 @@
#!/bin/sh
echo "$1" | grep datapackage || exit 0 # nothing to do
dir=$(dirname $1)
cd "$dir"
echo "[package_experience.sh] zipping $dir.zip"
test -d ~/tpl_godot.zip || timeout 50 wget "https://codeberg.org/coderofsalvation/xrfragment-godot/archive/main.zip" -O ~/tpl_godot.zip
cp ~/tpl_godot.zip package_godot.zip
zip package_godot.zip *.glb *.usdz *.obj

5
manyfold/test/rclone.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
which rclone &>/dev/null || { echo "[!] rclone not installed"; exit 0; }
test -d /mnt/models || { echo "[!] /mnt/models does not exist"; exit 0; }

View file

@ -0,0 +1,125 @@
# frozen_string_literal: true
class Components::ModelCard < Components::Base
include Phlex::Rails::Helpers::ImageTag
include Phlex::Rails::Helpers::Sanitize
include Phlex::Rails::Helpers::LinkTo
register_output_helper :status_badges
register_output_helper :server_indicator
register_value_helper :policy
def initialize(model:)
@model = model
end
def view_template
div class: "col mb-4" do
div class: "card preview-card" do
div(class: "card-header position-absolute w-100 top-0 z-3 bg-body-secondary text-secondary-emphasis opacity-75") { server_indicator @model } if @model.remote?
PreviewFrame(object: @model)
div(class: "card-body") { info_row }
actions
end
end
end
private
def title
div class: "card-title" do
a "data-editable-field": "model[name]", "data-editable-path": model_path(@model), contenteditable: "plaintext-only", "data-controller": "editable", "data-action": "focus->editable#onFocus blur->editable#onBlur" do
@model.name
end
if @model.sensitive
whitespace
Icon(icon: "explicit", label: Model.human_attribute_name(:sensitive))
end
whitespace
AccessIndicator(object: @model)
end
end
def open_button
if @model.remote?
link_to @model.federails_actor.profile_url, {class: "btn btn-primary btn-sm", "aria-label": translate("components.model_card.open_button.label", name: @model.name)} do
span { "" }
whitespace
span { t("components.model_card.open_button.text") }
end
else
link_to t("components.model_card.open_button.text"), @model, {class: "btn btn-primary btn-sm", "aria-label": translate("components.model_card.open_button.label", name: @model.name)}
end
end
def credits
ul class: "list-unstyled" do
if @model.remote?
if (creator = @model.federails_actor.extensions["attributedTo"])
li { creator target: creator["url"], name: creator["name"] }
end
if (collection = @model.federails_actor.extensions["context"])
li { collection target: collection["url"], name: collection["name"] }
end
else
li { creator target: @model.creator, name: @model.creator.name } if @model.creator
li { collection target: @model.collection, name: @model.collection.name } if @model.collection
end
end
end
def creator(target:, name:)
Icon icon: "person", label: Creator.model_name.human
whitespace
link_to name, target, "aria-label": [Creator.model_name.human, name].join(": ")
end
def collection(target:, name:)
Icon icon: "collection", label: Collection.model_name.human
whitespace
link_to name, target, "aria-label": [Collection.model_name.human, name].join(": ")
end
def caption
if @model.caption
span class: "card-subtitle text-muted" do
sanitize @model.caption
end
end
end
def info_row
div class: "row" do
div class: "col" do
title
caption
end
div class: "col-auto" do
small do
credits
end
end
end
end
def actions
div class: "card-footer" do
div class: "row" do
div class: "col" do
#open_button
#whitespace
status_badges @model
end
div class: "col col-auto" do
BurgerMenu do
DropdownItem(icon: "app", label: "Open in Godot Web" , path: "/godot/?url="+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/package_godot.zip", aria_label: translate("components.model_card.edit_button.label", name: @model.name))
DropdownItem(icon: "pencil", label: t("components.model_card.edit_button.text"), path: model_path(@model), aria_label: translate("components.model_card.edit_button.label", name: @model.name))
DropdownItem(icon: "trash", label: t("components.model_card.delete_button.text"), path: model_path(@model), method: :delete, aria_label: translate("components.model_card.delete_button.label", name: @model.name), confirm: translate("models.destroy.confirm")) if policy(@model).destroy?
DropdownItem(icon: "flag", label: t("general.report", type: ""), path: new_model_report_path(@model)) if SiteSettings.multiuser_enabled?
end
end
end
end
end
end

View file

@ -0,0 +1,10 @@
Rails.application.configure do
config.content_security_policy_nonce_generator = lambda do |request|
# Always exclude /godot/* from CSP
if request.path.start_with?("/godot/")
nil
elsif !(Rails.env.development? && ENV.fetch("SCOUT_DEV_TRACE", false) == "true")
request.session.id.to_s
end
end
end

View file

@ -0,0 +1,327 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="128.27411mm"
height="145.65482mm"
viewBox="0 0 128.27411 145.65482"
version="1.1"
id="svg5"
xml:space="preserve"
inkscape:export-filename="../../../../../Downloads/xrforge.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
sodipodi:docname="logo.svg"
inkscape:dataloss="true"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.56323837"
inkscape:cx="226.36952"
inkscape:cy="409.24058"
inkscape:window-width="1920"
inkscape:window-height="1030"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" /><defs
id="defs2"><linearGradient
inkscape:collect="always"
id="linearGradient12286"><stop
style="stop-color:#ea0bfe;stop-opacity:0.11569338;"
offset="0"
id="stop12282" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop12284" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient12159"><stop
style="stop-color:#fe83ff;stop-opacity:0.35045233;"
offset="0"
id="stop12155" /><stop
style="stop-color:#3c9cff;stop-opacity:0.32712477;"
offset="1"
id="stop12157" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient12153"><stop
style="stop-color:#fe83ff;stop-opacity:0.29342434;"
offset="0"
id="stop12149" /><stop
style="stop-color:#3c9cff;stop-opacity:0.31577286;"
offset="1"
id="stop12151" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient12139"><stop
style="stop-color:#ea0bfe;stop-opacity:0.50826901;"
offset="0"
id="stop12135" /><stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop12137" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient12102"><stop
style="stop-color:#fe83ff;stop-opacity:1;"
offset="0"
id="stop12098" /><stop
style="stop-color:#3c9cff;stop-opacity:0.81848603;"
offset="1"
id="stop12100" /></linearGradient><linearGradient
inkscape:collect="always"
id="linearGradient7688"><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop7684" /><stop
style="stop-color:#ff13f3;stop-opacity:0;"
offset="1"
id="stop7686" /></linearGradient><linearGradient
id="linearGradient6742"><stop
style="stop-color:#276fff;stop-opacity:1"
offset="0"
id="stop6738" /><stop
style="stop-color:#ff16bc;stop-opacity:1"
offset="1"
id="stop6740" /></linearGradient><linearGradient
xlink:href="#linearGradient6742"
id="linearGradient8637"
x1="154.78049"
y1="24.048252"
x2="273.12695"
y2="24.048252"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient7688"
id="linearGradient7692"
x1="115.42191"
y1="-2.709012"
x2="117.16759"
y2="131.87457"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12102"
id="linearGradient12104"
x1="54.029213"
y1="71.733955"
x2="176.85757"
y2="71.733955"
gradientUnits="userSpaceOnUse" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12159"
id="linearGradient12108"
gradientUnits="userSpaceOnUse"
x1="54.029213"
y1="71.733955"
x2="176.85757"
y2="71.733955"
gradientTransform="translate(0,4.7625002)" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12153"
id="linearGradient12112"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0,19.579173)"
x1="54.029213"
y1="71.733955"
x2="176.85757"
y2="71.733955" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12286"
id="linearGradient12141"
x1="137.33427"
y1="88.766113"
x2="177.37935"
y2="88.766113"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2850723,0,0,1.2367478,-50.791853,-16.999519)" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12139"
id="linearGradient12239"
gradientUnits="userSpaceOnUse"
x1="137.33427"
y1="88.766113"
x2="177.37935"
y2="88.766113"
gradientTransform="matrix(-1.2669282,0,0,1.2603766,278.3952,-19.18513)" /><filter
style="color-interpolation-filters:sRGB"
inkscape:label="Drop Shadow"
id="filter12743"
x="-0.079006463"
y="-0.2479955"
width="1.1580434"
height="1.4959902"><feFlood
flood-opacity="1"
flood-color="rgb(204,26,255)"
result="flood"
id="feFlood12733" /><feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite12735" /><feGaussianBlur
in="composite1"
stdDeviation="1.1"
result="blur"
id="feGaussianBlur12737" /><feOffset
dx="0"
dy="0"
result="offset"
id="feOffset12739" /><feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite12741" /></filter><filter
style="color-interpolation-filters:sRGB"
inkscape:label="Drop Shadow"
id="filter13745"
x="-0.13448349"
y="-0.73597109"
width="1.268967"
height="2.4719422"><feFlood
flood-opacity="1"
flood-color="rgb(26,135,255)"
result="flood"
id="feFlood13735" /><feComposite
in="flood"
in2="SourceGraphic"
operator="in"
result="composite1"
id="feComposite13737" /><feGaussianBlur
in="composite1"
stdDeviation="4.48865"
result="blur"
id="feGaussianBlur13739" /><feOffset
dx="0"
dy="0"
result="offset"
id="feOffset13741" /><feComposite
in="SourceGraphic"
in2="offset"
operator="over"
result="composite2"
id="feComposite13743" /></filter><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient12286"
id="linearGradient14475"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2850723,0,0,1.2367478,-50.791853,-16.999519)"
x1="137.33427"
y1="88.766113"
x2="177.37935"
y2="88.766113" /></defs><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-51.358538,-4.8451999)"><path
sodipodi:type="star"
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:2.3;stroke-dasharray:none"
id="path1638-3"
inkscape:flatsided="true"
sodipodi:sides="6"
sodipodi:cx="138.75616"
sodipodi:cy="263.41873"
sodipodi:r1="70.000412"
sodipodi:r2="60.622131"
sodipodi:arg1="-2.6179939"
sodipodi:arg2="-2.0943951"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 78.134029,228.41853 60.622131,-35.00021 60.62214,35.0002 0,70.00042 -60.62213,35.0002 -60.62214,-35.0002 z"
inkscape:transform-center-x="-4.0923148e-06"
inkscape:transform-center-y="-2.6621219e-06"
transform="matrix(1.0382846,0,0,1.0210168,-28.572793,-191.28234)" /><g
id="g12126"
inkscape:label="lines"><path
style="fill:none;fill-opacity:1;stroke:url(#linearGradient12104);stroke-width:0.5;stroke-dasharray:none;stroke-opacity:1"
d="M 54.029427,71.745371 176.85736,71.722537"
id="path12042"
inkscape:label="line" /><path
style="fill:none;fill-opacity:1;stroke:url(#linearGradient12108);stroke-width:0.6;stroke-dasharray:none;stroke-opacity:1"
d="M 54.029427,76.507874 176.85736,76.48504"
id="path12106"
inkscape:label="line" /><path
style="fill:none;fill-opacity:1;stroke:url(#linearGradient12112);stroke-width:0.8;stroke-dasharray:none;stroke-opacity:1"
d="M 54.029427,91.32455 176.85736,91.301716"
id="path12110"
inkscape:label="line" /><path
style="fill:url(#linearGradient12239);fill-opacity:1;stroke:none;stroke-width:2.416;stroke-dasharray:none;stroke-opacity:1"
d="M 104.40252,71.315371 53.668551,108.90527 v 5.16648 z"
id="path12133-5" /><path
style="fill:url(#linearGradient14475);fill-opacity:1;stroke:none;stroke-width:2.41042;stroke-dasharray:none;stroke-opacity:1"
d="m 125.69256,71.804339 51.46081,36.885251 v 5.06963 z"
id="path12133" /><path
style="fill:url(#linearGradient12141);fill-opacity:1;stroke:none;stroke-width:2.41042;stroke-dasharray:none;stroke-opacity:1"
d="m 115.37951,70.94784 5.14781,74.3852 c 0,0 -4.42958,5.94658 -10.22727,-0.9757 z"
id="path12280"
sodipodi:nodetypes="cccc" /></g><path
style="fill:url(#linearGradient7692);fill-opacity:1;stroke:none;stroke-width:2.3;stroke-dasharray:none;stroke-opacity:1"
d="M 53.906377,71.659657 H 177.09207 l 0.24519,40.701533 -61.93861,35.18517 -61.54407,-35.3442 z"
id="path7625"
sodipodi:nodetypes="cccccc" /><g
id="g4494"
transform="matrix(2.7825702,0,0,3.2095953,58.857189,44.497537)"
style="filter:url(#filter12743)"><g
transform="translate(-47.668322,-15.505759)"
id="g113"><g
transform="scale(0.26458)"
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal"
aria-label="SEARXR"
id="g111"><path
id="path105"
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;opacity:1;fill:#f7f7f7;fill-opacity:0.996078;stroke:url(#linearGradient8637);stroke-width:3.77953;stroke-miterlimit:4;stroke-dasharray:none"
d="m 158.51953,0.12890625 c -1.12928,0.0104375 -2.33343,0.0380832 -3.58789,0.09375 -0.30457,-0.13399831 -0.0547,13.73632775 -0.0547,13.73632775 2.81897,0.06348 6.79437,-0.315067 8.33985,1.041016 3.97475,3.093961 3.19147,2.418039 5.77734,5.003906 2.58587,2.585868 5.23601,5.171945 7.95117,7.757813 l -21.2931,18.782442 c -1.29339,1.292984 -2.45529,1.570562 8.42537,1.302881 9.59316,-0.08935 8.19237,0.720755 10.73745,-1.137203 7.83955,-6.121602 9.61287,-7.470425 12.32804,-10.185491 3.0599,2.434819 5.75483,4.092804 10.43494,7.218213 0,0 4.56752,2.32698 9.03546,3.466611 5.1614,0.869711 19.0651,0.856505 19.62872,0.659979 h 4.7207 c 0,0 0.0977,-8.957996 0.16992,-16.066407 0.12771,-10.909788 2.17195,-13.091574 4.75781,-15.80664 2.71507,-2.715066 6.01188,-2.072266 9.89063,-2.072266 h 21.3457 V 0.15429688 h -21.3457 c -7.6279,0 -14.15766,2.71429962 -19.58789,8.14453122 -5.30093,5.3009329 -7.95117,11.7666269 -7.95117,19.3945309 v 9.097657 c -2.05016,0.03977 -4.12643,0.0029 -5.92969,-0.160157 -1.85798,-0.167898 -4.68413,-1.320736 -8.3076,-3.088808 0,0 -4.88583,-3.065166 -7.4717,-5.780332 l 15.00318,-15.777875 c 1.25994,-1.325002 3.90091,-4.6189385 8.52807,-9.5834534 1.63566,-1.75491056 0.84973,-2.31134101 -4.04101,-2.19531248 -2.41247,0.00862 -6.69149,0.0175781 -8.63086,0.0175781 -1.81008,0 -3.42548,0.71063042 -4.84766,2.13281258 L 186.83594,18.064453 c -2.71507,-2.585867 -5.36541,-5.171945 -7.95117,-7.757812 l -7.95118,-7.9511722 c -1.42218,-1.42217213 -3.03953,-2.13281255 -4.84961,-2.13281255 -1.45453,0 -4.17661,-0.12506257 -7.56445,-0.09375 z"
transform="matrix(1.0000126,0,0,1.0000126,27.273414,60.371154)" /><path
d="m 267.38547,88.252296 c 0,-7.665647 2.6505,-14.161997 7.9515,-19.48895 5.4303,-5.456886 11.96,-8.185379 19.588,-8.185379 h 37.34533 v 13.837416 h -37.34533 c -3.8788,0 -7.1758,1.364246 -9.8909,4.092639 -2.5859,2.728493 -3.8788,5.976618 -3.8788,9.744475 v 19.634563 h -13.77 z"
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;fill:#f7f7f7;fill-opacity:0.997356;stroke:#54438e;stroke-width:3.78882;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path103" /><rect
style="fill:#f7f7f7;fill-opacity:0.996078;stroke:none;stroke-width:3.77958"
id="rect1105"
width="29.440615"
height="9.8188734"
x="269.93423"
y="62.516171" /></g></g><path
d="m 40.243755,6.8720423 -9.0863,-0.04493 c 0,0 -1.8872,0.04494 -1.8423,1.5727 0.04493,1.5277999 1.8772,1.4827999 1.8772,1.4827999 h 9.0514 z"
stroke="#000000"
stroke-width="0.26458px"
id="path117"
style="fill:#fefefe;fill-opacity:1;stroke:#54438e;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /></g><text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:19.7556px;font-family:Montserrat;-inkscape-font-specification:'Montserrat Bold';text-align:center;text-anchor:middle;fill:#ffffff;stroke:#ffffff;stroke-width:0.5;stroke-dasharray:none"
x="69.809654"
y="107.18471"
id="text1004"><tspan
sodipodi:role="line"
id="tspan1002"
style="font-style:normal;font-variant:normal;font-weight:100;font-stretch:normal;font-size:19.7556px;font-family:Montserrat;-inkscape-font-specification:'Montserrat Thin';stroke-width:0.5;stroke-dasharray:none"
x="69.809654"
y="107.18471">[</tspan></text><text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:19.7556px;font-family:Montserrat;-inkscape-font-specification:'Montserrat Bold';text-align:center;text-anchor:middle;fill:#ffffff;stroke:#ffffff;stroke-width:0.5;stroke-dasharray:none"
x="160.00148"
y="107.33738"
id="text1004-3"><tspan
sodipodi:role="line"
id="tspan1002-6"
style="font-style:normal;font-variant:normal;font-weight:100;font-stretch:normal;font-size:19.7556px;font-family:Montserrat;-inkscape-font-specification:'Montserrat Thin';stroke-width:0.5;stroke-dasharray:none"
x="160.00148"
y="107.33738">]</tspan></text><text
xml:space="preserve"
style="font-weight:100;font-size:16.2278px;font-family:Montserrat;-inkscape-font-specification:'Montserrat Thin';text-align:center;letter-spacing:0.529167px;writing-mode:tb-rl;text-orientation:upright;text-anchor:middle;fill:#020202;fill-opacity:1;stroke:#000000;stroke-width:2.3;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter13745)"
x="85.100029"
y="91.992111"
id="text3268"><tspan
sodipodi:role="line"
id="tspan3266"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16.2278px;font-family:Montserrat;-inkscape-font-specification:'Montserrat Bold';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.3;stroke-opacity:1"
x="85.100029"
y="91.992111">XR Forge</tspan></text></g></svg>

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

View file

@ -762,6 +762,24 @@ document.getElementById('startButton').onclick = function () {
startEditor(zip); startEditor(zip);
}); });
}; };
document.addEventListener('DOMContentLoaded', function(){
setTimeout( () => {
if( document.location.search ){
const urlParams = new URLSearchParams(window.location.search);
const url = urlParams.get('url');
if( url ){
fetch( url.replace('#','%23') )
.then( (res) => res.arrayBuffer() )
.then( (a) => {
console.dir(a)
return a
})
.then( (ab) => startEditor(ab) )
}
}
},500 )
})
</script> </script>
</body> </body>
</html> </html>