From c29a748151635adce6ff8439d9a60dbfa1e899d8 Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Wed, 12 Nov 2025 18:18:45 +0100 Subject: [PATCH] mimized scanning-frenzy [TODO: scan_libraries via dockercmd] --- manyfold/cli/manyfold.sh | 8 +- .../experience_updated/1000-scan-dir.sh | 6 +- .../hook.d/experience_updated/200-to-gltf.rb | 99 +++++++++++++++++++ .../300-package_godot_zip.sh | 2 +- .../experience_updated/300-package_janusxr.rb | 4 +- .../experience_updated/300-package_xrf.rb | 19 ++-- .../src/app/app/views/models/show.html.erb | 51 +++++----- 7 files changed, 151 insertions(+), 38 deletions(-) create mode 100755 manyfold/root/hook.d/experience_updated/200-to-gltf.rb mode change 100644 => 100755 manyfold/root/hook.d/experience_updated/300-package_godot_zip.sh diff --git a/manyfold/cli/manyfold.sh b/manyfold/cli/manyfold.sh index 7c00152..7ccee3b 100755 --- a/manyfold/cli/manyfold.sh +++ b/manyfold/cli/manyfold.sh @@ -206,12 +206,18 @@ start_syslog(){ } scan_libraries(){ - sleep 10 # wait for manyfold/redis to boot first cd /usr/src/app echocolor "scanning libraries" bin/manyfold libraries scan } +scan_experience(){ + id=$1 + cd /usr/src/app + # don't do this when all libraries are already being scanned + rails_query 'Model.find('$id').add_new_files_later(include_all_subfolders:false)' +} + rails_query(){ cd /usr/src/app echo "$*" | bin/rails console diff --git a/manyfold/root/hook.d/experience_updated/1000-scan-dir.sh b/manyfold/root/hook.d/experience_updated/1000-scan-dir.sh index 2136f8c..068cb69 100755 --- a/manyfold/root/hook.d/experience_updated/1000-scan-dir.sh +++ b/manyfold/root/hook.d/experience_updated/1000-scan-dir.sh @@ -3,5 +3,7 @@ dir="$(dirname $1)" cd "$dir" echo "[v] scan (new) files of model" id="$(basename "$dir" | sed 's/\#//g')" -cd /usr/src/app -echo "Model.find($id).add_new_files_later()" | /usr/src/app/bin/rails console +# TODO: better ratelimiting +test -f /tmp/.scan && test $id = "$(cat /tmp/.scan)" && exit +/manyfold/cli/manyfold.sh scan_experience $id +echo $id > /tmp/.scan diff --git a/manyfold/root/hook.d/experience_updated/200-to-gltf.rb b/manyfold/root/hook.d/experience_updated/200-to-gltf.rb new file mode 100755 index 0000000..f99541e --- /dev/null +++ b/manyfold/root/hook.d/experience_updated/200-to-gltf.rb @@ -0,0 +1,99 @@ +#!/usr/bin/env ruby + +require 'json' +require_relative './../../xrforge.rb' + +# Check if a filename is provided +if ARGV.length != 1 + puts "Usage: #{$0} " + exit 1 +end + +filename = ARGV[0] + +require 'base64' +require 'json' + +## Updates the 'uri' of an image in a GLTF hash when a matching PNG filename is found. +## +## gltf: a parsed JSON hash from a .gltf file +## png_path: path to the PNG file to embed +## +## returns: true if updated successfully, false if not found +#def update_gltf_image(gltf, png_path) +# # Get base name (without extension) +# name = File.basename(png_path, '.png') +# +# # Find image entry with the same name +# image_entry = gltf['images']&.find { |img| img['name'] == name } +# +# unless image_entry +# warn "No image named '#{name}' found in GLTF" +# return false +# end +# +# # Read and base64-encode the PNG file +# data = File.binread(png_path) +# encoded = Base64.strict_encode64(data) +# +# # Update the URI field with the base64-encoded PNG data URI +# image_entry['uri'] = "data:image/png;base64,#{encoded}" +# +# puts "Updated image '#{name}' in GLTF" +# true +#end + + +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" ) ) + + ext = File.extname(filename) + filenameWithoutExt = File.basename(filename, ext) + + if ! XRForge::MODEL_EXT.any?( ext ) + exit(0) # not a 3d file + end + + logfile = File.join( File.dirname(filename), ".xrforge/log.txt" ) + XRForge.log("✅ generating gltf", logfile) + gltf_path = ".xrforge/#{filenameWithoutExt}.gltf" + system("assimp export #{filename} #{gltf_path}") + system("assimp extract #{filename} | sed 's|/.*/||g'") + + # Read and parse the GLTF JSON + gltf = JSON.parse(File.read(gltf_path)) + + # Ensure images section exists + unless gltf['images'] && gltf['images'].is_a?(Array) + abort("No 'images' array found in #{gltf_path}") + end + + # Iterate through the images array + gltf['images'].each_with_index do |img, i| + name = img['name'] + next unless name && !name.empty? + + old_filename = "website_img#{i}.png" + new_filename = "#{name}.png" + + if File.exist?(old_filename) + XRForge.log("✅ Renaming #{old_filename} -> #{new_filename}", logfile) + File.rename(old_filename, new_filename) + end + end + + XRForge.log(" ", logfile) + +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 + diff --git a/manyfold/root/hook.d/experience_updated/300-package_godot_zip.sh b/manyfold/root/hook.d/experience_updated/300-package_godot_zip.sh old mode 100644 new mode 100755 index 29b7516..88180da --- a/manyfold/root/hook.d/experience_updated/300-package_godot_zip.sh +++ b/manyfold/root/hook.d/experience_updated/300-package_godot_zip.sh @@ -6,5 +6,5 @@ echo "[package_godot_zip.sh] zipping godot.zip" # overwrite empty godot template project-zip with given URL test -n "$GODOT_TEMPLATE_ZIP" && timeout 50 wget "$GODOT_TEMPLATE_ZIP" -O ~/template_godot.zip -cp ~/template_godot.zip package_godot.zip +cp ~/template_godot.zip .xrforge/godot.zip zip .xrforge/godot.zip *.glb *.usdz *.obj diff --git a/manyfold/root/hook.d/experience_updated/300-package_janusxr.rb b/manyfold/root/hook.d/experience_updated/300-package_janusxr.rb index 98c29b7..fd15ef8 100755 --- a/manyfold/root/hook.d/experience_updated/300-package_janusxr.rb +++ b/manyfold/root/hook.d/experience_updated/300-package_janusxr.rb @@ -68,10 +68,12 @@ begin - + + + JML html = <<~HTML diff --git a/manyfold/root/hook.d/experience_updated/300-package_xrf.rb b/manyfold/root/hook.d/experience_updated/300-package_xrf.rb index 04e527b..eee41b9 100755 --- a/manyfold/root/hook.d/experience_updated/300-package_xrf.rb +++ b/manyfold/root/hook.d/experience_updated/300-package_xrf.rb @@ -17,6 +17,7 @@ begin # Read and parse the JSON file data = JSON.parse( File.read( "datapackage.json" ) ) + logfile = File.join( File.dirname(filename), ".xrforge/log.txt" ) XRForge.log("✅ starting XR fragments check", logfile) # Extract the desired field (assuming the field is named 'model_file') @@ -47,16 +48,20 @@ begin # Check if a model file was found after the loop if model_file XRForge.log("✅ Final model file: '#{model_file}'", logfile) + # update datapackage + if ! data['keywords'].include?('xrfragments') + data['keywords'].push('xrfragments') + File.write("datapackage.json", JSON.pretty_generate(data) ) + end else XRForge.log("❌ No suitable 3D file found for XR Fragments-compatible experience", logfile) + # update datapackage + if data['keywords'].include?('xrfragments') + data['keywords'].delete('xrfragments') + File.write("datapackage.json", JSON.pretty_generate(data) ) + end end - - # Construct the output filename - output_file = "#{File.basename(model_file, File.extname(model_file))}.blend" - - # Execute the system call - puts("assimp", model_file, output_file) - system("assimp", model_file, output_file) + XRForge.log("✅ updating xrfragment tag", logfile) XRForge.log(" ", logfile) diff --git a/manyfold/usr/src/app/app/views/models/show.html.erb b/manyfold/usr/src/app/app/views/models/show.html.erb index 65e21b5..6b1dbc8 100644 --- a/manyfold/usr/src/app/app/views/models/show.html.erb +++ b/manyfold/usr/src/app/app/views/models/show.html.erb @@ -36,7 +36,7 @@ <% if @num_files > 0 %>

<%= t(".files") %>

- <%= render partial: "file", collection: @groups.delete(nil) %> + <%= render partial: "file", collection: (@groups.delete(nil)) + @images %>
<% @groups.each_pair do |group, files| %>

<%= group.strip.careful_titleize %>*

@@ -83,30 +83,30 @@ <% if ENV['FEDERATE_DRIVE_HOST'].present? %> <% if @model.tags.where(name: "janusxr" ).any? %> - - + + - - - <% - fediURL = ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html" - %> - <%= link_to "JanusXR address", fediURL, target:"_blank" %> - - -
- -
-   - - This is the JanusXR address.
- JanusXR is an Open Immersive Web-layer since 2015, which allows existing webpages to become spatial.
- It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc).
-
-
-
- - + + + <% + fediURL = ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html" + %> + <%= link_to "JanusXR address", fediURL, target:"_blank" %> + + +
+ +
+   + + This is the JanusXR address.
+ JanusXR is an Open Immersive Web-layer since 2015, which allows existing webpages to become spatial.
+ It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc).
+
+
+
+ + <% # lets generate a JanusXR spatial layer for the current scene @@ -117,10 +117,9 @@ end %> - <%== jml %> ---> <% end %>