]> git.sesse.net Git - nageru/blob - nageru/scene.h
Rename chain -> scene as appropriate.
[nageru] / nageru / scene.h
1 #ifndef _SCENE_H
2 #define _SCENE_H 1
3
4 // A Scene is an equivalent of an EffectChain, but each part is not a single
5 // Effect. (The name itself does not carry any specific meaning above that
6 // of what an EffectChain is; it was just chosen as a more intuitive name than
7 // an EffectChain when we had to change anyway.) Instead, it is a “block”,
8 // which can hold one or more effect alternatives, e.g., one block could hold
9 // ResizeEffect or IdentityEffect (effectively doing nothing), or many
10 // different input types. On finalization, every different combination of
11 // block alternatives are tried, and one EffectChain is generated for each.
12 // This also goes for whether the scene is destined for preview outputs
13 // (directly to screen, RGBA) or live (Y'CbCr output).
14
15 #include <stddef.h>
16 #include <functional>
17 #include <map>
18 #include <memory>
19 #include <string>
20 #include <vector>
21
22 class CEFCapture;
23 struct EffectBlueprint;
24 class FFmpegCapture;
25 class ImageInput;
26 struct InputState;
27 class LiveInputWrapper;
28 class Theme;
29 struct lua_State;
30
31 namespace movit {
32 class Effect;
33 class EffectChain;
34 class ResourcePool;
35 }  // namespace movit
36
37 struct Block {
38         // Index into the parent Scene's list of blocks.
39         using Index = size_t;
40         Index idx = 0;
41
42         // Each instantiation is indexed by the chosen alternative for each block.
43         // These are combined into one big variable-base number, ranging from 0
44         // to (B_0*B_1*B_2*...*B_n)-1, where B_i is the number of alternatives for
45         // block number i and n is the index of the last block.
46         //
47         // The actual index, given alternatives A_0, A_1, A_2, ..., is given as
48         //
49         //   A_0 + B_0 * (A_1 + B_1 * (A_2 + B_2 * (...)))
50         //
51         // where each A_i can of course range from 0 to B_i-1. In other words,
52         // the first block gets the lowest “bits” (or trits, or quats...) of the
53         // index number, the second block gets the ones immediately above,
54         // and so on. Thus, there are no holes in the sequence.
55         //
56         // Expanding the formula above gives the equivalent index
57         //
58         //   A_0 + A_1 * B_0 + A_2 * B_0 * B_1 + A_3 * ...
59         //
60         // or
61         //
62         //   A_0 * C_0 + A_1 * C_1 + A_2 * C_2 + A_3 * ...
63         //
64         // where C_0 = 0 and C_(i+1) = C_i * B_i. In other words, C_i is
65         // the product of the cardinalities of each previous effect; if we
66         // are e.g. at the third index and there have been C_2 = 3 * 5 = 15
67         // different alternatives for constructing the scene so far
68         // (with possible indexes 0..14), it is only logical that if we
69         // want three new options (B_2 = 3), we must add 0, 15 or 30 to
70         // the index. (Then the local possible indexes become 0..44 and
71         // C_3 = 45, of course.) Given an index number k, we can then get our
72         // own local “bits” of the index, giving the alternative for this
73         // block, by doing (k / 15) % 3.
74         //
75         // This specific member contains the value of C_i for this block.
76         // (B_i is alternatives.size().) Not set before finalize() has run.
77         size_t cardinality_base = 0;
78
79         std::vector<EffectBlueprint *> alternatives;  // Must all have the same amount of inputs. Pointers to make things easier for Lua.
80         std::vector<Index> inputs;  // One for each input of alternatives[0] (ie., typically 0 or 1, occasionally 2).
81         int currently_chosen_alternative = 0;
82         bool is_input = false;
83
84         // For LIVE_INPUT* only. We can't just always populate signal_to_connect,
85         // since when we set this, CEF and video signals may not have numbers yet.
86         // FIXME: Perhaps it would be simpler if they just did?
87         enum { CONNECT_NONE, CONNECT_SIGNAL, CONNECT_CEF, CONNECT_VIDEO } signal_type_to_connect = CONNECT_NONE;
88         int signal_to_connect = 0;  // For CONNECT_SIGNAL.
89 #ifdef HAVE_CEF
90         CEFCapture *cef_to_connect = nullptr;  // For CONNECT_CEF.
91 #endif
92         FFmpegCapture *video_to_connect = nullptr;  // For CONNECT_VIDEO.
93
94         std::string pathname;  // For IMAGE_INPUT only.
95
96         // Parameters to set on the effect prior to render.
97         // Will be set _before_ the ones from the EffectBlueprint, so that
98         // the latter takes priority.
99         std::map<std::string, int> int_parameters;
100         std::map<std::string, float> float_parameters;
101         std::map<std::string, std::array<float, 3>> vec3_parameters;
102         std::map<std::string, std::array<float, 4>> vec4_parameters;
103 };
104
105 int Block_display(lua_State* L);
106 int Block_choose(lua_State* L);
107 int Block_enable(lua_State *L);
108 int Block_disable(lua_State *L);
109 int Block_set_int(lua_State *L);
110 int Block_set_float(lua_State *L);
111 int Block_set_vec3(lua_State *L);
112 int Block_set_vec4(lua_State *L);
113
114 class Scene {
115 private:
116         std::vector<Block *> blocks;  // The last one represents the output node (after finalization). Pointers to make things easier for Lua.
117         struct Instantiation {
118                 std::unique_ptr<movit::EffectChain> chain;
119                 std::map<Block::Index, movit::Effect *> effects;  // So that we can set parameters.
120                 std::map<Block::Index, LiveInputWrapper *> inputs;  // So that we can connect signals.
121                 std::map<Block::Index, ImageInput *> image_inputs;  // So that we can connect signals.
122         };
123         std::vector<Instantiation> chains;  // Indexed by combination of each block's chosen alternative. See Block for information.
124
125         Theme *theme;
126         float aspect_nom, aspect_denom;
127         movit::ResourcePool *resource_pool;
128
129         movit::Effect *instantiate_effects(const Block *block, size_t chain_idx, Instantiation *instantiation);
130         size_t compute_chain_number_for_block(size_t block_idx) const;
131
132 public:
133         Scene(Theme *theme, float aspect_nom, float aspect_denom);
134         size_t compute_chain_number(bool is_main_chain) const;
135
136         std::pair<movit::EffectChain *, std::function<void()>>
137         get_chain(Theme *theme, lua_State *L, unsigned num, const InputState &input_state);
138
139         static int add_input(lua_State *L);
140         static int add_effect(lua_State *L);
141         static int add_optional_effect(lua_State *L);
142         static int finalize(lua_State *L);
143 };
144
145 #endif   // !defined(_SCENE_H)