refactor ruby scripts + updated templates + janus refactor
This commit is contained in:
parent
84a2812ad5
commit
6a13e0c2cc
9 changed files with 318 additions and 181 deletions
|
|
@ -20,7 +20,8 @@ begin
|
||||||
end
|
end
|
||||||
|
|
||||||
# Change the directory
|
# Change the directory
|
||||||
dir = File.dirname(filename)
|
dir = File.dirname(filename)
|
||||||
|
dirPublic = dir.gsub("/mnt/","").gsub("#","%23")
|
||||||
Dir.chdir( File.dirname(filename) )
|
Dir.chdir( File.dirname(filename) )
|
||||||
# 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" ) )
|
||||||
|
|
@ -31,37 +32,12 @@ begin
|
||||||
|
|
||||||
XRForge.log("✅ starting build janusXR XR scene", logfile)
|
XRForge.log("✅ starting build janusXR XR scene", logfile)
|
||||||
|
|
||||||
# Extract the desired field (assuming the field is named 'model_file')
|
model_file = XRForge.getExperienceFile(data,dir,logfile)
|
||||||
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
|
# Check if a model file was found after the loop
|
||||||
if model_file
|
if ! model_file
|
||||||
XRForge.log("✅ Final model file: '#{model_file}'", logfile)
|
XRForge.log("❌ No suitable 3D file found for JanusXR-compatible experience", logfile)
|
||||||
else
|
exit 0
|
||||||
XRForge.log("❌ No suitable 3D file found for XR Fragments- / JanusXR-compatible experience", logfile)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get the value of the environment variable FEDERATE_DRIVE_HOST
|
# Get the value of the environment variable FEDERATE_DRIVE_HOST
|
||||||
|
|
@ -70,7 +46,7 @@ begin
|
||||||
autogenerate = true
|
autogenerate = true
|
||||||
|
|
||||||
if data['description'] && data['description'].match(JMLHeuristic)
|
if data['description'] && data['description'].match(JMLHeuristic)
|
||||||
if data['description'].match(/autogenerate=['"]false['"]/)
|
if data['description'].match(/autogenerate=["']false["']/i)
|
||||||
XRForge.log("✅ autogenerate='false' found in JML..keeping this JML",logfile)
|
XRForge.log("✅ autogenerate='false' found in JML..keeping this JML",logfile)
|
||||||
autogenerate = false
|
autogenerate = false
|
||||||
jmlMatch = data['description'].match(JMLHeuristic)
|
jmlMatch = data['description'].match(JMLHeuristic)
|
||||||
|
|
@ -78,28 +54,62 @@ begin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if autogenerate
|
if autogenerate
|
||||||
|
assets = "<assetobject id=\"experience\" src=\"#{federate_drive_host}/#{dirPublic}/#{model_file.gsub("#","%23")}\"/>\n"
|
||||||
|
objects = ""
|
||||||
|
|
||||||
|
# detect audio track sidecarfile as per XR Fragment spec: https://xrfragment.org/#%F0%9F%93%9C%20level0%3A%20File
|
||||||
|
xrf_ext = File.extname(model_file)
|
||||||
|
xrf_base = File.basename(model_file, xrf_ext)
|
||||||
|
data['resources'].each do |resource|
|
||||||
|
ext = File.extname(resource['path'])
|
||||||
|
if ext.match(/mp3/i)
|
||||||
|
base = File.basename(resource['path'], ext)
|
||||||
|
if base == xrf_base
|
||||||
|
XRForge.log("✅ XR Fragments side-car file found: #{resource['path']}",logfile)
|
||||||
|
assets = assets + " <assetsound id=\"soundtrack\" src=\"#{federate_drive_host}/#{dirPublic}/#{resource["path"]}\"/>\n"
|
||||||
|
objects = objects + "<sound id=\"soundtrack\" loop=\"true\"/>\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private = data['keywords'].include?('singleuser') ? "private='true'" : ""
|
||||||
|
|
||||||
|
# tags to JML rooms *REFACTOR PLEASE*
|
||||||
|
use_local_asset = ""
|
||||||
|
use_local_asset = data['keywords'].include?('room1') ? "use_local_asset=\"room1\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room2') ? "use_local_asset=\"room2\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room3') ? "use_local_asset=\"room3\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room4') ? "use_local_asset=\"room4\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room5') ? "use_local_asset=\"room5\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room6') ? "use_local_asset=\"room5\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room1_pedestal') ? "use_local_asset=\"room1_pedestal\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room2_pedestal') ? "use_local_asset=\"room2_pedestal\"" : use_local_asset
|
||||||
|
use_local_asset = data['keywords'].include?('room2_narrow') ? "use_local_asset=\"room3_narrow\"" : use_local_asset
|
||||||
|
|
||||||
|
objects = objects + " <object pos=\"0 0 5\" rotation=\"-180 0 180\" lighting=\"false\" collision_id=\"experience\" id=\"experience\" />"
|
||||||
|
|
||||||
jml = <<~JML
|
jml = <<~JML
|
||||||
<FireBoxRoom>
|
<FireBoxRoom>
|
||||||
<Assets>
|
<Assets>
|
||||||
<assetobject id="experience" src="#{federate_drive_host}/#{model_file.gsub("#","%23")}"/>
|
#{assets}
|
||||||
</Assets>
|
</Assets>
|
||||||
<Room autogenerate="true" #{ data['keywords'].include?('singleuser') ? "private='true'" : ""}>
|
<Room autogenerate="true" #{use_local_asset} #{private}>
|
||||||
<object pos="0 0 5" rotation="-180 0 180" lighting="false" collision_id="experience" id="experience" />
|
#{objects}
|
||||||
</Room>
|
</Room>
|
||||||
</FireBoxRoom>
|
</FireBoxRoom>
|
||||||
<!-- archive.org hints -->
|
<!-- archive.org hints -->
|
||||||
<a href="#{federate_drive_host}/#{model_file.gsub("#","%23")}"></a>
|
<a href="#{federate_drive_host}/#{dirPublic}/#{model_file.gsub("#","%23")}"></a>
|
||||||
JML
|
JML
|
||||||
|
|
||||||
data['description'] = data['description'] ? data['description'] : "your description here\n"
|
data['description'] = data['description'] ? data['description'] : "your description here\n"
|
||||||
data['description'] = <<~DESCRIPTION#{data['description']}
|
data['description'] = <<~DESCRIPTION#{data['description']}
|
||||||
<!-- Hi there! Below is autogenerated JanusXR Markup (JML). -->
|
<!-- Hi there! Below is autogenerated JanusXR Markup (JML). -->
|
||||||
<!-- If you want to tweak it, then first disable autogeneration -->
|
<!-- If you want to tweak it, then first disable autogeneration -->
|
||||||
<!-- How? make sure to set autogenerate="false" (see room-tag below) -->
|
<!-- How? make sure to set autogenerate to "false" (see room-tag below) -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- JML info: -->
|
<!-- JML info: -->
|
||||||
<!-- https://coderofsalvation.github.io/janus-guide/#/examples/markup -->
|
<!-- https://coderofsalvation.github.io/janus-guide/#/examples/markup -->
|
||||||
<!-- https://janusxr.org/docs/build/introtojml/index.html -->
|
<!-- https://janusxr.org/docs/build/introtojml/index.html -->
|
||||||
|
|
||||||
#{jml}
|
#{jml}
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
|
||||||
|
|
@ -30,37 +30,12 @@ begin
|
||||||
|
|
||||||
XRForge.log("✅ starting build mml XR scene", logfile)
|
XRForge.log("✅ starting build mml XR scene", logfile)
|
||||||
|
|
||||||
# Extract the desired field (assuming the field is named 'model_file')
|
model_file = XRForge.getExperienceFile(data,dir,logfile)
|
||||||
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
|
# Check if a model file was found after the loop
|
||||||
if model_file
|
if ! model_file
|
||||||
XRForge.log("✅ Final model file: '#{model_file}'", logfile)
|
XRForge.log("❌ No suitable 3D file found for MML-compatible experience", logfile)
|
||||||
else
|
exit 0
|
||||||
XRForge.log("❌ No suitable 3D file found for XR Fragments- / MML-compatible experience", logfile)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Get the value of the environment variable FEDERATE_DRIVE_HOST
|
# Get the value of the environment variable FEDERATE_DRIVE_HOST
|
||||||
|
|
|
||||||
|
|
@ -13,36 +13,20 @@ filename = ARGV[0]
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Change the directory
|
# Change the directory
|
||||||
Dir.chdir( File.dirname(filename) )
|
dir = File.dirname(filename)
|
||||||
|
Dir.chdir( dir )
|
||||||
# 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" )
|
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||||
XRForge.log("✅ starting XR fragments check", logfile)
|
XRForge.log("✅ starting XR fragments check", logfile)
|
||||||
|
|
||||||
# Extract the desired field (assuming the field is named 'model_file')
|
model_file = XRForge.getExperienceFile(data,dir,logfile)
|
||||||
thumb_file = data['image']
|
|
||||||
XRForge.log("✅ thumbnail sidecar-file '#{thumb_file}' detected", logfile)
|
|
||||||
|
|
||||||
# Get the base name of the thumbnail file without its extension
|
# Check if a model file was found after the loop
|
||||||
base_name = File.basename(thumb_file, File.extname(thumb_file))
|
if ! model_file
|
||||||
|
XRForge.log("❌ No suitable 3D file found for XR Fragments-compatible experience", logfile)
|
||||||
model_file = nil # Initialize model_file to nil
|
exit 0
|
||||||
|
|
||||||
# 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 = 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
|
end
|
||||||
|
|
||||||
# Check if a model file was found after the loop
|
# Check if a model file was found after the loop
|
||||||
|
|
|
||||||
|
|
@ -106,4 +106,43 @@ module XRForge
|
||||||
{ root.name => x2j_rec(root) }
|
{ root.name => x2j_rec(root) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.getExperienceFile(datapackage, dir, logfile)
|
||||||
|
model_file = nil # Initialize model_file to nil
|
||||||
|
base_name = ""
|
||||||
|
# Extract the desired field (assuming the field is named 'model_file')
|
||||||
|
thumb_file = datapackage['image']
|
||||||
|
if thumb_file && ! thumb_file.empty?
|
||||||
|
# HEURISTIC: XR Fragments sidecarfile https://xrfragment.org/#%F0%9F%93%9C%20level0%3A%20File
|
||||||
|
# Get the base name of the thumbnail file without its extension
|
||||||
|
base_name = File.basename(thumb_file, File.extname(thumb_file))
|
||||||
|
XRForge.log("✅ thumbnail sidecar-file '#{thumb_file}' detected", logfile)
|
||||||
|
# Loop over the list of extensions
|
||||||
|
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 (heuristic: XRFragment sidecarfile)", 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
|
||||||
|
else
|
||||||
|
# HEURISTIC: get first suitable 3D file
|
||||||
|
datapackage['resources'].each do |resource|
|
||||||
|
ext = File.extname(resource['path'])
|
||||||
|
if MODEL_EXT.include?( ext )
|
||||||
|
model_file = resource['path']
|
||||||
|
XRForge.log("✅ 3D file '#{model_file}' detected (heuristic: first-found)", logfile)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return model_file
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
52
manyfold/usr/src/app/app/views/models/_form.html.erb
Normal file
52
manyfold/usr/src/app/app/views/models/_form.html.erb
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<%= form_with model: @model do |form| %>
|
||||||
|
<%= text_input_row form, :name %>
|
||||||
|
|
||||||
|
<%= render "tags_edit", form: form, name: "model[tag_list]", value: (@model.tags.order(taggings_count: :desc, name: :asc).map { |tag| tag.name }).join(","), label: translate(".tags"), tags: @available_tags %>
|
||||||
|
<div style="margin-left: 97px; max-height: 333px; overflow: scroll; margin-bottom: 50px; border: 1px solid #CCC; border-radius: 5px; margin-right:10px; background:black; padding:20px;">
|
||||||
|
<b>Available tags:</b><br>
|
||||||
|
<%= render 'models/tags_info' %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= collection_select_input_row form, :preview_file, @model.valid_preview_files, :id, :name, help: t(".preview_file.help") %>
|
||||||
|
|
||||||
|
<%= collection_select_input_row form,
|
||||||
|
:creator, @creators, :id, :name_with_domain,
|
||||||
|
include_blank: true,
|
||||||
|
selected: @default_creator&.id,
|
||||||
|
button: (if policy(:creator).new?
|
||||||
|
{
|
||||||
|
path: new_creator_path,
|
||||||
|
label: t("creators.general.new")
|
||||||
|
}
|
||||||
|
end) %>
|
||||||
|
|
||||||
|
<% if SiteSettings.show_libraries || current_user.is_administrator? %>
|
||||||
|
<%= unless @model.contains_other_models?
|
||||||
|
collection_select_input_row form,
|
||||||
|
:library, policy_scope(Library).all, :id, :name,
|
||||||
|
include_blank: true
|
||||||
|
end %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
<%= collection_select_input_row form,
|
||||||
|
:collection, @collections, :id, :name_with_domain,
|
||||||
|
include_blank: true,
|
||||||
|
button: (if policy(:collection).new?
|
||||||
|
{
|
||||||
|
path: new_collection_path,
|
||||||
|
label: t("collections.general.new")
|
||||||
|
}
|
||||||
|
end) %>
|
||||||
|
|
||||||
|
<%= render "links_form", form: form %>
|
||||||
|
<%= text_input_row form, :caption %>
|
||||||
|
<%= rich_text_input_row form, :notes, help: t(".notes.help_html") %>
|
||||||
|
<%= select_input_row form, :license, license_select_options(selected: @model.license), include_blank: true %>
|
||||||
|
<%= checkbox_input_row form, :sensitive %>
|
||||||
|
<%= select_input_row form, :indexable, indexable_select_options(form.object) %>
|
||||||
|
<%= select_input_row form, :ai_indexable, ai_indexable_select_options(form.object) if SiteSettings.allow_ai_bots %>
|
||||||
|
<%= render "caber_relations_form", form: form %>
|
||||||
|
|
||||||
|
<%= form.submit "Save", class: "btn btn-primary" %>
|
||||||
|
<% end %>
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
Features can be toggled via tags:<br>
|
|
||||||
<br>
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -12,21 +10,32 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a class="badge rounded-pill bg-secondary tag">janusxr</a>
|
<a class="badge rounded-pill bg-secondary tag">your@mastodon.online</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This generates an JanusXR address.<br>
|
Simply enter your mastodon address as tag, and XRForge will generate a 3D model, based on your last post on mastodon.<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<Hr/>
|
||||||
|
<b>JanusXR tags:</b>
|
||||||
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td style="vertical-align:top">
|
||||||
<a class="badge rounded-pill bg-secondary tag">mml</a>
|
<a class="badge rounded-pill bg-secondary tag">room1</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room2</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room3</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room4</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room5</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room6</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room1_pedestal</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room2_pedestal</a><br>
|
||||||
|
<a class="badge rounded-pill bg-secondary tag">room2_narrow</a><br>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
This generates an MML address.<br>
|
This wraps a room around the 3D asset:<br><Br>
|
||||||
Metaverse Markup Language (<a href="https://mml.io" target="_blank">MML</a>) is an open markup language used to define experiences.
|
<img src="/assets/jml_templates.png" style="width:100%; max-width:800px"/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
|
|
@ -46,19 +46,81 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3" id="sidebar">
|
<div class="col-md-3" id="sidebar">
|
||||||
<%= card :secondary, t(".model_details") do %>
|
|
||||||
|
<%= card :secondary, "XR networks" do %>
|
||||||
<table class="table table-borderless table-sm">
|
<table class="table table-borderless table-sm">
|
||||||
|
<% if ENV['FEDERATE_DRIVE_HOST'].present? %>
|
||||||
|
|
||||||
|
<% if @model.tags.where(name: "xrfragments" ).any? %>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<img src="/assets/janusxr.svg" style="width: 16px; transform: translate(0px,-2px);">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%
|
||||||
|
fediURL = ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html"
|
||||||
|
%>
|
||||||
|
<%= link_to "JanusXR", 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>
|
||||||
|
Click to view this page in a JanusXR (JML) browser like JanusWeb.<br>
|
||||||
|
<a href="https://janusxr.org/" target="_blank">JanusXR</a> is an Open XR content-weblayer since 2013, 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: "xrfragments" ).any? %>
|
||||||
|
<tr>
|
||||||
|
<td>⁂</td>
|
||||||
|
<td>
|
||||||
|
<%= link_to "XR Fragments", ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/scene.gltf" %>
|
||||||
|
<label for="toggle_gltf"><i class="bi bi-info-circle"></i></label>
|
||||||
|
<div class="toggle-box">
|
||||||
|
<input type="checkbox" id="toggle_gltf" hidden>
|
||||||
|
<div class="hidden-tooltip">
|
||||||
|
<i class="bi bi-arrow-90deg-up"></i>
|
||||||
|
<small>
|
||||||
|
This is the glTF JSON URL with embedded hyperlinks for immersive navigation to other 3D scene-files, as per the <a href="https://xrfragment.org" target="_blank">XR Fragments</a> spec.<br>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<% if SiteSettings.federation_enabled? %>
|
<% if SiteSettings.federation_enabled? %>
|
||||||
<tr>
|
<tr>
|
||||||
<td>⁂</td>
|
<td>⁂</td>
|
||||||
<td><% if @model.remote? %>
|
<td><% if @model.remote? %>
|
||||||
<small><%= link_to @model.federails_actor.at_address, @model.federails_actor.profile_url, target: "new" %></small>
|
<%= link_to @model.federails_actor.at_address, @model.federails_actor.profile_url, target: "new" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<small>
|
|
||||||
<%= @model.federails_actor.short_at_address %>
|
<%= @model.federails_actor.short_at_address %>
|
||||||
<%= render Components::CopyButton.new(text: @model.federails_actor.at_address) %>
|
<%= render Components::CopyButton.new(text: @model.federails_actor.at_address) %>
|
||||||
</small>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<label for="toggle_activitypub"><i class="bi bi-info-circle"></i></label>
|
<label for="toggle_activitypub"><i class="bi bi-info-circle"></i></label>
|
||||||
<div class="toggle-box">
|
<div class="toggle-box">
|
||||||
|
|
@ -74,62 +136,12 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if @model.creator %>
|
|
||||||
<tr>
|
|
||||||
<td><%= icon "person", Creator.model_name.human %></td>
|
|
||||||
<td><%= link_to @model.creator.name, @model.creator, itemprop: "author" %></td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
|
||||||
<% if ENV['FEDERATE_DRIVE_HOST'].present? %>
|
|
||||||
|
|
||||||
<% if @model.tags.where(name: "xrfragments" ).any? %>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<img src="/assets/janusxr.svg" style="width: 16px; transform: translate(0px,-2px);">
|
|
||||||
</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: "xrfragments" ).any? %>
|
<% if @model.tags.where(name: "xrfragments" ).any? %>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>⁂</td>
|
||||||
<i class="bi bi-eye-fill" role="img"></i>
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
<%= 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" %>
|
<%= link_to "MML", "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" %>
|
||||||
<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>
|
<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>
|
<label for="toggle_mml"><i class="bi bi-info-circle"></i></label>
|
||||||
<div class="toggle-box">
|
<div class="toggle-box">
|
||||||
|
|
@ -145,7 +157,20 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
<%= card :secondary, t(".model_details") do %>
|
||||||
|
<table class="table table-borderless table-sm">
|
||||||
|
|
||||||
|
<% if @model.creator %>
|
||||||
|
<tr>
|
||||||
|
<td><%= icon "person", Creator.model_name.human %></td>
|
||||||
|
<td><%= link_to @model.creator.name, @model.creator, itemprop: "author" %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<i class="bi bi-journal-check" role="img"></i>
|
<i class="bi bi-journal-check" role="img"></i>
|
||||||
|
|
@ -160,6 +185,8 @@
|
||||||
<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>
|
||||||
|
Features can be toggled via tags:<br>
|
||||||
|
<br>
|
||||||
<%= render 'models/tags_info' %>
|
<%= render 'models/tags_info' %>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -187,27 +214,6 @@
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!--
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<i class="bi bi-filetype-json" role="img"></i>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<%= link_to "glTF JSON", ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/scene.gltf" %>
|
|
||||||
<label for="toggle_gltf"><i class="bi bi-info-circle"></i></label>
|
|
||||||
<div class="toggle-box">
|
|
||||||
<input type="checkbox" id="toggle_gltf" hidden>
|
|
||||||
<div class="hidden-tooltip">
|
|
||||||
<i class="bi bi-arrow-90deg-up"></i>
|
|
||||||
<small>
|
|
||||||
This is the glTF JSON URL.<br>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
-->
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<% if @model.collection %>
|
<% if @model.collection %>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -282,6 +288,7 @@
|
||||||
<div class="mb-3 w-100 text-center">
|
<div class="mb-3 w-100 text-center">
|
||||||
<%= render Components::DownloadButton.new(model: @model) %>
|
<%= render Components::DownloadButton.new(model: @model) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<%= card :secondary, t("layouts.card_list_page.actions_heading") do %>
|
<%= card :secondary, t("layouts.card_list_page.actions_heading") do %>
|
||||||
<%= render Components::ReportButton.new(object: @model, path: new_model_report_path(@model)) %>
|
<%= render Components::ReportButton.new(object: @model, path: new_model_report_path(@model)) %>
|
||||||
|
|
|
||||||
|
|
@ -45,3 +45,64 @@ Rails.application.config.to_prepare do
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#class XRForgeRoutes
|
||||||
|
# # Rack endpoints must implement a #call method that accepts the Rack environment hash (env).
|
||||||
|
# def call(env)
|
||||||
|
# # Wrap the environment in a Rails Request object for easier parameter access
|
||||||
|
# request = ActionDispatch::Request.new(env)
|
||||||
|
#
|
||||||
|
# # 1. Access the model ID from the route parameters
|
||||||
|
# # The route path parameters are stored in the routing information
|
||||||
|
# model_id = request.path_parameters[:id]
|
||||||
|
#
|
||||||
|
# begin
|
||||||
|
# # 2. Find the model
|
||||||
|
# # Note: We are outside the controller, so we access Model directly.
|
||||||
|
# model = Model.find(model_id)
|
||||||
|
#
|
||||||
|
# puts "-------------------------"
|
||||||
|
# Rails.logger.info("build process for Model ID: #{model.id}")
|
||||||
|
# url_helpers = Rails.application.routes.url_helpers
|
||||||
|
# redirect_path = url_helpers.model_path(model)
|
||||||
|
#
|
||||||
|
# # 302 Found response for a temporary redirect
|
||||||
|
# [
|
||||||
|
# 302,
|
||||||
|
# {
|
||||||
|
# 'Content-Type' => 'text/html',
|
||||||
|
# 'Location' => redirect_path
|
||||||
|
# },
|
||||||
|
# ['Build process started successfully.']
|
||||||
|
# ]
|
||||||
|
#
|
||||||
|
# rescue ActiveRecord::RecordNotFound
|
||||||
|
# # Handle model not found error
|
||||||
|
# [
|
||||||
|
# 404,
|
||||||
|
# { 'Content-Type' => 'text/plain' },
|
||||||
|
# ["Model with ID #{model_id} not found."]
|
||||||
|
# ]
|
||||||
|
# rescue => e
|
||||||
|
# # Handle other errors
|
||||||
|
# Rails.logger.error("Build Rack App Error: #{e.message}")
|
||||||
|
# [
|
||||||
|
# 500,
|
||||||
|
# { 'Content-Type' => 'text/plain' },
|
||||||
|
# ["Internal Server Error: Could not initiate build."]
|
||||||
|
# ]
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#end
|
||||||
|
#
|
||||||
|
#Rails.configuration.to_prepare do
|
||||||
|
# Rails.application.routes.draw do
|
||||||
|
# resources :models, only: [] do
|
||||||
|
# member do
|
||||||
|
# # Point the route directly to an instance of the Rack application class.
|
||||||
|
# # The route is: POST /models/:id/build
|
||||||
|
# match 'build', to: XRForgeRoutes.new, via: :post
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#end
|
||||||
|
|
|
||||||
BIN
manyfold/usr/src/app/public/assets/jml_templates.png
Normal file
BIN
manyfold/usr/src/app/public/assets/jml_templates.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 239 KiB |
Loading…
Add table
Reference in a new issue