diff --git a/assets/shaders/dynamic_renderer/vertex_colors_default/fragment.frag.glsl b/assets/shaders/dynamic_renderer/vertex_colors_default/fragment.frag.glsl index 57cdabe..0e1acca 100644 --- a/assets/shaders/dynamic_renderer/vertex_colors_default/fragment.frag.glsl +++ b/assets/shaders/dynamic_renderer/vertex_colors_default/fragment.frag.glsl @@ -1,6 +1,5 @@ #version 300 es precision highp float; -#include in vec3 vPos; in vec3 vWorldPos; diff --git a/assets/shaders/dynamic_renderer/vertex_colors_default/vertex.vert.glsl b/assets/shaders/dynamic_renderer/vertex_colors_default/vertex.vert.glsl index df3615d..4179c1a 100644 --- a/assets/shaders/dynamic_renderer/vertex_colors_default/vertex.vert.glsl +++ b/assets/shaders/dynamic_renderer/vertex_colors_default/vertex.vert.glsl @@ -1,8 +1,6 @@ #version 300 es precision highp float; -// debug line shader - // input vertex layout(location = 0) in vec3 aPos; layout(location = 1) in vec4 aColor; diff --git a/lib/core/metaroom.js b/lib/core/metaroom.js index 70d4bfd..d43f8bf 100644 --- a/lib/core/metaroom.js +++ b/lib/core/metaroom.js @@ -5,7 +5,7 @@ import {MetaroomVRBackend} from "./webvr_backend.js"; import {ServerPublishSubscribe} from "./event_pubsub.js"; import {ViewpointController} from "./viewpoint_controller.js"; -import {Client} from "./object_sync_client.js"; +import {Client} from "./websocket_client.js"; import {EventBus} from "./eventbus.js"; // the "base" type diff --git a/lib/core/object_sync_client.js b/lib/core/object_sync_client.js deleted file mode 100644 index e7bf4c3..0000000 --- a/lib/core/object_sync_client.js +++ /dev/null @@ -1,151 +0,0 @@ -"use strict" - -import {Lock} from "./lock.js"; - -// TODO: add ping pong heartbeart to keep connections alive -// TODO: finish automatic reconnection -// TODO: max retries + timeout - -export class Client { - constructor(heartbeat = 30000) { - this.locks = {}; - this.heartbeatTick = heartbeat; - this.ws = null; - } - - backoff(t) { - if (t == 0) { - t = 1; - } else { - t *= 2 - } - - return t; - } - - // TODO: verify this is working - heartbeat() { - clearTimeout(this.pingTimeout); - - // Delay should be equal to the interval at which your server - // sends out pings plus a conservative assumption of the latency. - this.pingTimeout = setTimeout(() => { - // this.close(); // i.e. revisit this... - }, this.heartbeatTick + 1000); - } - - // expected as a js object - // TODO: - // add guaranteed delivery - send(message) { - this.ws.send(JSON.stringify(message)); - } - - connect(ip, port) { - try { - - console.log('ws://' + ip + ':' + port); - this.ws = new WebSocket('ws://' + ip + ':' + port); - console.log('connected'); - //ws.on('ping', this.heartbeat); - - let reconnectTimeout = null; - this.t = 0; - - // function reconnect - - this.ws.onopen = () => { - - this.heartbeat(); - // reset t, clean up later - this.t = 0; - console.log('websocket is connected ...'); - if (this.ws.readyState == WebSocket.OPEN) { - // TODO: - // send message with client side config if needed - } else { - // setTimeout((ws) => {if (ws.readyState == WebSocket.OPEN) { - // }, 10); - } - // ws.send('connected'); - }; - - this.ws.onmessage = (ev) => { - try { - //console.log(ev); - let json = JSON.parse(ev.data); - MR.EventBus.publish(json["type"], json); - } catch(err) { - // console.log("bad json:", json); - console.error(err); - } - //console.log(JSON.parse(ev)); - - }; - - //const payload = {'translation': [0.0, 1.0, 0.0], 'orientation': [0.0, 0.0, 0.0, 1.0]}; - //const payload = {'type': 'object', 'uid': 1}; - // const payload = {'type': 'restart', 'uid': 1}; - - // const interval = setInterval(() => ws.send(JSON.stringify(payload)), args.interval); - - this.ws.onclose = (event) => { - switch (event.code) { - // CLOSE_NORMAL - case 1000: - console.log("WebSocket: closed"); - break; - // Abnormal closure - default: - // console.log(event); - // reconnect(event); - console.log('reconnecting...'); - // /* - // this.ws = null; - /* - reconnectTimeout = setTimeout(() => { - try { - // this.backoff(this.t); - this.connect(ip, port); - clearTimeout(reconnectTimeout); - } catch(err) { - console.log(err); - // console.log('.'); - // clearInterval(reconnectTimeout); - // reconnectTimeout = setTimeout(reconnect, t); - } - - }, this.t); - */ - break; - // */ - } - console.log("disconnected"); - // clearInterval(interval); - clearTimeout(this.pingTimeout); - }; - - this.ws.onerror = (e) => { - switch (e.code) { - case 'ECONNREFUSED': - console.error(e); - // reconnect(e); - this.ws.close(); - break; - default: - // this.onerror(e); - break; - } - }; - - } catch (err) { - console.error("Couldn't load websocket", err); - } - } - // TODO: - // register event for lock and release, that return true or false from onlock in Lock class - createLock(uid) { - this.locks[uid] = new Lock(); - return this.locks[uid]; - } -}; \ No newline at end of file diff --git a/lib/core/profile.js b/lib/core/profile.js index 9505801..962bb94 100644 --- a/lib/core/profile.js +++ b/lib/core/profile.js @@ -1,20 +1,11 @@ "use strict"; -import {ShaderTextEditor} from "/lib/core/shader_text_editor.js"; - export default class Profile { - constructor(){ + constructor() { this.RESOLUTION = document.getElementById("resolution").getAttribute("value").split(','); } - main(){ - ShaderTextEditor.enable(); - - ShaderTextEditor.init({ - defaultShaderCompilationFunction : ShaderTextEditor.onNeedsCompilationDefault, - //externalWindowGetter : function() { return MR.engine.externalWindow; } - }); - + main() { MR.initWorldsScroll(); MR.initPlayerViewSelectionScroll(); MR.syncClient.connect(window.IP, window.PORT_SYNC); diff --git a/lib/core/shader_text_editor.js b/lib/core/shader_text_editor.js index ca675a8..aad6188 100644 --- a/lib/core/shader_text_editor.js +++ b/lib/core/shader_text_editor.js @@ -6,8 +6,8 @@ import * as WatchFile from "./watchfile.js"; // temp import {MenuItem} from "/lib/ui/default_window_menu.js"; -const _outEnabled = {}; -const _outDisabled = {}; +const ShaderTextEditorEnabled = {}; +const ShaderTextEditorDisabled = {}; const TEXT_COLOR_NO_ERROR = "#BFBFBF"; //'#BFBFBF';d3b58d const TEXT_COLOR_ERROR = '#dddda0'; @@ -19,33 +19,115 @@ let globalErrorMsgNode; let globalErrorMsgNodeText; let globalErrorMsgState = {vertex : "", fragment : "", link : ""}; -class Editor { +export class ShaderTextEditor { + + static instance = null; + + static makeCurrent(instance) { + ShaderTextEditor.instance = instance; + } + constructor() { this.libMap = null; this.tempCompiledShader = null; this.libToShaderMap = new Map(); } + + static init(args) { + + this.defaultShaderCompilationFunction = + args.defaultShaderCompilationFunction || this.onNeedsCompilationDefault; + + const doc = document; + + doc.addEventListener('input', function (event) { + if (event.target.tagName.toLowerCase() !== 'textarea') return; + autoExpand(event.target); + }, false); + + resetState(); + + const showHideState = { + idx : 0, + text : ["Show", "Hide Shader Editor"], + style : ["none", "block"], + classes : ["hidden", "shown"] + }; + ShaderTextEditor.toggleHideEditor = (event) => { + MR.wrangler.menu.hide.name = + showHideState.text[showHideState.idx]; + document.getElementById('text-areas').style.display = + showHideState.style[showHideState.idx]; + + showHideState.idx ^= 1; + + const classes = showHideState.classes; + globalErrorMsgNode.classList.remove(classes[1 - showHideState.idx]); + globalErrorMsgNode.classList.add(classes[showHideState.idx]); + + MR.wrangler.codeIsHidden = (showHideState.idx === 1); + }; + ShaderTextEditor.hideEditor = (event) => { + if (showHideState.idx == 0) { + ShaderTextEditor.toggleHideEditor(); + } + }; + ShaderTextEditor.showEditor = (event) => { + if (showHideState.idx == 1) { + ShaderTextEditor.toggleHideEditor(); + } + }; + + MR.wrangler.menu.hide = new MenuItem( + MR.wrangler.menu.el, 'ge_menu', 'Hide', + ShaderTextEditor.toggleHideEditor + ); + MR.wrangler.codeIsHidden = false; + + document.getElementById("text-areas").style.paddingBottom = + (MR.wrangler.menu.el.getBoundingClientRect().height * 1.5) + "px"; + + MR.wrangler.menu.save = new MenuItem(MR.wrangler.menu.el, 'ge_menu', 'Save', saveCallback); + document.addEventListener("keydown", function(e) { + if ((window.navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && e.keyCode == 83) { + e.preventDefault(); + saveCallback(e); + } + }, false); + + const header = doc.createElement("H1"); + header.classList.add("status_info"); + header.classList.add("hidden"); + header.classList.add("fixed"); + header.style.color = ERR_COLOR_MESSAGE; + const text = doc.createTextNode(''); + header.appendChild(text); + const textAreas = document.getElementById('text-areas'); + + textAreas.parentNode.insertBefore(header, textAreas); + + globalErrorMsgNode = header; + globalErrorMsgNodeText = text; + } } -const _out = new Editor(); -const ShaderTextEditor = _out; function hookIntoGFXLib(gfxLib__) { } -_out.hookIntoGFXLib = hookIntoGFXLib; +ShaderTextEditor.hookIntoGFXLib = hookIntoGFXLib; function disable() { } -_out.disable = disable; +ShaderTextEditor.disable = disable; function enable() { } -_out.enable = enable; +ShaderTextEditor.enable = enable; -_out.shaderMap = null; +ShaderTextEditor.shaderMap = null; function detectFeatures() { const textArea = document.createElement("textarea"); @@ -58,7 +140,7 @@ function detectFeatures() { document.body.removeChild(textArea); } -_out.detectFeatures = detectFeatures; +ShaderTextEditor.detectFeatures = detectFeatures; function autoExpand(field) { @@ -118,7 +200,7 @@ function resetState() { globalErrorMsgNodeText.nodeValue = ""; } { - _out.shaderMap = new Map(); + ShaderTextEditor.shaderMap = new Map(); const _tareas = document.getElementById("text-areas"); if (!_tareas) { return; @@ -147,14 +229,14 @@ function resetState() { } } - _out.libMap = null; - _out.libGroupMap = null; + ShaderTextEditor.libMap = null; + ShaderTextEditor.libGroupMap = null; GFX.tempCompiledShaderDirty = false; GFX.tempPreprocessorErrRecord = null; GFX.tempCompiledShader = null; } -_out.resetState = resetState; +ShaderTextEditor.resetState = resetState; const saveCallback = (event) => { let msgs = []; @@ -266,114 +348,16 @@ const saveCallback = (event) => { // } }; -function init(args) { - - this.defaultShaderCompilationFunction = - args.defaultShaderCompilationFunction || this.onNeedsCompilationDefault; - - this.getExternalWindow = args.externalWindowGetter; - - const doc = (this.getExternalWindow) ? this.getExternalWindow().document : document; - - doc.addEventListener('input', function (event) { - if (event.target.tagName.toLowerCase() !== 'textarea') return; - autoExpand(event.target); - }, false); - - resetState(); - - const showHideState = { - idx : 0, - text : ["Show", "Hide"], - style : ["none", "block"], - classes : ["hidden", "shown"] - }; - ShaderTextEditor.toggleHideEditor = (event) => { - MR.wrangler.menu.hide.name = - showHideState.text[showHideState.idx]; - document.getElementById('text-areas').style.display = - showHideState.style[showHideState.idx]; - - showHideState.idx ^= 1; - - const classes = showHideState.classes; - globalErrorMsgNode.classList.remove(classes[1 - showHideState.idx]); - globalErrorMsgNode.classList.add(classes[showHideState.idx]); - - MR.wrangler.codeIsHidden = (showHideState.idx === 1); - }; - ShaderTextEditor.hideEditor = (event) => { - MR.wrangler.menu.hide.name = - showHideState.text[0]; - document.getElementById('text-areas').style.display = - showHideState.style[0]; - - showHideState.idx = 1; - - const classes = showHideState.classes; - globalErrorMsgNode.classList.remove(classes[1]); - globalErrorMsgNode.classList.add(classes[0]); - - MR.wrangler.codeIsHidden = true; - }; - ShaderTextEditor.showEditor = (event) => { - MR.wrangler.menu.hide.name = - showHideState.text[1]; - document.getElementById('text-areas').style.display = - showHideState.style[1]; - - showHideState.idx = 0; - - const classes = showHideState.classes; - globalErrorMsgNode.classList.remove(classes[0]); - globalErrorMsgNode.classList.add(classes[1]); - - MR.wrangler.codeIsHidden = false; - }; - - MR.wrangler.menu.hide = new MenuItem( - MR.wrangler.menu.el, 'ge_menu', 'Hide', - ShaderTextEditor.toggleHideEditor - ); - MR.wrangler.codeIsHidden = false; - - document.getElementById("text-areas").style.paddingBottom = - (MR.wrangler.menu.el.getBoundingClientRect().height * 1.5) + "px"; - - MR.wrangler.menu.save = new MenuItem(MR.wrangler.menu.el, 'ge_menu', 'Save', saveCallback); - document.addEventListener("keydown", function(e) { - if ((window.navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey) && e.keyCode == 83) { - e.preventDefault(); - saveCallback(e); - } - }, false); - - const header = doc.createElement("H1"); - header.classList.add("status_info"); - header.classList.add("hidden"); - header.classList.add("fixed"); - header.style.color = ERR_COLOR_MESSAGE; - const text = doc.createTextNode(''); - header.appendChild(text); - const textAreas = document.getElementById('text-areas'); - - textAreas.parentNode.insertBefore(header, textAreas); - - globalErrorMsgNode = header; - globalErrorMsgNodeText = text; -} -_out.init = init; - -function compileValidateStringsAndHandleErrors(vertex, fragment) { +function compileValidateStrings(vertex, fragment) { GFX.tempCompiledShader = GFX.compileValidateStrings( vertex, fragment ); GFX.tempCompiledShaderDirty = true; } -_out.compileValidateStringsAndHandleErrors = compileValidateStringsAndHandleErrors; +ShaderTextEditor.compileValidateStrings = compileValidateStrings; -function preprocessAndCreateShaderProgramFromStringsAndHandleErrors(vertex, fragment, libMap, autoIncludes) { +function preprocessCompileValidateStrings(vertex, fragment, libMap, autoIncludes) { const vertRecord = GFX.preprocessShaderSource(vertex, libMap); const fragRecord = GFX.preprocessShaderSource(fragment, libMap); @@ -395,8 +379,8 @@ function preprocessAndCreateShaderProgramFromStringsAndHandleErrors(vertex, frag ); GFX.tempCompiledShaderDirty = true; } -_out.preprocessAndCreateShaderProgramFromStringsAndHandleErrors = preprocessAndCreateShaderProgramFromStringsAndHandleErrors; -async function loadShader(_gl, key, callbacks, options) { +ShaderTextEditor.preprocessCompileValidateStrings = preprocessCompileValidateStrings; +async function loadAndRegisterShader(_gl, key, callbacks, options) { if (!options || !options.paths || !options.paths.vertex || !options.paths.fragment) { return Promise.reject("No paths provided"); } @@ -413,7 +397,7 @@ async function loadShader(_gl, key, callbacks, options) { fsrc = await assetutil.loadTextRelativePath(options.paths.fragment); } - _out.registerShaderForLiveEditing( + ShaderTextEditor.registerShader( _gl, key, {vertex : vsrc, fragment : fsrc}, callbacks, @@ -425,8 +409,8 @@ async function loadShader(_gl, key, callbacks, options) { } }); } -_out.loadShader = loadShader; -_out.loadAndRegisterShaderForLiveEditing = loadShader; +ShaderTextEditor.loadAndRegisterShader = loadAndRegisterShader; +ShaderTextEditor.loadShader = loadAndRegisterShader; async function loadLibs(_gl, key, args, options) { return new Promise(async (resolve, reject) => { @@ -455,7 +439,7 @@ async function loadLibs(_gl, key, args, options) { if (err) { reject(null); } else { - _out.registerShaderLibrariesForLiveEditing(_gl, key, libArgs, options); + ShaderTextEditor.registerLibs(_gl, key, libArgs, options); resolve(libArgs); } }); @@ -464,12 +448,12 @@ async function loadLibs(_gl, key, args, options) { } }).catch((err) => { return null; }); } -_out.loadLibs = loadLibs; -_out.loadLibs = loadLibs; +ShaderTextEditor.loadLibs = loadLibs; +ShaderTextEditor.loadLibs = loadLibs; -_out.recompileDelayDefault = 50; +ShaderTextEditor.recompileDelayDefault = 50; -function registerShaderLibrariesForLiveEditing(_gl, key, args, options) { +function registerLibs(_gl, key, args, options) { if (!args) { console.warn("No libraries object specified. Libraries section will be empty."); return; @@ -714,7 +698,7 @@ function registerShaderLibrariesForLiveEditing(_gl, key, args, options) { const toWatch = [] for (let i = 0; i < args.length; i += 1) { const arg = args[i]; - let saveTo = _out.defaultShaderOutputPath; + let saveTo = ShaderTextEditor.defaultShaderOutputPath; if (arg.path) { const argPath = arg.path; @@ -761,7 +745,7 @@ function registerShaderLibrariesForLiveEditing(_gl, key, args, options) { } -_out.registerShaderLibrariesForLiveEditing = registerShaderLibrariesForLiveEditing; +ShaderTextEditor.registerLibs = registerLibs; function onNeedsCompilationDefault(args, libMap, userData) { const vertex = args.vertex; @@ -786,7 +770,7 @@ function onNeedsCompilationDefault(args, libMap, userData) { return {program : program, errRecord : errRecord} } -_out.onNeedsCompilationDefault = onNeedsCompilationDefault; +ShaderTextEditor.onNeedsCompilationDefault = onNeedsCompilationDefault; function onNeedsCompilationNoPreprocessorDefault(args, libMap, userData) { const vertex = args.vertex; @@ -801,7 +785,7 @@ function onNeedsCompilationNoPreprocessorDefault(args, libMap, userData) { return {program : program, errRecord : errRecord}; } -_out.onNeedsCompilationNoPreprocessorDefault = onNeedsCompilationNoPreprocessorDefault; +ShaderTextEditor.onNeedsCompilationNoPreprocessorDefault = onNeedsCompilationNoPreprocessorDefault; function saveLibsToFile(key) { if (!key) { @@ -810,12 +794,12 @@ function saveLibsToFile(key) { } } -_out.defaultShaderOutputPath = "worlds/saved_editor_shaders"; +ShaderTextEditor.defaultShaderOutputPath = "worlds/saved_editor_shaders"; function saveShaderToFile(key, status = {}) { - console.log("Saving:", key); + console.log("%cSaving: %s", "color: #00EE00;", key); if (!key) { status.message = "ERR_NO_KEY_SPECIFIED"; console.error("No shader key specified"); @@ -843,6 +827,9 @@ function saveShaderToFile(key, status = {}) { } const options = record.options; + if (options && options.readonly) { + return true; + } let writeQueue = []; function enqueueWrite(q, text, path, opts) { @@ -858,7 +845,7 @@ function saveShaderToFile(key, status = {}) { if (Object.prototype.hasOwnProperty.call(record.args, prop)) { const textE = record.textAreas[prop]; if (textE) { - let saveTo = _out.defaultShaderOutputPath; + let saveTo = ShaderTextEditor.defaultShaderOutputPath; let guardAgainstOverwrite = true; if (options && options.paths && options.paths[prop]) { guardAgainstOverwrite = false; @@ -866,20 +853,27 @@ function saveShaderToFile(key, status = {}) { const parentPath = getCurrentPath(window.location.pathname); // const localPath = options.saveTo[prop]; // console.log("parentPath:", parentPath); - // console.log("local file to save:", options.saveTo[prop]); // console.log("origin:", window.location.origin); - - saveTo = getPath(options.paths[prop]); + + saveTo = (options.useAbsolutePaths) ? + options.paths[prop] : + getPath(options.paths[prop]); + // console.log("original path:", options.paths[prop]); + // console.log("local path", saveTo); const origin = window.location.origin; + const originIdx = saveTo.indexOf(origin); - saveTo = saveTo.substring(originIdx + origin.length + 1); + if (originIdx >= 0) { + saveTo = saveTo.substring(originIdx + origin.length + 1); + } // console.log("remove origin:", saveTo); if (parentPath !== '/' && parentPath !== '\\') { const parentIdx = saveTo.indexOf(parentPath); saveTo = saveTo.substring(parentIdx + parentPath.length); } + } else { saveTo += "/" + prop + ".glsl"; } @@ -897,10 +891,10 @@ function saveShaderToFile(key, status = {}) { return true; } -_out.saveShaderToFile = saveShaderToFile; +ShaderTextEditor.saveShaderToFile = saveShaderToFile; function saveShaderLibsToFile(key, status = {}) { - console.log("Saving:", key); + console.log("%cSaving: %s", "color: #00EE00;", key); if (!key) { status.message = "ERR_NO_KEY_SPECIFIED"; console.error("No shader lib key specified"); @@ -921,6 +915,10 @@ function saveShaderLibsToFile(key, status = {}) { return false; } + if (record.options && record.options.readonly) { + return true; + } + let writeQueue = []; function enqueueWrite(q, text, path, opts) { q.push({path : path, text : text, opts : opts}); @@ -935,7 +933,7 @@ function saveShaderLibsToFile(key, status = {}) { const textE = record.textAreas[prop]; if (textE) { - let saveTo = _out.defaultShaderOutputPath; + let saveTo = ShaderTextEditor.defaultShaderOutputPath; let guardAgainstOverwrite = true; if (arg.path) { @@ -943,11 +941,21 @@ function saveShaderLibsToFile(key, status = {}) { const parentPath = getCurrentPath(window.location.pathname); - saveTo = getPath(arg.path); + saveTo = (record.options && record.options.useAbsolutePaths) ? + arg.path : + getPath(arg.path); + + //console.group("WEE"); + //console.log("SAVETO LIB:", saveTo); const origin = window.location.origin; + //console.log("ORIGIN:", origin); const originIdx = saveTo.indexOf(origin); - saveTo = saveTo.substring(originIdx + origin.length + 1); + if (originIdx >= 0) { + saveTo = saveTo.substring(originIdx + origin.length + 1); + } + + //console.log("SAVETO LIB:", saveTo); if (parentPath !== '/' && parentPath !== '\\') { const parentIdx = saveTo.indexOf(parentPath); @@ -968,9 +976,9 @@ function saveShaderLibsToFile(key, status = {}) { return true; } -_out.saveShaderLibsToFile = saveShaderLibsToFile; +ShaderTextEditor.saveShaderLibsToFile = saveShaderLibsToFile; -async function loadAndRegisterShaderForLiveEditing(_gl, key, callbacks, options) { +async function loadShader(_gl, key, callbacks, options) { if (!options || !options.paths || !options.paths.vertex || !options.paths.fragment) { return Promise.reject("No paths provided"); } @@ -979,7 +987,7 @@ async function loadAndRegisterShaderForLiveEditing(_gl, key, callbacks, options) const vsrc = await assetutil.loadText(options.paths.vertex); const fsrc = await assetutil.loadText(options.paths.fragment); - _out.registerShaderForLiveEditing( + ShaderTextEditor.registerShader( _gl, key, {vertex : vsrc, fragment : fsrc}, callbacks, @@ -993,9 +1001,9 @@ async function loadAndRegisterShaderForLiveEditing(_gl, key, callbacks, options) }); } -_out.loadAndRegisterShaderForLiveEditing = loadAndRegisterShaderForLiveEditing; +ShaderTextEditor.loadShader = loadShader; -_out.insertTextSupported = true; +ShaderTextEditor.insertTextSupported = true; function updateShaderCompilationCallbacks(key, callbacks) { if (!key) { @@ -1010,9 +1018,9 @@ function updateShaderCompilationCallbacks(key, callbacks) { record.onNeedsCompilation = callbacks.onNeedsCompilation || record.onNeedsCompilation; record.onAfterCompilation = callbacks.onAfterCompilation || record.onAfterCompilation; } -_out.updateShaderCompilationCallbacks = updateShaderCompilationCallbacks; +ShaderTextEditor.updateShaderCompilationCallbacks = updateShaderCompilationCallbacks; -function registerShaderForLiveEditing(_gl, key, args, callbacks, options) { +function registerShader(_gl, key, args, callbacks, options) { if (!key) { console.error("No shader key specified"); return; @@ -1381,7 +1389,7 @@ function registerShaderForLiveEditing(_gl, key, args, callbacks, options) { { //// watch files const toWatch = []; for (let prop in args) { - let saveTo = _out.defaultShaderOutputPath; + let saveTo = ShaderTextEditor.defaultShaderOutputPath; if (options && options.paths && options.paths[prop]) { const parentPath = getCurrentPath(window.location.pathname); @@ -1589,8 +1597,4 @@ function registerShaderForLiveEditing(_gl, key, args, callbacks, options) { return compile; } - -_out.registerShaderForLiveEditing = registerShaderForLiveEditing; - - -export {_out as ShaderTextEditor}; +ShaderTextEditor.registerShader = registerShader; diff --git a/lib/core/webvr_profile.js b/lib/core/webvr_profile.js index 2cfc880..b8af8a8 100644 --- a/lib/core/webvr_profile.js +++ b/lib/core/webvr_profile.js @@ -11,7 +11,12 @@ export default class WebVRProfile extends Profile { } async main(){ - ShaderTextEditor.detectFeatures(); + ShaderTextEditor.enable(); + + ShaderTextEditor.init({ + defaultShaderCompilationFunction : ShaderTextEditor.onNeedsCompilationDefault, + }); + this.deferredActions = []; wrangler.isTransitioning = false; diff --git a/lib/core/webxr_profile.js b/lib/core/webxr_profile.js index aa846f9..f5a226a 100644 --- a/lib/core/webxr_profile.js +++ b/lib/core/webxr_profile.js @@ -38,6 +38,13 @@ export default class WebXRProfile extends Profile { ui.makeModalCanvas(MR.getCanvas()); } + + ShaderTextEditor.enable(); + + ShaderTextEditor.init({ + defaultShaderCompilationFunction : ShaderTextEditor.onNeedsCompilationDefault, + }); + this.deferredActions = []; super.main(); diff --git a/lib/core/world_template.js b/lib/core/world_template.js index 6e3c233..37dca61 100644 --- a/lib/core/world_template.js +++ b/lib/core/world_template.js @@ -89,7 +89,7 @@ export default class WorldBase{ stageCode.substring(hdrEndIdx + 1); } } - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap @@ -97,7 +97,7 @@ export default class WorldBase{ } // load vertex and fragment shaders from the server, register with the editor - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( gl, "mainShader", { diff --git a/lib/render/dynamic_renderer_wgl.js b/lib/render/dynamic_renderer_wgl.js index 7d08dd7..bdf5e09 100644 --- a/lib/render/dynamic_renderer_wgl.js +++ b/lib/render/dynamic_renderer_wgl.js @@ -16,7 +16,7 @@ const STATE_CHANGE_CLOCK_SECONDS = 13; const STATE_CHANGE_TYPE_COUNT__ = 7; const ident = new Float32Array([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]); -const bufMat4 = new Float32Array(16).fill(0); +const bufMat4 = new Float32Array(16); /** * Multiplies two mat4s * @@ -848,8 +848,8 @@ export class ShaderCatalogue { const libs = args.libs || [ { key : "pnoise", - path : ROOT_SHADERS + "noise/pnoise.glsl", // TODO(TR): paths not in the local world - foldDefault : true + path : ROOT_SHADERS + "noise/pnoise.glsl", + foldDefault : true, }, { key : "trig", @@ -857,10 +857,11 @@ export class ShaderCatalogue { foldDefault : true } ]; - let shaderLibHandle = await ShaderTextEditor.loadLibs(ctx, "libs", + let shaderLibHandle = await ShaderTextEditor.loadLibs(ctx, "dynamic_renderer_libs", libs, { - useAbsolutePaths : true + useAbsolutePaths : true, + readonly : true } ); if (!shaderLibHandle) { @@ -869,7 +870,7 @@ export class ShaderCatalogue { defaultCatalogue.shaderLibs = shaderLibHandle; // color shader - let shaderHandle = await ShaderTextEditor.loadShader( + let shaderHandle = await ShaderTextEditor.loadAndRegisterShader( ctx, "vertex_colors_default", { @@ -892,7 +893,8 @@ export class ShaderCatalogue { // whether the editor should hide the shader sections by default foldDefault : {vertex : true, fragment : true}, - useAbsolutePaths : true + useAbsolutePaths : true, + readonly : true } ); if (!shaderHandle) { @@ -1469,12 +1471,15 @@ export class Renderer_GL { deinit() { this.ctx.bindVertexArray(null); - this.ctx.bindBuffer(gl.ARRAY_BUFFER, null); + for(let i = 0; i < this.gpuState.bufferCount; i += 1) { + this.ctx.bindBuffer(gl.ARRAY_BUFFER, this.gpuState.buffers[i].vbo); + this.ctx.bufferData(this.ctx.ARRAY_BUFFER, null, this.ctx.STATIC_DRAW); this.ctx.deleteBuffer(this.gpuState.buffers[i].vbo); this.ctx.deleteVertexArray(this.gpuState.buffers[i].vao); } + this.ctx.bindBuffer(gl.ARRAY_BUFFER, null); } beginRenderPass() { diff --git a/worlds/dynamic_renderer/dynamic_renderer.js b/worlds/dynamic_renderer/dynamic_renderer.js index 8c2dad7..d0de853 100644 --- a/worlds/dynamic_renderer/dynamic_renderer.js +++ b/worlds/dynamic_renderer/dynamic_renderer.js @@ -47,6 +47,8 @@ async function initRenderer(state) { async function setup(state) { hotReloadFile(getPath('dynamic_renderer.js')); + ShaderTextEditor.hideEditor(); + CanvasUtil.resize(MR.getCanvas(), 1280 / 2, 720 / 2); await initCommon(state); diff --git a/worlds/hp/hp.js b/worlds/hp/hp.js index 31d3604..8e2007f 100644 --- a/worlds/hp/hp.js +++ b/worlds/hp/hp.js @@ -439,7 +439,7 @@ async function setup(state) { // non-Meta_Room-controlled state. state.images = images; - let libSources = await ShaderTextEditor.loadAndRegisterShaderLibrariesForLiveEditing(gl, "libs", [ + let libSources = await ShaderTextEditor.loadLibs(gl, "libs", [ { key : "pnoise", path : "shaders/noise.glsl", foldDefault : true }, @@ -448,7 +448,7 @@ async function setup(state) { throw new Error("Could not load shader library"); } - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( // gl context gl, // name of shader as it should appear in the editor @@ -482,7 +482,7 @@ async function setup(state) { } // uses a preprocessor for custom extensions to GLSL - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap diff --git a/worlds/hp2/hp.js b/worlds/hp2/hp.js index 3b84e9b..d7f9fe6 100644 --- a/worlds/hp2/hp.js +++ b/worlds/hp2/hp.js @@ -385,7 +385,7 @@ async function setup(state) { state.video = GFX.setupVideo(getPath("resources/textures/bla2.mp4")); state.images = images; - let libSources = await ShaderTextEditor.loadAndRegisterShaderLibrariesForLiveEditing(gl, "libs", [ + let libSources = await ShaderTextEditor.loadLibs(gl, "libs", [ { key : "pnoise", path : "shaders/noise.glsl", foldDefault : true }, @@ -394,7 +394,7 @@ async function setup(state) { throw new Error("Could not load shader library"); } - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( // gl context gl, // name of shader as it should appear in the editor @@ -420,7 +420,7 @@ async function setup(state) { } // uses a preprocessor for custom extensions to GLSL - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap diff --git a/worlds/metanook2/metanook2.js b/worlds/metanook2/metanook2.js index fc86e1b..ef89eb3 100644 --- a/worlds/metanook2/metanook2.js +++ b/worlds/metanook2/metanook2.js @@ -43,7 +43,7 @@ async function setup(state) { getPath("./../../assets/textures/tiles.jpg"), ]); - let libSources = await ShaderTextEditor.loadAndRegisterShaderLibrariesForLiveEditing(gl, "libs", [ + let libSources = await ShaderTextEditor.loadLibs(gl, "libs", [ { key : "pnoise" , path : "shaders/noise.glsl" , foldDefault : true }, { key : "sharedlib1", path : "shaders/sharedlib1.glsl", foldDefault : true }, ]); @@ -51,7 +51,7 @@ async function setup(state) { throw new Error("Could not load shader library"); // load vertex and fragment shaders from the server, register with the editor - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( gl, "mainShader", { @@ -70,7 +70,7 @@ async function setup(state) { stageCode.substring(hdrEndIdx + 1); } } - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap diff --git a/worlds/triangles/triangles.js b/worlds/triangles/triangles.js index e745f22..097081b 100644 --- a/worlds/triangles/triangles.js +++ b/worlds/triangles/triangles.js @@ -334,7 +334,7 @@ async function setup(state) { // Editor Specific: // editor library function for loading shader snippets from files on disk - let libSources = await ShaderTextEditor.loadShader(gl, "libs", [ + let libSources = await ShaderTextEditor.loadAndRegisterShader(gl, "libs", [ { key : "pnoise", path : "shaders/noise.glsl", foldDefault : true }, @@ -348,9 +348,9 @@ async function setup(state) { // Editor Specific: // load vertex and fragment shaders from disk, register with the editor - // (You can also use ShaderTextEditor.registerShaderForLiveEditing to load a shader string + // (You can also use ShaderTextEditor.registerShader to load a shader string // created in the program - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( // gl context gl, // name of shader as it should appear in the editor @@ -385,7 +385,7 @@ async function setup(state) { } // uses a preprocessor for custom extensions to GLSL - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap diff --git a/worlds/webgpu_experimental/msaa_triangle/gpu_lib.js b/worlds/webgpu_experimental/msaa_triangle/gpu_lib.js index cd1f912..ecb3c00 100644 --- a/worlds/webgpu_experimental/msaa_triangle/gpu_lib.js +++ b/worlds/webgpu_experimental/msaa_triangle/gpu_lib.js @@ -155,7 +155,7 @@ export class Shader { } } -export async function loadShaderCompiler(state) { +export async function loadAndRegisterShaderCompiler(state) { state.shaderCompilerModule = await import( "https://unpkg.com/@webgpu/glslang@0.0.12/dist/web-devel/glslang.js" ); diff --git a/worlds/webgpu_experimental/msaa_triangle/main.js b/worlds/webgpu_experimental/msaa_triangle/main.js index 4040796..8d9ec0d 100644 --- a/worlds/webgpu_experimental/msaa_triangle/main.js +++ b/worlds/webgpu_experimental/msaa_triangle/main.js @@ -87,7 +87,7 @@ async function setup(state, info) { const canvas = MR.getCanvas(); state.gpuInfo = gpulib.defaultInitGPUState(gpu, info, canvas); // load a shader compiler (in this case, for GLSL) - await gpulib.loadShaderCompiler(state.gpuInfo); + await gpulib.loadAndRegisterShaderCompiler(state.gpuInfo); { const ubo = new MyUniformBufferObject(); diff --git a/worlds/week10/week10.js b/worlds/week10/week10.js index e57f6de..4e0f0a2 100644 --- a/worlds/week10/week10.js +++ b/worlds/week10/week10.js @@ -154,6 +154,8 @@ async function initRenderer(state) { async function setup(state) { hotReloadFile(getPath('week10.js')); + ShaderTextEditor.showEditor(); + state.noise = new ImprovedNoise(); state.rot4 = new Rot4(); await initCommon(state); @@ -197,7 +199,7 @@ async function setup(state) { stageCode.substring(hdrEndIdx + 1); } } - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap @@ -1304,7 +1306,7 @@ function onEndFrame(t, state) { // per-frame data state.dr.rewindToStart(); - pollAvatarData(); + //pollAvatarData(); /*----------------------------------------------------------------- diff --git a/worlds/week6/week6.js b/worlds/week6/week6.js index b506e5a..e2d91ea 100644 --- a/worlds/week6/week6.js +++ b/worlds/week6/week6.js @@ -272,7 +272,7 @@ async function setup(state) { throw new Error("Could not load shader library"); } - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( // gl context gl, // name of shader as it should appear in the editor @@ -306,7 +306,7 @@ async function setup(state) { } // uses a preprocessor for custom extensions to GLSL - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap diff --git a/worlds/week8/week8.js b/worlds/week8/week8.js index 791e7c6..465f292 100644 --- a/worlds/week8/week8.js +++ b/worlds/week8/week8.js @@ -76,7 +76,7 @@ async function setup(state) { throw new Error("Could not load shader library"); // load vertex and fragment shaders from the server, register with the editor - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( gl, "mainShader", { @@ -95,7 +95,7 @@ async function setup(state) { stageCode.substring(hdrEndIdx + 1); } } - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap diff --git a/worlds/week8plusviews/week8.js b/worlds/week8plusviews/week8.js index 3d5d29d..8dda37f 100644 --- a/worlds/week8plusviews/week8.js +++ b/worlds/week8plusviews/week8.js @@ -27,7 +27,7 @@ async function setup(state) { throw new Error("Could not load shader library"); // load vertex and fragment shaders from the server, register with the editor - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( gl, "mainShader", { @@ -46,7 +46,7 @@ async function setup(state) { stageCode.substring(hdrEndIdx + 1); } } - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap diff --git a/worlds/week9/week9.js b/worlds/week9/week9.js index 8399704..5aa22a8 100644 --- a/worlds/week9/week9.js +++ b/worlds/week9/week9.js @@ -134,7 +134,7 @@ async function setup(state) { stageCode.substring(hdrEndIdx + 1); } } - ShaderTextEditor.preprocessAndCreateShaderProgramFromStringsAndHandleErrors( + ShaderTextEditor.preprocessCompileValidateStrings( output[0], output[1], libMap @@ -142,7 +142,7 @@ async function setup(state) { } // load vertex and fragment shaders from the server, register with the editor - let shaderSource = await ShaderTextEditor.loadAndRegisterShaderForLiveEditing( + let shaderSource = await ShaderTextEditor.loadShader( gl, "mainShader", {