summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-09-03 00:58:20 -0400
committerpommicket <pommicket@gmail.com>2023-09-03 00:58:49 -0400
commit5bf510368ef795d793b04ae9e30569e4d13ad690 (patch)
tree0c53cc15212ce6d696cd8176b8354fb297fd749d
parent57db51a7c8837d970b5785e1e6ed5e81dbae6f12 (diff)
start separate creations
-rw-r--r--index.html7
-rw-r--r--package.json10
-rw-r--r--pugl.js107
-rw-r--r--style.css7
4 files changed, 109 insertions, 22 deletions
diff --git a/index.html b/index.html
index 950d0e7..5f2eb85 100644
--- a/index.html
+++ b/index.html
@@ -22,9 +22,10 @@
<div id="ui">
<div id="title">
<img src="icon.png" alt="" id="title-icon"> pugl
- <button id="about-button" class="img-button" title="about pugl">
- <img alt="about" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+CjxlbGxpcHNlIGN4PSIxNiIgY3k9IjE2IiByeD0iMTIiIHJ5PSIxMiIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMiIGZpbGw9Im5vbmUiIC8+Cjx0ZXh0IGZpbGw9IiNmZmYiIHg9IjE2IiB5PSIyNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjIwcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPj88L3RleHQ+Cjwvc3ZnPgo=">
- </button>
+ <input placeholder="Title" id="creation-title">
+ <button id="about-button" class="img-button" title="about pugl">
+ <img alt="about" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+CjxlbGxpcHNlIGN4PSIxNiIgY3k9IjE2IiByeD0iMTIiIHJ5PSIxMiIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMiIGZpbGw9Im5vbmUiIC8+Cjx0ZXh0IGZpbGw9IiNmZmYiIHg9IjE2IiB5PSIyNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjIwcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPj88L3RleHQ+Cjwvc3ZnPgo=">
+ </button>
</div>
<form action="#" method="dialog" id="code-form" class="ui-section inline-block">
<input type="text" placeholder="Code" id="code">
diff --git a/package.json b/package.json
index f56ed70..ab1069f 100644
--- a/package.json
+++ b/package.json
@@ -1,17 +1,15 @@
{
- "name": "fractiform",
+ "name": "pugl",
"version": "1.0.0",
- "description": "fractals",
- "main": "fractiform.js",
+ "description": "shaders on the world wide web",
+ "main": "pugl.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "pommicket",
"license": "WTFPL",
"devDependencies": {
- "eslint": "^8.45.0"
- },
- "dependencies": {
+ "eslint": "^8.45.0",
"prettier": "^3.0.0"
}
}
diff --git a/pugl.js b/pugl.js
index a45b995..e9cf513 100644
--- a/pugl.js
+++ b/pugl.js
@@ -7,6 +7,26 @@ TODO:
const APP_ID = 'dh3YgVZQdX1Q';
+function generate_creation_id() {
+ const parts = new Uint16Array(6);
+ crypto.getRandomValues(parts);
+ return Array.from(parts)
+ .map((x) => {
+ x = x.toString(16);
+ while (x.length < 4) x = '0' + x;
+ return x;
+ })
+ .join('-');
+}
+
+function parse_json(s) {
+ try {
+ return JSON.parse(s);
+ } catch (e) {
+ return undefined;
+ }
+}
+
let gl;
let program_main = null;
let program_post = null;
@@ -34,6 +54,10 @@ let paused = false;
let pause_element;
let step_element;
let play_element;
+let creation_metadata = {};
+let creation_id;
+let creation_title_element;
+let auto_update_element;
const mouse_pos_ndc = Object.preventExtensions({ x: 0, y: 0 });
@@ -973,8 +997,12 @@ ${type} _max(${type} a, ${type} b) {
).join('\n'),
];
+function get_creation_title() {
+ return creation_title_element.value || 'Untitled';
+}
+
function auto_update_enabled() {
- return document.getElementById('auto-update').checked;
+ return auto_update_element.checked;
}
function set_paused(p) {
@@ -2166,7 +2194,7 @@ function export_widgets() {
return;
}
console.assert(widgets instanceof Map);
- const data = [];
+ const data = ['_title=', get_creation_title(), ';;'];
for (const [name, widget] of widgets) {
data.push(widget.func);
data.push(';');
@@ -2200,13 +2228,17 @@ function export_widgets() {
function import_widgets(string) {
let widgets = [];
let output = null;
+ let title = null;
if (string) {
- console.log(string);
for (const widget_str of string.split(';;')) {
if (widget_str.startsWith('_out=')) {
output = widget_str.substring('_out='.length);
continue;
}
+ if (widget_str.startsWith('_title=')) {
+ title = widget_str.substring('_title='.length);
+ continue;
+ }
const parts = widget_str.split(';');
const func = parts[0];
@@ -2256,6 +2288,8 @@ function import_widgets(string) {
output = 'output';
}
+ creation_title_element.value = title || 'Untitled';
+
function assign_value(container, value) {
const element = container.getElementsByClassName('entry')[0];
if (!element) {
@@ -2316,19 +2350,35 @@ function import_widgets(string) {
}
set_display_output_and_update_shader(get_widget_by_name(output));
-}
-
-function import_widgets_from_local_storage() {
- const result = import_widgets(localStorage.getItem(`${APP_ID}-widgets`));
- if (result && result.error) {
- show_error(result);
- }
+ return true;
}
function export_widgets_to_local_storage() {
const widget_str = export_widgets();
code_input.value = widget_str;
- localStorage.setItem(`${APP_ID}-widgets`, widget_str);
+ localStorage.setItem(`${APP_ID}-${creation_id}-description`, widget_str);
+ creation_metadata[creation_id] = {
+ lastViewed: Date.now(),
+ };
+ localStorage.setItem(`${APP_ID}-metadata`, JSON.stringify(creation_metadata));
+}
+
+function load_creation(id) {
+ creation_id = id;
+ const metadata = creation_metadata[id];
+ if (!metadata) {
+ return { error: `bad id: ${id}` };
+ }
+ const result = import_widgets(
+ localStorage.getItem(`${APP_ID}-${id}-description`),
+ );
+ if (result.error) return result;
+ return true;
+}
+
+function new_creation() {
+ creation_id = generate_creation_id();
+ return import_widgets(null);
}
function get_shader_source() {
@@ -2373,7 +2423,6 @@ function get_shader_source() {
}
const code = state.get_code();
- console.log(code);
export_widgets_to_local_storage();
return code;
}
@@ -2417,6 +2466,9 @@ function startup() {
widgets_container = document.getElementById('widgets-container');
code_input = document.getElementById('code');
error_element = document.getElementById('error');
+ creation_title_element = document.getElementById('creation-title');
+ auto_update_element = document.getElementById('auto-update');
+
const resolution_x_element = document.getElementById('resolution-x');
const resolution_y_element = document.getElementById('resolution-y');
@@ -2484,6 +2536,10 @@ function startup() {
restart();
});
+ creation_title_element.addEventListener('change', () => {
+ if (!has_error()) export_widgets_to_local_storage();
+ });
+
gl = canvas.getContext('webgl2');
if (gl === null) {
// support for very-old-but-not-ancient browsers
@@ -2598,7 +2654,28 @@ void main() {
widget_search.addEventListener('input', () => {
update_widget_choices();
});
- import_widgets_from_local_storage();
+
+ creation_metadata = parse_json(localStorage.getItem(`${APP_ID}-metadata`));
+ let result;
+ if (creation_metadata) {
+ // load creation with largest lastViewed time
+ let load = undefined;
+ for (const id in creation_metadata) {
+ if (
+ !load ||
+ creation_metadata[id].lastViewed > creation_metadata[load].lastViewed
+ ) {
+ load = id;
+ }
+ }
+ result = load_creation(load);
+ } else {
+ creation_metadata = {};
+ result = new_creation();
+ }
+ if (result.error) {
+ show_error(result);
+ }
frame(0.0);
@@ -2824,6 +2901,10 @@ function compile_shader(name, type, source) {
return shader;
}
+function has_error() {
+ return error_element.style.display !== 'none';
+}
+
function clear_error() {
error_element.style.display = 'none';
for (const widget of document.querySelectorAll('.widget.error')) {
diff --git a/style.css b/style.css
index 7a44e57..e2981cb 100644
--- a/style.css
+++ b/style.css
@@ -6,15 +6,18 @@ body {
font-family: sans-serif;
padding: 0;
}
+
body,
dialog {
background-color: black;
color: var(--color-text);
}
+
a,
a:visited {
color: #8fc;
}
+
h1,
h2,
h3,
@@ -37,6 +40,10 @@ h6 {
overflow: hidden;
}
+#creation-title {
+ width: 5em;
+}
+
#error {
color: red;
border-top: 2px solid red;