diff --git a/src/.init.lua b/src/.init.lua
index 8ef02e8..bf5879d 100644
--- a/src/.init.lua
+++ b/src/.init.lua
@@ -79,6 +79,7 @@ app.plugin.peertube = app.addPlugin('plugin/peertube')
app.plugin.git = app.addPlugin('plugin/git')
app.plugin.webhook = app.addPlugin('plugin/webhook')
app.plugin.archive = app.addPlugin('plugin/archive')
+app.plugin.openbrush = app.addPlugin('plugin/openbrush')
--app.plugin.scheduler = app.addPlugin('plugin/scheduler') -- should always be second last
app.plugin.staticwebgen = app.addPlugin('plugin/staticwebgen') -- should always be last
diff --git a/src/css/xrforge.css b/src/css/xrforge.css
index c8fe12e..be4757a 100644
--- a/src/css/xrforge.css
+++ b/src/css/xrforge.css
@@ -297,7 +297,7 @@ img.icon{ display:none; }
.info{
background:#224;
- padding:10px 20px;
+ padding:20px 30px;
overflow:clip;
}
diff --git a/src/img/openbrush.png b/src/img/openbrush.png
new file mode 100644
index 0000000..a0a2771
Binary files /dev/null and b/src/img/openbrush.png differ
diff --git a/src/page/dir.lua b/src/page/dir.lua
index 24e97f4..7dc8080 100644
--- a/src/page/dir.lua
+++ b/src/page/dir.lua
@@ -31,7 +31,9 @@ return {
matchpath = rootpath
end
foreach( app.cache.items, function(k,v)
- if req.authenticated or app.plugin.moderation.isAllowed(v) then
+ if req.authenticated or
+ (app.plugin.moderation.isAllowed(v) and not app.plugin.janusxr.isWrapFile(v.path))
+ then
if v.parent then
-- trace( "path = " .. util.stripPath(v.path) .. " " ..
-- "parent = " .. util.stripPath(v.parent.path) .. " " ..
@@ -50,6 +52,7 @@ return {
if v.dir or v.view3D then
local parent = app.cache.items[ v.parent.id ]
res.items[ v.id ] = v
+ res.itemdir = v
res.parent = parent
end
if isroot then
@@ -83,7 +86,7 @@ return {
-- prioritize markup experience above binary 3D files as experience containers
if not data.item or (isMarkupExperience(v) and not isMarkupExperience(data.item)) then
-- update referrer url
- data.referrer = util.baseURLify(v.view3D and v.parent.parent.url or v.parent.url)
+ data.referrer = util.baseURLify(v.view3D and (v.parent.parent and v.parent.parent.url) or v.parent.url)
data.item = v
data.title = data.item.title
data.parent = v.parent
diff --git a/src/page/janusxr.html b/src/page/janusxr.html
index 6aa3a9e..6df6cd5 100644
--- a/src/page/janusxr.html
+++ b/src/page/janusxr.html
@@ -1,6 +1,8 @@
{if true then
- showfediportals = app.opts.plugin_federation_strategy == 'always' or
- (app.opts.plugin_federation_strategy == 'homepage' and urlpath == '/')
+ sidecarfile = (parent and parent.path or '') .. '/' .. app.opts.plugin_janusxr_wrap_custom
+ hasSidecarfile = util.fileExist(sidecarfile) and true or false
+ showfediportals = app.opts.plugin_federation_strategy == 'always' or
+ (app.opts.plugin_federation_strategy == 'homepage' and urlpath == '/')
-- optimize janus resource URLs for archive.org
app.plugin.archive.flush()
@@ -49,7 +51,7 @@ end}
pos = '0 0 2'
room = app.plugin.janusxr.wrapRoomAroundFile(item)
end
- if defined(item) and item.tag.xrfragments and item.tag.xrfragments.href then
+ if hasSidecarfile or (defined(item) and item.tag.xrfragments and item.tag.xrfragments.href) then
room = '' -- xrfragments 3D files dont need to be wrapped with room
end
print(' ')
@@ -148,10 +150,19 @@ end}
end}
- {if not defined(item) then
+ {if not defined(item) and not hasSidecarfile then
print('${janusxr_jml_deco}')
end}
- ${opts.plugin_janusxr_jml}
+ {if hasSidecarfile then
+ print(' ')
+ print(' ')
+
+
+ end}
+ {if #opts.plugin_janusxr_jml > 0 then
+ print(' ')
+ print(' ' .. app.opts.plugin_janusxr_jml)
+ end}
diff --git a/src/plugin/janusxr.lua b/src/plugin/janusxr.lua
index c207828..3fd931f 100644
--- a/src/plugin/janusxr.lua
+++ b/src/plugin/janusxr.lua
@@ -5,7 +5,6 @@ local pattern_title = "<[Tt][Ii][Tt][Ll][Ee]>(.*)<"
local pattern_aframe = " 100kb
+ if me.isWrapFile(exp.path) and size < 100000 then -- skip large binary files > 100kb
local data = util.readfile( exp.file.fullpath)
if data then
if data:match(pattern_fireboxroom) or
@@ -50,7 +49,7 @@ app.on('scan_experience_file', function(exp)
app.addExperience( exp, exp.file.ino )
exp.view3D = true
exp.parent.redirect = exp.url -- mark parent to redirect to this standalone url instead (not glb assets e.g.)
- exp.janusxr = {}
+ exp.janusxr = exp.janusxr or {}
print("✅ └─ plugin/janusxr: " .. exp.file.name)
if data:match(pattern_aframe) and app.opts.plugin_janusxr_wrap_aframe == 'enabled' then
exp.janusxr.wrap = {aframe = true }
@@ -89,6 +88,13 @@ local plugin = {
default="https://p.janusxr.org https://cors.xrforge.org",
values=''
},
+ {
+ key='app.opts.plugin_janusxr_wrap_custom',
+ title='VR wrap custom',
+ info='include "index.jml" files (if found) in generated JML',
+ default="index.jml",
+ values={ ["index.jml"] = "index.jml"}
+ },
{
key='app.opts.plugin_janusxr_wrap_3dfile',
title='VR wrap 3D file',
@@ -172,6 +178,11 @@ local plugin = {
}
},
+ isWrapFile = function(path)
+ return tostring(path):match("/" .. app.opts.plugin_janusxr_wrap_custom:gsub("%.",".") .. "jml$")
+ and true or false
+ end,
+
wrapRoomAroundFile = function(item)
local room = ''
if item.janusxr.wrap.object then
diff --git a/src/plugin/openbrush.lua b/src/plugin/openbrush.lua
new file mode 100644
index 0000000..8997a41
--- /dev/null
+++ b/src/plugin/openbrush.lua
@@ -0,0 +1,123 @@
+local util = require('util')
+
+app.on('init', function()
+end)
+
+app.on('scan_experience', function(exp)
+end)
+
+app.on('scan_experience_file', function(exp)
+end)
+
+app.on('set', function(k,v)
+end)
+
+app.on('scheduler', function(opts)
+-- if opts.interval == app.opts.plugin_archive_when then
+--
+-- end
+end)
+
+local sync_URL = app.opts_plugin_openbrush_sync_URL or ''
+
+-- this registers the plugin UI
+local plugin = {
+ name = "OpenBrush",
+ infowide = true,
+ info = [[
+
+ OpenBrush lets you paint in 3D space with virtual reality.
+ XRForge's webviewer (JanusWeb) supports interconnecting OpenBrush projects via 3D portals.
+ OpenBrush projects are stored in a (selfhosted) icosa.gallery instance, which can be configured below.
+ ]],
+ opts = {
+ {
+ key='app.opts.plugin_openbrush_sync_when',
+ title='When to sync',
+ info='when to check for new experiences?',
+ default = "hourly",
+ values={disabled="disabled", daily="daily", hourly="hourly"}
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_folder_thumbnail',
+ title='Sync to folder',
+ info='openbrush (icosa.gallery) assets will be saved here',
+ placeholder = "openbrush",
+ default = "openbrush",
+ values=''
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_folder',
+ title='Thumbnail',
+ info='URL of Thumbnail for folder/portal',
+ placeholder = "img/openbrush.png",
+ default = "img/openbrush.png",
+ values=''
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_URL',
+ title='Icosa gallery URL',
+ info='public/selfhosted icosa.gallery server-instance',
+ placeholder = "https://icosa.gallery",
+ default = "https://icosa.gallery",
+ values=''
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_category',
+ title='category',
+ info=( sync_URL and 'space-separated, leave empty or see API docs' or ''),
+ placeholder = "ART",
+ default = "",
+ values=''
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_keywords',
+ title='keywords',
+ info=( sync_URL and 'space-separated, leave empty or see API docs' or ''),
+ placeholder = "xrforge",
+ default = "",
+ values=''
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_tag',
+ title='tags',
+ info=( sync_URL and 'space-separated, leave empty or see API docs' or ''),
+ placeholder = "xrforge",
+ default = "",
+ values=''
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_triangle_max',
+ title='Polygons maximum',
+ info=( sync_URL and 'performance-cap, leave empty or see API docs' or ''),
+ placeholder = "10000",
+ default = "",
+ values=''
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_author',
+ title='Author name',
+ info='filter assets on specific Author name',
+ placeholder='sarah',
+ default = "",
+ values=""
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_authorid',
+ title='Author id',
+ info='filter assets on specific Author id',
+ placeholder='9e8b98fbe',
+ default = "",
+ values=""
+ },
+ {
+ key='app.opts.plugin_openbrush_sync_collection',
+ title='Collection required',
+ info='should assets be part of a collection?',
+ default = "enabled",
+ values={enabled="enabled", disabled="disabled"}
+ }
+ }
+}
+
+return plugin