-
Notifications
You must be signed in to change notification settings - Fork 1
/
emitter.c
120 lines (106 loc) · 3.54 KB
/
emitter.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
#include "emitter.h"
#include "audio.h"
#include "command.h"
#include "helper.h"
#include "particle.h"
#include "pextra.h"
#include "forces.h"
#include "plimits.h"
#include "drawer.h"
#include "random.h"
#include <string.h>
static struct emitter {
struct commands* commands;
plist_t particles;
flist* fl;
drawer_t drawer;
uint32_t frame_counts[VIS_MAX_FTYPE];
} emitter;
void emitter_setup(struct commands* cmds, plist_t plist, drawer_t drawer) {
ZEROINIT(&emitter);
emitter.commands = cmds;
emitter.particles = plist;
emitter.drawer = drawer;
for (ftype_id i = (ftype_id)0; i < VIS_MAX_FTYPE; ++i) {
emitter.frame_counts[i] = 0;
}
}
void emitter_free(UNUSED_PARAM(void* arg)) {
if (emitter.fl) {
flist_clear(emitter.fl);
flist_free(emitter.fl);
}
}
uint32_t emitter_get_frame_count(ftype_id ft) {
return emitter.frame_counts[ft];
}
void emitter_schedule(flist* frames) {
if (emitter.fl == NULL) {
emitter.fl = frames;
} else if (emitter.fl && emitter.fl != frames) {
flist_clear(emitter.fl);
flist_free(emitter.fl);
} else if (emitter.fl == frames) {
flist_restart(emitter.fl);
} else {
VIS_ASSERT(!"unreachable");
}
}
static plist_action_id do_mutate_fn(particle* p, void* mutate) {
((mutate_method*)mutate)->func(p, mutate);
return ACTION_NEXT;
}
void emitter_tick(void) {
flist_node* fn = flist_tick(emitter.fl);
while (fn != NULL) {
emitter.frame_counts[fn->type] += 1;
switch (fn->type) {
case VIS_FTYPE_EMIT:
emit_frame(fn->data.frame);
break;
case VIS_FTYPE_EXIT:
command_str(emitter.commands, "exit");
break;
case VIS_FTYPE_PLAY:
audio_play();
break;
case VIS_FTYPE_CMD:
command_str(emitter.commands, fn->data.cmd);
break;
case VIS_FTYPE_BGCOLOR:
drawer_bgcolor(emitter.drawer, fn->data.color[0],
fn->data.color[1], fn->data.color[2]);
break;
case VIS_FTYPE_MUTATE:
plist_foreach(emitter.particles, do_mutate_fn,
fn->data.method);
break;
case VIS_FTYPE_SCRIPTCB:
script_run_cb(fn->data.scriptcb->owner, fn->data.scriptcb,
NULL);
break;
case VIS_FTYPE_FRAMESEEK:
flist_goto_frame(emitter.fl, fn->data.frameseek);
break;
case VIS_MAX_FTYPE:
break;
}
/* do not process next node if this is a frame seek */
fn = fn->type != VIS_FTYPE_FRAMESEEK ? flist_node_next(fn) : NULL;
}
}
void emit_frame(emit_desc* frame) {
for (int i = 0; i < frame->n; ++i) {
particle* p = NULL;
float r = randfloat(frame->r - frame->ur, frame->r + frame->ur);
float g = randfloat(frame->g - frame->ug, frame->g + frame->ug);
float b = randfloat(frame->b - frame->ub, frame->b + frame->ub);
pextra* pe = new_pextra(r, g, b, frame->blender);
p = particle_new_full(frame->x, frame->y, frame->ux, frame->uy,
frame->rad, frame->urad, frame->ds, frame->uds,
frame->theta, frame->utheta,
frame->life, frame->ulife,
frame->force, frame->limit, pe);
plist_add(emitter.particles, p);
}
}