summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-11-03 14:48:51 -0400
committerpommicket <pommicket@gmail.com>2022-11-03 14:48:51 -0400
commit809ce7cdc95cd602223333b53761735238b5b48a (patch)
tree59f2ddd7cfcad5deae31761284518829297c470f
parent609cdb6f0cc9f6f5d86366fbf60364f463cba551 (diff)
custom bg-shader
-rw-r--r--command.c3
-rw-r--r--config.c63
-rw-r--r--main.c49
-rw-r--r--ted.c16
-rw-r--r--ted.cfg16
-rw-r--r--ted.h6
6 files changed, 138 insertions, 15 deletions
diff --git a/command.c b/command.c
index 51c5c24..ce447ed 100644
--- a/command.c
+++ b/command.c
@@ -203,6 +203,7 @@ void command_execute(Ted *ted, Command c, i64 argument) {
ted_new_file(ted, NULL);
break;
case CMD_SAVE:
+ ted->last_save_time = time_get_seconds();
if (buffer) {
if (buffer_is_untitled(buffer)) {
command_execute(ted, CMD_SAVE_AS, 1);
@@ -212,11 +213,13 @@ void command_execute(Ted *ted, Command c, i64 argument) {
}
break;
case CMD_SAVE_AS:
+ ted->last_save_time = time_get_seconds();
if (buffer && !buffer->is_line_buffer) {
menu_open(ted, MENU_SAVE_AS);
}
break;
case CMD_SAVE_ALL:
+ ted->last_save_time = time_get_seconds();
ted_save_all(ted);
break;
case CMD_RELOAD_ALL:
diff --git a/config.c b/config.c
index 17dbf73..612a647 100644
--- a/config.c
+++ b/config.c
@@ -43,6 +43,12 @@ static bool context_is_parent(const SettingsContext *parent, const SettingsConte
static void settings_copy(Settings *dest, const Settings *src) {
*dest = *src;
+
+ // we only use this function before generating these
+ assert(!src->bg_shader);
+ assert(!src->bg_buffer);
+ assert(!src->bg_array);
+
context_copy(&dest->context, &src->context);
for (u32 i = 0; i < LANG_COUNT; ++i) {
if (src->language_extensions[i])
@@ -59,7 +65,13 @@ static void settings_free(Settings *settings) {
context_free(&settings->context);
for (u32 i = 0; i < LANG_COUNT; ++i)
free(settings->language_extensions[i]);
- memset(settings, 0, sizeof *settings);
+ if (settings->bg_shader)
+ glDeleteProgram(settings->bg_shader);
+ if (settings->bg_buffer)
+ glDeleteBuffers(1, &settings->bg_buffer);
+ if (settings->bg_array)
+ glDeleteVertexArrays(1, &settings->bg_array);
+ memset(settings, 0, sizeof *settings);
}
static void config_part_free(ConfigPart *part) {
@@ -272,6 +284,7 @@ static OptionFloat const options_float[] = {
};
static OptionString const options_string[] = {
{"build-default-command", options_zero.build_default_command, sizeof options_zero.build_default_command, true},
+ {"bg-shader", options_zero.bg_shader_text, sizeof options_zero.bg_shader_text, true},
};
static void option_bool_set(Settings *settings, const OptionBool *opt, bool value) {
@@ -861,6 +874,54 @@ void config_parse(Ted *ted, ConfigPart **pparts) {
}
}
+ arr_foreach_ptr(ted->all_settings, Settings, s) {
+ if (*s->bg_shader_text) {
+ // load bg shader
+ char vshader[] = "#version 110\n\
+ attribute vec2 v_pos;\n\
+ varying vec2 t_pos;\n\
+ void main() { \n\
+ gl_Position = vec4(v_pos * 2.0 - 1.0, 0.0, 1.0);\n\
+ t_pos = v_pos;\n\
+ }";
+ char fshader[8192];
+ strbuf_printf(fshader, "#version 110\n\
+ varying vec2 t_pos;\n\
+ uniform float t_time;\n\
+ uniform float t_save_time;\n\
+ uniform vec2 t_aspect;\n\
+ #line 1\n\
+ %s", settings->bg_shader_text);
+ s->bg_shader = gl_compile_and_link_shaders(ted->error, vshader, fshader);
+ if (s->bg_shader) {
+ GLuint bg_buffer = 0, bg_array = 0;
+ glGenBuffers(1, &bg_buffer);
+ if (gl_version_major >= 3) {
+ glGenVertexArrays(1, &bg_array);
+ glBindVertexArray(bg_array);
+ }
+
+ s->bg_buffer = bg_buffer;
+ s->bg_array = bg_array;
+
+ float bg_buffer_data[][2] = {
+ {0,0},
+ {1,0},
+ {1,1},
+ {0,0},
+ {1,1},
+ {0,1}
+ };
+
+ GLuint v_pos = (GLuint)glGetAttribLocation(s->bg_shader, "v_pos");
+ glBindBuffer(GL_ARRAY_BUFFER, bg_buffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof bg_buffer_data, bg_buffer_data, GL_STATIC_DRAW);
+ glVertexAttribPointer(v_pos, 2, GL_FLOAT, 0, 2 * sizeof(float), 0);
+ glEnableVertexAttribArray(v_pos);
+ }
+ }
+ }
+
arr_foreach_ptr(parts, ConfigPart, part) {
config_part_free(part);
}
diff --git a/main.c b/main.c
index 0bd2c85..b61cf9f 100644
--- a/main.c
+++ b/main.c
@@ -1,9 +1,7 @@
/*
FUTURE FEATURES:
-- custom shaders
- - texture, time, time since last save
+- custom shaders texture
- config variables
-- config multi-line strings
- plugins?
*/
@@ -326,6 +324,7 @@ int main(int argc, char **argv) {
if (!ted) {
die("Not enough memory available to run ted.");
}
+ ted->last_save_time = -1e50;
// make sure signal handler has access to ted.
error_signal_handler_ted = ted;
@@ -411,13 +410,6 @@ int main(int argc, char **argv) {
char config_err[sizeof ted->error] = {0};
PROFILE_TIME(misc_end)
- PROFILE_TIME(configs_start)
- ted_load_configs(ted, false);
- if (ted_haserr(ted)) {
- strcpy(config_err, ted->error);
- ted_clearerr(ted); // clear the error so later things (e.g. loading font) don't detect an error
- }
- PROFILE_TIME(configs_end)
PROFILE_TIME(window_start)
SDL_Window *window = SDL_CreateWindow("ted", SDL_WINDOWPOS_UNDEFINED,
@@ -456,11 +448,11 @@ int main(int argc, char **argv) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif
glctx = SDL_GL_CreateContext(window);
- if (!glctx) {
+ if (glctx) {
+ break;
+ } else {
debug_println("Couldn't get GL %d.%d context. Falling back to %d.%d.",
gl_versions[i][0], gl_versions[i][1], gl_versions[i+1][0], gl_versions[i+1][1]);
- gl_version_major = 3;
- gl_version_minor = 0;
}
}
@@ -488,6 +480,14 @@ int main(int argc, char **argv) {
PROFILE_TIME(gl_end)
+ PROFILE_TIME(configs_start)
+ ted_load_configs(ted, false);
+ if (ted_haserr(ted)) {
+ strcpy(config_err, ted->error);
+ ted_clearerr(ted); // clear the error so later things (e.g. loading font) don't detect an error
+ }
+ PROFILE_TIME(configs_end)
+
PROFILE_TIME(fonts_start)
ted_load_fonts(ted);
PROFILE_TIME(fonts_end)
@@ -571,6 +571,8 @@ int main(int argc, char **argv) {
while (SDL_PollEvent(&event));
}
+ double start_time = time_get_seconds();
+
while (!ted->quit) {
double frame_start = time_get_seconds();
@@ -786,6 +788,27 @@ int main(int argc, char **argv) {
}
glClear(GL_COLOR_BUFFER_BIT);
+ {
+ // background shader
+ Settings *s = ted_active_settings(ted);
+ if (s->bg_shader) {
+ glUseProgram(s->bg_shader);
+ if (s->bg_array)
+ glBindVertexArray(s->bg_array);
+ double t = time_get_seconds();
+ glUniform1f(glGetUniformLocation(s->bg_shader, "t_time"), (float)fmod(t - start_time, 3600));
+ glUniform2f(glGetUniformLocation(s->bg_shader, "t_aspect"), (float)window_width / (float)window_height, 1);
+ glUniform1f(glGetUniformLocation(s->bg_shader, "t_save_time"), (float)(t - ted->last_save_time));
+ glBindBuffer(GL_ARRAY_BUFFER, s->bg_buffer);
+ if (!s->bg_array) {
+ GLuint v_pos = (GLuint)glGetAttribLocation(s->bg_shader, "v_pos");
+ glVertexAttribPointer(v_pos, 2, GL_FLOAT, 0, 2 * sizeof(float), 0);
+ glEnableVertexAttribArray(v_pos);
+ }
+ glDrawArrays(GL_TRIANGLES, 0, 6);
+ }
+ }
+
Font *font = ted->font;
// default window title
diff --git a/ted.c b/ted.c
index 2d19a02..5d82198 100644
--- a/ted.c
+++ b/ted.c
@@ -49,7 +49,21 @@ static void *ted_realloc(Ted *ted, void *p, size_t new_size) {
}
Settings *ted_active_settings(Ted *ted) {
- return ted->active_buffer ? buffer_settings(ted->active_buffer) : ted->default_settings;
+ if (ted->active_buffer)
+ return buffer_settings(ted->active_buffer);
+ Settings *settings = ted->default_settings;
+ int settings_score = 0;
+ arr_foreach_ptr(ted->all_settings, Settings, s) {
+ const SettingsContext *c = &s->context;
+ if (c->language != 0) continue;
+ if (!c->path || !str_has_prefix(ted->cwd, c->path)) continue;
+ int score = (int)strlen(c->path);
+ if (score > settings_score) {
+ settings = s;
+ settings_score = score;
+ }
+ }
+ return settings;
}
u32 ted_color(Ted *ted, ColorSetting color) {
diff --git a/ted.cfg b/ted.cfg
index c7a08a7..0c142b1 100644
--- a/ted.cfg
+++ b/ted.cfg
@@ -36,6 +36,22 @@ tags-max-depth = 2
# regenerate tags if an identifier is not found (with Ctrl+click)?
regenerate-tags-if-not-found = yes
+# you can make your own custom background for ted using a shader.
+# an example is provided here. you will have access to the following variables:
+# t_pos - screen position of fragment (0,0) to (1,1)
+# t_aspect - (window_width / window_height, 1)
+# t_time - current time in seconds, modulo 3600
+# t_save_time - time since last save, in seconds.
+# if you want your shader supported no matter what, only use stuff from GLSL version 110.
+# on non-ancient computers, you should be able to use GLSL version 130.
+# bg-shader = "void main() {
+# vec2 p = t_pos * t_aspect;
+# float r = pow(sin(p.x * 100.0 + t_time * 3.0), 60.0);
+# float g = pow(sin(p.y * 100.0 + t_time * 6.0), 60.0);
+# vec4 color = vec4(r, g, 1.0 - t_save_time, 0.2);
+# gl_FragColor = clamp(color, 0.0, 1.0);
+# }"
+
[keyboard]
# motion and selection
Left = :left
diff --git a/ted.h b/ted.h
index 5eebced..0271d64 100644
--- a/ted.h
+++ b/ted.h
@@ -166,6 +166,10 @@ typedef struct {
u8 padding;
u8 scrolloff;
u8 tags_max_depth;
+ u32 bg_shader;
+ u32 bg_buffer;
+ u32 bg_array;
+ char bg_shader_text[4096];
char build_default_command[256];
// [i] = comma-separated string of file extensions for language i, or NULL for none
char *language_extensions[LANG_COUNT];
@@ -407,6 +411,8 @@ typedef struct Ted {
float build_output_height; // what % of the screen the build output takes up
bool resizing_build_output;
+
+ double last_save_time; // last time a save command was executed. used for bg-shaders.
Process build_process;
// When we read the stdout from the build process, the tail end of the read could be an