cleanup hooks + added gltf-JSON section in show-template + added mastodonpost2image hook
This commit is contained in:
parent
2518383301
commit
54efe0da3d
6 changed files with 238 additions and 55 deletions
|
|
@ -14,36 +14,6 @@ filename = ARGV[0]
|
||||||
require 'base64'
|
require 'base64'
|
||||||
require 'json'
|
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
|
begin
|
||||||
|
|
||||||
# Change the directory
|
# Change the directory
|
||||||
|
|
@ -55,36 +25,20 @@ begin
|
||||||
ext = File.extname(filename)
|
ext = File.extname(filename)
|
||||||
filenameWithoutExt = File.basename(filename, ext)
|
filenameWithoutExt = File.basename(filename, ext)
|
||||||
|
|
||||||
if ! XRForge::MODEL_EXT.any?( ext )
|
if ! XRForge::MODEL_EXT.any?( ext ) || ext == ".gltf"
|
||||||
exit(0) # not a 3d file
|
exit(0) # not a 3d file
|
||||||
end
|
end
|
||||||
|
|
||||||
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||||
XRForge.log("✅ generating gltf", logfile)
|
XRForge.log("✅ generating gltf", logfile)
|
||||||
gltf_path = ".xrforge/#{filenameWithoutExt}.gltf"
|
gltf_path = ".xrforge/scene.gltf"
|
||||||
system("assimp export #{filename} #{gltf_path}")
|
system("assimp export #{filename} #{gltf_path}")
|
||||||
system("assimp extract #{filename} | sed 's|/.*/||g'")
|
system("assimp extract #{filename} | sed 's|/.*/||g'")
|
||||||
|
|
||||||
# Read and parse the GLTF JSON
|
# tag it!
|
||||||
gltf = JSON.parse(File.read(gltf_path))
|
if ! data['keywords'].include?('gltf')
|
||||||
|
data['keywords'].push('gltf')
|
||||||
# Ensure images section exists
|
File.write("datapackage.json", JSON.pretty_generate(data) )
|
||||||
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
|
end
|
||||||
|
|
||||||
XRForge.log(" ", logfile)
|
XRForge.log(" ", logfile)
|
||||||
|
|
|
||||||
101
manyfold/root/hook.d/experience_updated/250-to-textures.rb
Executable file
101
manyfold/root/hook.d/experience_updated/250-to-textures.rb
Executable file
|
|
@ -0,0 +1,101 @@
|
||||||
|
#!/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
|
||||||
|
|
||||||
|
puts "TODO"
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
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("✅ unpacking textures", 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
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@ require_relative './../../xrforge.rb'
|
||||||
|
|
||||||
# Check if a filename is provided
|
# Check if a filename is provided
|
||||||
if ARGV.length != 1
|
if ARGV.length != 1
|
||||||
puts "Usage: #{$0} <path/to/experience/somefile.xxx>"
|
puts "Usage: #{$0} <path/to/experience/datapackage.json>"
|
||||||
exit 1
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -13,6 +13,11 @@ filename = ARGV[0]
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
|
# dont run for each file-update
|
||||||
|
if ! filename.end_with?("datapackage.json")
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
# Change the directory
|
# Change the directory
|
||||||
dir = File.dirname(filename)
|
dir = File.dirname(filename)
|
||||||
Dir.chdir( File.dirname(filename) )
|
Dir.chdir( File.dirname(filename) )
|
||||||
|
|
@ -68,7 +73,7 @@ begin
|
||||||
<Assets>
|
<Assets>
|
||||||
<assetobject id="experience" src="#{federate_drive_host}/#{model_file.gsub("#","%23")}"/>
|
<assetobject id="experience" src="#{federate_drive_host}/#{model_file.gsub("#","%23")}"/>
|
||||||
</Assets>
|
</Assets>
|
||||||
<Room #{ data['keywords'].include?('singleuser') ? "private='true'" : ""}>
|
<Room pbr="true" #{ data['keywords'].include?('singleuser') ? "private='true'" : ""}>
|
||||||
<object pos="0 0 0" collision_id="experience" id="experience" />
|
<object pos="0 0 0" collision_id="experience" id="experience" />
|
||||||
</Room>
|
</Room>
|
||||||
</FireBoxRoom>
|
</FireBoxRoom>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@ end
|
||||||
|
|
||||||
filename = ARGV[0]
|
filename = ARGV[0]
|
||||||
|
|
||||||
|
# dont run for each file-update
|
||||||
|
if ! filename.end_with?("datapackage.json")
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
# Change the directory
|
# Change the directory
|
||||||
|
|
|
||||||
96
manyfold/root/hook.d/experience_updated/500-mastodon-post2image.rb
Executable file
96
manyfold/root/hook.d/experience_updated/500-mastodon-post2image.rb
Executable file
|
|
@ -0,0 +1,96 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'json'
|
||||||
|
require 'rss'
|
||||||
|
require 'open-uri'
|
||||||
|
require 'cgi'
|
||||||
|
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]
|
||||||
|
|
||||||
|
# dont run for each file-update
|
||||||
|
if ! filename.end_with?("datapackage.json")
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
# Change the directory
|
||||||
|
Dir.chdir( File.dirname(filename) )
|
||||||
|
# Read and parse the JSON file
|
||||||
|
data = JSON.parse( File.read( "datapackage.json" ) )
|
||||||
|
|
||||||
|
data['keywords'].any? do |tag|
|
||||||
|
if tag.match?(/@.*@.*\./) # scan for activitypub handle (@foo@mastodon.online e.g.)
|
||||||
|
APHandle = tag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if ! APHandle # nothing to do
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
APHandle = "@vladh@merveilles.town"
|
||||||
|
|
||||||
|
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||||
|
XRForge.log("✅ starting Mastodon post2image", logfile)
|
||||||
|
|
||||||
|
parts = APHandle.split("@")
|
||||||
|
server = parts[2].sub(/@/,"")
|
||||||
|
rssUrl = "https://#{server}/@#{parts[1]}.rss"
|
||||||
|
XRForge.log("✅ checking #{rssUrl}", logfile)
|
||||||
|
|
||||||
|
feed = RSS::Parser.parse(URI.open(rssUrl, 'User-Agent' => 'Ruby-RSS-Client'))
|
||||||
|
|
||||||
|
puts feed.channel.title
|
||||||
|
puts feed.channel.link
|
||||||
|
|
||||||
|
first_item = feed.items.first
|
||||||
|
if first_item
|
||||||
|
description = CGI.unescapeHTML(first_item.description.to_s).gsub(/<[^>]*>/, '')
|
||||||
|
description = description.length > 150 ? description = description[0,200] + " (..)" : description
|
||||||
|
else
|
||||||
|
XRForge.log("❌ did not find post", logfile)
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
puts description
|
||||||
|
|
||||||
|
# look for first image
|
||||||
|
MEDIA_REGEX = /<media:content url=['"]([^'"]+)['"]/
|
||||||
|
img = feed.to_s.match(MEDIA_REGEX)
|
||||||
|
if img and img[1] and img[1].match(/(png|jpg)/)
|
||||||
|
imgurl = img[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
text = "\n\"#{description}\"\n\n~ #{feed.channel.title}\n#{feed.channel.link}"
|
||||||
|
textFile = ".xrforge/mastodon-post.txt"
|
||||||
|
File.open(textFile,'w') do |file|
|
||||||
|
file.puts text
|
||||||
|
end
|
||||||
|
|
||||||
|
cmd = "magick -size 800x800 -background white -pointsize 48 -interline-spacing 10 -fill \\#555 -gravity center -font /usr/local/lib/ruby/3.4.0/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf caption:@#{textFile} mastodon-post.png"
|
||||||
|
puts cmd
|
||||||
|
system(cmd)
|
||||||
|
|
||||||
|
XRForge.log(" ", logfile)
|
||||||
|
|
||||||
|
rescue OpenURI::HTTPError => e
|
||||||
|
# Handle HTTP errors (e.g., 404 not found, 403 forbidden)
|
||||||
|
puts "Error fetching feed: #{e.message}"
|
||||||
|
exit
|
||||||
|
rescue => e
|
||||||
|
# Handle other parsing or connection errors
|
||||||
|
puts "An error occurred: #{e.message}"
|
||||||
|
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
|
||||||
|
|
@ -187,6 +187,28 @@
|
||||||
</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>
|
||||||
|
This is an opensource fallback-mechanism for developers/engine's which don't support <a href="https://xfragment.org" target="_blank">XR Fragments</a>.
|
||||||
|
deeplinks.<br><br>
|
||||||
|
Instead of <b>https://my.org/foo.glb#chair</b> they can do:
|
||||||
|
<code><pre>$ curl <gltfURL> | jq '.meshes[] | select(.name == "chair")'</pre></code>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @model.collection %>
|
<% if @model.collection %>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue