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