feat: arrow keys to control bpm/cycle
This commit is contained in:
+1
-1
@@ -119,7 +119,7 @@ make -f Makefile.dev release-arch
|
|||||||
- [x] Find and fix opengl errors 0500 ?
|
- [x] Find and fix opengl errors 0500 ?
|
||||||
- [ ] Extra features
|
- [ ] Extra features
|
||||||
- [x] `--auto-random-cycle=4`
|
- [x] `--auto-random-cycle=4`
|
||||||
- [ ] Arrows (up-down: bpm / left-right: cycle)
|
- [x] Arrows (up-down: bpm / left-right: cycle)
|
||||||
- [ ] Save states (numkey: load / shift + numkey: save)
|
- [ ] Save states (numkey: load / shift + numkey: save)
|
||||||
- [ ] Configurable key codes
|
- [ ] Configurable key codes
|
||||||
- [ ] Key codes as inputs
|
- [ ] Key codes as inputs
|
||||||
|
|||||||
@@ -157,11 +157,15 @@ make install
|
|||||||
|
|
||||||
When running, the following hotkeys are available:
|
When running, the following hotkeys are available:
|
||||||
|
|
||||||
* <kbd>Esc</kbd>: Exit window
|
| Hotkey | Function |
|
||||||
* <kbd>R</kbd>: Randomize internal values
|
| ------ | -------- |
|
||||||
* <kbd>0</kbd>: Reset internal values to 0
|
| <kbd>Esc</kbd> | Exit FORGE |
|
||||||
* <kbd>D</kbd>: Demo mode On/Off
|
| <kbd>R</kbd> | Randomize internal values |
|
||||||
* <kbd>A</kbd>: Auto Random mode On/Off
|
| <kbd>Shift</kbd> + <kbd>R</kbd> | Reset internal values to 0 |
|
||||||
|
| <kbd>D</kbd> | Demo mode On/Off |
|
||||||
|
| <kbd>A</kbd> | Auto Random mode On/Off |
|
||||||
|
| <kbd>←</kbd> / <kbd>→</kbd> | Auto Random Cycle -/+ 1 |
|
||||||
|
| <kbd>↑</kbd> / <kbd>↓</kbd> | BPM +/- 1 |
|
||||||
|
|
||||||
### CLI arguments
|
### CLI arguments
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ UNIFORM_IN_FPS_PREFIX=iInputFPS
|
|||||||
UNIFORM_DEMO=iDemo
|
UNIFORM_DEMO=iDemo
|
||||||
# 0/1 if auto random
|
# 0/1 if auto random
|
||||||
UNIFORM_AUTORAND=iAutoRand
|
UNIFORM_AUTORAND=iAutoRand
|
||||||
|
# auto random cycle length
|
||||||
|
UNIFORM_AUTORANDCYCLE=iAutoRandCycle
|
||||||
# Current page
|
# Current page
|
||||||
UNIFORM_PAGE=iPage
|
UNIFORM_PAGE=iPage
|
||||||
# Current selected shader
|
# Current selected shader
|
||||||
|
|||||||
@@ -372,6 +372,20 @@ float write_int(vec2 uv, vec2 pos, uint value, uint magnitude)
|
|||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float write_int_left(vec2 uv, vec2 pos, uint value, uint magnitude)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint m = 1;
|
||||||
|
float d = 0;
|
||||||
|
for (i = 0; i < magnitude; i++) {
|
||||||
|
if (i == 0 || value >= m) {
|
||||||
|
pos.x += 1;
|
||||||
|
m *= 10u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return write_int(uv, pos, value, magnitude);
|
||||||
|
}
|
||||||
|
|
||||||
int read(sampler2D tex, vec2 uv, float k, int d, float t)
|
int read(sampler2D tex, vec2 uv, float k, int d, float t)
|
||||||
{
|
{
|
||||||
float inv_k = 1 / k;
|
float inv_k = 1 / k;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ uniform int iInputFormat2;
|
|||||||
|
|
||||||
uniform int iDemo;
|
uniform int iDemo;
|
||||||
uniform int iAutoRand;
|
uniform int iAutoRand;
|
||||||
|
uniform int iAutoRandCycle;
|
||||||
uniform int iPage;
|
uniform int iPage;
|
||||||
uniform int iSelected;
|
uniform int iSelected;
|
||||||
|
|
||||||
@@ -225,22 +226,22 @@ vec4 debug(vec2 vUV)
|
|||||||
float x = 0;
|
float x = 0;
|
||||||
|
|
||||||
x = -15;
|
x = -15;
|
||||||
f += write_5(uv3, vec2(x,13), texts[0]);
|
f += write_5(uv3, vec2(x - 4,13), texts[0]);
|
||||||
f += write_int(uv3, vec2(x - 3.5,13), iFPS, 3);
|
f += write_int(uv3, vec2(x + 1, 13), iFPS, 3);
|
||||||
v = min(1, iFPS/60.0);
|
v = min(1, iFPS/60.0);
|
||||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||||
|
|
||||||
x = 0;
|
x = 0;
|
||||||
f += write_5(uv3, vec2(x,13), texts[1]);
|
f += write_5(uv3, vec2(x - 4,13), texts[1]);
|
||||||
f += write_int(uv3, vec2(x - 3.5,13), int(iTempo), 3);
|
f += write_int(uv3, vec2(x + 1,13), int(iTempo), 3);
|
||||||
v = fract(iBeats);
|
v = fract(iBeats);
|
||||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||||
|
|
||||||
x = 15;
|
x = 15;
|
||||||
f += write_5(uv3, vec2(x,13), texts[2]);
|
f += write_5(uv3, vec2(x - 4,13), texts[2]);
|
||||||
f += write_int(uv3, vec2(x - 5.5,13), int(iTime), 5);
|
f += write_int(uv3, vec2(x - 1,13), int(iTime), 5);
|
||||||
v = fract(iTime);
|
v = fract(iTime);
|
||||||
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
f += h_rect(uv3, vec2(x, 12), vec2(4, 0.5), 0.2);
|
||||||
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
f += rect(uv3, vec2(x + 4 * v - 4, 12), vec2(4 * v, 0.4));
|
||||||
@@ -248,6 +249,7 @@ vec4 debug(vec2 vUV)
|
|||||||
if (iAutoRand > 0) {
|
if (iAutoRand > 0) {
|
||||||
f += write_5(uv3, vec2(-4,-15), iDemo > 0 ? texts[3] : texts[4]);
|
f += write_5(uv3, vec2(-4,-15), iDemo > 0 ? texts[3] : texts[4]);
|
||||||
f += write_5(uv3, vec2(0,-15), texts[5]);
|
f += write_5(uv3, vec2(0,-15), texts[5]);
|
||||||
|
f += write_int_left(uv3, vec2(3, -15), iAutoRandCycle, 3);
|
||||||
} else {
|
} else {
|
||||||
f += write_5(uv3, vec2(-2,-15), iDemo > 0 ? texts[3] : texts[4]);
|
f += write_5(uv3, vec2(-2,-15), iDemo > 0 ? texts[3] : texts[4]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ UNIFORM_BEATS=iBeats
|
|||||||
UNIFORM_FPS=iFPS
|
UNIFORM_FPS=iFPS
|
||||||
# 0/1 if demo
|
# 0/1 if demo
|
||||||
UNIFORM_DEMO=iDemo
|
UNIFORM_DEMO=iDemo
|
||||||
# 0/1 if auto random
|
|
||||||
UNIFORM_AUTORAND=iAutoRand
|
|
||||||
# Seed for shader X
|
# Seed for shader X
|
||||||
UNIFORM_SEED_PREFIX=iSeed
|
UNIFORM_SEED_PREFIX=iSeed
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ uniform float iTempo; // current tempo in bpm
|
|||||||
uniform float iBeats; // elapsed beats since last tempo reset
|
uniform float iBeats; // elapsed beats since last tempo reset
|
||||||
uniform int iFPS; // output window frames per seconds
|
uniform int iFPS; // output window frames per seconds
|
||||||
uniform int iDemo; // 0/1 if demo mode
|
uniform int iDemo; // 0/1 if demo mode
|
||||||
uniform int iAutoRand; // 0/1 if auto random mode
|
|
||||||
uniform int iSeed1; // a random seed assigned at start
|
uniform int iSeed1; // a random seed assigned at start
|
||||||
uniform vec2 iResolution; // output window resolution in pixels
|
uniform vec2 iResolution; // output window resolution in pixels
|
||||||
uniform vec3 iMidi1_1[20]; // all midi inputs defined
|
uniform vec3 iMidi1_1[20]; // all midi inputs defined
|
||||||
|
|||||||
+3
-3
@@ -127,7 +127,7 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
|||||||
params->base_tempo = 60.0f;
|
params->base_tempo = 60.0f;
|
||||||
params->demo = false;
|
params->demo = false;
|
||||||
params->auto_random = false;
|
params->auto_random = false;
|
||||||
params->auto_random_cycles = 4;
|
params->auto_random_cycle = 4;
|
||||||
params->video_in.length = 0;
|
params->video_in.length = 0;
|
||||||
params->video_size = 0;
|
params->video_size = 0;
|
||||||
params->internal_size = 720;
|
params->internal_size = 720;
|
||||||
@@ -173,8 +173,8 @@ void args_parse(Parameters *params, int argc, char **argv) {
|
|||||||
} else if (is_arg(arg, "-nar") || is_arg(arg, "--no-auto-random")) {
|
} else if (is_arg(arg, "-nar") || is_arg(arg, "--no-auto-random")) {
|
||||||
params->auto_random = false;
|
params->auto_random = false;
|
||||||
} else if (is_arg(arg, "-arc") || is_arg(arg, "--auto-random-cycle")) {
|
} else if (is_arg(arg, "-arc") || is_arg(arg, "--auto-random-cycle")) {
|
||||||
params->auto_random_cycles = parse_uint(arg, value);
|
params->auto_random_cycle = parse_uint(arg, value);
|
||||||
if (params->auto_random_cycles == 0) {
|
if (params->auto_random_cycle == 0) {
|
||||||
invalid_value(arg, value);
|
invalid_value(arg, value);
|
||||||
}
|
}
|
||||||
} else if (is_arg(arg, "-v") || is_arg(arg, "--video-in")) {
|
} else if (is_arg(arg, "-v") || is_arg(arg, "--video-in")) {
|
||||||
|
|||||||
+1
-1
@@ -59,7 +59,7 @@ static void compute_fps(bool trace_fps) {
|
|||||||
|
|
||||||
static void init_context(const Parameters *params, unsigned int in_count) {
|
static void init_context(const Parameters *params, unsigned int in_count) {
|
||||||
state_init(context, &project.state_config, params->demo, params->auto_random,
|
state_init(context, &project.state_config, params->demo, params->auto_random,
|
||||||
params->auto_random_cycles, params->base_tempo, params->state_file,
|
params->auto_random_cycle, params->base_tempo, params->state_file,
|
||||||
params->load_state);
|
params->load_state);
|
||||||
|
|
||||||
context->monitor = params->monitor;
|
context->monitor = params->monitor;
|
||||||
|
|||||||
@@ -280,6 +280,9 @@ static void init_single_program(ShaderProgram *program, unsigned int i,
|
|||||||
program->iautorand_locations[i] = glGetUniformLocation(
|
program->iautorand_locations[i] = glGetUniformLocation(
|
||||||
program->programs[i],
|
program->programs[i],
|
||||||
config_file_get_str(config, "UNIFORM_AUTORAND", "iAutoRand"));
|
config_file_get_str(config, "UNIFORM_AUTORAND", "iAutoRand"));
|
||||||
|
program->iautorandcycle_locations[i] = glGetUniformLocation(
|
||||||
|
program->programs[i],
|
||||||
|
config_file_get_str(config, "UNIFORM_AUTORANDCYCLE", "iAutoRandCycle"));
|
||||||
program->ipage_locations[i] = glGetUniformLocation(
|
program->ipage_locations[i] = glGetUniformLocation(
|
||||||
program->programs[i],
|
program->programs[i],
|
||||||
config_file_get_str(config, "UNIFORM_PAGE", "iPage"));
|
config_file_get_str(config, "UNIFORM_PAGE", "iPage"));
|
||||||
@@ -545,6 +548,8 @@ static void use_program(const ShaderProgram *program, int i, bool output,
|
|||||||
write_uniform_1i(program->idemo_locations[i], context->demo ? 1 : 0);
|
write_uniform_1i(program->idemo_locations[i], context->demo ? 1 : 0);
|
||||||
write_uniform_1i(program->iautorand_locations[i],
|
write_uniform_1i(program->iautorand_locations[i],
|
||||||
context->auto_random ? 1 : 0);
|
context->auto_random ? 1 : 0);
|
||||||
|
write_uniform_1i(program->iautorandcycle_locations[i],
|
||||||
|
context->auto_random_cycle);
|
||||||
write_uniform_1i(program->ipage_locations[i], context->page);
|
write_uniform_1i(program->ipage_locations[i], context->page);
|
||||||
write_uniform_1i(program->iselected_locations[i], context->selected + 1);
|
write_uniform_1i(program->iselected_locations[i], context->selected + 1);
|
||||||
write_uniform_2f(program->ires_locations[i], &context->resolution);
|
write_uniform_2f(program->ires_locations[i], &context->resolution);
|
||||||
|
|||||||
+22
-2
@@ -301,6 +301,26 @@ void state_key_event(SharedContext *context, const StateConfig *state_config,
|
|||||||
log_info(
|
log_info(
|
||||||
(context->auto_random ? "[A] Auto Random OFF" : "[A] Auto Random ON"));
|
(context->auto_random ? "[A] Auto Random OFF" : "[A] Auto Random ON"));
|
||||||
context->auto_random = !context->auto_random;
|
context->auto_random = !context->auto_random;
|
||||||
|
} else if (code == 263) {
|
||||||
|
// LEFT ARROW
|
||||||
|
if (context->auto_random_cycle > 1) {
|
||||||
|
context->auto_random_cycle -= 1;
|
||||||
|
}
|
||||||
|
log_info("[LEFT] Auto Random Cycle: %d", context->auto_random_cycle);
|
||||||
|
} else if (code == 262) {
|
||||||
|
// RIGHT ARROW
|
||||||
|
context->auto_random_cycle += 1;
|
||||||
|
log_info("[RIGHT] Auto Random Cycle: %d", context->auto_random_cycle);
|
||||||
|
} else if (code == 265) {
|
||||||
|
// UP ARROW
|
||||||
|
tempo_set(&context->tempo, context->tempo.tempo + 1);
|
||||||
|
log_info("[UP] Tempo: %f", context->tempo);
|
||||||
|
} else if (code == 264) {
|
||||||
|
// DOWN ARROW
|
||||||
|
if (context->tempo.tempo > 0) {
|
||||||
|
tempo_set(&context->tempo, context->tempo.tempo - 1);
|
||||||
|
}
|
||||||
|
log_info("[DOWN] Tempo: %f", context->tempo);
|
||||||
} else {
|
} else {
|
||||||
log_info("[%d] No hotkey defined", code);
|
log_info("[%d] No hotkey defined", code);
|
||||||
}
|
}
|
||||||
@@ -353,7 +373,7 @@ bool state_background_write(SharedContext *context,
|
|||||||
last_active = beat_active;
|
last_active = beat_active;
|
||||||
|
|
||||||
change = tempo_progress(&context->tempo,
|
change = tempo_progress(&context->tempo,
|
||||||
(double)context->auto_random_cycles) < 0.5;
|
(double)context->auto_random_cycle) < 0.5;
|
||||||
|
|
||||||
if (context->auto_random && change && !last_change) {
|
if (context->auto_random && change && !last_change) {
|
||||||
state_randomize(context, state_config);
|
state_randomize(context, state_config);
|
||||||
@@ -416,7 +436,7 @@ void state_init(SharedContext *context, const StateConfig *state_config,
|
|||||||
tempo_set(&context->tempo, base_tempo);
|
tempo_set(&context->tempo, base_tempo);
|
||||||
context->demo = demo;
|
context->demo = demo;
|
||||||
context->auto_random = auto_random;
|
context->auto_random = auto_random;
|
||||||
context->auto_random_cycles = auto_random_cycles;
|
context->auto_random_cycle = auto_random_cycles;
|
||||||
|
|
||||||
context->state.length = state_config->select_frag_codes.length;
|
context->state.length = state_config->select_frag_codes.length;
|
||||||
memset(context->state.values, 0, sizeof(context->state.values));
|
memset(context->state.values, 0, sizeof(context->state.values));
|
||||||
|
|||||||
@@ -99,8 +99,17 @@ static void add_tap_to_chain(Tempo *tempo, long t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void tempo_set(Tempo *tempo, float value) {
|
void tempo_set(Tempo *tempo, float value) {
|
||||||
|
long t;
|
||||||
|
long progress;
|
||||||
|
|
||||||
|
t = now();
|
||||||
|
|
||||||
|
progress = (t - tempo->last_reset) % tempo->beat_length;
|
||||||
|
|
||||||
tempo->tempo = value;
|
tempo->tempo = value;
|
||||||
tempo->beat_length = 60000.0 / value;
|
tempo->beat_length = 60000.0 / value;
|
||||||
|
|
||||||
|
reset_tap_chain(tempo, t - progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tempo_tap(Tempo *tempo) {
|
void tempo_tap(Tempo *tempo) {
|
||||||
|
|||||||
+3
-2
@@ -43,7 +43,7 @@ typedef struct Parameters {
|
|||||||
float base_tempo;
|
float base_tempo;
|
||||||
bool demo;
|
bool demo;
|
||||||
bool auto_random;
|
bool auto_random;
|
||||||
unsigned int auto_random_cycles;
|
unsigned int auto_random_cycle;
|
||||||
StringArray video_in;
|
StringArray video_in;
|
||||||
unsigned int video_size;
|
unsigned int video_size;
|
||||||
unsigned int internal_size;
|
unsigned int internal_size;
|
||||||
@@ -105,6 +105,7 @@ typedef struct ShaderProgram {
|
|||||||
GLuint iinfps_locations[ARRAY_SIZE];
|
GLuint iinfps_locations[ARRAY_SIZE];
|
||||||
GLuint idemo_locations[ARRAY_SIZE];
|
GLuint idemo_locations[ARRAY_SIZE];
|
||||||
GLuint iautorand_locations[ARRAY_SIZE];
|
GLuint iautorand_locations[ARRAY_SIZE];
|
||||||
|
GLuint iautorandcycle_locations[ARRAY_SIZE];
|
||||||
GLuint iseed_locations[ARRAY_SIZE];
|
GLuint iseed_locations[ARRAY_SIZE];
|
||||||
GLuint istate_locations[ARRAY_SIZE];
|
GLuint istate_locations[ARRAY_SIZE];
|
||||||
GLuint ipage_locations[ARRAY_SIZE];
|
GLuint ipage_locations[ARRAY_SIZE];
|
||||||
@@ -183,7 +184,7 @@ typedef struct SharedContext {
|
|||||||
vec3 values[ARRAY_SIZE];
|
vec3 values[ARRAY_SIZE];
|
||||||
bool demo;
|
bool demo;
|
||||||
bool auto_random;
|
bool auto_random;
|
||||||
unsigned int auto_random_cycles;
|
unsigned int auto_random_cycle;
|
||||||
unsigned int seeds[MAX_FRAG];
|
unsigned int seeds[MAX_FRAG];
|
||||||
bool monitor;
|
bool monitor;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user