From f949436c988e5d194318d2717abe762827391faa Mon Sep 17 00:00:00 2001 From: lxsang Date: Mon, 21 Jun 2021 01:02:25 +0200 Subject: [PATCH] update --- ShaderPlayground/build/debug/main.js | 627 +++++++++++++++++- .../build/release/ShaderPlayground.zip | Bin 5754 -> 0 bytes ShaderPlayground/main.ts | 3 +- 3 files changed, 627 insertions(+), 3 deletions(-) delete mode 100644 ShaderPlayground/build/release/ShaderPlayground.zip diff --git a/ShaderPlayground/build/debug/main.js b/ShaderPlayground/build/debug/main.js index ccb86ca..420eb97 100644 --- a/ShaderPlayground/build/debug/main.js +++ b/ShaderPlayground/build/debug/main.js @@ -1 +1,626 @@ -var OS;!function(e){let t,i;!function(e){let t;!function(e){class t extends e.ListViewItemTag{itemlayout(){return{el:"div",children:[{el:"img",ref:"img"},{el:"p",ref:"name"}]}}ondatachange(){const e=this.data,t=this.refs.img,i=e.path.asFileHandle().getlink();t.src=i,$(this.refs.name).text(e.name)}init(){this.closable=!0}reload(e){}}e.define("afx-shader-texture-item",t)}(t=e.tag||(e.tag={}))}(t=e.GUI||(e.GUI={})),function(e){class i extends t.BasicDialog{constructor(){super("AddTextureDialog",i.scheme)}main(){super.main();const e=$("input",this.scheme);this.find("btnOk").onbtclick=t=>{let i={};for(const t of e){let e=t;if(""==e.value.trim())return this.notify(__("All fields should be filled"));i[e.name]=e.value.trim()}this.handle&&this.handle(i),this.quit()},this.find("btnFile").onbtclick=e=>{this.openDialog("FileDialog",{title:__("Select image file"),type:"file",mimes:["image/.*"]}).then(e=>{this.find("txtPath").value=e.file.path})}}}i.scheme='\n \n
\n \n
\n \n \n
\n \n \n \n \n \n
\n
\n \n
\n
\n
\n
\n
\n
';class s{constructor(e,t){this.glsl_values=[s.frg_template,""],this.renderer=t,this.ums=[new ace.UndoManager,new ace.UndoManager],this.current_idx=-1,this.tmp_canvas=$("")[0],this.gl_compiling_ctx=this.tmp_canvas.getContext("webgl"),this._filehandle=void 0,this.editormux=!1,ace.require("ace/ext/language_tools"),this._onfilechange=e=>{},this._ontextureadded=e=>{},this.editor=ace.edit(e),this.editor.setOptions({enableBasicAutocompletion:!0,enableLiveAutocompletion:!0,enableSnippets:!0,highlightActiveLine:!0}),this.editor.getSession().setUseWrapMode(!0),this.editor.session.setMode("ace/mode/glsl"),this.editor.setTheme("ace/theme/monokai"),this.cursors=[this.editor.getCursorPosition(),this.editor.getCursorPosition()],this.editor.on("input",e=>{const t=this.editor.getValue(),i=0==this.current_idx?this.gl_compiling_ctx.FRAGMENT_SHADER:this.gl_compiling_ctx.VERTEX_SHADER,s=this.compile(t,i);if(!1!==this.filehandle.dirty||this.editormux||(this.filehandle.dirty=!0,this._onfilechange(this.filehandle.path+"*")),this.editormux&&(this.editormux=!1),s){const e="ERROR:\\s*([0-9]+):([0-9]+):\\s*(.*)\\n",t=s.match(new RegExp(e,"g"));t&&this.editor.getSession().setAnnotations(t.map(t=>{const i=t.match(new RegExp(e));let s={};return i&&(s={row:parseInt(i[2])-1,column:0,text:i[3],type:"error"}),s}))}else this.editor.getSession().setAnnotations([]),this.glsl_values[this.current_idx]=t,this.renderer.apply_mat(this.glsl_values[0],this.glsl_values[1])})}set onfilechange(e){this._onfilechange=e}set ontextureadded(e){this._ontextureadded=e}set filehandle(e){this._filehandle=e,this.read()}get filehandle(){return this._filehandle}read(){return new Promise(async(e,t)=>{if(void 0===this._filehandle)return this.renderer.textures.length=0,this._filehandle="Untitled".asFileHandle(),this._onfilechange(this._filehandle.path),this.glsl_values=[s.frg_template,""],2!=this.current_idx&&-1!=this.current_idx&&(this.editormux=!0,this.editor.setValue(this.glsl_values[this.current_idx])),this._ontextureadded(void 0),e(void 0);try{const t=await this._filehandle.read("json");this.glsl_values[0]=t.source[0],this.glsl_values[1]=t.source[1],2!=this.current_idx&&-1!=this.current_idx&&(this.editormux=!0,this.editor.setValue(this.glsl_values[this.current_idx])),this._ontextureadded(void 0);for(const e of t.textures)this._ontextureadded(e);this._onfilechange(this._filehandle.path),e(void 0)}catch(e){t(e)}})}write(e){return new Promise(async(t,i)=>{let s=e;const n=__("Unknown save path");if(!s){if(void 0===this._filehandle)return i(n);s=this._filehandle.path}if("Untitled"===s)return i(n);try{this._filehandle.setPath(s);const e={};2!=this.current_idx&&(this.glsl_values[this.current_idx]=this.editor.getValue()),e.source=this.glsl_values,e.textures=this.renderer.textures.map(e=>({name:e.name,path:e.path})),this.filehandle.cache=e,await this.filehandle.write("object"),this._filehandle.dirty=!1,this._onfilechange(""+this.filehandle.path),t(void 0)}catch(e){i(e)}})}compile(e,t){let i=this.gl_compiling_ctx.createShader(t);this.gl_compiling_ctx.shaderSource(i,e),this.gl_compiling_ctx.compileShader(i);let s=void 0;return this.gl_compiling_ctx.getShaderParameter(i,this.gl_compiling_ctx.COMPILE_STATUS)||(s=this.gl_compiling_ctx.getShaderInfoLog(i)),this.gl_compiling_ctx.deleteShader(i),s}edit(e){if(e<0)return;if(2!=e&&2!=this.current_idx)0===e?(this.glsl_values[1]=this.editor.getValue(),this.cursors[1]=this.editor.getCursorPosition()):1===e&&(this.glsl_values[0]=this.editor.getValue(),this.cursors[0]=this.editor.getCursorPosition());else if(2==e)return this.glsl_values[this.current_idx]=this.editor.getValue(),this.cursors[this.current_idx]=this.editor.getCursorPosition(),void(this.current_idx=e);this.current_idx=e,this.editormux=!0,this.editor.getSession().setUndoManager(new ace.UndoManager),this.editor.setValue(this.glsl_values[e]),this.editor.getSession().setUndoManager(this.ums[e]);const t=this.cursors[e];this.editor.renderer.scrollCursorIntoView({row:t.row,column:t.column},.5),this.editor.selection.moveTo(t.row,t.column),this.editor.focus()}cleanup(){this.renderer.cleanup(),$(this.tmp_canvas).remove()}resize(){this.editor.resize(),this.renderer.viewport_resize()}}class n{constructor(e){this.textures=[],this.renderer=new THREE.WebGLRenderer({canvas:e,alpha:!0}),this.renderer.autoClearColor=!1,this.clock=new THREE.Clock,this.camera=new THREE.OrthographicCamera(-1,1,1,-1,-1,1),this.needupdateTexture=!1,this.scene=new THREE.Scene;const t=new THREE.MeshBasicMaterial({color:"white"}),i=new THREE.PlaneGeometry(2,2);this.mesh=new THREE.Mesh(i,t),this.scene.add(this.mesh),this.uniforms={u_resolution:{value:{x:0,y:0}},u_time:{value:0},u_mouse:{value:{x:0,y:0}}},this.viewport_resize(),this.ani_request_id=requestAnimationFrame(()=>this.viewport_render())}viewport_render(){this.needupdateTexture&&(this.update_textures(),this.needupdateTexture=!1),this.uniforms.u_time.value=this.clock.getElapsedTime();try{this.renderer.render(this.scene,this.camera)}catch(e){console.error(e)}this.ani_request_id=requestAnimationFrame(()=>this.viewport_render())}viewport_resize(){const e=this.renderer.domElement,t=e.clientWidth,i=e.clientHeight;this.uniforms.u_resolution.value.x=t,this.uniforms.u_resolution.value.y=i,(e.width!==t||e.height!==i)&&this.renderer.setSize(t,i,!1)}cleanup(){console.log("Stop the animation before quitting..."),window.cancelAnimationFrame(this.ani_request_id)}update_textures(){for(const e in this.uniforms)-1===["u_resolution","u_time","u_mouse"].indexOf(e)&&(this.uniforms[e]=new THREE.MeshBasicMaterial({color:"black"}));for(const e of this.textures)this.uniforms[e.name]={value:e.texture};console.log(this.uniforms)}apply_mat(e,t){const i={fragmentShader:""===e.trim()?"void main(){}":e,uniforms:this.uniforms,vertexShader:void 0};""!=t.trim()&&(i.vertexShader=t);const s=new THREE.ShaderMaterial(i);this.mesh.material=s,console.log(this.uniforms)}}s.frg_template="#ifdef GL_ES\nprecision mediump float;\n#endif\n// uniform vec2 u_resolution;\n// uniform vec2 u_mouse;\nuniform float u_time;\n\nvoid main() {\n gl_FragColor = vec4(abs(sin(u_time)),0.0,0.0,1.0);\n} ";class r extends e.BaseApplication{constructor(e){super("ShaderPlayground",e)}main(){this.init_editor(),this.init_textures_list(),this.bindKey("ALT-N",()=>this.newFile()),this.bindKey("ALT-O",()=>this.openFile()),this.bindKey("CTRL-S",()=>this.saveFile())}init_editor(){this.tabbar=this.find("tabbar"),this.tabbar.items=[{text:__("Fragment"),iconclass:"bi bi-palette"},{text:__("Vertex"),iconclass:"bi bi-intersect"},{text:__("Textures"),iconclass:"bi bi-image-alt"}],this.tabbar.ontabselect=e=>{this.selectTab()},this.editor=new s(this.find("editor-container"),new n(this.find("viewport"))),this.on("resize",e=>{this.editor.resize()}),this.editor.onfilechange=e=>{this.scheme.apptitle=e},this.editor.ontextureadded=e=>{this.add_texture(e)},this.editor.filehandle=void 0,this.tabbar.selected=0}add_texture(e){{const t=this.find("texture-list");if(!e)return this.editor.renderer.textures=[],t.data=this.editor.renderer.textures,void(this.editor.renderer.needupdateTexture=!0);const i=(new THREE.TextureLoader).load(e.path.asFileHandle().getlink());i.minFilter=THREE.NearestFilter,i.magFilter=THREE.NearestFilter,i.wrapS=THREE.RepeatWrapping,i.wrapT=THREE.RepeatWrapping,e.texture=i,t.push(e),this.editor.renderer.needupdateTexture=!0}}init_textures_list(){const e=this.find("texture-list");e.buttons=[{text:"__(Add texture)",iconclass:"bi bi-plus",onbtclick:e=>{this.openDialog(new i).then(e=>this.add_texture(e))}}],e.itemtag="afx-shader-texture-item",e.onitemclose=e=>(this.editor.renderer.needupdateTexture=!0,!0),this.add_texture(void 0)}selectTab(){const e=this.tabbar.selected;2===e?($(this.find("editor-container")).hide(),$(this.find("texture-list")).show()):($(this.find("editor-container")).show(),$(this.find("texture-list")).hide()),this.editor.edit(e)}menu(){return[{text:"__(File)",nodes:[{text:"__(New)",dataid:"new",shortcut:"A-N"},{text:"__(Open)",dataid:"open",shortcut:"A-O"},{text:"__(Save)",dataid:"save",shortcut:"C-S"}],onchildselect:e=>{switch(e.data.item.data.dataid){case"new":return this.newFile();case"open":return this.openFile();case"save":return this.saveFile()}}}]}ignore_unsaved(){return new Promise(async(e,t)=>!0===this.editor.filehandle.dirty?e(!!await this.ask({title:__("Unsaved shader"),text:__("Ignore unsaved file?")})):e(!0))}async newFile(){await this.ignore_unsaved()&&(this.editor.filehandle=void 0)}async openFile(){try{if(!await this.ignore_unsaved())return;const e=await this.openDialog("FileDialog",{title:__("Open file"),mimes:this.meta().mimes});this.editor.filehandle.setPath(e.file.path),await this.editor.read()}catch(e){this.error(__(e.toString()),e)}}async saveFile(){if("Untitled"!==this.editor.filehandle.path)return this.editor.write(void 0);const e=await this.openDialog("FileDialog",{title:__("Save as"),file:this.editor.filehandle});let t=e.file.path.asFileHandle();"file"===e.file.type&&(t=t.parent());try{await this.editor.write(`${t.path}/${e.name}`)}catch(e){this.error(__(e.toString()),e)}}cleanup(e){if(this.editor.filehandle.dirty)return this.ignore_unsaved().then(e=>{e&&(this.editor.filehandle.dirty=!1,this.quit(!0))}),void e.preventDefault();this.editor.cleanup()}}e.ShaderPlayground=r,r.dependencies=["pkg://libthreejs/main.js","pkg://ACECore/core/ace.js","pkg://ACECore/path.js","pkg://ACECore/core/ext-language_tools.js","pkg://ShaderPlayground/glslx.js"]}(i=e.application||(e.application={}))}(OS||(OS={})); \ No newline at end of file + +var OS; +(function (OS) { + let GUI; + (function (GUI) { + let tag; + (function (tag) { + class TextureListItem extends tag.ListViewItemTag { + itemlayout() { + return { + el: "div", + children: [ + { + el: "img", + ref: "img" + }, + { + el: "p", + ref: "name" + } + ] + }; + } + ondatachange() { + const v = this.data; + const img = this.refs.img; + const uri = v.path.asFileHandle().getlink(); + img.src = uri; + $(this.refs.name).text(v.name); + } + init() { + this.closable = true; + } + reload(d) { + } + } + tag.define("afx-shader-texture-item", TextureListItem); + })(tag = GUI.tag || (GUI.tag = {})); + })(GUI = OS.GUI || (OS.GUI = {})); + let application; + (function (application) { + class AddTextureDialog extends GUI.BasicDialog { + constructor() { + super("AddTextureDialog", AddTextureDialog.scheme); + } + main() { + super.main(); + const inputs = $("input", this.scheme); + this.find("btnOk").onbtclick = (e) => { + let cdata = {}; + for (const el of inputs) { + let input = el; + if (input.value.trim() == "") { + return this.notify(__("All fields should be filled")); + } + cdata[input.name] = input.value.trim(); + } + if (this.handle) + this.handle(cdata); + this.quit(); + }; + this.find("btnFile").onbtclick = (e) => { + this.openDialog("FileDialog", { + title: __("Select image file"), + type: "file", + mimes: ["image/.*"] + }) + .then((d) => { + this.find("txtPath").value = d.file.path; + }); + }; + } + } + AddTextureDialog.scheme = `\ + + +
+ +
+ + +
+ + + + + +
+
+ +
+
+
+
+
+
\ +`; + class ShaderEditor { + constructor(domel, renderer) { + this.glsl_values = [ShaderEditor.frg_template, ""]; + this.renderer = renderer; + this.ums = [new ace.UndoManager(), new ace.UndoManager()]; + this.current_idx = -1; + this.tmp_canvas = $("")[0]; + this.gl_compiling_ctx = this.tmp_canvas.getContext("webgl"); + this._filehandle = undefined; + this.editormux = false; + ace.require("ace/ext/language_tools"); + this._onfilechange = (v) => { }; + this._ontextureadded = (t) => { }; + this.editor = ace.edit(domel); + this.editor.setOptions({ + enableBasicAutocompletion: true, + enableLiveAutocompletion: true, + enableSnippets: true, + highlightActiveLine: true, + //fontSize: "9pt" + }); + this.editor.getSession().setUseWrapMode(true); + this.editor.session.setMode("ace/mode/glsl"); + this.editor.setTheme("ace/theme/monokai"); + this.cursors = [ + this.editor.getCursorPosition(), + this.editor.getCursorPosition() + ]; + this.editor.on("input", (e) => { + const value = this.editor.getValue(); + const stype = this.current_idx == 0 ? this.gl_compiling_ctx.FRAGMENT_SHADER : this.gl_compiling_ctx.VERTEX_SHADER; + const errors = this.compile(value, stype); + if (this.filehandle.dirty === false && !this.editormux) { + this.filehandle.dirty = true; + this._onfilechange(`${this.filehandle.path}*`); + } + if (this.editormux) { + this.editormux = false; + } + if (errors) { + const reg_str = "ERROR:\\s*([0-9]+):([0-9]+):\\s*(.*)\\n"; + const matches = errors.match(new RegExp(reg_str, "g")); + if (matches) { + this.editor.getSession().setAnnotations(matches.map((match) => { + const err_data = match.match(new RegExp(reg_str)); + let ret = {}; + if (err_data) { + ret = { + row: parseInt(err_data[2]) - 1, + column: 0, + text: err_data[3], + type: "error" + }; + } + return ret; + })); + } + } + else { + this.editor.getSession().setAnnotations([]); + this.glsl_values[this.current_idx] = value; + this.renderer.apply_mat(this.glsl_values[0], this.glsl_values[1]); + } + }); + } + set onfilechange(fn) { + this._onfilechange = fn; + } + set ontextureadded(fn) { + this._ontextureadded = fn; + } + set filehandle(v) { + this._filehandle = v; + this.read(); + } + get filehandle() { + return this._filehandle; + } + read() { + return new Promise(async (resolve, reject) => { + if (this._filehandle === undefined) { + this.renderer.textures.length = 0; + this._filehandle = "Untitled".asFileHandle(); + this._onfilechange(this._filehandle.path); + this.glsl_values = [ShaderEditor.frg_template, ""]; + if (this.current_idx != 2 && this.current_idx != -1) { + this.editormux = true; + this.editor.setValue(this.glsl_values[this.current_idx]); + } + this._ontextureadded(undefined); + return resolve(undefined); + } + try { + const data = await this._filehandle.read("json"); + this.glsl_values[0] = data.source[0]; + this.glsl_values[1] = data.source[1]; + if (this.current_idx != 2 && this.current_idx != -1) { + this.editormux = true; + this.editor.setValue(this.glsl_values[this.current_idx]); + } + this._ontextureadded(undefined); + for (const v of data.textures) { + this._ontextureadded(v); + } + this._onfilechange(this._filehandle.path); + resolve(undefined); + } + catch (e) { + reject(e); + } + }); + } + write(p) { + return new Promise(async (resolve, reject) => { + let path = p; + const error = __("Unknown save path"); + if (!path) { + if (this._filehandle === undefined) + return reject(error); + path = this._filehandle.path; + } + if (path === "Untitled") { + return reject(error); + } + try { + this._filehandle.setPath(path); + const data = {}; + if (this.current_idx != 2) { + this.glsl_values[this.current_idx] = this.editor.getValue(); + } + data.source = this.glsl_values; + data.textures = this.renderer.textures.map((v) => { + return { + name: v.name, + path: v.path + }; + }); + this.filehandle.cache = data; + const ret = await this.filehandle.write("object"); + this._filehandle.dirty = false; + this._onfilechange(`${this.filehandle.path}`); + resolve(undefined); + } + catch (e) { + reject(e); + } + }); + } + compile(code, type) { + // Compiles either a shader of type gl.VERTEX_SHADER or gl.FRAGMENT_SHADER + let shader = this.gl_compiling_ctx.createShader(type); + this.gl_compiling_ctx.shaderSource(shader, code); + this.gl_compiling_ctx.compileShader(shader); + let errors = undefined; + if (!this.gl_compiling_ctx.getShaderParameter(shader, this.gl_compiling_ctx.COMPILE_STATUS)) { + errors = this.gl_compiling_ctx.getShaderInfoLog(shader); + } + this.gl_compiling_ctx.deleteShader(shader); + return errors; + } + edit(index) { + if (index < 0) { + return; + } + if (index != 2 && this.current_idx != 2) { + if (index === 0) { + this.glsl_values[1] = this.editor.getValue(); + this.cursors[1] = this.editor.getCursorPosition(); + } + else if (index === 1) { + this.glsl_values[0] = this.editor.getValue(); + this.cursors[0] = this.editor.getCursorPosition(); + } + } + else if (index == 2) { + this.glsl_values[this.current_idx] = this.editor.getValue(); + this.cursors[this.current_idx] = this.editor.getCursorPosition(); + this.current_idx = index; + return; + } + this.current_idx = index; + this.editormux = true; + this.editor.getSession().setUndoManager(new ace.UndoManager()); + this.editor.setValue(this.glsl_values[index]); + this.editor.getSession().setUndoManager(this.ums[index]); + const c = this.cursors[index]; + this.editor.renderer.scrollCursorIntoView({ + row: c.row, + column: c.column, + }, 0.5); + this.editor.selection.moveTo(c.row, c.column); + this.editor.focus(); + } + cleanup() { + this.renderer.cleanup(); + $(this.tmp_canvas).remove(); + } + resize() { + this.editor.resize(); + this.renderer.viewport_resize(); + } + } + ; + class ShaderRenderer { + constructor(canvas) { + this.textures = []; + this.renderer = new THREE.WebGLRenderer({ + canvas: canvas, + alpha: true + }); + this.renderer.autoClearColor = false; + this.clock = new THREE.Clock(); + this.camera = new THREE.OrthographicCamera(-1, // left + 1, // right + 1, // top + -1, // bottom + -1, // near, + 1); + this.needupdateTexture = false; + this.scene = new THREE.Scene(); + const material = new THREE.MeshBasicMaterial({ + color: 'white', + }); + const plane = new THREE.PlaneGeometry(2, 2); + this.mesh = new THREE.Mesh(plane, material); + this.scene.add(this.mesh); + this.uniforms = { + u_resolution: { value: { x: 0, y: 0 } }, + u_time: { value: 0.0 }, + u_mouse: { value: { x: 0, y: 0 } }, + }; + this.viewport_resize(); + this.ani_request_id = requestAnimationFrame(() => this.viewport_render()); + } + viewport_render() { + if (this.needupdateTexture) { + this.update_textures(); + this.needupdateTexture = false; + } + this.uniforms.u_time.value = this.clock.getElapsedTime(); + try { + this.renderer.render(this.scene, this.camera); + } + catch (e) { + console.error(e); + } + this.ani_request_id = requestAnimationFrame(() => this.viewport_render()); + } + viewport_resize() { + const canvas = this.renderer.domElement; + const width = canvas.clientWidth; + const height = canvas.clientHeight; + this.uniforms.u_resolution.value.x = width; + this.uniforms.u_resolution.value.y = height; + const needResize = canvas.width !== width || canvas.height !== height; + if (needResize) { + this.renderer.setSize(width, height, false); + } + } + cleanup() { + console.log("Stop the animation before quitting..."); + window.cancelAnimationFrame(this.ani_request_id); + } + update_textures() { + for (const key in this.uniforms) { + if (["u_resolution", "u_time", "u_mouse"].indexOf(key) === -1) { + this.uniforms[key] = new THREE.MeshBasicMaterial({ + color: 'black', + }); + } + } + for (const v of this.textures) { + this.uniforms[v.name] = { value: v.texture }; + } + console.log(this.uniforms); + } + apply_mat(fragment_shader, vertex_shader) { + const empty_main = "void main(){}"; + const opts = { + fragmentShader: fragment_shader.trim() === "" ? empty_main : fragment_shader, + uniforms: this.uniforms, + vertexShader: undefined + }; + if (vertex_shader.trim() != "") + opts.vertexShader = vertex_shader; + const mat = new THREE.ShaderMaterial(opts); + this.mesh.material = mat; + console.log(this.uniforms); + } + } + ShaderEditor.frg_template = `\ +#ifdef GL_ES +precision mediump float; +#endif +// uniform vec2 u_resolution; +// uniform vec2 u_mouse; +uniform float u_time; + +void main() { + gl_FragColor = vec4(abs(sin(u_time)),0.0,0.0,1.0); +}\ + `; + /** + * + * @class ShaderPlayground + * @extends {BaseApplication} + */ + class ShaderPlayground extends application.BaseApplication { + constructor(args) { + super("ShaderPlayground", args); + } + main() { + this.init_editor(); + this.init_textures_list(); + this.bindKey("ALT-N", () => { + return this.newFile(); + }); + this.bindKey("ALT-O", () => { + return this.openFile(); + }); + this.bindKey("CTRL-S", () => { + return this.saveFile(); + }); + } + /** + * Init the editor for fragment and + * vertex shader + */ + init_editor() { + this.tabbar = this.find("tabbar"); + this.tabbar.items = [ + { + text: __("Fragment"), + iconclass: "bi bi-palette" + }, + { + text: __("Vertex"), + iconclass: "bi bi-intersect" + }, + { + text: __("Textures"), + iconclass: "bi bi-image-alt" + } + ]; + this.tabbar.ontabselect = (_e) => { + this.selectTab(); + }; + this.editor = new ShaderEditor(this.find("editor-container"), new ShaderRenderer(this.find("viewport"))); + this.on("resize", (e) => { + this.editor.resize(); + }); + this.editor.onfilechange = (v) => { + this.scheme.apptitle = v; + }; + this.editor.ontextureadded = (v) => { + this.add_texture(v); + }; + this.editor.filehandle = undefined; + this.tabbar.selected = 0; + } + add_texture(data) { + { + const listview = this.find("texture-list"); + if (!data) { + this.editor.renderer.textures = []; + listview.data = this.editor.renderer.textures; + this.editor.renderer.needupdateTexture = true; + return; + } + const loader = new THREE.TextureLoader(); + const texture = loader.load(data.path.asFileHandle().getlink()); + texture.minFilter = THREE.NearestFilter; + texture.magFilter = THREE.NearestFilter; + texture.wrapS = THREE.RepeatWrapping; + texture.wrapT = THREE.RepeatWrapping; + data.texture = texture; + listview.push(data); + this.editor.renderer.needupdateTexture = true; + } + } + init_textures_list() { + const listview = this.find("texture-list"); + listview.buttons = [ + { + text: "__(Add texture)", + iconclass: "bi bi-plus", + onbtclick: (_e) => { + this + .openDialog(new AddTextureDialog()) + .then((data) => this.add_texture(data)); + } + } + ]; + listview.itemtag = "afx-shader-texture-item"; + listview.onitemclose = (e) => { + this.editor.renderer.needupdateTexture = true; + return true; + }; + this.add_texture(undefined); + } + selectTab() { + const index = this.tabbar.selected; + if (index === 2) { + $(this.find("editor-container")).hide(); + $(this.find("texture-list")).show(); + } + else { + $(this.find("editor-container")).show(); + $(this.find("texture-list")).hide(); + } + this.editor.edit(index); + } + menu() { + return [ + { + text: "__(File)", + nodes: [ + { + text: "__(New)", + dataid: "new", + shortcut: 'A-N' + }, + { + text: "__(Open)", + dataid: "open", + shortcut: 'A-O' + }, + { + text: "__(Save)", + dataid: "save", + shortcut: 'C-S' + } + ], + onchildselect: (e) => { + switch (e.data.item.data.dataid) { + case "new": + return this.newFile(); + case "open": + return this.openFile(); + case "save": + return this.saveFile(); + } + } + } + ]; + } + ignore_unsaved() { + return new Promise(async (resolve, reject) => { + if (this.editor.filehandle.dirty === true) { + const r = await this.ask({ + title: __("Unsaved shader"), + text: __("Ignore unsaved file?") + }); + if (!r) { + return resolve(false); + } + return resolve(true); + } + return resolve(true); + }); + } + async newFile() { + const ignore = await this.ignore_unsaved(); + if (!ignore) + return; + this.editor.filehandle = undefined; + } + async openFile() { + try { + const ignore = await this.ignore_unsaved(); + if (!ignore) + return; + const d = await this.openDialog("FileDialog", { + title: __("Open file"), + mimes: this.meta().mimes + }); + this.editor.filehandle.setPath(d.file.path); + await this.editor.read(); + } + catch (e) { + this.error(__(e.toString()), e); + } + } + async saveFile() { + if (this.editor.filehandle.path !== "Untitled") { + return this.editor.write(undefined); + } + const f = await this.openDialog("FileDialog", { + title: __("Save as"), + file: this.editor.filehandle + }); + let handle = f.file.path.asFileHandle(); + if (f.file.type === "file") { + handle = handle.parent(); + } + try { + await this.editor.write(`${handle.path}/${f.name}`); + } + catch (e) { + this.error(__(e.toString()), e); + } + } + cleanup(e) { + if (this.editor.filehandle.dirty) { + this.ignore_unsaved() + .then((d) => { + if (d) { + this.editor.filehandle.dirty = false; + this.quit(true); + } + }); + e.preventDefault(); + return; + } + this.editor.cleanup(); + } + } + application.ShaderPlayground = ShaderPlayground; + /** + * Application dependenicies preload + */ + ShaderPlayground.dependencies = [ + "pkg://libthreejs/main.js", + "pkg://ACECore/core/ace.js", + "pkg://ACECore/path.js", + "pkg://ACECore/core/ext-language_tools.js" + ]; + })(application = OS.application || (OS.application = {})); +})(OS || (OS = {})); diff --git a/ShaderPlayground/build/release/ShaderPlayground.zip b/ShaderPlayground/build/release/ShaderPlayground.zip deleted file mode 100644 index 214df133718536f73c40136a24be741b09d442f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5754 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 diff --git a/ShaderPlayground/main.ts b/ShaderPlayground/main.ts index 053a4ac..71afec2 100644 --- a/ShaderPlayground/main.ts +++ b/ShaderPlayground/main.ts @@ -753,8 +753,7 @@ void main() { "pkg://libthreejs/main.js", "pkg://ACECore/core/ace.js", "pkg://ACECore/path.js", - "pkg://ACECore/core/ext-language_tools.js", - "pkg://ShaderPlayground/glslx.js" + "pkg://ACECore/core/ext-language_tools.js" ]; } } \ No newline at end of file