forked from smcameron/space-nerds-in-space
/
snis_sliders.c
308 lines (276 loc) · 7.49 KB
/
snis_sliders.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "snis_font.h"
#include "snis_typeface.h"
#include "snis_graph.h"
#include "wwviaudio.h"
#include "mtwist.h"
#include "mathutils.h"
#define SLIDERS_DEFINE_GLOBALS
#include "snis_sliders.h"
#undef SLIDERS_DEFINE_GLOBALS
struct slider {
float x, y, length, height;
int color;
double value, input;
char label[20], label1[5], label2[5];
double r1, r2;
slider_monitor_function sample;
slider_clicked_function clicked;
int vertical;
int font;
int colors_reversed;
unsigned char timer;
unsigned char fuzz;
};
static int slider_sound = -1;
struct slider *snis_slider_init(float x, float y, float length, float height, int color,
char *label, char *l1, char *l2, double r1, double r2,
slider_monitor_function gmf, slider_clicked_function clicked)
{
struct slider *s;
s = malloc(sizeof(*s));
s->x = x;
s->y = y;
s->length = length;
s->height = height;
s->color = color;
strncpy(s->label, label, sizeof(s->label) - 1);
s->label[sizeof(s->label) - 1] = '\0';
strncpy(s->label1, l1, sizeof(s->label1) - 1);
s->label1[sizeof(s->label1) - 1] = '\0';
strncpy(s->label2, l2, sizeof(s->label2) - 1);
s->label2[sizeof(s->label2) - 1] = '\0';
s->r1 = r1;
s->r2 = r2;
s->sample = gmf;
s->clicked = clicked;
s->value = (s->sample() - s->r1) / (s->r2 - s->r1);
s->input = 0.0;
s->vertical = 0;
s->colors_reversed = 0;
s->timer = 0;
s->font = TINY_FONT;
s->fuzz = 0;
return s;
}
void snis_slider_set_vertical(struct slider *s, int v)
{
s->vertical = v;
}
static int choose_barcolor(struct slider *s, double v)
{
if (s->clicked)
return DARKGREEN;
if (!s->colors_reversed) {
if (v <= 15.0)
return ((s->timer & 0x04) == 0) ? BLACK : RED;
if (v <= 40.0)
return RED;
if (v <= 75.0)
return AMBER;
return DARKGREEN;
}
if (v < 75.0)
return DARKGREEN;
if (v < 90.0)
return AMBER;
return ((s->timer & 0x04) == 0) ? BLACK : RED;
}
static void snis_slider_draw_vertical(struct slider *s)
{
double v;
int height, ty1;
int bar_color;
int ptr_height = s->height / 2;
int ptr_width = s->height / 3;
float f;
if (s->fuzz) {
f = (float) ((snis_randn(1000) - 500.0f) * s->fuzz) / 100000.0f;
f = f * s->length;
} else {
f = 0.0f;
}
s->timer++;
v = s->sample();
s->value = (v - s->r1) / (s->r2 - s->r1);
if (s->value == 0)
f = 0.0f; /* no fuzz if no power */
v = s->sample();
ty1 = (int) (s->y + s->length - s->input * s->length);
bar_color = choose_barcolor(s, v);
sng_set_foreground(s->color);
sng_current_draw_rectangle(0, s->x, s->y, s->height, s->length);
height = s->value * s->length - 1;
height += f;
if (height < 0)
height = 0;
if (height > s->length - 1)
height = s->length - 1;
if (!s->clicked)
sng_set_foreground(bar_color);
sng_current_draw_rectangle(1, s->x + 1, s->y + s->length - height,
s->height - 2, height);
if (!s->clicked)
sng_set_foreground(s->color);
if (s->clicked) {
sng_current_draw_line(s->x, ty1, s->x - ptr_height, ty1 - ptr_width);
sng_current_draw_line(s->x - ptr_height, ty1 - ptr_width, s->x - ptr_height, ty1 + ptr_width);
sng_current_draw_line(s->x - ptr_height, ty1 + ptr_width, s->x, ty1);
sng_current_draw_line(s->x + s->height, ty1, s->x + ptr_height + s->height, ty1 - ptr_width);
sng_current_draw_line(s->x + ptr_height + s->height, ty1 - ptr_width,
s->x + ptr_height + s->height, ty1 + ptr_width);
sng_current_draw_line(s->x + ptr_height + s->height, ty1 + ptr_width,
s->x + s->height, ty1);
}
/* sng_abs_xy_draw_string(s->label, s->font, s->x + s->length + 5, s->y + 2 * s->height / 3); */
}
void snis_slider_draw(struct slider *s)
{
double v;
float width, tx1;
int bar_color = DARKGREEN;
float ptr_height = s->height / 2.0;
float ptr_width = s->height / 3.0;
s->timer++;
if (s->vertical) {
snis_slider_draw_vertical(s);
return;
}
float f;
if (s->fuzz) {
f = (float) ((snis_randn(1000) - 500.0f) * s->fuzz) / 100000.0f;
f = f * s->length;
} else {
f = 0.0f;
}
v = s->sample();
s->value = (v - s->r1) / (s->r2 - s->r1);
if (s->value == 0)
f = 0.0f; /* no fuzz if no power */
v = s->sample();
bar_color = choose_barcolor(s, v);
sng_set_foreground(s->color);
sng_current_draw_rectangle(0, s->x, s->y, s->length, s->height);
width = s->value * (s->length - 2.0);
width = width + f;
if (width < 0.0)
width = 0;
if (width > s->length - 2.0)
width = s->length - 2.0;
if (!s->clicked)
sng_set_foreground(bar_color);
sng_current_draw_rectangle(1, s->x + 1.0, s->y + 1.0, width, s->height - 2.0);
if (!s->clicked)
sng_set_foreground(s->color);
tx1 = (s->input * s->length) + s->x;
if (s->clicked) {
sng_current_draw_line(tx1, s->y, tx1 - ptr_width, s->y - ptr_height);
sng_current_draw_line(tx1, s->y, tx1 + ptr_width, s->y - ptr_height);
sng_current_draw_line(tx1 - ptr_width, s->y - ptr_height,
tx1 + ptr_width, s->y - ptr_height);
sng_current_draw_line(tx1, s->y + s->height,
tx1 - ptr_width, s->y + s->height + ptr_height);
sng_current_draw_line(tx1, s->y + s->height,
tx1 + ptr_width, s->y + s->height + ptr_height);
sng_current_draw_line(tx1 - ptr_width, s->y + s->height + ptr_height,
tx1 + ptr_width, s->y + s->height + ptr_height);
}
sng_abs_xy_draw_string(s->label, s->font,
s->x + s->length + 5.0, s->y + 2.0 * s->height / 3.0);
}
double snis_slider_get_value(struct slider *s)
{
return s->value;
}
double snis_slider_get_input(struct slider *s)
{
return s->input;
}
static int snis_slider_button_press_vertical(struct slider *s, int x, int y)
{
if (x < s->x || x > s->x + s->height ||
y < s->y - 5 || y > s->y + s->length + 5)
return 0;
if (y >= s->y + s->length)
s->input = 0.0;
else if (y <= s->y)
s->input = 1.0;
else
s->input = ((double) (s->y + s->length) - (double) y) / (double) s->length;
if (s->clicked) {
s->clicked(s);
if (slider_sound != -1)
wwviaudio_add_sound(slider_sound);
}
return 1;
}
int snis_slider_button_press(struct slider *s, int x, int y)
{
if (s->vertical)
return snis_slider_button_press_vertical(s, x, y);
if (x < s->x - 5 || x > s->x + s->length + 5 ||
y < s->y || y > s->y + s->height)
return 0;
if (x >= s->x + s->length)
s->input = 1.0;
else if (x <= s->x)
s->input = 0.0;
else
s->input = ((double) x - (double) s->x) / (double) s->length;
if (s->clicked) {
s->clicked(s);
if (slider_sound != -1)
wwviaudio_add_sound(slider_sound);
}
return 1;
}
void snis_slider_set_sound(int sound)
{
slider_sound = sound;
}
void snis_slider_set_input(struct slider *s, double input)
{
s->input = input;
}
void snis_slider_poke_input(struct slider *s, double input, int with_sound)
{
s->input = input;
if (s->clicked) {
s->clicked(s);
if (slider_sound != -1 && with_sound)
wwviaudio_add_sound(slider_sound);
}
}
void snis_slider_set_color_scheme(struct slider *s, int reversed)
{
s->colors_reversed = reversed;
}
void snis_slider_set_label_font(struct slider *s, int font)
{
s->font = font;
}
void snis_slider_set_fuzz(struct slider *s, int fuzz)
{
s->fuzz = fuzz & 0x0ff;
}
static int snis_slider_mouse_inside_vertical(struct slider *s, int x, int y)
{
return !(x < s->x || x > s->x + s->height ||
y < s->y - 5 || y > s->y + s->length + 5);
}
int snis_slider_mouse_inside(struct slider *s, int x, int y)
{
if (s->vertical)
return snis_slider_mouse_inside_vertical(s, x, y);
return !(x < s->x - 5 || x > s->x + s->length + 5 ||
y < s->y || y > s->y + s->height);
}
void snis_slider_get_location(struct slider *s, float *x, float *y, float *length, float *height)
{
*x = s->x;
*y = s->y;
*length = s->length;
*height = s->height;
}