wip
This commit is contained in:
parent
d725c9c73a
commit
0ace214070
7 changed files with 534 additions and 367 deletions
|
|
@ -1,5 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
dir="$(dirname $1)"
|
|
||||||
cd "$dir"
|
|
||||||
echo "[package_experience.sh] zipping experience.zip"
|
|
||||||
zip -D ".xrforge/experience.zip * | tee -a .xrforge/log.txt
|
|
||||||
0
manyfold/root/hook.d/experience_updated/300-package_godot_zip.sh
Executable file → Normal file
0
manyfold/root/hook.d/experience_updated/300-package_godot_zip.sh
Executable file → Normal file
|
|
@ -19,78 +19,90 @@ begin
|
||||||
# Read and parse the JSON file
|
# Read and parse the JSON file
|
||||||
data = JSON.parse( File.read( "datapackage.json" ) )
|
data = JSON.parse( File.read( "datapackage.json" ) )
|
||||||
|
|
||||||
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
if data['keywords'].empty? || data['keywords'].include?('janusxr')
|
||||||
|
|
||||||
XRForge.log("✅ starting build janusXR XR scene", logfile)
|
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||||
|
|
||||||
# Extract the desired field (assuming the field is named 'model_file')
|
XRForge.log("✅ starting build janusXR XR scene", logfile)
|
||||||
thumb_file = data['image']
|
|
||||||
|
|
||||||
XRForge.log("✅ thumbnail sidecar-file '#{thumb_file}' detected", logfile)
|
# Extract the desired field (assuming the field is named 'model_file')
|
||||||
|
thumb_file = data['image']
|
||||||
|
|
||||||
# Get the base name of the thumbnail file without its extension
|
XRForge.log("✅ thumbnail sidecar-file '#{thumb_file}' detected", logfile)
|
||||||
base_name = File.basename(thumb_file, File.extname(thumb_file))
|
|
||||||
|
|
||||||
model_file = nil # Initialize model_file to nil
|
# Get the base name of the thumbnail file without its extension
|
||||||
|
base_name = File.basename(thumb_file, File.extname(thumb_file))
|
||||||
|
|
||||||
# Loop over the list of extensions
|
model_file = nil # Initialize model_file to nil
|
||||||
XRForge::MODEL_EXT.each do |ext|
|
|
||||||
# Construct the filename with the current extension
|
|
||||||
filename = "#{base_name}#{ext}"
|
|
||||||
|
|
||||||
# Check if the file exists
|
# Loop over the list of extensions
|
||||||
if File.exist?(filename)
|
XRForge::MODEL_EXT.each do |ext|
|
||||||
XRForge.log("✅ 3D file '#{filename}' detected", logfile)
|
# Construct the filename with the current extension
|
||||||
model_file = "#{dir.gsub("/mnt/","")}/#{filename}" # Store the found filename
|
filename = "#{base_name}#{ext}"
|
||||||
break # Stop the loop once a file is found
|
|
||||||
|
# Check if the file exists
|
||||||
|
if File.exist?(filename)
|
||||||
|
XRForge.log("✅ 3D file '#{filename}' detected", logfile)
|
||||||
|
model_file = "#{dir.gsub("/mnt/","")}/#{filename}" # Store the found filename
|
||||||
|
break # Stop the loop once a file is found
|
||||||
|
else
|
||||||
|
# Log a message for the file that was not found, but don't stop
|
||||||
|
XRForge.log("⚠️ 3D file '#{filename}' not detected", logfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check if a model file was found after the loop
|
||||||
|
if model_file
|
||||||
|
XRForge.log("✅ Final model file: '#{model_file}'", logfile)
|
||||||
else
|
else
|
||||||
# Log a message for the file that was not found, but don't stop
|
XRForge.log("❌ No suitable 3D file found for XR Fragments- / JanusXR-compatible experience", logfile)
|
||||||
XRForge.log("⚠️ 3D file '#{filename}' not detected", logfile)
|
end
|
||||||
|
|
||||||
|
# Get the value of the environment variable FEDERATE_DRIVE_HOST
|
||||||
|
federate_drive_host = ENV['FEDERATE_DRIVE_HOST']
|
||||||
|
|
||||||
|
# Define the HTML content using a multi-line string (heredoc)
|
||||||
|
# Ruby's heredoc allows for variable interpolation (using #{})
|
||||||
|
jml = <<~JML
|
||||||
|
<FireBoxRoom>
|
||||||
|
<Assets>
|
||||||
|
<assetobject id="experience" src="#{federate_drive_host}/#{model_file.gsub("#","%23")}"/>
|
||||||
|
</Assets>
|
||||||
|
<Room>
|
||||||
|
<object pos="0 0 0" collision_id="experience" id="experience" />
|
||||||
|
</Room>
|
||||||
|
</FireBoxRoom>
|
||||||
|
JML
|
||||||
|
|
||||||
|
html = <<~HTML
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>janusxr room</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="https://web.janusvr.com/janusweb.js"></script>
|
||||||
|
<janus-viewer>
|
||||||
|
#{jml}
|
||||||
|
</janus-viewer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
File.write('.xrforge/janusxr.html', html)
|
||||||
|
File.write('.xrforge/scene.jml', jml)
|
||||||
|
|
||||||
|
XRForge.log("✅ generated scene.jml", logfile)
|
||||||
|
XRForge.log("✅ generated janusxr.html", logfile)
|
||||||
|
XRForge.log(" ", logfile)
|
||||||
|
|
||||||
|
# tag it!
|
||||||
|
if ! data['keywords'].include?('janusxr')
|
||||||
|
data['keywords'].push('janusxr')
|
||||||
|
File.write(file_path, JSON.pretty_generate(data) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check if a model file was found after the loop
|
|
||||||
if model_file
|
|
||||||
XRForge.log("✅ Final model file: '#{model_file}'", logfile)
|
|
||||||
else
|
|
||||||
XRForge.log("❌ No suitable 3D file found for XR Fragments- / JanusXR-compatible experience", logfile)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Get the value of the environment variable FEDERATE_DRIVE_HOST
|
|
||||||
federate_drive_host = ENV['FEDERATE_DRIVE_HOST']
|
|
||||||
|
|
||||||
# Define the HTML content using a multi-line string (heredoc)
|
|
||||||
# Ruby's heredoc allows for variable interpolation (using #{})
|
|
||||||
jml = <<~HTML
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>janusxr room</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<script src="https://web.janusvr.com/janusweb.js"></script>
|
|
||||||
<janus-viewer>
|
|
||||||
<FireBoxRoom>
|
|
||||||
<Assets>
|
|
||||||
<assetobject id="experience" src="#{federate_drive_host}/#{model_file.gsub("#","%23")}"/>
|
|
||||||
</Assets>
|
|
||||||
<Room>
|
|
||||||
<object pos="0 0 0" collision_id="experience" id="experience" />
|
|
||||||
</Room>
|
|
||||||
</FireBoxRoom>
|
|
||||||
</janus-viewer>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
HTML
|
|
||||||
|
|
||||||
# Write the content to the specified file
|
|
||||||
# File.write is the concise equivalent of 'echo "$jml" > filename'
|
|
||||||
File.write('.xrforge/janusxr.html', jml)
|
|
||||||
|
|
||||||
XRForge.log("✅ written janusxr.html", logfile)
|
|
||||||
|
|
||||||
XRForge.log(" ", logfile)
|
|
||||||
|
|
||||||
rescue Errno::ENOENT
|
rescue Errno::ENOENT
|
||||||
puts "File #{filename} not found"
|
puts "File #{filename} not found"
|
||||||
rescue JSON::ParserError
|
rescue JSON::ParserError
|
||||||
|
|
|
||||||
87
manyfold/root/hook.d/experience_updated/300-package_mml.rb
Executable file
87
manyfold/root/hook.d/experience_updated/300-package_mml.rb
Executable file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require_relative './../../xrforge.rb'
|
||||||
|
|
||||||
|
# Check if a filename is provided
|
||||||
|
if ARGV.length != 1
|
||||||
|
puts "Usage: #{$0} <path/to/experience/somefile.xxx>"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
filename = ARGV[0]
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
# Change the directory
|
||||||
|
dir = File.dirname(filename)
|
||||||
|
Dir.chdir( File.dirname(filename) )
|
||||||
|
# Read and parse the JSON file
|
||||||
|
data = JSON.parse( File.read( "datapackage.json" ) )
|
||||||
|
|
||||||
|
if data['keywords'].empty? || data['keywords'].include?('mml')
|
||||||
|
|
||||||
|
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||||
|
|
||||||
|
XRForge.log("✅ starting build mml XR scene", logfile)
|
||||||
|
|
||||||
|
# Extract the desired field (assuming the field is named 'model_file')
|
||||||
|
thumb_file = data['image']
|
||||||
|
|
||||||
|
XRForge.log("✅ thumbnail sidecar-file '#{thumb_file}' detected", logfile)
|
||||||
|
|
||||||
|
# Get the base name of the thumbnail file without its extension
|
||||||
|
base_name = File.basename(thumb_file, File.extname(thumb_file))
|
||||||
|
|
||||||
|
model_file = nil # Initialize model_file to nil
|
||||||
|
|
||||||
|
# Loop over the list of extensions
|
||||||
|
XRForge::MODEL_EXT.each do |ext|
|
||||||
|
# Construct the filename with the current extension
|
||||||
|
filename = "#{base_name}#{ext}"
|
||||||
|
|
||||||
|
# Check if the file exists
|
||||||
|
if File.exist?(filename)
|
||||||
|
XRForge.log("✅ 3D file '#{filename}' detected", logfile)
|
||||||
|
model_file = "#{dir.gsub("/mnt/","")}/#{filename}" # Store the found filename
|
||||||
|
break # Stop the loop once a file is found
|
||||||
|
else
|
||||||
|
# Log a message for the file that was not found, but don't stop
|
||||||
|
XRForge.log("⚠️ 3D file '#{filename}' not detected", logfile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Check if a model file was found after the loop
|
||||||
|
if model_file
|
||||||
|
XRForge.log("✅ Final model file: '#{model_file}'", logfile)
|
||||||
|
else
|
||||||
|
XRForge.log("❌ No suitable 3D file found for XR Fragments- / MML-compatible experience", logfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get the value of the environment variable FEDERATE_DRIVE_HOST
|
||||||
|
federate_drive_host = ENV['FEDERATE_DRIVE_HOST']
|
||||||
|
|
||||||
|
# https://viewer.mml.io/main/v1/?url=https%3A%2F%2Ffoo.org%2Fbar.mml
|
||||||
|
mml = <<~MML
|
||||||
|
<m-model src="#{federate_drive_host}/#{model_file.gsub("#","%23")}" anim-loop="true" anim-enabled="true"></m-model>
|
||||||
|
MML
|
||||||
|
|
||||||
|
File.write('.xrforge/scene.mml', mml)
|
||||||
|
|
||||||
|
XRForge.log("✅ generated scene.mml", logfile)
|
||||||
|
XRForge.log(" ", logfile)
|
||||||
|
|
||||||
|
# tag it!
|
||||||
|
if ! data['keywords'].include?('mml')
|
||||||
|
data['keywords'].push('mml')
|
||||||
|
File.write(file_path, JSON.pretty_generate(data) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue Errno::ENOENT
|
||||||
|
puts "File #{filename} not found"
|
||||||
|
rescue JSON::ParserError
|
||||||
|
puts "Error parsing JSON from #{filename}"
|
||||||
|
rescue => e
|
||||||
|
puts "An error occurred: #{e.message}"
|
||||||
|
end
|
||||||
32
manyfold/usr/src/app/app/views/models/_tags_info.html.erb
Normal file
32
manyfold/usr/src/app/app/views/models/_tags_info.html.erb
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
Features can be toggled via tags:<br>
|
||||||
|
<br>
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">menu</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
This will generate a navigator-menu <b>into</b> your main 3D file.<br>
|
||||||
|
The links can be edited <%= link_to "here", edit_model_path(@model) %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">janusxr</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
This generates an JanusXR address.<br>
|
||||||
|
<a href="https://janusxr.org/" target="_blank">JanusXR</a> is an Open Immersive Web-layer since 2015, which allows existing webpages to become spatial.<br>
|
||||||
|
It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc).<br>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">mml</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
This generates an MML address.<br>
|
||||||
|
Metaverse Markup Language (<a href="https://mml.io" target="_blank">MML</a>) is an open markup language used to define experiences.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
@ -81,32 +81,72 @@
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if ENV['FEDERATE_DRIVE_HOST'].present? %>
|
<% if ENV['FEDERATE_DRIVE_HOST'].present? %>
|
||||||
|
|
||||||
|
<% if @model.tags.where(name: "janusxr" ).any? %>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<i class="bi bi-eye-fill" role="img"></i>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%
|
||||||
|
fediURL = ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html"
|
||||||
|
%>
|
||||||
|
<%= link_to "JanusXR address", fediURL, target:"_blank" %>
|
||||||
|
<a href="" target="_blank"><i class="bi bi-link-45deg"></i></a>
|
||||||
|
<label for="toggle_janusxr"><i class="bi bi-info-circle"></i></label>
|
||||||
|
<div class="toggle-box">
|
||||||
|
<input type="checkbox" id="toggle_janusxr" hidden>
|
||||||
|
<div class="hidden-tooltip">
|
||||||
|
<i class="bi bi-arrow-90deg-up"></i>
|
||||||
|
<small>
|
||||||
|
This is the JanusXR address.<br>
|
||||||
|
<a href="https://janusxr.org/" target="_blank">JanusXR</a> is an Open Immersive Web-layer since 2015, which allows existing webpages to become spatial.<br>
|
||||||
|
It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc).<br>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<%
|
||||||
|
# lets generate a JanusXR spatial layer for the current scene
|
||||||
|
jmlfile = @model.library.path+"/"+@model.path+"/.xrforge/scene.jml"
|
||||||
|
jml = ""
|
||||||
|
if File.exist?(jmlfile)
|
||||||
|
jml = File.read(jmlfile)
|
||||||
|
end
|
||||||
|
%>
|
||||||
|
|
||||||
|
<!-- JML (https://janusxr.org) spatial markup
|
||||||
|
|
||||||
|
<%== jml %>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if @model.tags.where(name: "mml" ).any? %>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<i class="bi bi-people" role="img"></i>
|
<i class="bi bi-eye-fill" role="img"></i>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<%= link_to "JanusXR Metaverse", ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html" %>
|
<%= link_to "MML address", "https://viewer.mml.io/main/v1/?url="+URI.encode_www_form_component(ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/scene.mml"), target:"_blank" %>
|
||||||
<label for="toggle_janusxr"><i class="bi bi-info-circle"></i></label>
|
<a href="<%= ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/scene.mml" %>" target="_blank"><i class="bi bi-link-45deg"></i></a>
|
||||||
|
<label for="toggle_mml"><i class="bi bi-info-circle"></i></label>
|
||||||
<div class="toggle-box">
|
<div class="toggle-box">
|
||||||
<input type="checkbox" id="toggle_janusxr" hidden>
|
<input type="checkbox" id="toggle_mml" hidden>
|
||||||
<div class="hidden-tooltip">
|
<div class="hidden-tooltip">
|
||||||
<i class="bi bi-arrow-90deg-up"></i>
|
<i class="bi bi-arrow-90deg-up"></i>
|
||||||
<small>
|
<small>
|
||||||
This is the JanusXR address.<br>
|
This is the MML address.<br>
|
||||||
<a href="https://janusxr.org/" target="_blank">JanusXR</a> is an established Metaverse since 2015.<br>
|
Metaverse Markup Language (<a href="https://mml.io" target="_blank">MML</a>) is an open markup language used to define experiences.
|
||||||
It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc).
|
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<% end %>
|
||||||
<td>
|
|
||||||
<i class="bi bi-file-zip" role="img"></i>
|
|
||||||
</td>
|
|
||||||
<td><%= link_to "zip archive", "/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/experience.zip" %></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<i class="bi bi-journal-check" role="img"></i>
|
<i class="bi bi-journal-check" role="img"></i>
|
||||||
|
|
@ -121,19 +161,7 @@
|
||||||
<small>
|
<small>
|
||||||
This is the build log of XR Forge.<br>
|
This is the build log of XR Forge.<br>
|
||||||
When you add files, they are processed, validated (for <a href="https://xrfragment.org" target="_blank">XR Fragment</a> compliance).<br>
|
When you add files, they are processed, validated (for <a href="https://xrfragment.org" target="_blank">XR Fragment</a> compliance).<br>
|
||||||
But also features can be toggled via tags:<br>
|
<% render 'models/tags_info' %>
|
||||||
<br>
|
|
||||||
<table class="table">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<a class="badge rounded-pill bg-secondary tag">menu</a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
This will generate a navigator-menu <b>into</b> your main 3D file.<br>
|
|
||||||
The links can be edited <%= link_to "here", edit_model_path(@model) %>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -161,6 +189,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @model.collection %>
|
<% if @model.collection %>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%= icon "collection", Collection.model_name.human(count: 100) %></td>
|
<td><%= icon "collection", Collection.model_name.human(count: 100) %></td>
|
||||||
|
|
@ -202,7 +231,18 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><%= icon "tag", t(".tags") %></td>
|
<td><%= icon "tag", t(".tags") %></td>
|
||||||
<td><%= render "tag_list", tags: @model.tags.order(taggings_count: :desc, name: :asc), filter: @filter %></td>
|
<td><%= render "tag_list", tags: @model.tags.order(taggings_count: :desc, name: :asc), filter: @filter %>
|
||||||
|
<label for="toggle_tags"><i class="bi bi-info-circle"></i></label>
|
||||||
|
<div class="toggle-box">
|
||||||
|
<input type="checkbox" id="toggle_tags" hidden>
|
||||||
|
<div class="hidden-tooltip" style="max-height:400px">
|
||||||
|
<i class="bi bi-arrow-90deg-up"></i>
|
||||||
|
<small>
|
||||||
|
<% render 'models/tags_info' %>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% if SiteSettings.social_enabled? %>
|
<% if SiteSettings.social_enabled? %>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ rec
|
||||||
pkgs.pkgsStatic.inotify-tools # inotifywait e.g.
|
pkgs.pkgsStatic.inotify-tools # inotifywait e.g.
|
||||||
pkgs.pkgsStatic.zip # inotifywait e.g.
|
pkgs.pkgsStatic.zip # inotifywait e.g.
|
||||||
pkgs.pkgsStatic.ts # job management
|
pkgs.pkgsStatic.ts # job management
|
||||||
|
pkgs.janus-gateway # webrtc server
|
||||||
myAssimp # cli 3D editing/conversion
|
myAssimp # cli 3D editing/conversion
|
||||||
./..
|
./..
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue