summaryrefslogtreecommitdiff
path: root/fractiform.js
diff options
context:
space:
mode:
Diffstat (limited to 'fractiform.js')
-rw-r--r--fractiform.js67
1 files changed, 34 insertions, 33 deletions
diff --git a/fractiform.js b/fractiform.js
index 59a3e40..70ff412 100644
--- a/fractiform.js
+++ b/fractiform.js
@@ -2,14 +2,8 @@
/*
TODO:
-- detect duplicate widget names
-- forbid .,;|/\:(){}[]+-<>'"`~?!#%^&* in widget names
- widgets:
- rotate 3D
-- parse input expressions
-- show which widget generated an error
- - don't make the error a whole big pop-up
- - switch 'change' event listener to 'input' for auto-update
*/
let gl;
@@ -622,7 +616,7 @@ function rgba_hex_to_float(hex) {
return null;
}
- let color = {
+ const color = {
r: r,
g: g,
b: b,
@@ -792,6 +786,7 @@ function add_widget(func) {
delete_button.classList.add('widget-delete');
delete_button.addEventListener('click', () => {
root.remove();
+ update_shader();
});
root.appendChild(delete_button);
}
@@ -806,6 +801,7 @@ function add_widget(func) {
let name_input = document.createElement('div');
name_input.contentEditable = true;
name_input.classList.add('widget-name');
+ name_input.addEventListener('input', () => update_shader());
// generate unique name
let names = get_widget_names();
@@ -1155,6 +1151,15 @@ function parse_widgets() {
if (!name) {
return {error: 'widget has no name. please give it one.', widget: id};
}
+ for (const c of name) {
+ if ('.,;|/\\:(){}[]+-<>\'"`~?!#%^&*'.indexOf(c) !== -1) {
+ return {error: `widget name cannot contain the character ${c}`, widget: id};
+ }
+ }
+ if (widgets.has(name)) {
+ return {error: `duplicate widget name: ${name}`, widget: id};
+ }
+
const inputs = new Map();
const controls = new Map();
for (const input of widget_div.getElementsByClassName('in')) {
@@ -1176,9 +1181,6 @@ function parse_widgets() {
}
controls.set(id, value);
}
- if (widgets.has(name)) {
- return {error: `duplicate widget name: ${name}`, widget: id};
- }
widgets.set(name, {
func,
id,
@@ -1197,9 +1199,7 @@ function export_widgets() {
}
console.assert(widgets instanceof Map);
let data = [];
- for (let kv of widgets) {
- let name = kv[0];
- let widget = kv[1];
+ for (const [name, widget] of widgets) {
data.push(widget.func);
data.push(';');
data.push('n:');
@@ -1306,22 +1306,22 @@ function import_widgets(string) {
}
}
widgets_container.innerHTML = '';
- for (let widget of widgets) {
- let name = widget.name;
+ for (const widget of widgets) {
+ const name = widget.name;
if (!widget_info.has(widget.func)) {
return {error: `bad import string (widget type '${widget.func}' does not exist)`};
}
- let element = add_widget(widget.func);
+ const element = add_widget(widget.func);
element.getElementsByClassName('widget-name')[0].innerText = name;
for (const [input, value] of widget.inputs) {
- let container = Array.from(element.getElementsByClassName('in')).find(
+ const container = Array.from(element.getElementsByClassName('in')).find(
(e) => e.dataset.id === input
);
assign_value(container, value);
}
for (const [control, value] of widget.controls) {
- let container = Array.from(element.getElementsByClassName('control')).find(
+ const container = Array.from(element.getElementsByClassName('control')).find(
(e) => e.dataset.id === control
);
assign_value(container, value);
@@ -1350,13 +1350,13 @@ function get_shader_source() {
show_error('no output chosen');
return null;
}
- let widgets = parse_widgets();
+ const widgets = parse_widgets();
if (widgets.error) {
show_error(widgets);
return null;
}
- let state = new GLSLGenerationState(widgets);
- let output = state.compute_input(get_widget_name(display_output));
+ const state = new GLSLGenerationState(widgets);
+ const output = state.compute_input(get_widget_name(display_output));
if (output.error) {
show_error(output);
return null;
@@ -1387,11 +1387,11 @@ function get_shader_source() {
}
function update_widget_choices() {
- let search_term = widget_search.value.toLowerCase();
- let choices = widget_choices.getElementsByClassName('widget-choice');
+ const search_term = widget_search.value.toLowerCase();
+ const choices = widget_choices.getElementsByClassName('widget-choice');
for (const choice of choices) {
- let name = widget_info.get(choice.dataset.id).name;
- let shown = name.toLowerCase().indexOf(search_term) !== -1;
+ const name = widget_info.get(choice.dataset.id).name;
+ const shown = name.toLowerCase().indexOf(search_term) !== -1;
choice.style.display = shown ? 'block' : 'none';
}
for (const category of widget_choices.getElementsByClassName('widget-category')) {
@@ -1552,10 +1552,10 @@ void main() {
function frame(time) {
current_time = time * 1e-3;
- let container_width = canvas_container.offsetWidth;
- let container_height = canvas_container.offsetHeight;
- let aspect_ratio = width / height;
+ const container_width = canvas_container.offsetWidth;
+ const container_height = canvas_container.offsetHeight;
+ const aspect_ratio = width / height;
let canvas_x = 0, canvas_y = 0;
if (container_width / aspect_ratio < container_height) {
// landscape mode
@@ -1589,7 +1589,7 @@ function frame(time) {
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, sampler_texture);
gl.uniform1i(gl.getUniformLocation(program_post, 'u_texture'), 0);
- let v_pos = gl.getAttribLocation(program_post, 'v_pos');
+ const v_pos = gl.getAttribLocation(program_post, 'v_pos');
gl.enableVertexAttribArray(v_pos);
gl.vertexAttribPointer(v_pos, 2, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
@@ -1620,7 +1620,7 @@ function perform_step() {
gl.uniform2f(gl.getUniformLocation(program_main, 'ff_texture_size'), width, height);
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer_main);
- let v_pos = gl.getAttribLocation(program_main, 'v_pos');
+ const v_pos = gl.getAttribLocation(program_main, 'v_pos');
gl.enableVertexAttribArray(v_pos);
gl.vertexAttribPointer(v_pos, 2, gl.FLOAT, false, 8, 0);
gl.drawArrays(gl.TRIANGLES, 0, 6);
@@ -1631,7 +1631,7 @@ function perform_step() {
function compile_program(name, shaders) {
let program = gl.createProgram();
- for (let type in shaders) {
+ for (const type in shaders) {
let source = shaders[type];
let gl_type;
if (type === 'vertex') {
@@ -1640,6 +1640,7 @@ function compile_program(name, shaders) {
gl_type = gl.FRAGMENT_SHADER;
} else {
show_error('unrecognized shader type: ' + type);
+ return null;
}
let shader = compile_shader(name + ' ' + type, gl_type, source);
if (shader === null)
@@ -1657,7 +1658,7 @@ function compile_program(name, shaders) {
function set_up_framebuffer() {
framebuffer = gl.createFramebuffer();
- let sampler_pixels = new Uint8Array(width * height * 4);
+ const sampler_pixels = new Uint8Array(width * height * 4);
sampler_pixels.fill(0);
set_up_rgba_texture(sampler_texture, width, height, sampler_pixels);
set_up_rgba_texture(framebuffer_color_texture, width, height, null);
@@ -1681,7 +1682,7 @@ function set_up_rgba_texture(texture, width, height, pixels) {
}
function compile_shader(name, type, source) {
- let shader = gl.createShader(type);
+ const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);