]> git.sesse.net Git - nageru/commitdiff
Make it possible for auto white balance to be controlled by another input.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 12 Feb 2020 16:59:12 +0000 (17:59 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 12 Feb 2020 16:59:12 +0000 (17:59 +0100)
This is useful if you want to run white balance on something that could
e.g. have an overlay.

nageru/scene.cpp
nageru/scene.h

index a9268360b97bd34cab472701be2757cef4a1d777..f4320b45f9e6d02de38c3ffa608c7ae2a109de5e 100644 (file)
@@ -178,8 +178,8 @@ bool Scene::is_noncanonical_chain(size_t chain_idx) const
                        }
 
                        // Auto white balance is always disabled for image inputs.
-                       if (block->root_input_block != nullptr) {
-                               const Block *input = block->root_input_block;
+                       if (block->white_balance_controller_block != nullptr) {
+                               const Block *input = block->white_balance_controller_block;
                                if (input->alternatives[input->chosen_alternative(chain_idx)]->effect_type == IMAGE_INPUT) {
                                        return true;
                                }
@@ -235,6 +235,24 @@ int Scene::add_input(lua_State* L)
        return wrap_lua_existing_object_nonowned<Block>(L, "Block", block);
 }
 
+Block *Scene::find_block_from_arg(lua_State *L, Scene *scene, int idx)
+{
+       if (luaL_testudata(L, idx, "Block")) {
+               return *(Block **)luaL_checkudata(L, idx, "Block");
+       } else {
+               EffectBlueprint *blueprint = *(EffectBlueprint **)luaL_checkudata(L, idx, "EffectBlueprint");
+
+               // Search through all the blocks to figure out which one contains this effect.
+               for (Block *block : scene->blocks) {
+                       if (find(block->alternatives.begin(), block->alternatives.end(), blueprint) != block->alternatives.end()) {
+                               return block;
+                       }
+               }
+               luaL_error(L, "Input effect in parameter #%d has not been added to this scene", idx - 1);
+               return nullptr;  // Dead code.
+       }
+}
+
 void Scene::find_inputs_for_block(lua_State *L, Scene *scene, Block *block, int first_input_idx)
 {
        if (lua_gettop(L) == first_input_idx - 1) {
@@ -245,24 +263,7 @@ void Scene::find_inputs_for_block(lua_State *L, Scene *scene, Block *block, int
        }
 
        for (int idx = first_input_idx; idx <= lua_gettop(L); ++idx) {
-               Block *input_block = nullptr;
-               if (luaL_testudata(L, idx, "Block")) {
-                       input_block = *(Block **)luaL_checkudata(L, idx, "Block");
-               } else {
-                       EffectBlueprint *blueprint = *(EffectBlueprint **)luaL_checkudata(L, idx, "EffectBlueprint");
-
-                       // Search through all the blocks to figure out which one contains this effect.
-                       for (Block *block : scene->blocks) {
-                               if (find(block->alternatives.begin(), block->alternatives.end(), blueprint) != block->alternatives.end()) {
-                                       input_block = block;
-                                       break;
-                               }
-                       }
-                       if (input_block == nullptr) {
-                               luaL_error(L, "Input effect in parameter #%d has not been added to this scene", idx - 1);
-                       }
-               }
-               block->inputs.push_back(input_block->idx);
+               block->inputs.push_back(find_block_from_arg(L, scene, idx)->idx);
        }
 }
 
@@ -360,14 +361,24 @@ int Scene::add_auto_white_balance(lua_State* L)
 
        block->canonical_alternative = 1;
 
-       find_inputs_for_block(L, scene, block, /*first_input_idx=*/2);
-
-       if (block->inputs.size() != 1) {
-               luaL_error(L, "add_auto_white_balance() needs exactly one input");
+       if (lua_gettop(L) == 1) {
+               // The last added effect is implicitly both the input and gives the white balance controller.
+               assert(!scene->blocks.empty());
+               block->inputs.push_back(scene->blocks.size() - 1);
+               block->white_balance_controller_block = scene->find_root_input_block(L, block);
+       } else if (lua_gettop(L) == 2) {
+               // The given effect is both the input and the white balance controller.
+               block->inputs.push_back(find_block_from_arg(L, scene, 2)->idx);
+               block->white_balance_controller_block = scene->find_root_input_block(L, block);
+       } else if (lua_gettop(L) == 3) {
+               // We have explicit input and white balance controller.
+               block->inputs.push_back(find_block_from_arg(L, scene, 2)->idx);
+               block->white_balance_controller_block = find_block_from_arg(L, scene, 3);
+       } else {
+               luaL_error(L, "add_auto_white_balance([input], [white_balance_controller]) takes zero, one or two arguments");
        }
-       block->root_input_block = scene->find_root_input_block(L, block);
-       if (block->root_input_block == nullptr) {
-               luaL_error(L, "add_auto_white_balance() was not connected to an input");
+       if (block->white_balance_controller_block == nullptr || !block->white_balance_controller_block->is_input) {
+               luaL_error(L, "add_auto_white_balance() does not get its white balance from an input");
        }
 
        scene->blocks.push_back(block);
@@ -525,7 +536,7 @@ Scene::get_chain(Theme *theme, lua_State *L, unsigned num, const InputState &inp
        map<Block *, array<float, 3>> white_balance;
        for (size_t block_idx = 0; block_idx < blocks.size(); ++block_idx) {
                Block *block = blocks[block_idx];
-               const Block *input = block->root_input_block;
+               const Block *input = block->white_balance_controller_block;
                if (input == nullptr) {
                        continue;  // Not an auto white balance block.
                }
index 8cff06a8d3e53946af18ad4e41aedfe56e5236b0..4e1181bbf4cf9f504625d5eae9708db79a057ba1 100644 (file)
@@ -134,7 +134,7 @@ struct Block {
 
        // Only for AUTO_WHITE_BALANCE_EFFECT. Points to the parent block with is_input = true,
        // so that we know which signal to get the white balance from.
-       const Block *root_input_block = nullptr;
+       const Block *white_balance_controller_block = nullptr;
 };
 
 int Block_display(lua_State* L);
@@ -167,6 +167,7 @@ private:
        movit::Effect *instantiate_effects(const Block *block, size_t chain_idx, Instantiation *instantiation);
        size_t compute_chain_number_for_block(size_t block_idx, const std::bitset<256> &disabled) const;
        static void find_inputs_for_block(lua_State *L, Scene *scene, Block *block, int first_input_idx = 3);
+       static Block *find_block_from_arg(lua_State *L, Scene *scene, int idx);
 
        // Find out which blocks (indexed by position in the “blocks” array),
        // if any, are disabled in a given instantiation. A disabled block is