diff --git a/ShaderPlayground/build/debug/main.js b/ShaderPlayground/build/debug/main.js
index 420eb97..8a044b5 100644
--- a/ShaderPlayground/build/debug/main.js
+++ b/ShaderPlayground/build/debug/main.js
@@ -1,626 +1 @@
-
-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 = {}));
+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';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"]}(i=e.application||(e.application={}))}(OS||(OS={}));
\ No newline at end of file