diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 47900781..fb548bb5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,6 +21,12 @@ jobs: inklecate_url: https://github.com/inkle/ink/releases/download/v1.1.1/inklecate_mac.zip proof: false unreal: false + - os: macos-14 + artifact: macos-arm + name: MacOSX-ARM + inklecate_url: https://github.com/inkle/ink/releases/download/v1.1.1/inklecate_mac.zip + proof: false + unreal: false - os: windows-latest artifact: win64 name: Windows x64 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c283433a..f54ab92c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,12 +26,12 @@ jobs: run: | mkdir artifacts ID=$(gh run list -b master --limit 1 --json databaseId | jq '.[0].databaseId') - gh run download $ID -D artifacts -n linux-cl -n linux-lib -n linux-clib -n unreal -n macos-cl -n macos-lib -n macos-clib -n win64-cl -n win64-lib -n win64-clib -n python-package-distribution + gh run download $ID -D artifacts -n linux-cl -n linux-lib -n linux-clib -n unreal -n macos-cl -n macos-lib -n macos-clib -n macos-arm-cl -n macos-arm-lib -n macos-arm-clib -n win64-cl -n win64-lib -n win64-clib -n python-package-distribution mv artifacts/python-package-distribution dist - name: Zip working-directory: ${{github.workspace}}/artifacts run: | - for f in linux-cl linux-lib linux-clib unreal macos-cl macos-lib macos-clib win64-cl win64-lib win64-clib; do zip -r ../$f.zip $f; done + for f in linux-cl linux-lib linux-clib unreal macos-cl macos-lib macos-clib macos-arm-cl macos-arm-lib macos-arm-clib win64-cl win64-lib win64-clib; do zip -r ../$f.zip $f; done - name: List run: tree - name: Publish to PyPI @@ -45,5 +45,5 @@ jobs: --repo="$GITHUB_REPOSITORY" \ --title="${GITHUB_REPOSITORY#*/} ${tag#v}" \ --generate-notes \ - "$tag" "linux-cl.zip" "linux-lib.zip" "linux-clib.zip" "unreal.zip" "macos-cl.zip" "macos-lib.zip" "macos-clib.zip" "win64-cl.zip" "win64-lib.zip" "win64-clib.zip" + "$tag" "linux-cl.zip" "linux-lib.zip" "linux-clib.zip" "unreal.zip" "macos-cl.zip" "macos-lib.zip" "macos-clib.zip" "win64-cl.zip" "macos-arm-cl.zip" "macos-arm-lib.zip" "macos-arm-clib.zip "win64-lib.zip" "win64-clib.zip" diff --git a/.gitignore b/.gitignore index d7443423..8921e3a5 100644 --- a/.gitignore +++ b/.gitignore @@ -11,9 +11,8 @@ inkcpp_cl/*.ink *.code-workspace # Doxygen -Documentation/* -!Documentation/cmake_example/ -!Documentation/cmake_example.zip +Documentation/html/ +Documentation/inkcpp_py.html # Output Build/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 4df05d0d..015e8ed0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,10 +83,11 @@ if (DOXYGEN_FOUND) if (INKCPP_DOC_BlueprintUE) # TODO: make as dependecy file(COPY "${PROJECT_SOURCE_DIR}/unreal/blueprint_filter.js" DESTINATION ${PROJECT_BINARY_DIR}) - file(DOWNLOAD - "https://blueprintue.com/bue-render/render.css" - "${PROJECT_BINARY_DIR}/render.css" - EXPECTED_HASH SHA256=875364e36f8aa5d6c1d41d58043f13b48a499b5c969e8daef35bd29bbf7c6e8d) + # file(DOWNLOAD + # "https://raw.githubusercontent.com/blueprintue/blueprintue-self-hosted-edition/main/www/bue-render/render.css" + # "${PROJECT_BINARY_DIR}/render.css" + # EXPECTED_HASH SHA256=875364e36f8aa5d6c1d41d58043f13b48a499b5c969e8daef35bd29bbf7c6e8d) + file(COPY "${PROJECT_SOURCE_DIR}/unreal/render.css" DESTINATION ${PROJECT_BINARY_DIR}) file(APPEND "${PROJECT_BINARY_DIR}/render.css" ".bue-render .icon { background-color: unset; }") file(READ "${PROJECT_SOURCE_DIR}/Doxyfile" DOXYFILE) string(REPLACE "FILTER_PATTERNS =" "FILTER_PATTERNS = \"*/unreal/*=node ${PROJECT_BINARY_DIR}/blueprint_filter.js\"" DOXYFILE2 ${DOXYFILE}) diff --git a/README.md b/README.md index 677c9c86..86f00fa2 100644 --- a/README.md +++ b/README.md @@ -30,18 +30,21 @@ KeyFeatures: snapshots, observers, binding ink functions, support ink [function ## Unreal Plugin -The current version of the UE plugin can be downloaded from the [release page](https://github.com/JBenda/inkcpp/releases/latest) with te corresponding name of the OS (e.g. win64-unreal). +InkCPP is available via the [UE Marketplace](https://www.unrealengine.com/marketplace/product/inkcpp). + +Alternativly is the latest version of the UE plugin can be downloaded from the [release page](https://github.com/JBenda/inkcpp/releases/latest) (`unreal.zip`). Place the content of this file at your plugin folder of your UE project and at the next start up it will be intigrated. -A example project can be found [here](https://cloud.julian-benda.de/index.php/s/cRMBGBWbHPCcdwb). + +A example project can be found [here](https://jbenda.github.io/inkcpp/unreal/InkCPP_DEMO.zip). And here the [Documentation](https://jbenda.github.io/inkcpp/html/group__unreal.html). Code for the Unreal plugin is located in the `unreal` directory. In order to install it, run `cmake --install . --component unreal --prefix Path/To/Unreal/Plugins/` which will add an `inkcpp` folder there with the `.uplugin`, the code for the UClasses, and all the inkcpp source files required. `config.h` will automatically detect it is being built in an Unreal plugin environment and disable STL and enable Unreal extensions (FString support, Unreal asserts, CityHash, etc.). -If you compile the UE Plugin by your self feel free to visit the [wiki page](https://github.com/brwarner/inkcpp/wiki/Unreal) for a more debug oriented build process. +If you compile the UE Plugin by your self feel free to visit the [wiki page](https://github.com/JBenda/inkcpp/wiki/Unreal) for a more debug oriented build process. ## Use standalone -1. Grep the current version from the [release page](https://github.com/brwarner/inkcpp/releases/latest) depending on your OS (e.g. macos-cl). +1. Grep the current version from the [release page](https://github.com/JBenda/inkcpp/releases/latest) depending on your OS (e.g. macos-cl). 2. unpack it to a location found by your path 3. run your story: `inkcpp-cl -p story.json` 4. if you want to compile `.ink` flies directly make sure `inklecate` is in your path. If you not have it you can grep it from the [official page](https://github.com/inkle/ink/releases/latest) @@ -56,7 +59,7 @@ Nice features for testing: Instructions: -1. Download the for your OS macthing lib archive from the [release page](https://github.com/brwarner/inkcpp/releases/latest) (e.g. linux-lib). +1. Download the for your OS macthing lib archive from the [release page](https://github.com/JBenda/inkcpp/releases/latest) (e.g. linux-lib). 2. The following must be linked into your build solution for your C++ to compile correctly: - `include/ink`: contains important shared headers. + For a Visual Studio project, link this directory as an Include Directory in VC++ Directories. @@ -70,7 +73,7 @@ Instructions: #include #include ``` -6. if you use cmake checkout the (wiki)[https://github.com/brwarner/inkcpp/wiki/building#cmake-example] for including the library via cmake +6. if you use cmake checkout the (wiki)[https://github.com/JBenda/inkcpp/wiki/building#cmake-example] for including the library via cmake ### Example @@ -129,7 +132,7 @@ To install the different components use `cmake --install . --component _py` eg `linux_py`. - ## Dependencies The compiler depends on Nlohmann's JSON library and the C++ STL. diff --git a/inkcpp/globals_impl.cpp b/inkcpp/globals_impl.cpp index 5eef3cb7..f907f8b9 100644 --- a/inkcpp/globals_impl.cpp +++ b/inkcpp/globals_impl.cpp @@ -31,7 +31,8 @@ globals_impl::globals_impl(const story_impl* story) while (*flags != null_flag) { list_table::list l = _lists.create_permament(); while (*flags != null_flag) { - _lists.add_inplace(l, *flags); + list_flag flag = _lists.external_fvalue_to_internal(*flags); + _lists.add_inplace(l, flag); ++flags; } ++flags; diff --git a/inkcpp/list_operations.cpp b/inkcpp/list_operations.cpp index 40e82641..45023bfc 100644 --- a/inkcpp/list_operations.cpp +++ b/inkcpp/list_operations.cpp @@ -12,195 +12,265 @@ #include "list_table.h" #define call4_Wrap(OP, RET, FUN) call4_Wrap_diff(OP, RET, RET, RET, RET, FUN) -#define call4_Wrap_diff(OP, RET0, RET1, RET2, RET3, FUN) \ - void operation::operator()(\ - basic_eval_stack& stack, value* vals)\ - {\ - call4(RET0, RET1, RET2, RET3, FUN);\ +#define call4_Wrap_diff(OP, RET0, RET1, RET2, RET3, FUN) \ + void operation::operator()( \ + basic_eval_stack& stack, value* vals \ + ) \ + { \ + call4(RET0, RET1, RET2, RET3, FUN); \ } -#define call4(RET0, RET1, RET2, RET3, FUN) \ - if (vals[0].type() == value_type::list_flag) { \ - if(vals[1].type() == value_type::list) { \ - stack.push(value{}.set( \ - _list_table.FUN( \ - vals[0].get(), \ - vals[1].get() \ - ) \ - )); \ - } else {\ - inkAssert(vals[1].type()==value_type::list_flag, "list operation was called but second argument is not a list or list_flag");\ - stack.push(value{}.set( \ - _list_table.FUN( \ - vals[0].get(), \ - vals[1].get() \ - )\ - )); \ - } \ - } else { \ - inkAssert(vals[0].type() == value_type::list, "list operation was called but first argument is not a list or a list_flag!"); \ - if(vals[1].type() == value_type::list) { \ - stack.push(value{}.set( \ - _list_table.FUN( \ - vals[0].get(), \ - vals[1].get() \ - ) \ - )); \ - } else {\ - inkAssert(vals[1].type()==value_type::list_flag, "list operation was called but second argument ist not a list or list_flag!");\ - stack.push(value{}.set( \ - _list_table.FUN( \ - vals[0].get(), \ - vals[1].get() \ - )\ - )); \ - } \ +#define call4(RET0, RET1, RET2, RET3, FUN) \ + if (vals[0].type() == value_type::list_flag) { \ + if (vals[1].type() == value_type::list) { \ + stack.push(value{}.set( \ + _list_table.FUN(vals[0].get(), vals[1].get()) \ + )); \ + } else { \ + inkAssert( \ + vals[1].type() == value_type::list_flag, \ + "list operation was called but second argument is not a list or list_flag" \ + ); \ + stack.push(value{}.set(_list_table.FUN( \ + vals[0].get(), vals[1].get() \ + ))); \ + } \ + } else { \ + inkAssert( \ + vals[0].type() == value_type::list, \ + "list operation was called but first argument is not a list or a list_flag!" \ + ); \ + if (vals[1].type() == value_type::list) { \ + stack.push(value{}.set( \ + _list_table.FUN(vals[0].get(), vals[1].get()) \ + )); \ + } else { \ + inkAssert( \ + vals[1].type() == value_type::list_flag, \ + "list operation was called but second argument ist not a list or list_flag!" \ + ); \ + stack.push(value{}.set( \ + _list_table.FUN(vals[0].get(), vals[1].get()) \ + )); \ + } \ } -#define call2(OP, RET0, RET1, FUN) \ - void operation::operator()( \ - basic_eval_stack& stack, value* vals)\ - {\ - stack.push(value{}.set(\ - _list_table.FUN(vals[0].get())\ - ));\ - }\ - void operation::operator()(\ - basic_eval_stack& stack, value* vals)\ - {\ - stack.push(value{}.set(\ - _list_table.FUN(vals[0].get())\ - ));\ +#define call2(OP, RET0, RET1, FUN) \ + void operation::operator()( \ + basic_eval_stack& stack, value* vals \ + ) \ + { \ + stack.push(value{}.set(_list_table.FUN(vals[0].get()))); \ + } \ + void operation::operator()( \ + basic_eval_stack& stack, value* vals \ + ) \ + { \ + stack.push(value{}.set(_list_table.FUN(vals[0].get()) \ + )); \ } -namespace ink::runtime::internal { - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - if(vals[1].type() == value_type::int32 - || vals[1].type() == value_type::uint32) - { - int i = vals[1].type() == value_type::int32 - ? vals[1].get() - : static_cast(vals[1].get()); - inkAssert(vals[0].type() == value_type::list, "try to use list add function but value is not of type list"); - stack.push(value{}.set( - _list_table.add(vals[0].get(), i) - )); - } else { - call4(list, list, list, list, add); - } - } - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - inkAssert(vals[0].type() == value_type::list_flag, "try to use add function with list_flag results but first argument is not a list_flag!"); - inkAssert(vals[1].type() == value_type::int32 - || vals[1].type() == value_type::uint32, - "try modify a list flag with a non intiger type!"); +namespace ink::runtime::internal +{ +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + if (vals[1].type() == value_type::int32 || vals[1].type() == value_type::uint32) { int i = vals[1].type() == value_type::int32 - ? vals[1].get() - : static_cast(vals[1].get()); - stack.push(value{}.set( - _list_table.add(vals[0].get(), i) - )); + ? vals[1].get() + : static_cast(vals[1].get()); + inkAssert( + vals[0].type() == value_type::list, + "try to use list add function but value is not of type list" + ); + stack.push(value{}.set(_list_table.add(vals[0].get(), i))); + } else { + call4(list, list, list, list, add); } +} - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - if(vals[1].type() == value_type::int32 - || vals[1].type() == value_type::uint32) - { - int i = vals[1].type() == value_type::int32 - ? vals[1].get() - : vals[1].get(); - inkAssert(vals[0].type() == value_type::list, "A in list resulting subtraction needs at leas one list as argument!"); - stack.push(value{}.set( - _list_table.sub(vals[0].get(), i) - )); - } else { - call4(list_flag, list_flag, list, list, sub); - } - } - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - inkAssert(vals[0].type() == value_type::list_flag, "subtraction resulting in list_flag needs a list_flag as first arguments!"); - inkAssert(vals[1].type() == value_type::int32 - || vals[1].type() == value_type::uint32, - "Try to subtract non integer value from list_flag."); - int i = vals[1].type() == value_type::int32 - ? vals[1].get() - : vals[1].get(); - stack.push(value{}.set( - _list_table.sub(vals[0].get(), i) - )); - } +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + inkAssert( + vals[0].type() == value_type::list_flag, + "try to use add function with list_flag results but first argument is not a list_flag!" + ); + inkAssert( + vals[1].type() == value_type::int32 || vals[1].type() == value_type::uint32, + "try modify a list flag with a non intiger type!" + ); + int i = vals[1].type() == value_type::int32 ? vals[1].get() + : static_cast(vals[1].get()); + stack.push( + value{}.set(_list_table.add(vals[0].get(), i)) + ); +} - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - call4(list_flag, list_flag, list, list_flag, intersect); +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + if (vals[1].type() == value_type::int32 || vals[1].type() == value_type::uint32) { + int i = vals[1].type() == value_type::int32 ? vals[1].get() + : vals[1].get(); + inkAssert( + vals[0].type() == value_type::list, + "A in list resulting subtraction needs at leas one list as argument!" + ); + stack.push(value{}.set(_list_table.sub(vals[0].get(), i))); + } else { + call4(list_flag, list_flag, list, list, sub); } +} - call2(LIST_COUNT, int32, int32, count); - call2(LIST_MIN, list_flag, list_flag, min); - call2(LIST_MAX, list_flag, list_flag, max); - call2(LIST_ALL, list, list, all); - call2(LIST_INVERT, list, list, invert); - - call4_Wrap(LESS_THAN, boolean, less); - call4_Wrap(LESS_THAN_EQUALS, boolean, less_equal); - call4_Wrap(GREATER_THAN, boolean, greater); - call4_Wrap(GREATER_THAN_EQUALS, boolean, greater_equal); - call4_Wrap(IS_EQUAL, boolean, equal); - call4_Wrap(NOT_EQUAL, boolean, not_equal); - call4_Wrap(HAS, boolean, has); - call4_Wrap(HASNT, boolean, hasnt); - - - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - stack.push(value{}.set( - _list_table.lrnd(vals[0].get(), _prng) - )); - } - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - stack.push(value{}.set( - _list_table.lrnd(vals[0].get()) - )); - } +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + inkAssert( + vals[0].type() == value_type::list_flag, + "subtraction resulting in list_flag needs a list_flag as first arguments!" + ); + inkAssert( + vals[1].type() == value_type::int32 || vals[1].type() == value_type::uint32, + "Try to subtract non integer value from list_flag." + ); + int i = vals[1].type() == value_type::int32 ? vals[1].get() + : vals[1].get(); + stack.push( + value{}.set(_list_table.sub(vals[0].get(), i)) + ); +} + +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + call4(list_flag, list_flag, list, list_flag, intersect); +} + +call2(NOT, boolean, boolean, not_bool); +call2(LIST_COUNT, int32, int32, count); +call2(LIST_MIN, list_flag, list_flag, min); +call2(LIST_MAX, list_flag, list_flag, max); +call2(LIST_ALL, list, list, all); +call2(LIST_INVERT, list, list, invert); + +call4_Wrap(LESS_THAN, boolean, less); +call4_Wrap(LESS_THAN_EQUALS, boolean, less_equal); +call4_Wrap(GREATER_THAN, boolean, greater); +call4_Wrap(GREATER_THAN_EQUALS, boolean, greater_equal); +call4_Wrap(IS_EQUAL, boolean, equal); +call4_Wrap(NOT_EQUAL, boolean, not_equal); +call4_Wrap(HAS, boolean, has); +call4_Wrap(HASNT, boolean, hasnt); - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - inkAssert(vals[0].type() == value_type::string, "list_flag construction needs the list name as string as first argument!"); - inkAssert(vals[1].type() == value_type::int32, "list_flag construction needs the flag numeric value as second argument!"); - list_flag entry = _list_table.get_list_id(vals[0].get()); - entry.flag = vals[1].get() - 1; - stack.push(value{}.set(entry)); +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + stack.push( + value{}.set(_list_table.lrnd(vals[0].get(), _prng)) + ); +} + +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + stack.push( + value{}.set(_list_table.lrnd(vals[0].get())) + ); +} + +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + inkAssert( + vals[0].type() == value_type::string, + "list_flag construction needs the list name as string as first argument!" + ); + inkAssert( + vals[1].type() == value_type::int32, + "list_flag construction needs the flag numeric value as second argument!" + ); + list_flag entry = _list_table.get_list_id(vals[0].get()); + entry.flag = vals[1].get(); + entry = _list_table.external_fvalue_to_internal(entry); + stack.push(value{}.set(entry)); +} + +int get_limit(const value& val, const list_table& lists) +{ + if (val.type() == value_type::int32) { + return val.get(); + } else { + inkAssert(val.type() == value_type::list_flag, "flag value must be a integer or a list_flag"); + return lists.get_flag_value(val.get()); } +} + +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + inkAssert(vals[0].type() == value_type::list, "Can't get range of non list type!"); + stack.push(value{}.set(_list_table.range( + vals[0].get(), get_limit(vals[1], _list_table), + get_limit(vals[2], _list_table) + ))); +} - int get_limit(const value& val) { - if(val.type() == value_type::int32) { - return val.get() - 1; - } else { - inkAssert(val.type() == value_type::list_flag, "flag value must be a integer or a list_flag"); - return val.get().flag; +void convert_bools(value* vals, const list_table& lists, bool* res) +{ + for (int i = 0; i < 2; ++i) { + switch (vals[i].type()) { + case value_type::list: res[i] = lists.to_bool(vals[i].get()); break; + case value_type::list_flag: + res[i] = lists.to_bool(vals[i].get()); + break; + default: res[i] = casting::numeric_cast(vals[i]); } } - void operation::operator()( - basic_eval_stack& stack, value* vals) - { - inkAssert(vals[0].type() == value_type::list, "Can't get range of non list type!"); - stack.push(value{}.set(_list_table.range( - vals[0].get(), - get_limit(vals[1]), - get_limit(vals[2])))); - } } +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + bool res[2]; + convert_bools(vals, _list_table, res); + stack.push(value{}.set(res[0] && res[1])); +} + +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + bool res[2]; + convert_bools(vals, _list_table, res); + stack.push(value{}.set(res[0] && res[1])); +} + +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + bool res[2]; + convert_bools(vals, _list_table, res); + stack.push(value{}.set(res[0] || res[1])); +} + +void operation::operator()( + basic_eval_stack& stack, value* vals +) +{ + bool res[2]; + convert_bools(vals, _list_table, res); + stack.push(value{}.set(res[0] || res[1])); +} +} // namespace ink::runtime::internal diff --git a/inkcpp/list_operations.h b/inkcpp/list_operations.h index 15dd4d86..70798e42 100644 --- a/inkcpp/list_operations.h +++ b/inkcpp/list_operations.h @@ -8,239 +8,349 @@ /// defines operations on lists -namespace ink::runtime::internal { - - namespace casting { - // define valid castings - template<> - struct cast - { static constexpr value_type value = value_type::list; }; - template<> - struct cast - { static constexpr value_type value = value_type::list; }; - template<> - - struct cast - { static constexpr value_type value = value_type::list_flag; }; - template<> - struct cast - { static constexpr value_type value = value_type::list_flag; }; - - template<> - struct cast - { static constexpr value_type value = value_type::list; }; - - // opertions on mulitple list_flags results potential in a new list - template<> - struct cast - { static constexpr value_type value = value_type::list; }; +#include "value.h" - } - - template - class redefine : public operation_base { - public: - using operation_base::operation_base; - value operator()(const list_table::list& lh, const list_table::list& rh) { - return value{}.set(_list_table.redefine(lh,rh)); - } - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; +namespace ink::runtime::internal +{ +namespace casting +{ + // define valid castings template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list; }; template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list; }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list; }; template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list_flag; }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list_flag; }; template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list_flag; }; template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list; }; + // opertions on mulitple list_flags results potential in a new list template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::list; }; +} // namespace casting - template<> - class operation: public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - inkAssert(vals[0].type() == value_type::list_flag, "LIST_VALUE only works on list_flag values"); - stack.push(value{}.set(static_cast( - vals[0].get().flag) + 1)); - } - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; - - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); - }; -} +template +class redefine : public operation_base +{ +public: + using operation_base::operation_base; + value operator()(const list_table::list& lh, const list_table::list& rh) + { + return value{}.set(_list_table.redefine(lh, rh)); + } +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation + : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation + : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation + : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation + : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation + : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + inkAssert(vals[0].type() == value_type::list_flag, "LIST_VALUE only works on list_flag values"); + stack.push(value{}.set( + static_cast(vals[0].get().flag) + 1 + )); + } +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; +} // namespace ink::runtime::internal diff --git a/inkcpp/list_table.cpp b/inkcpp/list_table.cpp index 880acfd5..fd267602 100644 --- a/inkcpp/list_table.cpp +++ b/inkcpp/list_table.cpp @@ -5,6 +5,7 @@ * https://github.com/JBenda/inkcpp for full license details. */ #include "list_table.h" +#include "system.h" #include "traits.h" #include "header.h" #include "random.h" @@ -40,6 +41,7 @@ list_table::list_table(const char* data, const ink::internal::header& header) const char* ptr = data; int start = 0; while ((flag = header.read_list_flag(ptr)) != null_flag) { + // start of new list if (_list_end.size() == flag.list_id) { start = _list_end.size() == 0 ? 0 : _list_end.back(); _list_end.push() = start; @@ -49,11 +51,8 @@ list_table::list_table(const char* data, const ink::internal::header& header) } ++ptr; // skip string } - while (_list_end.back() - start < flag.flag) { - _flag_names.push() = nullptr; - ++_list_end.back(); - } _flag_names.push() = ptr; + _flag_values.push() = flag.flag; ++_list_end.back(); while (*ptr) { ++ptr; @@ -119,9 +118,10 @@ size_t list_table::stringLen(const list_flag& e) const { return c_str_len(toStri const char* list_table::toString(const list_flag& e) const { if (e.list_id < 0 || e.flag < 0) { - return nullptr; + return ""; } - return _flag_names[toFid(e)]; + const char* res = _flag_names[toFid(e)]; + return res == nullptr ? "" : res; } size_t list_table::stringLen(const list& l) const @@ -146,38 +146,55 @@ size_t list_table::stringLen(const list& l) const return len; } +/// @todo check ouput order for explicit valued lists +/// @sa list_table::write() char* list_table::toString(char* out, const list& l) const { char* itr = out; const data_t* entry = getPtr(l.lid); + int last_value = 0; + int last_list = -1; bool first = true; - int max_list_len = 0; - for (int i = 0; i < numLists(); ++i) { - if (hasList(entry, i)) { - int len = _list_end[i] - listBegin(i); - if (len > max_list_len) - max_list_len = len; - } - } - for (int j = 0; j < max_list_len; ++j) { + int min_value = 0; + int min_id = -1; + int min_list = -1; + + while (1) { + bool change = false; for (int i = 0; i < numLists(); ++i) { - int len = _list_end[i] - listBegin(i); - if (j < len && hasList(entry, i)) { - int flag = j + listBegin(i); - if (hasFlag(entry, flag) && _flag_names[flag]) { - if (! first) { - *itr++ = ','; - *itr++ = ' '; - } else { - first = false; + if (hasList(entry, i)) { + for (int j = listBegin(i); j < _list_end[i]; ++j) { + if (! hasFlag(entry, j)) { + continue; } - for (const char* c = _flag_names[flag]; *c; ++c) { - *itr++ = *c; + int value = _flag_values[j]; + if (first || value > last_value || (value == last_value && i > last_list)) { + if (min_id == -1 || value < min_value) { + change = true; + min_list = i; + min_value = value; + min_id = j; + } + break; } } } } + if (! change) { + break; + } + if (! first) { + *itr++ = ','; + *itr++ = ' '; + } + first = false; + for (const char* c = _flag_names[min_id]; *c; ++c) { + *itr++ = *c; + } + last_value = min_value; + last_list = min_list; + min_id = -1; } return itr; } @@ -192,9 +209,13 @@ list_table::list list_table::range(list_table::list l, int min, int max) if (hasList(in, i)) { bool has_flag = false; for (int j = listBegin(i); j < _list_end[i]; ++j) { - if (j - listBegin(i) < min || j - listBegin(i) > max) { + int value = _flag_values[j]; + if (value < min) { continue; } + if (value > max) { + break; + } if (hasFlag(in, j)) { setFlag(out, j); has_flag = true; @@ -282,7 +303,7 @@ list_table::list list_table::sub(list lh, list rh) for (int i = 0; i < numLists(); ++i) { if (hasList(r, i)) { if (hasList(l, i)) { - for (int j = listBegin(i); j < _list_end[j]; ++j) { + for (int j = listBegin(i); j < _list_end[i]; ++j) { if (hasFlag(o, j)) { setList(o, i); active_flag = true; @@ -337,6 +358,7 @@ list_flag list_table::sub(list_flag lh, list rh) return lh; } +/// @todo early exit if value + n is outside of range list_table::list list_table::add(list arg, int n) { // TODO: handle i == 0 (for performance only) @@ -351,10 +373,16 @@ list_table::list list_table::add(list arg, int n) for (int i = 0; i < numLists(); ++i) { if (hasList(l, i)) { bool has_flag = false; - for (int j = listBegin(i); j < _list_end[i] - i; ++j) { + for (int j = listBegin(i); j < _list_end[i]; ++j) { if (hasFlag(l, j)) { - setFlag(o, j + n); - has_flag = true; + int value = _flag_values[j] + n; + for (int k = j + 1; k < _list_end[i]; ++k) { + if (value == _flag_values[k]) { + setFlag(o, k); + has_flag = true; + break; + } + } } } if (has_flag) { @@ -369,15 +397,23 @@ list_table::list list_table::add(list arg, int n) return res; } -list_flag list_table::add(list_flag arg, int i) +list_flag list_table::add(list_flag arg, int n) { - arg.flag += i; - if (arg.flag < 0 || arg.flag > _list_end[arg.list_id] - listBegin(arg.list_id)) { - arg.flag = -1; + if (arg == null_flag || arg == empty_flag || arg.flag == -1) { + return arg; + } + int value = _flag_values[arg.flag] + n; + for (int i = listBegin(arg.list_id); i < _list_end[arg.list_id]; ++i) { + if (_flag_values[i] == value) { + arg.flag = i; + return arg; + } } + arg.flag = -1; return arg; } +/// @todo early exit if value - n is outside of range list_table::list list_table::sub(list arg, int n) { // TODO: handle i == 0 (for perofrgmance only) @@ -391,10 +427,16 @@ list_table::list list_table::sub(list arg, int n) for (int i = 0; i < numLists(); ++i) { if (hasList(l, i)) { bool has_flag = false; - for (int j = listBegin(i) + i; j < _list_end[i]; ++j) { + for (int j = listBegin(i); j < _list_end[i]; ++j) { if (hasFlag(l, j)) { - setFlag(o, j - n); - has_flag = true; + int value = _flag_values[j] - n; + for (int k = j - 1; k >= listBegin(i); --k) { + if (_flag_values[k] == value) { + setFlag(o, k); + has_flag = true; + break; + } + } } } if (has_flag) { @@ -409,23 +451,26 @@ list_table::list list_table::sub(list arg, int n) return res; } -list_flag list_table::sub(list_flag arg, int i) +list_flag list_table::sub(list_flag arg, int i) { return add(arg, -i); } + +int list_table::count(list_flag lf) const { - arg.flag -= i; - if (arg.flag < 0 || arg.flag > _list_end[arg.list_id] - listBegin(arg.list_id)) { - arg.flag = -1; + if (lf == empty_flag || lf == null_flag || lf.flag == -1) { + return 0; } - return arg; + if (_flag_names[toFid(lf)] == nullptr) { + return 0; + } + return 1; } - int list_table::count(list l) const { int count = 0; const data_t* data = getPtr(l.lid); for (int i = 0; i < numLists(); ++i) { if (hasList(data, i)) { - for (int j = listBegin(i); j < _list_end[j]; ++j) { - if (hasFlag(data, j)) { + for (int j = listBegin(i); j < _list_end[i]; ++j) { + if (_flag_names[j] != nullptr && hasFlag(data, j)) { ++count; } } @@ -442,7 +487,7 @@ list_flag list_table::min(list l) const if (hasList(data, i)) { for (int j = listBegin(i); j < _list_end[i]; ++j) { if (hasFlag(data, j)) { - int value = j - listBegin(i); + int value = _flag_values[j]; if (res.flag < 0 || value < res.flag) { res.flag = value; res.list_id = i; @@ -463,7 +508,7 @@ list_flag list_table::max(list l) const if (hasList(data, i)) { for (int j = _list_end[i] - 1; j >= listBegin(i); --j) { if (hasFlag(data, j)) { - int value = j - listBegin(i); + int value = _flag_values[j]; if (value > res.flag) { res.flag = value; res.list_id = i; @@ -730,34 +775,49 @@ list_interface* list_table::handout_list(list l) } #ifdef INK_ENABLE_STL +/// @sa list_table::toString(char*,const list&) std::ostream& list_table::write(std::ostream& os, list l) const { - bool first = true; - const data_t* entry = getPtr(l.lid); - int max_list_len = 0; - for (int i = 0; i < numLists(); ++i) { - if (hasList(entry, i)) { - int len = _list_end[i] - listBegin(i); - if (len > max_list_len) - max_list_len = len; - } - } - for (int j = 0; j < max_list_len; ++j) { + int last_value = 0; + int last_list = -1; + bool first = true; + int min_value = 0; + int min_id = -1; + int min_list = -1; + + while (1) { + bool change = false; for (int i = 0; i < numLists(); ++i) { - int len = _list_end[i] - listBegin(i); - if (j < len && hasList(entry, i)) { - int flag = listBegin(i) + j; - if (hasFlag(entry, flag) && _flag_names[flag]) { - if (! first) { - os << ", "; - } else { - first = false; + if (hasList(entry, i)) { + for (int j = listBegin(i); j < _list_end[i]; ++j) { + if (! hasFlag(entry, j)) { + continue; + } + int value = _flag_values[j]; + if (first || value > last_value || (value == last_value && i > last_list)) { + if (min_id == -1 || value < min_value) { + min_value = value; + min_id = j; + min_list = i; + change = true; + } + break; } - os << _flag_names[flag]; } } } + if (! change) { + break; + } + if (! first) { + os << ", "; + } + first = false; + os << _flag_names[min_id]; + last_value = min_value; + last_list = min_list; + min_id = -1; } return os; } diff --git a/inkcpp/list_table.h b/inkcpp/list_table.h index cc4e41de..03827ac1 100644 --- a/inkcpp/list_table.h +++ b/inkcpp/list_table.h @@ -61,6 +61,33 @@ class list_table : public snapshot_interface /** @return list_flag with list_id set to list with name list_name */ list_flag get_list_id(const char* list_name) const; + /** @brief converts external flag value to internal */ + list_flag external_fvalue_to_internal(list_flag flag) const + { + if (flag == null_flag || flag == empty_flag) { + return flag; + } + // origin flag (no flag but list origin) + if (flag.list_id < -1) { + flag.list_id = -flag.list_id - 2; + flag.flag = -1; + return flag; + } + for (int i = listBegin(flag.list_id); i < _list_end[flag.list_id]; ++i) { + if (_flag_values[i] == flag.flag) { + flag.flag = i - listBegin(flag.list_id); + return flag; + } + } + flag.flag = -1; + return flag; + } + + int get_flag_value(list_flag flag) const + { + return _flag_values[listBegin(flag.list_id) + flag.flag]; + } + /// zeros all usage values void clear_usage(); @@ -140,9 +167,16 @@ class list_table : public snapshot_interface list_flag intersect(list_flag lh, list_flag rh) { return lh == rh ? lh : null_flag; } - int count(list l) const; + bool to_bool(list l) const { return count(l) > 0; } + + bool not_bool(list l) const { return ! to_bool(l); } - int count(list_flag f) const { return f.flag < 0 ? 0 : 1; } + bool to_bool(list_flag lf) const { return count(lf) > 0; } + + bool not_bool(list_flag lf) const { return ! to_bool(lf); } + + int count(list l) const; + int count(list_flag f) const; list_flag min(list l) const; @@ -305,6 +339,7 @@ class list_table : public snapshot_interface // defined list (meta data) managed_array _list_end; managed_array _flag_names; + managed_array _flag_values; managed_array _list_names; /// keep track over lists accessed with get_var, and clear then at gc time managed_array _list_handouts; diff --git a/inkcpp/numeric_operations.h b/inkcpp/numeric_operations.h index 7246c551..674aa27f 100644 --- a/inkcpp/numeric_operations.h +++ b/inkcpp/numeric_operations.h @@ -11,430 +11,519 @@ /// use generalized types numeric and integral to keep redundancy minimal. /// define a cast to support operations like int + float, bool + uint etc. -namespace ink::runtime::internal { - - /// list of numeric value types - /// produces a SFINAE error if type is not part of list - template - using is_numeric_t = typename enable_if< - ty == value_type::boolean - || ty == value_type::int32 - || ty == value_type::uint32 - || ty == value_type::float32, void>::type; - - template - using is_signed_numeric_t = typename enable_if< - ty == value_type::int32 - || ty == value_type::float32, void>::type; - - /// list of internal value types - /// produces a SFINAE error if type is not part of list - template - using is_integral_t = typename enable_if< - ty == value_type::boolean - || ty == value_type::int32 - || ty == value_type::uint32, void>::type; - - namespace casting { - /// define valid casts - - /// result of operation with int and float is float. - template<> - struct cast - { static constexpr value_type value = value_type::float32; }; - - /// result of operation with uint and bool is uint - template<> - struct cast - { static constexpr value_type value = value_type::uint32; }; - - // result of operation with bool and int is int - template<> - struct cast - { static constexpr value_type value = value_type::int32; }; - - /// defined numeric cast - /// generic numeric_cast only allow casting to its one type - template - inline typename value::ret::type numeric_cast(const value& v) { - if (to == v.type()) { return v.get(); } - else { - inkFail("invalid numeric_cast! from %i to %i", v.type(), to); - return 0; - } - } - - /// specialisation for uint32 - template<> - inline typename value::ret::type numeric_cast(const value& v) { - switch(v.type()) { - case value_type::uint32: - return v.get(); - /// bool value can cast to uint32 - case value_type::boolean: - return static_cast(v.get()); - default: - inkFail("invalid cast to uint!"); - return 0; - } - } - - template<> - inline typename value::ret::type numeric_cast(const value& v) { - switch(v.type()) { - case value_type::int32: - return v.get(); - case value_type::boolean: - return static_cast(v.get()); - default: - inkFail("invalid cast to int!"); - return 0; - } - } - - /// specialisation for float32 - template<> - inline float numeric_cast(const value& v) { - switch(v.type()) { - case value_type::float32: - return v.get(); - // int value can cast to float - case value_type::int32: - return static_cast(v.get()); - default: - inkFail("invalid numeric_cast!"); - return 0; - } - } - - /// specialisation for boolean - template<> - inline bool numeric_cast(const value& v) { - switch(v.type()) { - case value_type::boolean: - return v.get(); - case value_type::int32: - return v.get() != 0; - case value_type::uint32: - return v.get() != 0; - case value_type::float32: - return v.get() != 0; - default: - inkFail("invalid numeric_cast to boolean from: %i", v.type()); - return false; - } - } - } - +namespace ink::runtime::internal +{ + +/// list of numeric value types +/// produces a SFINAE error if type is not part of list +template +using is_numeric_t = typename enable_if< + ty == value_type::boolean || ty == value_type::int32 || ty == value_type::uint32 + || ty == value_type::float32, + void>::type; + +template +using is_signed_numeric_t = + typename enable_if::type; + +/// list of internal value types +/// produces a SFINAE error if type is not part of list +template +using is_integral_t = typename enable_if< + ty == value_type::boolean || ty == value_type::int32 || ty == value_type::uint32, void>::type; + +namespace casting +{ + /// define valid casts + + /// result of operation with int and float is float. template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::float32; }; template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals); + struct cast { + static constexpr value_type value = value_type::float32; }; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - static_cast(vals->get()) - )); - } + template<> + struct cast { + static constexpr value_type value = value_type::float32; }; template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - vals[0].get() - == vals[1].get())); - } + struct cast { + static constexpr value_type value = value_type::int32; }; + + /// result of operation with uint and bool is uint template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - vals[0].get() - != vals[1].get())); - } + struct cast { + static constexpr value_type value = value_type::uint32; }; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - // for integral types floor(i) == i - stack.push(vals[0]); - } + // result of operation with bool and int is int + template<> + struct cast { + static constexpr value_type value = value_type::int32; }; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - // for integral types ceil(i) == i - stack.push(vals[0]); + /// defined numeric cast + /// generic numeric_cast only allow casting to its one type + template + inline typename value::ret::type numeric_cast(const value& v) + { + if (to == v.type()) { + return v.get(); + } else { + inkFail("invalid numeric_cast! from %i to %i", v.type(), to); + return 0; } - }; + } - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) + - casting::numeric_cast(vals[1]) )); + /// specialisation for uint32 + template<> + inline typename value::ret::type + numeric_cast(const value& v) + { + switch (v.type()) { + case value_type::uint32: return v.get(); + /// bool value can cast to uint32 + case value_type::boolean: return static_cast(v.get()); + default: inkFail("invalid cast to uint!"); return 0; } - }; + } - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) - - casting::numeric_cast(vals[1]) )); + template<> + inline typename value::ret::type numeric_cast(const value& v + ) + { + switch (v.type()) { + case value_type::int32: return v.get(); + case value_type::uint32: return static_cast(v.get()); + case value_type::boolean: return static_cast(v.get()); + default: inkFail("invalid cast to int!"); return 0; } - }; + } + /// specialisation for float32 template<> - class operation : public operation_base { - operation op_int; - public: - template operation(const T& t) : operation_base{t}, op_int{t} {} - void operator()(basic_eval_stack& stack, value* vals) { - op_int(stack, vals); + inline float numeric_cast(const value& v) + { + switch (v.type()) { + case value_type::float32: return v.get(); + // int value can cast to float + case value_type::int32: return static_cast(v.get()); + case value_type::uint32: return static_cast(v.get()); + default: inkFail("invalid numeric_cast!"); return 0; } - }; + } - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) / - casting::numeric_cast(vals[1]) )); - } - }; - + /// specialisation for boolean template<> - class operation : public operation_base { - operation op_int; - public: - template operation(const T& t) : operation_base{t}, op_int{t} {} - void operator()(basic_eval_stack& stack, value* vals) { - op_int(stack, vals); + inline bool numeric_cast(const value& v) + { + switch (v.type()) { + case value_type::boolean: return v.get(); + case value_type::int32: return v.get() != 0; + case value_type::uint32: return v.get() != 0; + case value_type::float32: return v.get() != 0; + default: inkFail("invalid numeric_cast to boolean from: %i", v.type()); return false; } - }; + } +} // namespace casting + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals); +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set(static_cast(vals->get()))); + } +}; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) * - casting::numeric_cast(vals[1]) )); - } - }; +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) - % casting::numeric_cast(vals[1]))); - } - }; + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + vals[0].get() == vals[1].get() + )); + } +}; - template<> - class operation : public operation_base { - operation op_int; - public: - template operation(const T& t) : operation_base{t}, op_int{t} {} - void operator()(basic_eval_stack& stack, value* vals) { - op_int(stack, vals); - } - }; +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) == - casting::numeric_cast(vals[1]) - )); - } - }; + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + vals[0].get() != vals[1].get() + )); + } +}; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) > - casting::numeric_cast(vals[1]) - )); - } - }; +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + void operator()(basic_eval_stack& stack, value* vals) + { + // for integral types floor(i) == i + stack.push(vals[0]); + } +}; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) < - casting::numeric_cast(vals[1]) - )); - } - }; +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) >= - casting::numeric_cast(vals[1]) - )); - } - }; + void operator()(basic_eval_stack& stack, value* vals) + { + // for integral types ceil(i) == i + stack.push(vals[0]); + } +}; +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) <= - casting::numeric_cast(vals[1]) - )); - } - }; + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push( + value{}.set(casting::numeric_cast(vals[0]) + casting::numeric_cast(vals[1])) + ); + } +}; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) != - casting::numeric_cast(vals[1]) - )); - } - }; +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) - && casting::numeric_cast(vals[1]))); - } - }; + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push( + value{}.set(casting::numeric_cast(vals[0]) - casting::numeric_cast(vals[1])) + ); + } +}; + +template<> +class operation : public operation_base +{ + operation op_int; + +public: + template + operation(const T& t) + : operation_base{t} + , op_int{t} + { + } - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()( basic_eval_stack& stack, value* vals ) - { - stack.push(value{}.set( - casting::numeric_cast(vals[0]) - || casting::numeric_cast(vals[1]))); - } - }; + void operator()(basic_eval_stack& stack, value* vals) { op_int(stack, vals); } +}; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - typename value::ret::type n[2] = { - casting::numeric_cast(vals[0]), - casting::numeric_cast(vals[1]) - }; - stack.push(value{}.set(n[0] < n[1] ? n[0] : n[1])); - } - }; +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - typename value::ret::type n[2] = { - casting::numeric_cast(vals[0]), - casting::numeric_cast(vals[1]) - }; - stack.push(value{}.set(n[0] > n[1] ? n[0] : n[1])); - } - }; + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push( + value{}.set(casting::numeric_cast(vals[0]) / casting::numeric_cast(vals[1])) + ); + } +}; + +template<> +class operation : public operation_base +{ + operation op_int; + +public: + template + operation(const T& t) + : operation_base{t} + , op_int{t} + { + } - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set(!vals[0].get())); - } - }; + void operator()(basic_eval_stack& stack, value* vals) { op_int(stack, vals); } +}; - template - class operation> : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set(-vals[0].get())); - } - }; - template<> - class operation : public operation_base { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - stack.push(value{}.set(!vals[0].get())); - } - }; +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; - template<> - class operation : public operation_base - { - public: - using operation_base::operation_base; - void operator()(basic_eval_stack& stack, value* vals) { - int min = casting::numeric_cast(vals[0]); - int max = casting::numeric_cast(vals[1]); - stack.push(value{}.set(static_cast(_prng.rand(max - min + 1) + min))); - } - }; -} + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push( + value{}.set(casting::numeric_cast(vals[0]) * casting::numeric_cast(vals[1])) + ); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push( + value{}.set(casting::numeric_cast(vals[0]) % casting::numeric_cast(vals[1])) + ); + } +}; + +template<> +class operation : public operation_base +{ + operation op_int; + +public: + template + operation(const T& t) + : operation_base{t} + , op_int{t} + { + } + + void operator()(basic_eval_stack& stack, value* vals) { op_int(stack, vals); } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) == casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) > casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) < casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) >= casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) <= casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) != casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) + && casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set( + casting::numeric_cast(vals[0]) + || casting::numeric_cast(vals[1]) + )); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + typename value::ret::type n[2] + = {casting::numeric_cast(vals[0]), casting::numeric_cast(vals[1])}; + stack.push(value{}.set(n[0] < n[1] ? n[0] : n[1])); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + typename value::ret::type n[2] + = {casting::numeric_cast(vals[0]), casting::numeric_cast(vals[1])}; + stack.push(value{}.set(n[0] > n[1] ? n[0] : n[1])); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set(! vals[0].get())); + } +}; + +template +class operation> : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set(-vals[0].get())); + } +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + stack.push(value{}.set(! vals[0].get())); + } +}; + +template<> +class operation : public operation_base +{ +public: + using operation_base::operation_base; + + void operator()(basic_eval_stack& stack, value* vals) + { + int min = casting::numeric_cast(vals[0]); + int max = casting::numeric_cast(vals[1]); + stack.push(value{}.set(static_cast(_prng.rand(max - min + 1) + min)) + ); + } +}; +} // namespace ink::runtime::internal diff --git a/inkcpp/value.cpp b/inkcpp/value.cpp index 106c1b42..d16c4452 100644 --- a/inkcpp/value.cpp +++ b/inkcpp/value.cpp @@ -42,8 +42,7 @@ bool truthy_impl(const value& v, const list_table& lists) { // if list is not empty -> valid flag -> filled list if (v.type() == value_type::list_flag) { - auto flag = v.get(); - return flag != null_flag && flag != empty_flag; + return lists.to_bool(v.get()); } else { return truthy_impl(v, lists); } @@ -54,7 +53,7 @@ bool truthy_impl(const value& v, const list_table& lists) { // if list is not empty if (v.type() == value_type::list) { - return lists.count(v.get()) > 0; + return lists.to_bool(v.get()); } else { return truthy_impl(v, lists); } diff --git a/inkcpp_compiler/binary_emitter.cpp b/inkcpp_compiler/binary_emitter.cpp index c3380ff2..77938d87 100644 --- a/inkcpp_compiler/binary_emitter.cpp +++ b/inkcpp_compiler/binary_emitter.cpp @@ -439,7 +439,7 @@ void binary_emitter::set_list_meta(const list_data& list_defs) ++list_names; _lists.write('\0'); } - _lists.write(reinterpret_cast(flag.name.c_str()), flag.name.size() + 1); + _lists.write(reinterpret_cast(flag.name->c_str()), flag.name->size() + 1); } _lists.write(null_flag); } diff --git a/inkcpp_compiler/json_compiler.cpp b/inkcpp_compiler/json_compiler.cpp index f71bbfb9..a16ad91e 100644 --- a/inkcpp_compiler/json_compiler.cpp +++ b/inkcpp_compiler/json_compiler.cpp @@ -15,417 +15,397 @@ namespace ink::compiler::internal { - using nlohmann::json; - using std::vector; +using nlohmann::json; +using std::vector; - typedef std::tuple defer_entry; +typedef std::tuple defer_entry; - json_compiler::json_compiler() - : _emitter(nullptr), _next_container_index(0) - { } +json_compiler::json_compiler() + : _emitter(nullptr) + , _next_container_index(0) +{ +} - void json_compiler::compile(const nlohmann::json& input, emitter* output, compilation_results* results) - { - // Get the runtime version - _ink_version = input["inkVersion"]; +void json_compiler::compile( + const nlohmann::json& input, emitter* output, compilation_results* results +) +{ + // Get the runtime version + _ink_version = input["inkVersion"]; - // Start the output - set_results(results); - _emitter = output; + // Start the output + set_results(results); + _emitter = output; - // Initialize emitter - _emitter->start(_ink_version, results); + // Initialize emitter + _emitter->start(_ink_version, results); - if(auto itr = input.find("listDefs"); itr != input.end()) { - compile_lists_definition(*itr); - _emitter->set_list_meta(_list_meta); - } - // Compile the root container - compile_container(input["root"], 0); + if (auto itr = input.find("listDefs"); itr != input.end()) { + compile_lists_definition(*itr); + _emitter->set_list_meta(_list_meta); + } + // Compile the root container + compile_container(input["root"], 0); - // finalize - _emitter->finish(_next_container_index); + // finalize + _emitter->finish(_next_container_index); - // Clear - _emitter = nullptr; - _next_container_index = 0; - clear_results(); - } + // Clear + _emitter = nullptr; + _next_container_index = 0; + clear_results(); +} - struct container_meta - { - std::string name; - container_t indexToReturn = ~0; - bool recordInContainerMap = false; - vector deferred; - CommandFlag cmd_flags = CommandFlag::NO_FLAGS; - }; - - void json_compiler::handle_container_metadata( - const json& meta, container_meta& data) - { - if (meta.is_object()) - { - for (auto& meta_iter : meta.items()) - { - // Name - if (meta_iter.key() == "#n") +struct container_meta { + std::string name; + container_t indexToReturn = ~0; + bool recordInContainerMap = false; + vector deferred; + CommandFlag cmd_flags = CommandFlag::NO_FLAGS; +}; + +void json_compiler::handle_container_metadata(const json& meta, container_meta& data) +{ + if (meta.is_object()) { + for (auto& meta_iter : meta.items()) { + // Name + if (meta_iter.key() == "#n") { + data.name = meta_iter.value().get(); + } + // Flags + else if (meta_iter.key() == "#f") { + int flags = meta_iter.value().get(); + + bool visits = false, turns = false, onlyFirst = false; + + if ((flags & 0x1) > 0) // Should record visit counts { - data.name = meta_iter.value().get(); + visits = true; } - // Flags - else if (meta_iter.key() == "#f") + if ((flags & 0x2) > 0) // Should record turn counts { - int flags = meta_iter.value().get(); - - bool visits = false, turns = false, onlyFirst = false; - - if ((flags & 0x1) > 0) // Should record visit counts - { - visits = true; - } - if ((flags & 0x2) > 0) // Should record turn counts - { - turns = true; - } - if ((flags & 0x4) > 0) // Only count when you enter the first subelement - { - onlyFirst = true; - } + turns = true; + } + if ((flags & 0x4) > 0) // Only count when you enter the first subelement + { + onlyFirst = true; + } - if (visits || turns) - { - container_t myIndex = _next_container_index++; + if (visits || turns) { + container_t myIndex = _next_container_index++; - // Make appropriate flags - data.cmd_flags = CommandFlag::NO_FLAGS; - if (visits) - data.cmd_flags |= CommandFlag::CONTAINER_MARKER_TRACK_VISITS; - if (turns) - data.cmd_flags |= CommandFlag::CONTAINER_MARKER_TRACK_TURNS; - if (onlyFirst) - data.cmd_flags |= CommandFlag::CONTAINER_MARKER_ONLY_FIRST; + // Make appropriate flags + data.cmd_flags = CommandFlag::NO_FLAGS; + if (visits) + data.cmd_flags |= CommandFlag::CONTAINER_MARKER_TRACK_VISITS; + if (turns) + data.cmd_flags |= CommandFlag::CONTAINER_MARKER_TRACK_TURNS; + if (onlyFirst) + data.cmd_flags |= CommandFlag::CONTAINER_MARKER_ONLY_FIRST; - data.indexToReturn = myIndex; + data.indexToReturn = myIndex; - //if (!onlyFirst) // ???? - { - data.recordInContainerMap = true; - } + // if (!onlyFirst) // ???? + { + data.recordInContainerMap = true; } } - // Child container - else - { - // Add to deferred compilation list - data.deferred.push_back(std::make_tuple(meta_iter.value(), meta_iter.key())); - } + } + // Child container + else { + // Add to deferred compilation list + data.deferred.push_back(std::make_tuple(meta_iter.value(), meta_iter.key())); } } } +} - void json_compiler::compile_container( - const nlohmann::json& container, int index_in_parent, - const std::string& name_override) - { - // Grab metadata from the last object in this container - container_meta meta; - handle_container_metadata(*container.rbegin(), meta); - - // tell the emitter we're beginning a new container - uint32_t position = _emitter->start_container(index_in_parent, name_override.empty() ? meta.name : name_override); - // Write command out at this position - if(meta.cmd_flags != CommandFlag::NO_FLAGS) { - _emitter->write(Command::START_CONTAINER_MARKER, meta.indexToReturn, meta.cmd_flags); - } - if(meta.recordInContainerMap) { - _emitter->add_start_to_container_map(position, meta.indexToReturn); - } - - // Now, we want to iterate children of this container, save the last - // The last is the settings object handled above - int index = -1; - auto end = container.end() - 1; - for (auto iter = container.begin(); iter != end; ++iter) - { - // Increment index - index++; - - // Arrays are child containers. Recurse. - if (iter->is_array()) - compile_container(*iter, index); - - // Strings are either commands, nops, or raw strings - else if (iter->is_string()) - { - // Get the string - std::string string = iter->get(); - - if (string[0] == '^') - _emitter->write_string(Command::STR, CommandFlag::NO_FLAGS, string); - else if (string == "nop") - _emitter->handle_nop(index); - else - compile_command(string); - } +void json_compiler::compile_container( + const nlohmann::json& container, int index_in_parent, const std::string& name_override +) +{ + // Grab metadata from the last object in this container + container_meta meta; + handle_container_metadata(*container.rbegin(), meta); + + // tell the emitter we're beginning a new container + uint32_t position = _emitter->start_container( + index_in_parent, name_override.empty() ? meta.name : name_override + ); + // Write command out at this position + if (meta.cmd_flags != CommandFlag::NO_FLAGS) { + _emitter->write(Command::START_CONTAINER_MARKER, meta.indexToReturn, meta.cmd_flags); + } + if (meta.recordInContainerMap) { + _emitter->add_start_to_container_map(position, meta.indexToReturn); + } - // Numbers (floats and integers) - else if (iter->is_number()) - { - if (iter->is_number_float()) - { - float value = iter->get(); - _emitter->write(Command::FLOAT, value); - } - else - { - int value = iter->get(); - _emitter->write(Command::INT, value); - } - } + // Now, we want to iterate children of this container, save the last + // The last is the settings object handled above + int index = -1; + auto end = container.end() - 1; + for (auto iter = container.begin(); iter != end; ++iter) { + // Increment index + index++; + + // Arrays are child containers. Recurse. + if (iter->is_array()) + compile_container(*iter, index); + + // Strings are either commands, nops, or raw strings + else if (iter->is_string()) { + // Get the string + std::string string = iter->get(); + + if (string[0] == '^') + _emitter->write_string(Command::STR, CommandFlag::NO_FLAGS, string); + else if (string == "nop") + _emitter->handle_nop(index); + else + compile_command(string); + } - // Booleans - else if (iter->is_boolean()) - { - int value = iter->get() ? 1 : 0; - _emitter->write(Command::BOOL, value); + // Numbers (floats and integers) + else if (iter->is_number()) { + if (iter->is_number_float()) { + float value = iter->get(); + _emitter->write(Command::FLOAT, value); + } else { + int value = iter->get(); + _emitter->write(Command::INT, value); } + } - // Complex commands - else if (iter->is_object()) - { - compile_complex_command(*iter); - } + // Booleans + else if (iter->is_boolean()) { + int value = iter->get() ? 1 : 0; + _emitter->write(Command::BOOL, value); + } - else { - throw ink_exception("Failed to container member!"); - } + // Complex commands + else if (iter->is_object()) { + compile_complex_command(*iter); } - if (meta.deferred.size() > 0) - { - std::vector divert_positions; + else { + throw ink_exception("Failed to container member!"); + } + } - // Write empty divert to be patched later - uint32_t divert_position = _emitter->fallthrough_divert(); - divert_positions.push_back(divert_position); + if (meta.deferred.size() > 0) { + std::vector divert_positions; - // (2) Write deffered containers - for (auto& t : meta.deferred) - { - using std::get; + // Write empty divert to be patched later + uint32_t divert_position = _emitter->fallthrough_divert(); + divert_positions.push_back(divert_position); - // Add to named child list - compile_container(get<0>(t), -1, get<1>(t)); + // (2) Write deffered containers + for (auto& t : meta.deferred) { + using std::get; - // Need a divert here - uint32_t pos = _emitter->fallthrough_divert(); - divert_positions.push_back(pos); - } + // Add to named child list + compile_container(get<0>(t), -1, get<1>(t)); - // (3) Set divert positions - for (size_t offset : divert_positions) - _emitter->patch_fallthroughs(offset); + // Need a divert here + uint32_t pos = _emitter->fallthrough_divert(); + divert_positions.push_back(pos); } - // End container - uint32_t end_position = _emitter->end_container(); + // (3) Set divert positions + for (size_t offset : divert_positions) + _emitter->patch_fallthroughs(offset); + } - // Write end container marker, End pointer should point to End command (form symetry with START command) - if (meta.indexToReturn != ~0) - _emitter->write(Command::END_CONTAINER_MARKER, meta.indexToReturn, meta.cmd_flags); + // End container + uint32_t end_position = _emitter->end_container(); - // Record end position in map - if (meta.recordInContainerMap) - _emitter->add_end_to_container_map(end_position, meta.indexToReturn); - } + // Write end container marker, End pointer should point to End command (form symetry with START + // command) + if (meta.indexToReturn != ~0) + _emitter->write(Command::END_CONTAINER_MARKER, meta.indexToReturn, meta.cmd_flags); - void json_compiler::compile_command(const std::string& command) - { - // Find command - for (int i = 0; i < (int)Command::NUM_COMMANDS; i++) - { - if (CommandStrings[i] != nullptr && command == CommandStrings[i]) - { - _emitter->write_raw((Command)i, CommandFlag::NO_FLAGS, nullptr, 0); - return; - } + // Record end position in map + if (meta.recordInContainerMap) + _emitter->add_end_to_container_map(end_position, meta.indexToReturn); +} + +void json_compiler::compile_command(const std::string& command) +{ + // Find command + for (int i = 0; i < ( int ) Command::NUM_COMMANDS; i++) { + if (CommandStrings[i] != nullptr && command == CommandStrings[i]) { + _emitter->write_raw(( Command ) i, CommandFlag::NO_FLAGS, nullptr, 0); + return; } + } + + // Missing command warning + err() << "Unknown command '" << command << "'. Skipping." << std::flush; +} - // Missing command warning - err() << "Unknown command '" << command << "'. Skipping." << std::flush; +void json_compiler::compile_complex_command(const nlohmann::json& command) +{ + std::string val; + + // Divert + if (get(command, "->", val)) { + // Check if this is a conditional divert + bool isConditional = false; + CommandFlag flag = CommandFlag::NO_FLAGS; + if (get(command, "c", isConditional) && isConditional) + flag = CommandFlag::DIVERT_HAS_CONDITION; + + // Switch on whether this is a variable divert or a path divert + bool isVariableDivert = false; + if (get(command, "var", isVariableDivert) && isVariableDivert) + _emitter->write_variable(Command::DIVERT_TO_VARIABLE, flag, val); + else + _emitter->write_path(Command::DIVERT, flag, val); } - void json_compiler::compile_complex_command(const nlohmann::json& command) - { - std::string val; - - // Divert - if (get(command, "->", val)) - { - // Check if this is a conditional divert - bool isConditional = false; - CommandFlag flag = CommandFlag::NO_FLAGS; - if (get(command, "c", isConditional) && isConditional) - flag = CommandFlag::DIVERT_HAS_CONDITION; - - // Switch on whether this is a variable divert or a path divert - bool isVariableDivert = false; - if (get(command, "var", isVariableDivert) && isVariableDivert) - _emitter->write_variable(Command::DIVERT_TO_VARIABLE, flag, val); - else - _emitter->write_path(Command::DIVERT, flag, val); - } + // Divert to a value + else if (get(command, "^->", val)) { + // Write path in a divert_val command + _emitter->write_path(Command::DIVERT_VAL, CommandFlag::NO_FLAGS, val); + } - // Divert to a value - else if (get(command, "^->", val)) - { - // Write path in a divert_val command - _emitter->write_path(Command::DIVERT_VAL, CommandFlag::NO_FLAGS, val); + // Tunnel + else if (get(command, "->t->", val)) { + bool is_var; + if (get(command, "var", is_var) && is_var) { + _emitter->write_variable(Command::TUNNEL, CommandFlag::TUNNEL_TO_VARIABLE, val); + } else { + _emitter->write_path(Command::TUNNEL, CommandFlag::NO_FLAGS, val); } + } - // Tunnel - else if (get(command, "->t->", val)) - { - bool is_var; - if(get(command, "var", is_var) && is_var) { - _emitter->write_variable(Command::TUNNEL, - CommandFlag::TUNNEL_TO_VARIABLE, - val); - } else { - _emitter->write_path(Command::TUNNEL, CommandFlag::NO_FLAGS, val); - } - } + // Declare temporary variable + else if (get(command, "temp=", val)) { + bool is_redef = false; + get(command, "re", is_redef); + _emitter->write_variable( + Command::DEFINE_TEMP, + is_redef ? CommandFlag::ASSIGNMENT_IS_REDEFINE : CommandFlag::NO_FLAGS, val + ); + } - // Declare temporary variable - else if (get(command, "temp=", val)) - { - bool is_redef = false; - get(command, "re", is_redef); - _emitter->write_variable(Command::DEFINE_TEMP, - is_redef ? CommandFlag::ASSIGNMENT_IS_REDEFINE : CommandFlag::NO_FLAGS, - val); - } + // Set variable + else if (get(command, "VAR=", val)) { + // check if it's a redefinition + bool is_redef = false; + get(command, "re", is_redef); // Set variable - else if (get(command, "VAR=", val)) - { - // check if it's a redefinition - bool is_redef = false; - get(command, "re", is_redef); - - // Set variable - _emitter->write_variable(Command::SET_VARIABLE, - is_redef ? CommandFlag::ASSIGNMENT_IS_REDEFINE : CommandFlag::NO_FLAGS, - val); - } + _emitter->write_variable( + Command::SET_VARIABLE, + is_redef ? CommandFlag::ASSIGNMENT_IS_REDEFINE : CommandFlag::NO_FLAGS, val + ); + } - // create pointer value - else if (get(command, "^var", val)) { - int ci; - if(!get(command, "ci", ci)) { throw ink_exception("failed to parse ci for pointer!");} - inkAssert(ci < 255, "only support until 255 stack hight for refernces"); - _emitter->write_variable(Command::VALUE_POINTER, static_cast(ci+1), val); + // create pointer value + else if (get(command, "^var", val)) { + int ci; + if (! get(command, "ci", ci)) { + throw ink_exception("failed to parse ci for pointer!"); } + inkAssert(ci < 255, "only support until 255 stack hight for refernces"); + _emitter->write_variable(Command::VALUE_POINTER, static_cast(ci + 1), val); + } - // Push variable - else if (get(command, "VAR?", val)) - { - _emitter->write_variable(Command::PUSH_VARIABLE_VALUE, CommandFlag::NO_FLAGS, val); - } + // Push variable + else if (get(command, "VAR?", val)) { + _emitter->write_variable(Command::PUSH_VARIABLE_VALUE, CommandFlag::NO_FLAGS, val); + } - // Choice - else if (get(command, "*", val)) - { - // Get flags - int flags = 0; - get(command, "flg", flags); + // Choice + else if (get(command, "*", val)) { + // Get flags + int flags = 0; + get(command, "flg", flags); - // Write choice path - _emitter->write_path(Command::CHOICE, (CommandFlag)flags, val); - } + // Write choice path + _emitter->write_path(Command::CHOICE, ( CommandFlag ) flags, val); + } - // Read count - else if (get(command, "CNT?", val)) - { - // TODO: Why is this true again? - _emitter->write_path(Command::READ_COUNT, CommandFlag::NO_FLAGS, val, true); - } + // Read count + else if (get(command, "CNT?", val)) { + // TODO: Why is this true again? + _emitter->write_path(Command::READ_COUNT, CommandFlag::NO_FLAGS, val, true); + } - // Internal function call - else if (get(command, "f()", val)) - { - bool is_var; // function address is stored in jump - if(get(command, "var", is_var) && is_var) { - _emitter->write_variable(Command::FUNCTION, - CommandFlag::FUNCTION_TO_VARIABLE, - val); - } else { - _emitter->write_path(Command::FUNCTION, CommandFlag::NO_FLAGS, val); - } + // Internal function call + else if (get(command, "f()", val)) { + bool is_var; // function address is stored in jump + if (get(command, "var", is_var) && is_var) { + _emitter->write_variable(Command::FUNCTION, CommandFlag::FUNCTION_TO_VARIABLE, val); + } else { + _emitter->write_path(Command::FUNCTION, CommandFlag::NO_FLAGS, val); } - - // External function call - else if (get(command, "x()", val)) - { - // Get argument count - int numArgs = 0; - get(command, "exArgs", numArgs); - - // Encode argument count into command flag and write out the hash of the function name - _emitter->write(Command::CALL_EXTERNAL, hash_string(val.c_str()), - static_cast(numArgs)); - _emitter->write_path(Command::FUNCTION, CommandFlag::FALLBACK_FUNCTION, val); } - // list initialisation - else if (has(command, "list")) - { - std::vector entries; - auto& list = command["list"]; - - if(list.size()) { - for ( const auto& [key,value] : list.items()) { - entries.push_back({ - _list_meta.get_lid(key.substr(0,key.find('.'))), - static_cast(value.get() - 1) - }); + // External function call + else if (get(command, "x()", val)) { + // Get argument count + int numArgs = 0; + get(command, "exArgs", numArgs); + + // Encode argument count into command flag and write out the hash of the function name + _emitter->write( + Command::CALL_EXTERNAL, hash_string(val.c_str()), static_cast(numArgs) + ); + _emitter->write_path(Command::FUNCTION, CommandFlag::FALLBACK_FUNCTION, val); + } + // list initialisation + else if (has(command, "list")) { + std::vector entries; + auto& list = command["list"]; + + if (list.size()) { + for (const auto& [key, value] : list.items()) { + entries.push_back( + {_list_meta.get_lid(key.substr(0, key.find('.'))), + static_cast(value.get())} + ); + } + } else { + if (has(command, "origins")) { + for (const auto& origin_list : command["origins"]) { + // list id < -1 -> origin flag + entries.push_back( + {static_cast(-2 - _list_meta.get_lid(origin_list.get())), -1} + ); } } else { - if(has(command, "origins")) { - for( const auto& origin_list : command["origins"]) { - entries.push_back({ _list_meta.get_lid(origin_list.get()), -1 }); - } - } else { - entries.push_back(empty_flag); - } + entries.push_back(empty_flag); } - - _emitter->write_list(Command::LIST, CommandFlag::NO_FLAGS, entries); } - else if (get(command, "#", val)) - { - if (_ink_version > 20) { - ink_exception("with inkVerison 21 the tag system chages, and the '#: ' is deprecated now"); - } - _emitter->write_string(Command::TAG, CommandFlag::NO_FLAGS, val); - } + _emitter->write_list(Command::LIST, CommandFlag::NO_FLAGS, entries); + } - else { - throw ink_exception("failed to parse complex command!"); + else if (get(command, "#", val)) { + if (_ink_version > 20) { + ink_exception("with inkVerison 21 the tag system chages, and the '#: ' is deprecated now" + ); } + _emitter->write_string(Command::TAG, CommandFlag::NO_FLAGS, val); } - void json_compiler::compile_lists_definition(const nlohmann::json& list_defs) - { - for(auto& [list_name, flags] : list_defs.items()) { - _list_meta.new_list(list_name); - for(auto& [flag_name, value] : flags.items()) { - _list_meta.new_flag(flag_name, value.get()); - } + else { + throw ink_exception("failed to parse complex command!"); + } +} + +void json_compiler::compile_lists_definition(const nlohmann::json& list_defs) +{ + for (auto& [list_name, flags] : list_defs.items()) { + _list_meta.new_list(list_name); + for (auto& [flag_name, value] : flags.items()) { + _list_meta.new_flag(flag_name, value.get()); } } + _list_meta.sort(); } +} // namespace ink::compiler::internal diff --git a/inkcpp_compiler/list_data.cpp b/inkcpp_compiler/list_data.cpp index 859f6fdc..4062f4af 100644 --- a/inkcpp_compiler/list_data.cpp +++ b/inkcpp_compiler/list_data.cpp @@ -7,44 +7,41 @@ #include "list_data.h" #include +#include namespace ink::compiler::internal { - void list_data::new_list(const std::string& list_name) - { - _lists.insert({list_name, static_cast(_list_end.size())}); - _list_name.emplace_back(list_name); - int current_back = _list_end.empty() ? 0 : _list_end.back(); - _current_list_start = current_back; - _list_end.push_back(current_back); - } +void list_data::new_list(const std::string& list_name) +{ + _lists.insert({list_name, static_cast(_list_end.size())}); + _list_name.emplace_back(list_name); + int current_back = _list_end.empty() ? 0 : _list_end.back(); + _list_end.push_back(current_back); +} - void list_data::new_flag(const std::string& flag_name, size_t value) - { - while(_flag_names.size() < _current_list_start + value) { - _flag_names.push_back(""); - } - if(_current_list_start + value > _list_end.back()) { - _list_end.back() = _current_list_start + value; - } - _flag_names[_current_list_start + value - 1] = flag_name; - } +void list_data::new_flag(const std::string& flag_name, int value) +{ + inkAssert( + value <= std::numeric_limits::max() + && value >= std::numeric_limits::min(), + "Value outside of current supported scope" + ); + _list_end.back() += 1; + _flags.emplace_back( + &flag_name, + list_flag{ + .list_id = static_cast(_list_name.size() - 1), + .flag = static_cast(value)} + ); +} - std::vector list_data::get_flags() const { - std::vector result{}; - size_t begin = 0; - for(size_t i = 0; i < _list_end.size(); ++i) { - for(size_t j = begin; j < _list_end[i]; ++j) { - if (_flag_names[j] != "") { - result.push_back({ - _flag_names[j], - { static_cast(i), - static_cast(j - begin)} - }); - } - } - begin = _list_end[i]; - } - return result; +void list_data::sort() +{ + size_t begin = 0; + for (size_t i = 0; i < _list_end.size(); ++i) { + std::sort(_flags.begin() + begin, _flags.begin() + _list_end[i]); + begin = _list_end[i]; } } + +} // namespace ink::compiler::internal diff --git a/inkcpp_compiler/list_data.h b/inkcpp_compiler/list_data.h index 7faaf95b..0df93c53 100644 --- a/inkcpp_compiler/list_data.h +++ b/inkcpp_compiler/list_data.h @@ -15,37 +15,56 @@ namespace ink::compiler::internal { - class list_data { - using flag_t = decltype(list_flag::flag); - using lid_t = decltype(list_flag::list_id); +class list_data +{ + using flag_t = decltype(list_flag::flag); + using lid_t = decltype(list_flag::list_id); + +public: + // add new list and set it to current + void new_list(const std::string& list_name); - public: + // add flag to current list + void new_flag(const std::string& flag_name, int value); - // add new list and set it to current - void new_list(const std::string& list_name); + // sort flags per list + void sort(); - // add flag to current list - void new_flag(const std::string& flag_name, size_t value); + lid_t get_lid(const std::string_view& list_name) + { + auto itr = _lists.find(list_name); + return static_cast(itr->second); + } - lid_t get_lid(const std::string_view& list_name) { - auto itr = _lists.find(list_name); - return static_cast(itr->second); + bool empty() const { return _lists.empty(); } + + struct named_list_flag { + named_list_flag(const std::string* name, list_flag flag) + : name{name} + , flag{flag} + { } - bool empty() const { return _lists.empty(); } - struct named_list_flag { - const std::string& name; - list_flag flag; - }; - std::vector get_flags() const; - const std::vector& get_list_names() const { - return _list_name; + const std::string* name; + list_flag flag; + + bool operator<(const named_list_flag& oth) const + { + inkAssert( + flag.list_id == oth.flag.list_id, "Compare flags from different lists is not supported" + ); + return flag.flag < oth.flag.flag; } - private: - std::map> _lists; - std::vector _list_end; - std::vector _list_name; - size_t _current_list_start = 0; - std::vector _flag_names; }; -} + + const std::vector& get_flags() const { return _flags; } + + const std::vector& get_list_names() const { return _list_name; } + +private: + std::map> _lists; + std::vector _list_name; + std::vector _list_end; + std::vector _flags; +}; +} // namespace ink::compiler::internal diff --git a/inkcpp_test/Lists.cpp b/inkcpp_test/Lists.cpp index 0e24e316..51be2d8a 100644 --- a/inkcpp_test/Lists.cpp +++ b/inkcpp_test/Lists.cpp @@ -10,6 +10,41 @@ using namespace ink::runtime; +SCENARIO("List logic operations", "[lists]") +{ + GIVEN("a demo story") + { + auto ink = story::from_file(INK_TEST_RESOURCE_DIR "ListLogicStory.bin"); + runner thread = ink->new_runner(); + WHEN("just run") + { + std::string out = thread->getall(); + + REQUIRE(out == R"==(A, C +yes +false +true +true +true +true +A +B +>B +> +> Z, A, B, C +> +> +B, C +>C > > > +>A, C >B > +>B +> +> >Z >A > +Hey +)=="); + } + } +} SCENARIO("run a story with lists", "[lists]") { GIVEN("a story with multi lists") diff --git a/inkcpp_test/ink/ListLogicStory.ink b/inkcpp_test/ink/ListLogicStory.ink new file mode 100644 index 00000000..90922816 --- /dev/null +++ b/inkcpp_test/ink/ListLogicStory.ink @@ -0,0 +1,40 @@ +LIST list = (A=2),B,(C=5),Z=-1 +{list} +{list: yes} +{not list} +{list and true} +{not list or true} +{true or not list} +{true and list} +VAR x = A +~ x += B +// expect list "A, B" +// expect list "A" +~ x -= 1 +{x} +// expect list "B", since A got moved out +~ x += 1 +{x} +VAR y = A +~ y = list(3) +>{y} +~ y = list(4) +// list with no named element +>{y} {y+1} +> {LIST_ALL(y)} +// list element out of range +~ y = list(1) +>{y} {y+1} +~ y = list(6) +>{y} {y-1} +{LIST_RANGE(LIST_ALL(y), 3, 5)} +~ y = list(5) +>{y} >{y+1} >{(y+1)-1} >{(y-1)+1} +>{list} >{list+1} >{(list+1)+1} +~list += 1 +>{list} +~list += 1 +>{list} +~list += 1 +>{list} >{list(-1)} >{list(-1) + 3} >{list(-1)+2+1} +Hey diff --git a/unreal/inkcpp/Source/inkcpp/Public/InkRuntime.h b/unreal/inkcpp/Source/inkcpp/Public/InkRuntime.h index 845f2b64..65b98c6e 100644 --- a/unreal/inkcpp/Source/inkcpp/Public/InkRuntime.h +++ b/unreal/inkcpp/Source/inkcpp/Public/InkRuntime.h @@ -136,7 +136,7 @@ class INKCPP_API AInkRuntime : public AActor UFUNCTION(BlueprintCallable, Category="Ink") /** On variable change provides old and new value. - * @see #ObserverVariable() #ObserverVariable() + * @see #ObserverVariableEvent() #ObserverVariable() * @attention if the varibale set for the firs time, the old value has value type @ref * EInkVarType::None * diff --git a/unreal/inkcpp/Source/inkcpp/Public/inkcpp.h b/unreal/inkcpp/Source/inkcpp/Public/inkcpp.h index ebe3e2ae..467fa66d 100644 --- a/unreal/inkcpp/Source/inkcpp/Public/inkcpp.h +++ b/unreal/inkcpp/Source/inkcpp/Public/inkcpp.h @@ -10,12 +10,12 @@ /** * @defgroup unreal Unreal Blueprints * Blueprint Classes usable in Unreal. An example can be found - * [here](unreal/InkCPP_DEMO.zip), do not forgett to install the plugin via the marketplace(soonTM) - * or unzipping the `unreal.zip` from the [release - * page](https://github.com/JBenda/inkcpp/releases/latest) to `/YOUR_UNREAL_PROJECT/Plugins/`.
- * And eitherway activating the plugin. + * [here](unreal/InkCPP_DEMO.zip), do not forgett to install the plugin via the + * [marketplace](https://www.unrealengine.com/marketplace/product/inkcpp) or unzipping the + * `unreal.zip` from the [release page](https://github.com/JBenda/inkcpp/releases/latest) to + * `/YOUR_UNREAL_PROJECT/Plugins/`.
And eitherway activating the plugin. * - * The C++ API will be available soon(TM). + * The C++ API will be available soon([Issue](https://github.com/JBenda/inkcpp/issues/60)). * * + @ref ue_setup "General setup" * + @ref ue_components "UE5 Blueprits" @@ -30,10 +30,10 @@ * On this instance set the `Ink|InkAsset` property to the story that you will run. * To create this InkAsset you need to import a `.ink` file or `.ink.json` file. * - * With the @ref AInkRuntime you can then create @ref UInkThreads with @ref AInkRuntime::Start(). + * With the @ref AInkRuntime you can then create a @ref UInkThread with @ref AInkRuntime::Start(). * In addition does the runtime allows you access to the global variables via @ref - * AInkRuntime::ObserveChange() "observer" or directly @ref AInkRuntime::Set() "setter" und @ref - * AInkRuntime::Get() "getter". + * AInkRuntime::ObserverVariableChange() "observer" or directly @ref + * AInkRuntime::SetGlobalVariable() "setter" und @ref AInkRuntime::GetGlobalVariable() "getter". * * Notice that all threads spawned in the * same runtime will share a global state. So if you want to play the same story with different @@ -103,7 +103,7 @@ * @subsection ue_example_setup Setup * * To setup the [example project](../unreal/InkCPP_DEMO.zip) install the Plugin via the [UE - * marketplace](https://www.unrealengine.com/product/494904fc50f747db879c297ee57cf122) place unpack + * marketplace](https://www.unrealengine.com/product/inkcpp) place unpack * the `unreal.zip` from the [release page](https://github.com/JBenda/inkcpp/releases/latest) inside * `/PATH/InkCPP_DEMO/Plugins/`. * @@ -130,7 +130,8 @@ * All UI elements and other used components are created on the `BeginPlay` event in the following * order. * 1. The UI components are created and configured - * 2. Load an existing save game if its exists. + * 2. Load an existing save game if its exists (the Save game is stored at + * `InkCPP_DEMO/Saved/SaveGames`). * 3. Create the main thread of class `DemoThread` and register the external function. * 4. Create menu thread(`InfoThread`), set path to `Wait` to avoid any output in the beginging. * 5. Set observer for the variable `Heath` to update the healthbar. diff --git a/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.cpp b/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.cpp index e99c257a..19b657de 100644 --- a/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.cpp +++ b/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.cpp @@ -10,6 +10,7 @@ #include "Misc/FileHelper.h" #include "Misc/Paths.h" #include "Interfaces/IPluginManager.h" +#include "Internationalization/Regex.h" #include "InkAsset.h" #include "ink/compiler.h" @@ -18,6 +19,8 @@ #include #include #include +#include +#include #include UInkAssetFactory::UInkAssetFactory(const FObjectInitializer& ObjectInitializer) @@ -34,7 +37,47 @@ UInkAssetFactory::UInkAssetFactory(const FObjectInitializer& ObjectInitializer) // Fuck data tables TODO - some criteria? ImportPriority = 99999; - + FReimportManager::Instance()->RegisterHandler(*this); +} + +UInkAssetFactory::~UInkAssetFactory() { FReimportManager::Instance()->UnregisterHandler(*this); } + +/// @todo only finds first include match? +void TraversImports( + UAssetImportData& AssetImportData, std::unordered_set& visited, + std::filesystem::path filepath +) +{ + UE_LOG( + InkCpp, Display, TEXT("InkAsset Import: Traverse '%s'"), *FString(filepath.string().c_str()) + ); + if (visited.find(filepath) != visited.end()) { + return; + } + int id = visited.size(); + visited.insert(filepath); + AssetImportData.AddFileName( + FString(filepath.string().c_str()), id, id == 0 ? TEXT("MainFile") : TEXT("Include") + ); + + std::ifstream file(filepath); + if (! file) { + UE_LOG( + InkCpp, Warning, TEXT("Failed to open story file: %s"), *FString(filepath.string().c_str()) + ); + return; + } + std::stringstream file_data; + file_data << file.rdbuf(); + FRegexMatcher matcher( + FRegexPattern(FString("(^|\n)[ \t]*INCLUDE[ \t]+(.*)"), ERegexPatternFlags{0}), + FString(file_data.str().c_str()) + ); + while (matcher.FindNext()) { + std::filesystem::path match_file_path = filepath; + match_file_path.replace_filename(TCHAR_TO_ANSI(*matcher.GetCaptureGroup(2))); + TraversImports(AssetImportData, visited, match_file_path); + } } UObject* UInkAssetFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, FFeedbackContext* Warn, bool& bOutOperationCanceled) @@ -45,7 +88,10 @@ UObject* UInkAssetFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, static const std::string ink_suffix{".ink"}; try { + using path = std::filesystem::path; std::string cFilename = TCHAR_TO_ANSI(*Filename); + path story_path(cFilename, path::format::generic_format); + story_path.make_preferred(); bool use_temp_file = false; if (cFilename.size() > ink_suffix.size() && std::equal(ink_suffix.rbegin(), ink_suffix.rend(), cFilename.rbegin())) @@ -55,12 +101,9 @@ UObject* UInkAssetFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, UE_LOG(InkCpp, Warning, TEXT("Inklecate provided with the plugin, please import ink.json files")); return nullptr; } - using path = std::filesystem::path; path path_bin(TCHAR_TO_ANSI(*IPluginManager::Get().FindPlugin(TEXT("InkCPP"))->GetBaseDir()), path::format::generic_format); path_bin.make_preferred(); path_bin /= path(inklecate_cmd, path::format::generic_format).make_preferred(); - path story_path(cFilename, path::format::generic_format); - story_path.make_preferred(); const char* filename = std::tmpnam(nullptr); if(filename == nullptr) { UE_LOG(InkCpp, Error, TEXT("Failed to create temporary file")); @@ -96,7 +139,8 @@ UObject* UInkAssetFactory::FactoryCreateFile(UClass* InClass, UObject* InParent, FMemory::Memcpy(asset->CompiledStory.GetData(), data.c_str(), data.length()); // Paths - asset->AssetImportData->Update(CurrentFilename); + std::unordered_set visited{}; + TraversImports(*asset->AssetImportData, visited, story_path); // Not cancelled bOutOperationCanceled = false; @@ -124,18 +168,19 @@ bool UInkAssetFactory::CanReimport(UObject* Obj, TArray& OutFilenames) UInkAsset* InkAsset = Cast(Obj); if (InkAsset != nullptr && InkAsset->AssetImportData) { + UE_LOG(InkCpp, Warning, TEXT("Can Reimport")); InkAsset->AssetImportData->ExtractFilenames(OutFilenames); return true; } - + UE_LOG(InkCpp, Warning, TEXT("Failed to reimport")); return false; } void UInkAssetFactory::SetReimportPaths(UObject* Obj, const TArray& NewReimportPaths) { + UE_LOG(InkCpp, Warning, TEXT("SetReimportPaths")); UInkAsset* InkAsset = Cast(Obj); - if (InkAsset && ensure(NewReimportPaths.Num() == 1)) - { + if (InkAsset != nullptr && NewReimportPaths.Num() > 0) { InkAsset->AssetImportData->UpdateFilenameOnly(NewReimportPaths[0]); } } @@ -150,8 +195,9 @@ TObjectPtr* UInkAssetFactory::GetFactoryObject() const return const_cast*>(&object_ptr); } -EReimportResult::Type UInkAssetFactory::Reimport(UObject* Obj) +EReimportResult::Type UInkAssetFactory::Reimport(UObject* Obj, int SourceID) { + UE_LOG(InkCpp, Warning, TEXT("Reimport started")); UInkAsset* InkAsset = Cast(Obj); if (!InkAsset) return EReimportResult::Failed; @@ -168,6 +214,7 @@ EReimportResult::Type UInkAssetFactory::Reimport(UObject* Obj) if (ImportObject(InkAsset->GetClass(), InkAsset->GetOuter(), *InkAsset->GetName(), RF_Public | RF_Standalone, Filename, nullptr, OutCanceled) != nullptr) { + /// TODO: add aditional pathes InkAsset->AssetImportData->Update(Filename); // Try to find the outer package so we can dirty it up diff --git a/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.h b/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.h index d3e85b05..6b143b6c 100644 --- a/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.h +++ b/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.h @@ -19,6 +19,7 @@ class UInkAssetFactory : public UFactory, public FReimportHandler public: UInkAssetFactory(const FObjectInitializer& ObjectInitializer); + ~UInkAssetFactory(); // Begin UFactory virtual UObject* FactoryCreateFile(UClass* InClass, UObject* InParent, FName InName, @@ -28,10 +29,13 @@ class UInkAssetFactory : public UFactory, public FReimportHandler // End UFactory // Begin FReimportHandler - bool CanReimport(UObject* Obj, TArray& OutFilenames) override; - TObjectPtr* GetFactoryObject() const override; - EReimportResult::Type Reimport(UObject* Obj) override; - void SetReimportPaths(UObject* Obj, const TArray& NewReimportPaths) override; + virtual bool CanReimport(UObject* Obj, TArray& OutFilenames) override; + virtual TObjectPtr* GetFactoryObject() const override; + virtual EReimportResult::Type Reimport(UObject* Obj, int SourceID) override; + + virtual EReimportResult::Type Reimport(UObject* Obj) override { return Reimport(Obj, 0); } + + virtual void SetReimportPaths(UObject* Obj, const TArray& NewReimportPaths) override; virtual int32 GetPriority() const override; // End FReimportHandle private: diff --git a/unreal/inkcpp/inkcpp.uplugin b/unreal/inkcpp/inkcpp.uplugin index ffdc905d..1bc8940c 100644 --- a/unreal/inkcpp/inkcpp.uplugin +++ b/unreal/inkcpp/inkcpp.uplugin @@ -9,7 +9,7 @@ "CreatedBy": "Julian Benda", "CreatedByURL": "https://github.com/JBenda/inkcpp/", "DocsURL": "https://jbenda.github.io/inkcpp/html/group__unreal.html#ue_example", - "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/494904fc50f747db879c297ee57cf122", + "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/inkcpp", "SupportURL": "https://github.com/JBenda/inkcpp/issues", "CanContainContent": false, "IsBetaVersion": false, diff --git a/unreal/render.css b/unreal/render.css new file mode 100644 index 00000000..08ed5f7a --- /dev/null +++ b/unreal/render.css @@ -0,0 +1 @@ +.bue-render{-webkit-touch-callout:none;border:0;color:#fff;font-family:Roboto,sans-serif;font-size:13px;line-height:normal;margin:0;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:baseline;width:100%}.bue-render .frame{background-color:#a6a6a6;height:250px;overflow:hidden;position:relative}.bue-render .layer{height:100%;left:0;position:absolute;top:0;width:100%}.bue-render .reference{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACABAMAAAAxEHz4AAAAG1BMVEUVFRUWFhYkJCQlJSUzMzMmJiY0NDQxMTEyMjIQl+acAAAAXklEQVR4AWKAA0HyAAOTkrIxCDiHQkAqifSgMWDUgFEDRg1g7wCCFhcgcEsjB4wGIqCdOhYAAAAAGORvPYw9CXQ2AQCADwAAgA8AAIAPAACADwAAgA8AAIAPfgAAAASSCCi35k/7bwAAAABJRU5ErkJggg==) repeat 32768px 32768px;height:65536px;margin:-32768px 0 0 -32768px;position:absolute;width:65536px}.bue-render .canvas{height:100%;position:absolute;transform-origin:0 0 0;width:100%}.bue-render .multi-select{border:1px solid transparent;border-image-repeat:round;border-image-slice:6;border-image-source:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAAW0lEQVR42u2VQQoAMQgD56e+LS91L7LYQw+rhYViPBkwiAYChqIMUrfjVsZAHkCkbsetDAK5VzfIAhWcErBY6zvqk6d07H3jz0ccgXHiOHGMdJ2RetHWC9dmvD+e8yPwCj5gxgAAAABJRU5ErkJggg==);border-image-width:6px;position:absolute}.bue-render .link{overflow:initial;position:absolute;z-index:4}.bue-render .frame-header{align-items:center;background-color:rgba(0,0,0,.5);display:flex;font-size:18px;height:40px;pointer-events:none;position:absolute;top:0;white-space:nowrap;width:100%}.bue-render .frame-header__buttons{border-right:1px solid #fff;color:#fff;display:flex;padding:0 5px;pointer-events:all}.bue-render .frame-header__buttons-fullscreen{cursor:pointer;padding:0 5px}.bue-render .frame-header__buttons-fullscreen:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAe0lEQVR42t2TwQnAIAxFs53O0Q1cyCk8uo54b7ynET4ltB4suVV4YIj/ozEhEWnKqbAyQFHoQTF5hqaRrFdfGPTXKSQY+6wcIC4MoslnaHgmBoKg0CYBmmGfkD4YJGju4lRz7R0iNGUGLn5g4C6i+xvdjeRuZfcwucf5AiDSUkJYHhoGAAAAAElFTkSuQmCC);padding-right:5px;vertical-align:middle}.bue-render .frame-header__buttons-fullscreen:hover{background-color:#c89307}.bue-render .frame-header__buttons-fullscreen--exit:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAdklEQVR42t2TIQ7AMAhFe/6qKuR8bTU36AnaY+wCjGUIQsiy5LuRPNNPnqBQRMRDyqkMJWbDMvLvsanLUzMRTMv6m6BZEycCtqxFASmHsT8ItuunInmtRLAklhsOB2oiqEnfuAOIHwjgIcLfCC8Susr4McHnfAHzdlKqYXJTxwAAAABJRU5ErkJggg==)}.bue-render .frame-header__buttons-panel{cursor:pointer}.bue-render .frame-header__buttons-panel:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAApklEQVR42oWRMQ6CUBBE5xB02FLwC+5hFFs4ENacAbA0FCTcg4Qea+k4wbMAv58EYbqZnWRnZyULfDomJjpO2gIRX0TrQUCGkcitIZcIuRPMhgoY6XHR8wYekjizh4soHPokIaF2lFKEtAtpbKpmUVqMJDxeAFyt4QbAgDdTjwGA2Bpix4DZXRGK0olUk5KuQhbHZ/4tagSqvaoN2VL14bM23u3/1A9okEUmPlbeSQAAAABJRU5ErkJggg==);padding:0 5px;position:relative;top:2px}.bue-render .frame-header__buttons-panel:hover{background-color:#c89307}.bue-render .frame-header__buttons-reset{cursor:pointer;padding:0 5px}.bue-render .frame-header__buttons-reset:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAjElEQVR42oWQuw2AMAxELVFRsgIrZAPECkyAREWLkgEomIUVMgFDpKajon8UBCF+5tydnu5sizxETYchOY0Vd5kJgBl3AO6W0NJTkJ6GE13vAAsZDcM3UOIJagUBq1VUjGoCyw4JNROtdkMH9BpggEIET7kH34GEmVSEnICNe78/Chu3/izL8X/A+HQ3faBo29cKeDwAAAAASUVORK5CYII=);padding-right:5px;vertical-align:middle}.bue-render .frame-header__buttons-reset:hover{background-color:#c89307}.bue-render .frame-header__buttons-separator{position:relative;width:10px}.bue-render .frame-header__buttons-separator:before{border-left:1px solid #fff;bottom:0;content:"";left:4px;position:absolute;top:0}.bue-render .frame-header__breadcrumb{color:hsla(0,0%,100%,.65);flex-grow:1;overflow:hidden;padding:0 10px 0 5px;text-overflow:ellipsis}.bue-render .frame-header__breadcrumb-item{cursor:pointer;padding:0 5px;pointer-events:auto}.bue-render .frame-header__breadcrumb-item:hover{background-color:#c89307}.bue-render .frame-header__breadcrumb-separator{border:solid #fff;border-width:0 2px 2px 0;display:inline-block;margin-right:8px;padding:6px;transform:rotate(-45deg)}.bue-render .frame-header__current-zoom{color:hsla(0,0%,100%,.25);font-weight:700;padding-right:10px;transition:color 2s ease-out}.bue-render .frame-header__current-zoom.update{color:hsla(0,0%,100%,.65);transition:none}.bue-render .blueprint-type{bottom:16px;color:hsla(0,0%,100%,.15);font-size:55px;font-weight:700;pointer-events:none;position:absolute;right:16px;text-transform:uppercase}.bue-render .panel{background-color:rgba(0,0,0,.5);bottom:0;display:none;max-width:85%;min-width:225px;overflow:auto;position:absolute;resize:horizontal;top:40px;width:225px}.bue-render .panel__button{display:block;padding:5px}.bue-render .panel__infos{background-color:rgba(36,36,36,.75);border:1px solid rgba(0,0,0,.75);display:none;padding:5px}.bue-render .overlay{align-items:center;background-color:rgba(0,0,0,.3);display:flex;font-size:24px;height:100%;justify-content:center;pointer-events:none;position:relative;text-align:center}.bue-render .node-color.event{background-color:red}.bue-render .node-color.event.gradient{background:linear-gradient(90deg,rgba(255,0,0,.4) 0,rgba(255,0,0,.1))}.bue-render .node-color.function-call{background-color:#79c9ff}.bue-render .node-color.function-call.gradient{background:linear-gradient(90deg,rgba(121,201,255,.4) 0,rgba(121,201,255,.1))}.bue-render .node-color.pure-function-call{background-color:#aaeea0}.bue-render .node-color.pure-function-call.gradient{background:linear-gradient(90deg,rgba(170,238,160,.4) 0,rgba(170,238,160,.1))}.bue-render .node-color.parent-function-call{background-color:#ff7200}.bue-render .node-color.parent-function-call.gradient{background:linear-gradient(90deg,rgba(255,114,0,.4) 0,rgba(255,114,0,.1))}.bue-render .node-color.function-terminator{background-color:#c0f}.bue-render .node-color.function-terminator.gradient{background:linear-gradient(90deg,rgba(204,0,255,.4) 0,rgba(204,0,255,.1))}.bue-render .node-color.exec-branch{background-color:#fff}.bue-render .node-color.exec-branch.gradient{background:linear-gradient(90deg,hsla(0,0%,100%,.4) 0,hsla(0,0%,100%,.1))}.bue-render .node-color.exec-sequence{background-color:#e8aaaa}.bue-render .node-color.exec-sequence.gradient{background:linear-gradient(90deg,hsla(0,57%,79%,.4) 0,hsla(0,57%,79%,.1))}.bue-render .node-color.result{background-color:#ffd3aa}.bue-render .node-color.result.gradient{background:linear-gradient(90deg,rgba(255,211,170,.4) 0,rgba(255,211,170,.1))}.bue-render .node-color.default-comment{background-color:#fff}.bue-render .node-color.default-comment.gradient{background:linear-gradient(90deg,hsla(0,0%,100%,.4) 0,hsla(0,0%,100%,.1))}.bue-render .node-color.macro{background-color:#fff}.bue-render .node-color.macro.gradient{background:linear-gradient(90deg,hsla(0,0%,100%,.4) 0,hsla(0,0%,100%,.1))}.bue-render .node-color.material-graph-root{background-color:#ffdab4}.bue-render .node-color.material-graph-root.gradient{background:linear-gradient(90deg,rgba(255,218,180,.4) 0,rgba(255,218,180,.1))}.bue-render .node-color.material-constant{background-color:#907623}.bue-render .node-color.material-constant.gradient{background:linear-gradient(90deg,rgba(144,118,35,.4) 0,rgba(144,118,35,.1))}.bue-render .node-color.cast{background-color:#137479}.bue-render .node-color.cast.gradient{background:linear-gradient(90deg,rgba(19,116,121,.4) 0,rgba(19,116,121,.1))}.bue-render .node-color.switch{background-color:#ff0}.bue-render .node-color.switch.gradient{background:linear-gradient(90deg,rgba(255,255,0,.4) 0,rgba(255,255,0,.1))}.bue-render .node-color.timeline{background-color:#ffb100}.bue-render .node-color.timeline.gradient{background:linear-gradient(90deg,rgba(255,177,0,.4) 0,rgba(255,177,0,.1))}.bue-render .node-color.break-struct{background-color:#0059cc}.bue-render .node-color.break-struct.gradient{background:linear-gradient(90deg,rgba(0,89,204,.4) 0,rgba(0,89,204,.1))}.bue-render .node-color.pcg-execute-bp{background-color:#0059cc}.bue-render .node-color.pcg-execute-bp.gradient{background:linear-gradient(90deg,rgba(0,89,204,.4) 0,rgba(0,89,204,.1))}.bue-render .node-color.pcg-density{background-color:#79c9ff}.bue-render .node-color.pcg-density.gradient{background:linear-gradient(90deg,rgba(121,201,255,.4) 0,rgba(121,201,255,.1))}.bue-render .node-color.pcg-input{background-color:red}.bue-render .node-color.pcg-input.gradient{background:linear-gradient(90deg,rgba(255,0,0,.4) 0,rgba(255,0,0,.1))}.bue-render .node-color.pcg-attribute{background-color:#fff}.bue-render .node-color.pcg-attribute.gradient{background:linear-gradient(90deg,hsla(0,0%,100%,.4) 0,hsla(0,0%,100%,.1))}.bue-render .node-color.pcg-default{background-color:#000}.bue-render .node-color.pcg-default.gradient{background:linear-gradient(90deg,rgba(0,0,0,.4) 0,rgba(0,0,0,.1))}.bue-render .node-color.pcg-spatial{background-color:#c0f}.bue-render .node-color.pcg-spatial.gradient{background:linear-gradient(90deg,rgba(204,0,255,.6) 0,rgba(204,0,255,.1))}.bue-render .node-color.pcg-spawn{background-color:#197667}.bue-render .node-color.pcg-spawn.gradient{background:linear-gradient(90deg,#197667 0,rgba(25,118,103,.1))}.bue-render .node-color.pcg-params{background-color:#ff7200}.bue-render .node-color.pcg-params.gradient{background:linear-gradient(90deg,rgba(255,114,0,.4) 0,rgba(255,114,0,.1))}.bue-render .node-color.pcg-filter{background-color:#3e2d61}.bue-render .node-color.pcg-filter.gradient{background:linear-gradient(90deg,#3e2d61 0,rgba(62,45,97,.1))}.bue-render .node{background-color:hsla(0,0%,6%,.7);border:1px solid #000;border-radius:5px;box-shadow:0 5px 5px 1px rgba(0,0,0,.3);color:#fff;cursor:move;display:inline-block;font-family:Roboto,sans-serif;font-size:13px;font-weight:500;white-space:nowrap;z-index:5}.bue-render .node.rounded{border-radius:15px}.bue-render .node .header{border-radius:5px 5px 0 0;line-height:22px;padding:1px 1px 1px 10px}.bue-render .node .header .name{margin-right:20px}.bue-render .node .header .name .subname{color:#889478;font-style:italic;font-weight:300}.bue-render .node .header .icon{display:inline-block;height:16px;position:absolute;top:3px;width:16px}.bue-render .node .header .icon.function-call:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxElEQVR4AZ3MJVREQQCFYayfg1uikqh4xN3JZDKW0Yb3jPeINtzdHdZ9Z2+46zbzwvd07p8ghJA2uCfG4BuewADvKuNxELDF9wM4kR1ng5OBIn6rgxLZwAjHxtB/8YZZUA3HDNxCgUqgFy7AxYABNqQDjKSAg4EOflcK1HHshDQtgRkGPvlNObDHwI7WwBcDU8oBjDLAyUCllkAzxxZIiRngoA/6A94XGVjmt7iBXzBDPhSCHfSQJhu4BAdH33AM+RHH5AG/KfjGRY2Y0QAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.pure-function-call:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAxUlEQVR4AZ3MJVREQQCFYayfg1uikqh4xN3JZHogow2PVFx6RBvu7g7rvrM33HWbeeF7OvdPEEJIW/idG4JveAIDvKuMh0HAFt8P4ER2nA1OBor4rQ5KZAMDHBtD/8UbZkE1HDNwCwUqgV64ABcDBtiQDjCSAg4GOvhdKVDHsRPStAQmGPjkN+XAHgM7WgNfDIwpBzDKACcDlVoCzRxbICVmgIM+6A94n2Vgmd/iBn7BDPlQCHbQQ5ps4BIcHH3DMeRHHJMHtdT2LANcbFsAAAAASUVORK5CYII=)}.bue-render .node .header .icon.break-struct:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACMklEQVR4AZWTA5BcSxSG583atm3btm3b9r7Ytm1bxdi2k1tr2zo5szb+qu+y+2uTAGBebNu2je/Lly+WP378WFJaWnpz3bp14pTv8xZYWVnr//79uxqGc/v2bbEFCRQVFbk+fvz4a7h+b1NTk9C8BRGhAczfv39/AJh9+/atOHXq1OkrV66IzFtw8MRtck1N1Z2nTx7tpbwLCgr+9////9NMEBi75qbbJ1z6ZRN3gbCOOUtYRp8hzEIOlJqHHim1jDxZ6ph844mB6/9yE+XDAkk1Dx/H3BeQcrwa0k7VQurpGkjG54SjlRCzvwwi95SA58qvYBpxpnpagWX4iWtOBR8h7kAFxB+qhNiD5RBNqbi3BMJ2ERC8/Q94bvgKFrlPYVoBn4RRnE7gFTBNfgFmqeNIfwHmmS/BPOslWC95A5YpV+ppaBmkSCSSIaI8YQ4k1Zw2yZjmdsqaL+6VN/+/U9lmRZ2y7YpaFdvlNco2y6pUbP7/wMYrk4UVs5EcxGeCQEnbmSwirS/AxMprT8/IFjkGeyQzK3dEVFTMChlpqbSRluno6BimLCPGBVmDrEBWDrNMgJ9vc3d3F3z48KFOUlLS7fjx41G7d++mm07gjCxDlo+D8l7k7e19pqurq6+2tra9v7+fuHfv3rQCMsKHCCNCiCAiQCaT+URERGIIgugETHV1dTkbGxvXgs5CcHCwC27h558/f27CQ9XEzMystCABhhuJpKGhWYrzsAbvEpTv/wA6y1RMxTJupwAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.make-struct:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACBklEQVR4AZXSA7BWbRAA4O9HNciuUbbtrm3btm3btm3btm1zPLm2vbZ25jnntQkAQKioqBAoLC4OXEgf1OKnrKzMHf8QEROrFZ+QyFhQVct5oAGePXt2pLy8PBkw/mCkFxQrHGgAJSWl/0tLS+1hORKzskUPNICjk9Ox2PhE9ZraurDBwf7yys5RygMNsN4HBg0lKumEPnKJuJF3HI4jn3i9Rz/z+40SCQSNkoiEj9LIpVW8YTC8ue0A1x4zs9No1IB86DQoRsyCQuQMyGFaOngSxH3HQMRrBFjMO+GTcNT0/Rd0/28ZgEQoLIVWuxUk/SZAKmASJPzHQWyho/cICHoMAZ/rALDYdQKxRiV8pFU4s2WAC1ffS77kSYJPcjXwWWEdpRogUqkFItVaIDNqABL5pPmbD8i3rGB5G7QONz9pfL1FZPjzDpH+1wfkZnMPKMxmH1KYzjwgN5l6SK7fcun6pwcbzkBcXPxQZ2en8MzMjHtzc2MeCxurOYFAEEeqiH8dPsSDmNGF1QFcXV3/KykpUYXl0NYzjMEGGsga2SxYTlsiC2SH6DZsISYmRhIwfvz48dPO0SUVG8ggueW/FJJAokgEsaFLqwMYGhp+BozIyMjq169fB3Jy8xRiAxr0z4I9HxIREdFlR0fH8HPnzrljBxUkhu4f6CViXERk6MRy/t/9DPAXmoNf4gvM5s4AAAAASUVORK5CYII=)}.bue-render .node .header .icon.make-array:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABCElEQVR4AWM4duxY3P6DB+eb2tgykIMZjhw5MvU/ECxbtbpi7br1/vtOnA4nyQAjIyP2o0ePbgQZ8g8Itu47mEeSAQUFBSyHDx/u/Q8F63fsTCbJgP4JE3hXr11feur0mSX37989evz6Y3eQBMxAfGwQxmEyQiEDA0MtLjbMAJwYpAiE8bGxahxiXkhNTWW9fv164qtXr6ZevHh+Dz4vgDRheGHy5MnMhw4dKoZJVNbUryLZC6tWrUoHCf769et3T/+kzSR5ob6+3h6kefny5SfNzc3nh0dG7QdKegExIwgTTIkODg5S/f39S0VFRacCNRQBcQoQaxOblGFOlQBiFyDmh/KZiDUAAB5wcNBYHyBEAAAAAElFTkSuQmCC)}.bue-render .node .header .icon.event:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAo0lEQVR4AXXBTUpCUQAG0M/2FDxoVpMoG9REooFZ1qgSBSFRl9DW3jpqDUEnnncg159zUnPlMsd515nlMBN8ecIq+0x1msQd1ql5U/STxC0+s2WGH61Wkw33WKXwoTNMxQjzJC4U4+ywwPlJflP0squXwkjnIRXPmKbwim+tVpMNAyyy5VHRTxJ9zFMz1jlN3GCZfV6wdO3POocZ6kxynMZZKv+91JsD8SUcfAAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.exec-branch:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAA6UlEQVQoz2NgwArOtu5QxyqxX+1k5qPeh7P//f/1/krZOmEUyRU8dyb9RwEXW3qY4dJRnA/3/P//fN/hmCMmF8N+fX6weJ/lKlYk/Uf7/v8/3g9hZ3LvVEGzu0Pkz8+X5xoYsTpss90+u+P5//9vzcTuI4b/XyBO2uJErgKCViAc6cDEoMzgyODLEMoQxTCDoYbBn0EWxZs9pxlKGQIZrESsvCMY0oAKjRigYcnGYMCRseU17oBiYZBnCORev3EbnqAGAl2GOpOurpn7l59Y9+//l69z5xs7MqBGFwMjgyLEkbM3aK+AOBIARSWU16VenEYAAAAASUVORK5CYII=)}.bue-render .node .header .icon.macro:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADIUlEQVR4AXSRA5A2RxRFJ7Zt27bz21rbtm0bn22jNmvbtm3b+9ITc6rO+J7qvg97+6PT/4lftCQ5s3x0XJI7OKZtl+T4f//9ryAoXs6o61yEzPJxOKnro//7e03zmGPHLrvf/J8Cax/u835xPxldMQpzN3dO8ihtnIOsigmIp1dUWXrx9SxcUw2K6mfAPVwuePH1r2/9Q3DZIPAEQdBaJ8wc3swsnwLPcPnsBV1frSx0X1Q3C5Wt84Df51ZNQ037ApQ2zcElwyCHPwTPv/7VvVZu6SRZ3jioiiYghly++8n3+p9+fVz/By3TQPN4cm4ZLiqun4WssrEjr0gu8YerDo/9bQtuwQKWKGsU2KpeoEp64Pvzjud///biWz9e7+CVllJQOwPS3KGj78476P3RgW9cLssrOltBEfdsMNVDYBxAide1ik46edXD4K/9vPz29zeksyvacYmjP6/623NOd14xiX4AIwh6tpnKIWDKhyBF2AnGwcyTeOCjb7Sv/+dk7LzIIXgXXHXfPl3WORZJLO3GwtMrBpNZrZs06SBquxkt3Unn/0Zr78uxVRZMgBr1lFs5DencxhXs3U8vPP/eF1dejiRWTlBlg6Bnm6rCMOwmxHGEJ8ID8QniBrdgIVlRMA5kUetGGrtqOCA+o+kXMzruPH7RjktDgkRW6xGSCtC7txF2CGeEy733PxaayqrfEGaOwFen9RV33P3AS69/dPxxPPz8cy9/fMzEiVCfyu0CsrgfCMIecAiUZFp5CzX17Ain9WySQuNpdfO8jBE04qq9x555wwLlbkXcjMDsn3v5QzFB1A/J7E6IJtcBRTwA+GqIwh5EL+Als9XDwEBFUyV94BeXv3zfg09G4VkEdhvivq9+1M+1dKev3HH3Q4QvjxnSw1LLZ9P53UjaCoFxOUNapmGCsOTCVVzkFiwavPu+R46h3Lu/d/Ao4uclsbJxtgPpVJCfkwqm3py58g7Itv+iUio9QLECTT27LbEZnTe5uAUSQM5HSYlAwAXEoiA2GzsXh294+aGqjq3vCxvWfFJUtwiEyqsBsSUQi4NiBaQWAFVQthrhyarSAAAAAElFTkSuQmCC)}.bue-render .node .header .icon.event-custom:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAA0UlEQVR4AXXBz0rCAADA4R/UA4UQDCoPihX9uXSJ6GCK61SJi8Ll9gi9WISHnqKuwWJB2y/WIBnq99HkkYes562ViNUcq88O1YRlTqwE4Jma0uSNtX0AT9QpC0bqh3Nfi8CgbIMXakLNOyt9gO8wS8ppvgUO1AfArrURFK08Acg2AYzVDrathVDs/UT880ntAA6sXAKUsWl2/9kCh+qEmtfqu3Nfvnpvux644bkas+CVf/IugD31kSZHVrbBU3XGMkN15rGlKavZtzJmPQN3aPgF+BS+KvXYCsQAAAAASUVORK5CYII=)}.bue-render .node .header .icon.input-key:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADHElEQVR4AWKcNWs2Azs7u7ybp9duQNvkAANJEgXQ3xhbZ9u2bTNOzjZinW3btm2sPcjYVttd+3utl7yyEQ6HGVnVpNmzZv1wwP77nYB50mx1yo1apb7r7rvvGwmHjR9++OHrQbfzDKyARWHHHXeMBgKBHVmGBQIG8KJM+32+3RmGBs0wd9V0XUgmYhvZNsDue+0n/NH9dtUANAoMtjRMC0xCwLRxCMtSnTzBOsxqhmEqhokZCmAyGevgsOYKqtWaUOxNZ9mE8lM05W93uo1vfv0rRbMuYpoGJ44Hwu8z5rhCobCZzxU6sAbLzmAlb7/7/gnvvPvuO5Zlma1uX583Z3bjtNNO3R6rrN5wnP3up1/PL+Ry5olHHqRtcIBSsXjqPQ888B2FS231xtqsGf+Vzj7zjN1YGqBYay/446fv9oV1oNfM7L3PPrheBaaiCqKi2aqm27Kqg6hZMJpMTdgAzI033uRpNptHxOOx7ectWLRbsdFJ5ItlEct6vV63sSiTV4qVqlQqlRq59OLFW2y+2WaXXnrpVnvttefmxWpThCVL0lvxsmoquk26I548/9pbc2vNtjLmBH3u4uzg5dfeTPdGE23Ci/r/s+eX585bMFEMm4iyRrLl5hm0qqpgmpZGiA2MywWxeMIVDoXdwWDQFQgEXYlk0hWJRN2hUMCl6hqRFZmiGQoomgZBVoB+/PHHKZzNJ+kWSJoBuG/vVFLo/piH9mBo9Ycj0ukP7c6Qszu9gT0Yjc0xL4NmA0x5kTBHHH2stjhf+e/hB+//7K3XXkn//N3X/Y8//ji7aOEC2e1iAroswz///c///+8/AkVMSkXmLky/+eOvf9z931+/zwTnGh2RKLozejF658033/ynTQgx0J///Jf77Isvp07a4Zbb73gS2wRRhr3yyisYTOyHHoX6URFVff4ATWECxc/mpTSP10k7OGe2D0ZnoX+zK8pa6C+ojfJO3Ov3D56XKRiGrlO5QkEQxiMSSW3icbG01esPFmKbX1Fh2UvcENdce81uFMPuSWyCKyEDAOL8swQQ0Amxsi++8GIRkKWao+KEz2+NEQAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.flipflop:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAA30lEQVR4AZXBoU7DUABA0ZssoDBV+PEFy3NYhh6mjgSHmJh9mUIgKGKpboKa3Adg6tDlC8gLGlODIyGXdOxtFs7hH9yokT2DWpFZ2Kste1ZqIDP6a8yOyY4DO5OtesuWpRrJDGplVBu23NhbkFmpwbGaACzs3XBgsgMwqQGMaklmqUYAGzWCycSBrT1blmrrVK3IHKsNBZFHbuztbdTAJfecAUZ9m3HHnGvqj1cHHResmDAwfb+zZMExI5ZPL6rPNSsmDJzqumXOiMHp1Vq/PqkJ7JywYM4R2TkVD0z4qx9tmayOri2bGwAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.sequence:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAABAElEQVR4AaXBvUqCYRzG4d//9dHXBgkE+1hqkloaHFqcmzqTzqJj6BQ6jiKipaZaElKKqEhLzY8SfD+eO9QcAoeg6+LfDEAhp2zh8GBFHXJASoqQbTomYqoMOSPAgDZGkU+gzpykPgsFzI1YyKkACAiVQ8gSftO5mmpKSvSguhqgY/XV07WOABwNcgSsknyNRytRAhflirxT+eSNPbrMSPEHZapMZAEjQ551Sg4I2IVxyD5dSrRos8ESnh6XeAdY4R68y9/t1MxdNSqFaFxb9gExjogZKdWgrWfdQPoet3LGD8fU4LabtUwn8+phaE+daJsaU8ZclTVmmky88MhffAPYR3LALeaIrAAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.cast:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAVElEQVR42s2QsQ3AMAgEPdqPxqhfs8SlCCh2pFhpIoXujxMCxvhpKRQboABm0qCRAhalQEkKplxCFjHGQOdSFCbJaUKeyjXBtx1c+uMVXtsv/vBtHbXUa0gw2w7CAAAAAElFTkSuQmCC)}.bue-render .node .header .icon.do_n:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAlUlEQVR4AaXBsQoBcQDA4d/VPyHD2Uxmi0iZTCalPJN7FavRC3gAq9XAYLIYdCJ+Mih0R/J9/ERNQHkSeDWWD9RElTwKJsrf7Lpx5Yg89p2qqUOIQMlzjEqBuyt77iSiChw4EwM7stlwpm5tkc2eC+d2AAJQ5035kk6IaXJiGYABcuEhQFqgRpGYIsuILBXaFFix5rsbWsFEQ+tzCUAAAAAASUVORK5CYII=)}.bue-render .node .header .icon.do_once:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAlElEQVR42mNgIAX8b/j/H7+C/wQUgJQQtOJ/AwErCFoCVmj6/9H/u/99cStw/L/q////3/97IRmMFXyHKfj7/x0Yvv3/Dizx5f97MP0YlxUa/zf9////2X99XAqs/5/+v/+/EYwvhw45LRhyGGoY4hl0IApSGVIYEuEwlSGVIZuhhaGHoYchHZc/eRhsGJwY5ImKYQD+WHEvPFQJQgAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.loop:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAABDUlEQVR4Aa3BvSuEAQDA4d97dzHISSlRt3AdJfnKgJSPukFRNotBGZTFaDH6F/wJBqMyyqAYDEcmOp3oOKXuCJfi/emKdEUWz8N/ctArL5zmJ3Y45rhbatkpE06Y4otJd3z1W9kVy766YxKw1awVZZ8sWnHtogUrsrbihlpywXY73VZv7DFu0gVL6gbm1FUARzxyz34+uarmsKimAYxQxbRajJAHZgGCkGqzQD7GJuss3dedHhRrMl0v9U2FgbO20nVj9zDzwCZzicsTf3F5MpcIWIs3bzeM9kZajL7FDKLv0XcgDG/3j2ceHu8Clklxyi6PwBshATECIM4k3ZwH1DJEH3WEVIvwTIZD/vIB8XLEOPFRlsoAAAAASUVORK5CYII=)}.bue-render .node .header .icon.foreach:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAABHElEQVR42pWPO0sCABRGDzVEDQYtgdFSki2SCLW0VIND6WJTQ0PS0lZLSLTY4JDg6NgPaHAonHOVJnFwMYWCCAqUCEQcTktkr6UDZ7n34z7gE5e9984kf2HYNde9VHtuOuuGC8NmyLJ9h/Q8tGffsiHAoM2P8psdVR/c90nVpkEsql33nHfRK/XRJQOG3LOrFrGtZgBc9dYbY5+rM2obO2ocwJEfh8fVzn8Cv14fBp4TzDBHhANO2CHEJHMEnxNqh0FDK1VOOVbOlHMlxhGnlaoOGpSuVV8vGGOaFLusMM5od/v1QrV0zVS+3lKF76rWW1N5yAYKtaI1IDzUF2u1YqBAFqJkyJH+PoEUaXJkiAJMECEObH0xSZwIE/AOYCnwUXtA5vgAAAAASUVORK5CYII=)}.bue-render .node .header .icon.gate:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAABVElEQVR4AaVRM6CcQRD+5tf5LrZt27bbqIztKlXUF6+JbaeMbVSxzcPmP+3uZPP68C3GHmL8/pTdwDkR6306WDkvoTVJcnUczFIXVF77RVavdjpFqaqiVgBATvhfCvHPdpA8y7WiFIhEIE45opBLhmoxOyQ+bl65b79QPe0mVIfeUotdY0aLr84k9cFXuLipWsumXZduGzj8zrp+HzQkpzkYZnCGGE9OV+uXyZEddB14UNACzGQH8k6Qbk51AO0z/LfJ17ZW5FKN5uHKGkX96maoSdVEPmMMbN/CodWLNqD0bAs3XNZ0ulfhYyqUqpowKeCWXJ7U8djTl69D0vuuCsniV9WixdB25U1yjYVzHC6uMLlHNHAaMAgo/SYFcvAM/UCYFPdeHq565tXTJ7DIYku7Mi7jxlCNq17euv6WjN8EtMFXJEH4eTQsRBAGmQ+UlH1ZPwADYJqX7zDGbwAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.spawn-actor:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACoklEQVR4AY2SA5QcWxRF+9u2bdu2jdi2bdtuq6oGbWts27ZtnNw4jeCutYvv7EcegEtisVh+nzt37sdn3g0Gw00cx306bNiwKy9LYLVavystLS2kwO0ikeiZlpaWBD6f/xcAnlfjJUuWXr1169YPDhw4OHb37j3j6P3DPXv2vgxgoK6uLrGzs7OaZLFn2ruFFy5c9BvLcokmkxkWixWxsXEoKChESUlJ4cDAQDdOV1xc3DqJRHKtm2Ds2HETjEYT7HYHKEzYEBIagbz8QnR2dsGzaBqZMTEx406Gf/rpp3cDA1V9ZrMFBKKjY5CVnYuIqDjojDakZ+bgTPX09DRmZmaOJL6kkbxyUrBu3XqlwWCEXm+AzWZHbV09qFBSVglHcDjqGxqRkZ2PpLQsdHd317Ese63bGhw6dLiIRgCNRksjsCKP5t3S2o60zFy4QqMQGhkHldEOTmtFcnp2p91me8JNcPTosUaGYUESaHVGWO0uBIVFweoMhcEWDL09HHpnJAKMTgiU6tYZs+c94CbYunVboUQiBcNwCFBpoNIaodZboKH562yhCEopRHBWBVS2SGzafaT2yquuvs9NMHXqNPmRI0chEkuhYPzBBmjAqfTwUxupVxccaSWwZ5SBNYVi5MTpOTwe7ws3wTvvvPP2mjVruw8cPIKjAgmEMgZipT8krApiTguZ2g5RoBU7jioGHnr0cYYEf3odpBdeeGHCshWrsHPvIew5yMe+I2Ls58uwjy/HXgGDDXsFg2++/3E4hXcQr/o8iQ8+9NCmf4YM75q/bA1WbNyJVVv2YfH6nRg5ZW7b408/F0NBAfEbcaVPAdV1xKjb77jL+PhTz2Y/8cwLeXfec18CfQsklhJvn2nrLXAX3Uq8QnxIvEE8RFzhq+1xp0uyH3vDKqEAAAAASUVORK5CYII=)}.bue-render .node .header .icon.isvalid:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAgklEQVR42mNgoCL4b/P/9H8QOP3fC7s0MojAVHAHrFeYgeH/tP///79Dl1YC69NHmIXPLdhMgEsK/98BNssLlwKQ9Dvc0vpg3Tb4QgKP85gZfBl6GHoYchiSGSoZ2hlC0RWwMTh3FoBN0GaoYtjM0IXbiiUMvgxSuCySY6hhqCApCgEvhWJnAgJmhQAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.blueprint-node:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAByUlEQVR4AWJ8eOvASkkFLUDj5OwvVxTE8d+cexaxbdtNzL/qtUEf1rGdVHGVLmaXVLGzupqZxZ3PPuN77DPaowYyFK2BWguoIQqFqMIpv3/9tMP7wshNpRpPUGE0oVZFMKBZZTgY8D4PP2LSBh+Fle9FYJaqACA7oOgbhQFmQZxE352kyX9CF7IPYyioyH9fLv0pjwVB1a5p9TEgBEDI4d/fH3/95ROHD6za9uF3kiT5THxCvlAkco4IWQI1cAQy3QQuACs+3zxz7J6fOnnymLlTx69NkzhHRNooCLyHKqCiEGUwMyQr2uwTCLUwLBZyAfu5i5ZtGzFuxhqBgtoiKIys38ranicCOBixcsOOykwfhtWfYViBsHbRNPUtOKjzgnyhHEfR36akpcw7MID27SdWiBySJElv37ygvlar/ldlAA6Kvi4iGO1VB0IcVdzj55+XeObkv4hk/1Lt23n68M44jmppiJLnJCkrMxDYBX3IbDKg6ziOwmoY4revlss1ChxcrgiI9KG4Lh3D54vgNIkBlPy+Q1c/dgTFuyPGTFoumgbmOPZpgvVgULPvc3l+++rpIwA1suunAJjTJdzISle0y3wK4DOAL3Wxrg3PNG+67QAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.select:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABZElEQVR4AaySA3IsQRiAn3mCLTwztm3b9gXiS8SniVFOSoOeWcxsbJvT+Xttd9XX/r/mC4yxV/hGsLs75ieILTuC2LwriE37gtB4QOpqdZfaJcHO7nC6Qll2JVcU3HF82hPHpz/STDBmUQz2+AgsipVYFOWNIIrsQLLsR1zcEYwJQKFTAeISrAQcn3pHxoAbIE97iXsT39fWe5ZYFCeRc5Pt00wIZthIkCQ9kTmi2LqlEmpPdME6ou81gqmpTj/ElR+TLQNkANNMKAjCDAKVquaEl2ffmwhgLP7a7hEYlkyKk6yPFv+kDY4ldxHsQBBp8xk5PuUMAueAMNJ2IIggx4AZL0qAOOCr3WeUyWQBLEqQyOchQdpS+5Hevn370ek/+Pz5c+DySvItCdYSAoRhparmWLu6+Q4gvTUTQPoJJAEJQLyOSNNgoBCoAlqBQaAF+Ge+HZhoh+eBDDEA4mioRR5QSyQB57aHAAKZXiEAAAAASUVORK5CYII=)}.bue-render .node .header .icon.switch:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAABBElEQVR4AY3BwUrCcADH8e9/bpYogt6EJPASRBAEnYLoHAQ9RD1Jlx6ha9Bz1KFLnXoCCwrJTKJtOv/Tbb/QoSQk9Pmwirpq64TV9CFppGPDjG6o4pGRIs65osYRU2OX3CllOjj4DKlSVxMZA0TkFClgiQ0l9bRLTqEiluhNd9pjTl+K+Jsu1denrLIs0EC+LlTjF4cKGVBApmCxzuvBtUfOAzDMyKdoSpVtbRIPy7zzzRYbxDy4zCQFh1bjeZ97QopYxoiUEN9lqjla99LhWd2hmKRBwC0hIW3mvFI8kKwmyVi9fmOHNRZcgMmIx5fDyLGY5KkbGGIWDHMNWoDBoUOb//sBgDV++n4nGX4AAAAASUVORK5CYII=)}.bue-render .node .header .icon.input-gamepad:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACK0lEQVR4AdzPg46dQRgG4H99HbXC2rZt27a7tm3bOljb5rHNtfft1IjTsDN5os8UgH/yPzXYe95tC1feL5ZrjBKpZpCbkc1w9/fz+xgZEfmxqLjSTaQwcpWGIaVYO6w89zTq8B8N1m7YZZKWQcvR949CYRjHNPl/v6npaej6xyHQjKGqqbt29YY9Vj8bfPr4fidfrERerQbRTBU4sn40srRgNGpR2KRGRZcWLIkemdUKRBYJ0aUYgbt/8JWfDXKyc/LrOkSIYQiRUEoK68Uob+YhntGN5KJe0GrYSC3sQGSxGKnlYsRVKdDYI2q98+iFBXXlytWZtQ2to42dXNCqupBb2YPC2na0chXoECjRwVeiS6hBWUMnYnPr4J3HRYtID65uFHbugasoaxvbU+V1bSiu70FmcT2iskoQllM1bRuQIP/gFckneNa+MZLQFOZkIq0SMdllqBUZ0DM8grBk2gvKPyDobX5pA3LKW5BZ1oowWiOWbNpTbmZh6UqZmNkR1iZm5vYz58xnugXFTqUXNaKoQ4bmwWFkVHcGUydOnb2eSq8iNzYgqbwbBy7el1EUlU3kEzQi/7vM5avW8iLSC5FZ2YVy6SDufXBxoMzMzBeduXa/1SksffTM/XciM3OLGJLsStgQnwhrwp5wI6J2Hz4ldI3KmXpsHyD+PF5BYTcGIGAHYjkOLh5TIK0BxKJAzA3EHEiYE4h5gVgciHW5ePldgLQeEPMPfF4AABrQozcZBuj0AAAAAElFTkSuQmCC)}.bue-render .node .header .icon.input-touch:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACnklEQVR4AWL8//8/AyUAbEBbW4d7WVkpoAxy4JIlC4Jw1C21xzNr27b3fyyOls+2bdu2bdu2bZZvvrxjfN3RyIiTHZ3jiZGMEEK6riPPnTsvfd+n5557ThYWFiAMI0gVYQYMG926Ue2/p0EtmD177v9UiStXrlLXHn2oaZtO1Kx1R2rdtiMdOnyYypCsNbuOduE3CDCGaeaglCAIMX7iFDz73Ito3rAuWjatj6++/Bxjx03EzVu3oCAwFKWhUFuWL1/Zl0q5eu0adezSg6Ioosr07T+INm7aTIqQte3w2UnlDex4PA+lpFMpgCROnzmLilYB+BbIzs0FAZAsoSEHjAEmnkzmKUNjJRIJfPXF5xg6fCRX/wIpXrh7z17k5hXgjTdehyNLcrFYLKt8gW0nc0IAZYNff/0Z2Tk52LJtB9yLV/DeR5/g55++RwiBgIO64Jxhptv2HaujY8fO5okzl4+5RKQUsCTVRHkP2Lznl7yfvfH4fK/Rs5PG7l079Y+++vHBgwCPokgaQkDThAaNsSxLtdV8PyTBBjQ2+WGYBt28dTtcPHuybpw6dQpzZ06ek0hlfonC8GmABFcQ4C2nTp92NUB7+ZVXbNWLdxKgSd0wH92+dWPtqoUzXfz++59fPuZKHvfmdhRV+gszFiy/PnP23OvE+Dx0QqKHHFS6/SiU737w8cfGmbNn8iMJOJ4E94YQSkDcAmDYkSYDBAAeeQARIDmmcpata1nZOflGUVHRcxaHw0iAoCgJluT0OB8EEYAyU/0A+GnqQHZO7jOG6/n2ibPXfMcNeKSOx2LiyRj4BteM8LE4c/FO2nM8Nkp9rhhPmhRJSvBn/elkJvsDnscATaHeBM/p4f27V1U+lcl+mojKTJUSLPfOzWu7nwDYK7XSckdYIgAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.input-mouse:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACg0lEQVR4AXRTA5TjUBR9vxnbtn2wtm3bB2vbtm3btu3t2LYZtpPsm3Td7j25n8/5DyRJ0uKxY8eDYmPjTnz48FEZG5f48dMX5eIdu/eb6JLVOujZs1fzgoKiYglx9sIl6cnzl1IdYhJTn3Xs3NXyX3kF/IHhw0dYrlmz5rSJqZkdIKITUkD5TQlqFPTy9Ww9ZeacHfAP/jLQtGnTcfb2Dp4cL8h7UyMDMDc3kw2wvAgNmjQdtnjVhhCdBvr166/w9/cfKm8IkadAHw/w8ffTCCoIGBtTeiFhEaN1GvD19XMHyiAkOjkdvsQmwYuvcRCTkgVfI+Pg9adI+KKMh7jETLBxcG4+Z8kaomUgMyfXMykzx7iK5kDCfa1ahNbtOkL9+o0ARApEUYTi0gpITk1zSE1NMfypp/dz0bJpE+vG4UFgYW0L+obGoNAzAErfAF1QGgGicefj7WdpaWlljDvurwiiY6IZmmWhhmGB4XhgkTTDAINksaisIMqFrKisEmKiI9VaEdTU0OmVFRW8sZmlIVGp8IKAQpJd4EeBAiVFkKCyuqYI5eifetTy5cvlxfbt26s8PDwG2Ds6OWieB0EFAIkQAEyFmBBcAzx/8PjBxsXTrmkV8eXLF+r79+89pGkaw+eAF1QyBUENaiLXEb0LcO7InnhCiL6WATw0ePzo4Rflt68ch/kzWA+OxxnXnEqT/4Prt4pjvn2sC99O10tUoOeCY0cOPklLS4VqmkUyMqsw5U8vvtUe2Lj0CYCUCwAs/MSvrtL8KEdkLy8fvzOT5y0v3nL0irT11C1xwsL1WQ4uHvsBoCfSFUn+240IY6Q3sp2Ftd1wM0ubwbj+PguoRg509QAd7YHBADTl/wAAAABJRU5ErkJggg==)}.bue-render .node .header .icon.timeline:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAA1ElEQVR42n2RPQ5EQBiGTSeZimqvoKHnGs7AGQj3UOv3FIJ+FNQusVE9GzNYdjfyFtM8k+/9sSyLW1kaEEh8CkYWFiZKfCRiBwQPElpmempqOmZaUh4rsgKSBEVDToSHR0ROgyJFGsCnpSHGRVBRIXCIaWgJDFAwk+NqU4pBvy45M6UBRnoiY+kABCEdkwEWauwtluKFQlHhUbP8Ak8GrQsw0R0ndl1OlNqkcwEcso/Jc0zz+yumJN2KCrGxCcmuRa1Vp7rq7n/VZqyAkukYKziPdas3Gzo9V0WjmTwAAAAASUVORK5CYII=)}.bue-render .node .header .icon.pill:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAvElEQVR4AdXBvS5DYRgA4Oc955QmLRJxAVYWP5GYJWJ1lSaJxeJnqPYKxGgRiYQ0ISVSLf2+z2SzGjyP/yC4W7zpl41ujGSBUIRWbl/H3sFbQ/9qfXMVlSJLkpnko3rcfri025S5o62OZZUiy5KZLzO1WnuHRnoq9/EuFBRZkWVZ+EQTaf95fuUFgUAIodZ1MaRhcJYO1xY6suJHURm+npzS8Hnea/X8qk+NWx1LsqmpiYmxsbGRgWPJ3/sGBOxJ/BmgVT0AAAAASUVORK5CYII=)}.bue-render .node .header .has-icon{display:block;margin-left:20px}.bue-render .node .header .pin{display:inline-block;height:16px;position:absolute;right:0;top:3px;width:16px}.bue-render .node .header.icon-async:after{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAACGklEQVR42s2VL2wacRTHP7CUf+0CS7vCAfd7U7hLEIhlM8tUcbihlpkmExVLMMsUU6s7OdUgKxAkNc2p1eFA1ZFUIJbUkCmo6Zug6125ozvEkr1n3/fzy/v7g39mKbbJkuXJ5tIsFgYJuI1Fga044gT7CEKNI1w8hni4dHAQDBaZx+VJqggN+iwOtKun+kMH2tWWZpQzmgg2hfXyDAbBzd90da6r1tOSckINwx6JKHmaKg7eS51ptM21rYxoYNgPZ57DQvBaOr8NiliBdJUJDsLuQ3keC4P7ZkU+DAFUPykXCMJTH7BNGcPr4s3s9mFwFEC1rhwi2P6EFLERPDcUGg0YKFNqfhoJbAQnvZjHBKjWlXcI9rIbSQxCpxURuA7wTTlBMGSXAEHof98AMFZGCMKzZQoG4WKwAeBKmSIIe8sqVBFGwzUA3x/OB+KXsYQwPI8E+B60mXKNIH/2ooDQ72l8u1IuEYTcErCFzfHHDQA9pY9ggqP06sUGgLbSQaj6w5yjyug8pvynphc4SHAnE5Q4rMcEtJRjBEMquJE7GLzPMeT3mxC6CWUcpn/rxVjTC94iVEiGb7GhybX76Ov5G94jVKKP/S6GBpctHUeWrq1MaSJY4deDCOErvw60d38b53qqHzS9wKWGeewqLxtaweBwxBmTuy2Y4PGFBjbPo+9xGLJPmSo25s5timTjiYOfTIosO2yvz/j/sN/WVncLEyOa6AAAAABJRU5ErkJggg==);height:32px;position:absolute;right:-16px;top:-16px;width:32px}.bue-render .node .header.icon-message:after{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAF6klEQVR4Ae2TA7AsuxaGv5XGTM/W7Nk+tp9t27Zt27Zd9rNt2+/gYh/b52zPTHeSl5tKV9c8m/erWbVW0un5/5WkuZJ/N1ci/A084kVvu8fw8rWvjpN0HFHMnDv91cOX/uq5wFH+SuQOj3gmfym1SOoTaza9ZnB8hX/JWouIoOKEzuLC4elf/fBJwOf4K5A7Pfq5f5m4mG1Tm676gb7myI2N1nhEAB+oKMICRy7f+cbLfvbdlwFt/gLkGre8K3+O9Zu2PWjl9mu/M05rLS/uhUEQrIjP/ieKKEk5e+Lw93d+78uPB3bxZ5Dr3fF+/DHmTh9rXvtWd33L+Notj7TGYK0JYtK7A35YzcXORLfdnt3z42+8EHgPfwK53cOezh/i+PTO61/vdvf+QGtyxVWLvIunEgu/ykBlyBcoFfm7cWjPzz/8s6996mnAKf4AsuHq1+d3mVi57qnXudVdXx/X6pnO81I0JPk9sd7a57BESNIaF8+d2vfjL3z4CcBXf/8O3OLOlAzWZEV9bN1br3ajW9xH5wXG6D8qGEZ/8AhKLB5/JNrxwy9+4rWZPv9GYJ6A3PLOdwPgac98ZlIbGv/+8Yv6OucuzBIphVLlJavO24TOqs6rC2hteBZCwhptLIhixcQQambfK4GXEYif+OznALBn1065z4Ou1bxqX4NL959i+tBp2t2COIqQIGrFVz0iXrjXlA/l5704rf4aW1c32Tze4GvfvnSQCuKIHIDr3eimWiTqiBK2b5pkxWST3dNH2e+M5IUmSWJEqfDNK6AyYKxFhWceV2ttybKULatH2bR6mHqsWAJWrF6T9xhwEwT0/Nxc3uivk3dhoK/ODa+5gTXLR/nVzr0cOHwCURFpLUW5bKtria+V8rkojF+zed2Ua2QZTde9BrrB3uTKlabHgJugpD3b1UbjKTSIi6nxJpO3vDbT+4/wo5/u4sTJE8RJgjHahQVARSrsBGxYv5IbXGcryyeGMUBuoUQJHD9xUvcYOHXiJJTkqugfyCgKPP4PQr1540rWrJril7++lO//4OdsWreW0dEmAAcOHuXMmTPc4bY3YduWdSgFuQFrQ9uBSODQvv29BtwEJTt2XKvQRXgRQELtotuFKIrZumkdK6amGBsfcWM817jaDk6dOM7IWBML5Bqw+FpCRvCFKYreI3ATlFw8f74YGGygc6B6ByWQ5zlzM/PEcY3WyAhFDnm5ThSTy1cwc+Eic7OnaY0Nk6YJ1gRx8I0sGVi3aUv/tVYtU2GDie9z61tSctnZpcL/qa26F4HFxTbtpS5ZY5A4jtAFIJVBv87FULNJp9Ph3OmLDAw1aPT1+WclSsF3vvrVbcB6YB9gFFQcPXSwmyTVEVhjmZ9bpMgt/f2D/vYbAx4L1kdVaw1JUqM5PEZ7UbsdncEag4Rmogj2/ObXG4E7AMMAPQYO7ps2cYynyLXrvEMUpdTrGaZX7I9GabB/cJAornPxwjyddheAVODyPbtTYKTUjiNHltVTl4wLrIU8L9CF9d2ISNU1YKW6YFQ1QoX3qaGW1kiS1O3Gkm+oUctwx6IipZTLw8CZeHR0dMCRxZEyypF3cYKKOFZY6BH3W1mNe5St7Z0X5d9FELJGw1/ihSXI6plkjSwZGxsbBIhbrVafM9DnDNg0qWf1OljrxaszrgjjYIZekCpR1uKDtJaQpTgzfQqLtta3Qqy1NleEiKQ//u7XvzF74dRprEoWFhZaFy+cX+PWDQlEviUgUgpxUQlJaQ1xWIs1RoOFvMjpdDu2yAtbFLmLjt31y58vqCiSInz+0mw2+7MsayilhnVR1B1X3IfxpfbSLZ2vGyolg+IAQaqfKOXnwFpXK0w4K1Hiv55yo1xzQVxbdwzGWrvo1n+zVqt9CPhZPDMzszQ3N2dFJHVh4zgGiNzCtov9QB2IAAXEIhKXY1crt0YcESCujgCqeQHA1ViPz2033y13ILYO59IA80DHuXSZApgD+oAUSEJ48VBTGevJEmpFRVlbIAf2OZ3ZYFb4d/Jb3G2oVXRHrgwAAAAASUVORK5CYII=);height:32px;position:absolute;right:-16px;top:-16px;width:32px}.bue-render .node .header.icon-client-event:after{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAC1ElEQVR42u2VS2zMURjFf9P+RVvaMTVTiqqoJkhUZaaejUWVCmrahCZEvOMVyRDBxkI8YieKCGJnQ8NC7tAmY1ESjwUixKOdkqkEiWdDTKI6cyyGdmbazmwsfd/6/O653733XPjnZSOPqdTQwKpBu4EappKHrb88k2I2chWTtq+yniIykgH5bLP8jW2hsFJW54/Gl5afTdhjMosCZlJPHRsx50Md0UqRsiv1KnKqHUNZDFDAur/WLH9YlXKoSt6kXqjpKlRGL+JrBENtDODGXOuUpOMvXC2SXdVJ4uXyqEyOOA92SY5m1gJk4MW8/iV9Vl6bMyCNTJIv02S5lZmwCbskZ4BNALn4SgOSdLCHZmdAcibIl2i8ZvVaTwJsBijmzI4nUpccQUwyoFb5mq1h/cYYD/BgLn6QDkVo7g+YpFEqG+Ac+gA2lmKed3+Xq2P5Hd+jRMBcofnKSwnIYXthS48eRp93SXNeJALsytWiAW9CH2AsJzY8it2vVnErHlAhVKJZaQDlmLPvpbCkVd8SZ+ASmqnyNIAKzL3wEe2IdMp6GA9YLJtQlWakAUzgaNEX2pu+7O/GT2MfwCOElqXdQhbTOIcJ/nK1sQufMyDZVSWvSoQseVWdCrAeYAT7pty80E0Lc1lptYRVqeGap9FCQ+WVV9kDvsewaKYOYByNe55Nf8d+CvDgPx0NKv1zDupoFEM5QBGnd76hFQ8WTnw5obM9H6OpA+VT5GTP0CDbcQBM5tLsNg7gACxK2UuIn32rZWuLtsid6OEnr/ExkQyw4c6+bN2mliF/0smFm9UcoykWMU2dkhQKZ13HYLjCSXZTzwycWLE4KWQJNYyKS8YcqrmCyb1Rfzfw9q/tB5/W3M+9gcGwlTHJUZ4Y0MUcP/w0MsgcAm8xVKT+G0o5d+bjYAN83I1hXmpAPivoGPQQuzhISWpAJiNxUzfgr7SSBZSQxf/qrd+kdAqEuQK2cAAAAABJRU5ErkJggg==);height:32px;position:absolute;right:-16px;top:-16px;width:32px}.bue-render .node .header.icon-server-event:after{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEjElEQVR4AcXXA3AsSxQG4Bfz2rZt27Zt27Zt28by2rbtu7GNnfT7T6onNbVva7Ks11VfNOh/uk93Zv9hjP2vbHYjNAdICyWhIVcFikBW8ARHuwRA84LyMBLOgELiECyBUdAF6kA+cDMaAM0VMkN+KAjZxZMN8acqCYNBkT59+stLliwJ/Pbtm3D37t2EAwcORE6aNOlP69at3+bPn/+mJNRCKPqfAGjuUAEmwk7YAzOgMoUwOK8gf6Ljzs7OqilTpuj8/PySmEwLCwtjt27dSnB3d9fgug7gbBigAKykxJScDBgw4Bv+Nhdy8tHJA21gOyjo+OfPnwVmQouJiWEDBw70z5Ahw3VcOwLcDYuoISju37+fyHhbvnx5EO+sEJSC+aBo0aLFmydPnuiZiU2v17PRo0cHYaSSMmbMeAf3GAte0gBuMNDb2/tSfHx8ypBlzpz5Cv4+mtfEmCpVqjzWarXxzMw2d+7cUHQuTJ8+nWXKlOmusQDZYXm7du3eMd5WrVpFT6/gNVAWLk6YMEE3bdo0v2XLlgUqlcpYnU4nO+/8PhETJ05M7lwuQBlQUKcMLTIykuXOnfsGH/Ic0ISO//79O6XDV69e6anS582bF0Ch6FoanYCAACa2gwcPxo4bN05PHacWoBEoqEoZ2tatW8P40x+AWtANFL9+/ZKd50ePHiX27dv3K4bbF3PuO378+ETqVDYAr+7+tDyoUsWnL1as2F2k/8NHYYRsAEnTaDSJ9H3Dhg2809QDZIXFVNkMjUbh7NmzMfREtBRxbD0MNDWASqUS6DvqxOQAJeHMokWLAgw3DloVfKdrCYq1a9cKmFdGMNxGA2hPnxbY5ctmBWgACsPltWnTplBeB5WgueEIfPz4kR05coRQoOTvX758YefOnROwR5gWAM0ZetJ2Sk/84cMH4fDhw5E0/FQDODYVMkK71KaA9g/8D0g6efKkngJR9ZsSwBU6lS1b9gHt5xRk7969EWq1Oo465KPjBG3EAKY2U0fACQrBMFAQGgX6f4Cf10BuPk1N+DZt2wD85k6QCxbRv03aYHiY9uAq3SdOo8DE+SbXrl2jZWtdAIKWBzYOHjz4O196h6CI5HhLY1NAux62ZIZlyy5cuEA/U3FaFKAYHKXtlC+9/uAlOd7O1Br4/v07bUZs6tSpgqlT4ABVQDFixIhf+H4aSoGDNICNi3AUeIg3d4aO2bNnv8aXXn9IQ8dsHYCWpqen5zXcqzu4SIuwuYeHxwl8nwMFwMnWAehlJE+ePPSGdRbKg4O0gxxQEfKInds6QLly5XS4xxVoKtaXYScOMq/eTawJ0LBhw0BcfxNaS6fXnHf/ErC7e/fuibT+//79a3KAjh07huPae9ALMkrva+6Hj5pwAf5CbIECBdjQoUPZ8ePHma+vr9EAeAuOdXFxeYrz50EecLQoAEFz5zepDh1hKdwHHcRhBdGbL21KyRvUrFmzBOwpb3DsIK8vF5t9NOMrJx0U4iPTGVbDE/CFeHT+kzY3qA3u9v5w6gzpoQjvsAP0hLJixds8gAmflp3kVhb5F3+yRKkpSI7UAAAAAElFTkSuQmCC);height:32px;position:absolute;right:-16px;top:-16px;width:32px}.bue-render .node .header.icon-replicated:after{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADzklEQVR4Ae2VA3BkaRSFR2vbZnlt2x4rXI+N2olt27Zt20kj7GQnbaats3etUrTsU/U133v3+70GwN/Kkm+0s7O72crKaiPhQbgSH+3YseOGVRdwcHDYsHv37m+OHTtuqKiqxuQMB1yhCJ09/QgKCdd//vmXx9esWbN2VQQ2bty4ft++fR3ZOXngCYQwmc0wAz+8awxGyDR6tHYPwNs3sHlVBKibj6WnZ0GhMvxQ9Lcx0nepVg+uVA0WR4QzDm7OKypAxS/fv3+/jsGcgkKthxn4k4BYq8OcRIXxswokZ5Vov++xFROwtrZ+KS4uDlMcPkRyLQym3ytojUbMq6n1fCmYHCGG2Vz4+QdO7ztwIMrGxubGlRA4nJeXjxHGDGbmFyBW6KA2GKGhwkqDAVyNBpN8AWRK9Q+9oTeZoDIYSVYFmpxqK8pyh+DztLR0tHUOY4jBBZsjxzRfiRmpEiM8PmaEEuiNJph/MzcM9HlBZ4BArkF1Qzu2bdv1/nIEHnVzc0dRaS3qW0fQ3j+LnjEhethiDI5NQiLTwow/R009xCUBjlCFiJgUxfbt2y9dksCePXvOs7Ozl0RExiMrvwZFlT2oaGSgomkC05x5CCSaP60MUBQGA2alKkxwF9DHFMDR1d9pycuQdroPDh46Ag/vUITF5CI2rRpxaRVgsmcxRwVUegPMf2g9j+YGW6zA6JwM3aMiJGRVjS1rJ3zuuefKrKxscOi4C067hCMgLAU9/QwwxvmY46sgVGgh1+kh0ekwq1KBJVdgcF6KnnExGrrnkVrZKluWAOXDK664ouOJJ5/Wv/P+Juw/fAo1dW1o72FhkCXE6LQMjLNyjPHlGBRK0csVo41+bxzgo6CGhdSG9tnlCpxPbCQK1q5dO3zzzTcbUtNzUFzejLpWBpp7OGgb4qNtVIimUQHq6XNFx7fIr51AclE/3CJTUlfkNKRcSbxw//33Rzg4OCEiOhXpefXIKe1EYfUIiurYKKibRHYVGwl5vYhMb4VnaLbpkksuO0L3Xb0MgT+zdevWka/3HICbdxR8QzMQHFuKkIQqBCfUICCuCl7hJXAPzsETz7xcTcUdiGPEvSsmcNFFF227++67ObZ2X2DvIQccPROMEy5ROOkWR+8x2HPMG48/8zKTigYTPoQ78cyKCVBuJk5cffXV7Acfelj1xNMvm5576S3z0y+8aXjy+TeUl1x6WTv9n0PEEX7Ey8QFKyYAgrKOeJ/wJ+qIdqKVqCUyfir8JnHtnybhSkO5nLiNuJe4g7j0e8FlHEarh0XAImARsAhYBL4DM6GerW1wPn4AAAAASUVORK5CYII=);height:32px;position:absolute;right:-16px;top:-16px;width:32px}.bue-render .node .body{font-size:12px;font-weight:300;min-height:15px;overflow:hidden;padding-top:8px}.bue-render .node .body .left-col{display:inline-table;float:left;padding-left:10px;padding-right:10px;top:0}.bue-render .node .body .right-col{display:inline-table;float:right;padding-left:10px;padding-right:10px;text-align:right;top:0}.bue-render .node .body .pin{margin-bottom:10px}.bue-render .node .less,.bue-render .node .more{border-radius:0 0 5px 5px;cursor:pointer;height:16px;overflow:hidden;text-align:center;width:100%}.bue-render .node .less:hover,.bue-render .node .more:hover{background-color:hsla(0,0%,39%,.4)}.bue-render .node .less>span,.bue-render .node .more>span{border:6px solid transparent;display:inline-block;height:0;position:relative;width:0}.bue-render .node .more>span{border-top:9px solid #c3c3c3;top:3px}.bue-render .node .less>span{border-bottom:9px solid #c3c3c3;top:-3px}.bue-render .node.selected{border:1px solid #f1b000}.bue-render .node.knot{background-color:transparent;border:1px solid transparent;box-shadow:none}.bue-render .node.knot.selected{border:1px solid #f1b000}.bue-render .node.knot .body{width:30px}.bue-render .node.knot .label-text{display:none}.bue-render .node.knot .left-col,.bue-render .node.knot .right-col{position:absolute;top:4px}.bue-render .node .tooltip{background-color:#cfcfcf;border-radius:5px;color:#545454;line-height:15px;padding:5px;position:absolute}.bue-render .node .tooltip:after{border-color:#cfcfcf transparent transparent;border-style:solid;border-width:8px 2px 0;bottom:-8px;content:" ";height:0;left:8px;position:absolute;width:0}.bue-render .node .fake-input.hlsl{background-color:#fff;border-radius:5px;color:#000;font-size:12px;margin:0 10px 10px;padding:7px;white-space:pre}.bue-render .node.ncomment{border:0;border-radius:0;color:#fff;cursor:default;font-size:22px;font-weight:700;z-index:1}.bue-render .node.ncomment .header{border-radius:0;cursor:move;line-height:26px;margin-left:3px;margin-right:3px;margin-top:4px;min-height:26px;overflow:hidden;padding-bottom:4px;padding-left:12px;padding-top:8px;text-shadow:2px 2px 1px #000;white-space:normal}.bue-render .node.ncomment:after{bottom:0;content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAQAAAD8fJRsAAAAOklEQVR42mNgIAX0ufStwS78us+FSsJ9Bn1TsAu/6IumknCffF8VduF7fWUgibUQB/ZNgxjSVw0SBgAZBjp8dl6w7QAAAABJRU5ErkJggg==);height:22px;position:absolute;right:0;width:14px}.bue-render .node.ncomment.selected{outline:3px solid #f1b000}.bue-render .node.nvariableget{border-radius:15px;min-width:130px}.bue-render .node.nvariableget.default{background:linear-gradient(90deg,hsla(37,48%,77%,0) 0,hsla(37,48%,77%,.3) 50%,hsla(37,48%,77%,0))}.bue-render .node.nvariableget.exec{background:linear-gradient(90deg,hsla(0,0%,100%,0) 0,hsla(0,0%,100%,.3) 50%,hsla(0,0%,100%,0))}.bue-render .node.nvariableget.bool{background:linear-gradient(90deg,rgba(149,0,0,0) 0,rgba(149,0,0,.3) 50%,rgba(149,0,0,0))}.bue-render .node.nvariableget.byte{background:linear-gradient(90deg,rgba(0,111,101,0) 0,rgba(0,111,101,.3) 50%,rgba(0,111,101,0))}.bue-render .node.nvariableget.class{background:linear-gradient(90deg,rgba(89,0,188,0) 0,rgba(89,0,188,.3) 50%,rgba(89,0,188,0))}.bue-render .node.nvariableget.double{background:linear-gradient(90deg,rgba(56,213,0,0) 0,rgba(56,213,0,.3) 50%,rgba(56,213,0,0))}.bue-render .node.nvariableget.int{background:linear-gradient(90deg,rgba(31,227,175,0) 0,rgba(31,227,175,.3) 50%,rgba(31,227,175,0))}.bue-render .node.nvariableget.int64{background:linear-gradient(90deg,rgba(172,227,175,0) 0,rgba(172,227,175,.3) 50%,rgba(172,227,175,0))}.bue-render .node.nvariableget.float{background:linear-gradient(90deg,rgba(161,255,69,0) 0,rgba(161,255,69,.3) 50%,rgba(161,255,69,0))}.bue-render .node.nvariableget.name{background:linear-gradient(90deg,rgba(205,130,255,0) 0,rgba(205,130,255,.3) 50%,rgba(205,130,255,0))}.bue-render .node.nvariableget.asset{background:linear-gradient(90deg,rgba(149,255,255,0) 0,rgba(149,255,255,.3) 50%,rgba(149,255,255,0))}.bue-render .node.nvariableget.asset-class{background:linear-gradient(90deg,rgba(255,149,255,0) 0,rgba(255,149,255,.3) 50%,rgba(255,149,255,0))}.bue-render .node.nvariableget.delegate{background:linear-gradient(90deg,rgba(255,56,56,0) 0,rgba(255,56,56,.3) 50%,rgba(255,56,56,0))}.bue-render .node.nvariableget.object{background:linear-gradient(90deg,rgba(0,170,245,0) 0,rgba(0,170,245,.3) 50%,rgba(0,170,245,0))}.bue-render .node.nvariableget.interface{background:linear-gradient(90deg,rgba(241,255,170,0) 0,rgba(241,255,170,.3) 50%,rgba(241,255,170,0))}.bue-render .node.nvariableget.real{background:linear-gradient(90deg,rgba(56,213,0,0) 0,rgba(56,213,0,.3) 50%,rgba(56,213,0,0))}.bue-render .node.nvariableget.string{background:linear-gradient(90deg,rgba(255,0,212,0) 0,rgba(255,0,212,.3) 50%,rgba(255,0,212,0))}.bue-render .node.nvariableget.text{background:linear-gradient(90deg,rgba(231,124,170,0) 0,rgba(231,124,170,.3) 50%,rgba(231,124,170,0))}.bue-render .node.nvariableget.struct{background:linear-gradient(90deg,rgba(0,89,203,0) 0,rgba(0,89,203,.3) 50%,rgba(0,89,203,0))}.bue-render .node.nvariableget.wildcard{background:linear-gradient(90deg,hsla(0,3%,48%,0) 0,hsla(0,3%,48%,.3) 50%,hsla(0,3%,48%,0))}.bue-render .node.nvariableget.vector{background:linear-gradient(90deg,rgba(255,202,35,0) 0,rgba(255,202,35,.3) 50%,rgba(255,202,35,0))}.bue-render .node.nvariableget.rotator{background:linear-gradient(90deg,rgba(160,180,255,0) 0,rgba(160,180,255,.3) 50%,rgba(160,180,255,0))}.bue-render .node.nvariableget.transform{background:linear-gradient(90deg,rgba(255,115,0,0) 0,rgba(255,115,0,.3) 50%,rgba(255,115,0,0))}.bue-render .node.nvariableget.index{background:linear-gradient(90deg,rgba(31,227,175,0) 0,rgba(31,227,175,.3) 50%,rgba(31,227,175,0))}.bue-render .node.nvariableget.soft-class{background:linear-gradient(90deg,rgba(255,149,255,0) 0,rgba(255,149,255,.3) 50%,rgba(255,149,255,0))}.bue-render .node.nvariableget.soft-object{background:linear-gradient(90deg,rgba(149,255,255,0) 0,rgba(149,255,255,.3) 50%,rgba(149,255,255,0))}.bue-render .node.nvariableget .right-col{float:right;padding-left:17px}.bue-render .node.nvariableget .body{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAApUlEQVQY02NgQAPfxb/5fy/73vK97/ssFIlP6p+rf5398/DPve/bP0x6VoQk9Trxx9lfd15NPREJg1CJJxyP8r+efbN2Z8y2SASESh4O+XT67rTFkagQLNWn92L75ckTI9EhUKpecHnevbX1kZgQKJnp9HhPSUxeJCZkiOSLi9o7ISESG2Tw151WFhqJHTJ4uR6ZExiJHTJ4hm7swinpEduch0sSANy8jegouf+HAAAAAElFTkSuQmCC) no-repeat left 1px,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAnklEQVQY02P41v+19mvxp+j3Bh/5GNDBw9RXtV8Wfd/+bdPb9uv2t/hRJE9EwuDtoietp6L3GyBJbotEwB1RV6u2RG2w28YMlVwciQoPlyyMmu4ElZwYiQ63F/VF1RuBJesjMeHGipLYImGgZF4kJiyMyo2K9QBKJkRig1OLQhKD+RlCI7HDgFg3I4bASOwwIMrBD6dkYrxjDB5JhxQAFjKCyDrNoo8AAAAASUVORK5CYII=) no-repeat right 1px}.bue-render .node.nvariableget .body .round-bg{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAANCAQAAADC3sx5AAAAJklEQVR4AWP8Po3p8WGmdwwg9JYBynjPwPSJgekrA9MfBiYGEAIAHbwLxMfQ6vkAAAAASUVORK5CYII=) repeat-x left 1px;height:13px;left:14px;position:absolute;right:14px;top:0;z-index:-1}.bue-render .node.nvariableset{background-color:hsla(0,0%,6%,.3);border-radius:15px;min-width:130px}.bue-render .node.nvariableset .round-bg-color.default{background:linear-gradient(90deg,hsla(37,48%,77%,0) 0,hsla(37,48%,77%,.3) 50%,hsla(37,48%,77%,0))}.bue-render .node.nvariableset .round-bg-color.exec{background:linear-gradient(90deg,hsla(0,0%,100%,0) 0,hsla(0,0%,100%,.3) 50%,hsla(0,0%,100%,0))}.bue-render .node.nvariableset .round-bg-color.bool{background:linear-gradient(90deg,rgba(149,0,0,0) 0,rgba(149,0,0,.3) 50%,rgba(149,0,0,0))}.bue-render .node.nvariableset .round-bg-color.byte{background:linear-gradient(90deg,rgba(0,111,101,0) 0,rgba(0,111,101,.3) 50%,rgba(0,111,101,0))}.bue-render .node.nvariableset .round-bg-color.class{background:linear-gradient(90deg,rgba(89,0,188,0) 0,rgba(89,0,188,.3) 50%,rgba(89,0,188,0))}.bue-render .node.nvariableset .round-bg-color.double{background:linear-gradient(90deg,rgba(56,213,0,0) 0,rgba(56,213,0,.3) 50%,rgba(56,213,0,0))}.bue-render .node.nvariableset .round-bg-color.int{background:linear-gradient(90deg,rgba(31,227,175,0) 0,rgba(31,227,175,.3) 50%,rgba(31,227,175,0))}.bue-render .node.nvariableset .round-bg-color.int64{background:linear-gradient(90deg,rgba(172,227,175,0) 0,rgba(172,227,175,.3) 50%,rgba(172,227,175,0))}.bue-render .node.nvariableset .round-bg-color.float{background:linear-gradient(90deg,rgba(161,255,69,0) 0,rgba(161,255,69,.3) 50%,rgba(161,255,69,0))}.bue-render .node.nvariableset .round-bg-color.name{background:linear-gradient(90deg,rgba(205,130,255,0) 0,rgba(205,130,255,.3) 50%,rgba(205,130,255,0))}.bue-render .node.nvariableset .round-bg-color.asset{background:linear-gradient(90deg,rgba(149,255,255,0) 0,rgba(149,255,255,.3) 50%,rgba(149,255,255,0))}.bue-render .node.nvariableset .round-bg-color.asset-class{background:linear-gradient(90deg,rgba(255,149,255,0) 0,rgba(255,149,255,.3) 50%,rgba(255,149,255,0))}.bue-render .node.nvariableset .round-bg-color.delegate{background:linear-gradient(90deg,rgba(255,56,56,0) 0,rgba(255,56,56,.3) 50%,rgba(255,56,56,0))}.bue-render .node.nvariableset .round-bg-color.object{background:linear-gradient(90deg,rgba(0,170,245,0) 0,rgba(0,170,245,.3) 50%,rgba(0,170,245,0))}.bue-render .node.nvariableset .round-bg-color.interface{background:linear-gradient(90deg,rgba(241,255,170,0) 0,rgba(241,255,170,.3) 50%,rgba(241,255,170,0))}.bue-render .node.nvariableset .round-bg-color.real{background:linear-gradient(90deg,rgba(56,213,0,0) 0,rgba(56,213,0,.3) 50%,rgba(56,213,0,0))}.bue-render .node.nvariableset .round-bg-color.string{background:linear-gradient(90deg,rgba(255,0,212,0) 0,rgba(255,0,212,.3) 50%,rgba(255,0,212,0))}.bue-render .node.nvariableset .round-bg-color.text{background:linear-gradient(90deg,rgba(231,124,170,0) 0,rgba(231,124,170,.3) 50%,rgba(231,124,170,0))}.bue-render .node.nvariableset .round-bg-color.struct{background:linear-gradient(90deg,rgba(0,89,203,0) 0,rgba(0,89,203,.3) 50%,rgba(0,89,203,0))}.bue-render .node.nvariableset .round-bg-color.wildcard{background:linear-gradient(90deg,hsla(0,3%,48%,0) 0,hsla(0,3%,48%,.3) 50%,hsla(0,3%,48%,0))}.bue-render .node.nvariableset .round-bg-color.vector{background:linear-gradient(90deg,rgba(255,202,35,0) 0,rgba(255,202,35,.3) 50%,rgba(255,202,35,0))}.bue-render .node.nvariableset .round-bg-color.rotator{background:linear-gradient(90deg,rgba(160,180,255,0) 0,rgba(160,180,255,.3) 50%,rgba(160,180,255,0))}.bue-render .node.nvariableset .round-bg-color.transform{background:linear-gradient(90deg,rgba(255,115,0,0) 0,rgba(255,115,0,.3) 50%,rgba(255,115,0,0))}.bue-render .node.nvariableset .round-bg-color.index{background:linear-gradient(90deg,rgba(31,227,175,0) 0,rgba(31,227,175,.3) 50%,rgba(31,227,175,0))}.bue-render .node.nvariableset .round-bg-color.soft-class{background:linear-gradient(90deg,rgba(255,149,255,0) 0,rgba(255,149,255,.3) 50%,rgba(255,149,255,0))}.bue-render .node.nvariableset .round-bg-color.soft-object{background:linear-gradient(90deg,rgba(149,255,255,0) 0,rgba(149,255,255,.3) 50%,rgba(149,255,255,0))}.bue-render .node.nvariableset .right-col{float:right;padding-left:17px}.bue-render .node.nvariableset .body{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAApUlEQVQY02NgQAPfxb/5fy/73vK97/ssFIlP6p+rf5398/DPve/bP0x6VoQk9Trxx9lfd15NPREJg1CJJxyP8r+efbN2Z8y2SASESh4O+XT67rTFkagQLNWn92L75ckTI9EhUKpecHnevbX1kZgQKJnp9HhPSUxeJCZkiOSLi9o7ISESG2Tw151WFhqJHTJ4uR6ZExiJHTJ4hm7swinpEduch0sSANy8jegouf+HAAAAAElFTkSuQmCC) no-repeat left 1px,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAnklEQVQY02P41v+19mvxp+j3Bh/5GNDBw9RXtV8Wfd/+bdPb9uv2t/hRJE9EwuDtoietp6L3GyBJbotEwB1RV6u2RG2w28YMlVwciQoPlyyMmu4ElZwYiQ63F/VF1RuBJesjMeHGipLYImGgZF4kJiyMyo2K9QBKJkRig1OLQhKD+RlCI7HDgFg3I4bASOwwIMrBD6dkYrxjDB5JhxQAFjKCyDrNoo8AAAAASUVORK5CYII=) no-repeat right 1px}.bue-render .node.nvariableset .body .round-bg{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAANCAQAAADC3sx5AAAAJklEQVR4AWP8Po3p8WGmdwwg9JYBynjPwPSJgekrA9MfBiYGEAIAHbwLxMfQ6vkAAAAASUVORK5CYII=) repeat-x left 1px;font-weight:700}.bue-render .node.nvariableset .body .round-bg,.bue-render .node.nvariableset .body .round-bg-color{height:13px;left:14px;padding-top:7px;position:absolute;right:14px;text-align:center;top:0;z-index:-1}.bue-render .node.nconv{background-color:hsla(0,0%,6%,.3);border-radius:15px;min-width:100px}.bue-render .node.nconv .body{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAApUlEQVQY02NgQAPfxb/5fy/73vK97/ssFIlP6p+rf5398/DPve/bP0x6VoQk9Trxx9lfd15NPREJg1CJJxyP8r+efbN2Z8y2SASESh4O+XT67rTFkagQLNWn92L75ckTI9EhUKpecHnevbX1kZgQKJnp9HhPSUxeJCZkiOSLi9o7ISESG2Tw151WFhqJHTJ4uR6ZExiJHTJ4hm7swinpEduch0sSANy8jegouf+HAAAAAElFTkSuQmCC) no-repeat left 1px,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAnklEQVQY02P41v+19mvxp+j3Bh/5GNDBw9RXtV8Wfd/+bdPb9uv2t/hRJE9EwuDtoietp6L3GyBJbotEwB1RV6u2RG2w28YMlVwciQoPlyyMmu4ElZwYiQ63F/VF1RuBJesjMeHGipLYImGgZF4kJiyMyo2K9QBKJkRig1OLQhKD+RlCI7HDgFg3I4bASOwwIMrBD6dkYrxjDB5JhxQAFjKCyDrNoo8AAAAASUVORK5CYII=) no-repeat right 1px}.bue-render .node.nconv .body .round-bg{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAANCAQAAADC3sx5AAAAJklEQVR4AWP8Po3p8WGmdwwg9JYBynjPwPSJgekrA9MfBiYGEAIAHbwLxMfQ6vkAAAAASUVORK5CYII=) repeat-x left 1px;height:13px;left:14px;position:absolute;right:14px;top:0;z-index:-1}.bue-render .node.nconv:after{background-color:grey;border-radius:10px;color:grey;content:"0";font-size:0;height:8px;left:50%;position:absolute;top:40%;width:6px;z-index:-1}.bue-render .node.ndot{background-color:hsla(0,0%,6%,.3);border-radius:15px;min-width:100px}.bue-render .node.ndot .body{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAApUlEQVQY02NgQAPfxb/5fy/73vK97/ssFIlP6p+rf5398/DPve/bP0x6VoQk9Trxx9lfd15NPREJg1CJJxyP8r+efbN2Z8y2SASESh4O+XT67rTFkagQLNWn92L75ckTI9EhUKpecHnevbX1kZgQKJnp9HhPSUxeJCZkiOSLi9o7ISESG2Tw151WFhqJHTJ4uR6ZExiJHTJ4hm7swinpEduch0sSANy8jegouf+HAAAAAElFTkSuQmCC) no-repeat left 1px,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAnklEQVQY02P41v+19mvxp+j3Bh/5GNDBw9RXtV8Wfd/+bdPb9uv2t/hRJE9EwuDtoietp6L3GyBJbotEwB1RV6u2RG2w28YMlVwciQoPlyyMmu4ElZwYiQ63F/VF1RuBJesjMeHGipLYImGgZF4kJiyMyo2K9QBKJkRig1OLQhKD+RlCI7HDgFg3I4bASOwwIMrBD6dkYrxjDB5JhxQAFjKCyDrNoo8AAAAASUVORK5CYII=) no-repeat right 1px}.bue-render .node.ndot .body .round-bg{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAANCAQAAADC3sx5AAAAJklEQVR4AWP8Po3p8WGmdwwg9JYBynjPwPSJgekrA9MfBiYGEAIAHbwLxMfQ6vkAAAAASUVORK5CYII=) repeat-x left 1px;height:13px;left:14px;position:absolute;right:14px;top:0;z-index:-1}.bue-render .node.ndot:after{background-color:grey;color:grey;content:".";font-size:0;height:4px;left:50%;position:absolute;top:58%;width:5px;z-index:-1}.bue-render .node.nkismetmath{background-color:hsla(0,0%,6%,.3);border-radius:15px;min-width:130px}.bue-render .node.nkismetmath .body{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAApUlEQVQY02NgQAPfxb/5fy/73vK97/ssFIlP6p+rf5398/DPve/bP0x6VoQk9Trxx9lfd15NPREJg1CJJxyP8r+efbN2Z8y2SASESh4O+XT67rTFkagQLNWn92L75ckTI9EhUKpecHnevbX1kZgQKJnp9HhPSUxeJCZkiOSLi9o7ISESG2Tw151WFhqJHTJ4uR6ZExiJHTJ4hm7swinpEduch0sSANy8jegouf+HAAAAAElFTkSuQmCC) no-repeat left 1px,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAnklEQVQY02P41v+19mvxp+j3Bh/5GNDBw9RXtV8Wfd/+bdPb9uv2t/hRJE9EwuDtoietp6L3GyBJbotEwB1RV6u2RG2w28YMlVwciQoPlyyMmu4ElZwYiQ63F/VF1RuBJesjMeHGipLYImGgZF4kJiyMyo2K9QBKJkRig1OLQhKD+RlCI7HDgFg3I4bASOwwIMrBD6dkYrxjDB5JhxQAFjKCyDrNoo8AAAAASUVORK5CYII=) no-repeat right 1px}.bue-render .node.nkismetmath .body .center-text{color:hsla(0,0%,100%,.35);font-family:Roboto,sans-serif;font-size:28px;font-weight:700;height:100%;pointer-events:none;position:absolute;text-align:center;top:0;width:100%}.bue-render .node.nkismetmath .body .center-text span{float:left;left:50%;position:relative;top:50%;transform:translate(-50%,-50%)}.bue-render .node.nkismetmath .body .round-bg{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAANCAQAAADC3sx5AAAAJklEQVR4AWP8Po3p8WGmdwwg9JYBynjPwPSJgekrA9MfBiYGEAIAHbwLxMfQ6vkAAAAASUVORK5CYII=) repeat-x left 1px;height:13px;left:14px;position:absolute;right:14px;top:0;z-index:-1}.bue-render .node.narray{background-color:hsla(0,0%,6%,.3);border-radius:15px;min-width:130px}.bue-render .node.narray .body{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAApUlEQVQY02NgQAPfxb/5fy/73vK97/ssFIlP6p+rf5398/DPve/bP0x6VoQk9Trxx9lfd15NPREJg1CJJxyP8r+efbN2Z8y2SASESh4O+XT67rTFkagQLNWn92L75ckTI9EhUKpecHnevbX1kZgQKJnp9HhPSUxeJCZkiOSLi9o7ISESG2Tw151WFhqJHTJ4uR6ZExiJHTJ4hm7swinpEduch0sSANy8jegouf+HAAAAAElFTkSuQmCC) no-repeat left 1px,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAnklEQVQY02P41v+19mvxp+j3Bh/5GNDBw9RXtV8Wfd/+bdPb9uv2t/hRJE9EwuDtoietp6L3GyBJbotEwB1RV6u2RG2w28YMlVwciQoPlyyMmu4ElZwYiQ63F/VF1RuBJesjMeHGipLYImGgZF4kJiyMyo2K9QBKJkRig1OLQhKD+RlCI7HDgFg3I4bASOwwIMrBD6dkYrxjDB5JhxQAFjKCyDrNoo8AAAAASUVORK5CYII=) no-repeat right 1px;min-height:75px}.bue-render .node.narray .body .center-text{color:hsla(0,0%,100%,.35);font-family:Roboto,sans-serif;font-size:28px;font-weight:700;height:100%;pointer-events:none;position:absolute;text-align:center;text-transform:uppercase;top:0;width:100%}.bue-render .node.narray .body .center-text .img-array,.bue-render .node.narray .body .center-text span{float:left;left:50%;position:relative;top:50%;transform:translate(-50%,-50%)}.bue-render .node.narray .body .center-text .img-array{background:#817a7a url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAG0lEQVR4AWMQFRVFxv/x8Wmr+D+xeNTNZCsGACg0RaB8zNMXAAAAAElFTkSuQmCC) no-repeat;background-size:cover;height:64px;opacity:.2;width:64px;z-index:-1}.bue-render .node.narray .body .center-text .img-array.default{background-color:#e1ccaa}.bue-render .node.narray .body .center-text .img-array.exec{background-color:#fff}.bue-render .node.narray .body .center-text .img-array.bool{background-color:#950000}.bue-render .node.narray .body .center-text .img-array.byte{background-color:#006f65}.bue-render .node.narray .body .center-text .img-array.class{background-color:#5900bc}.bue-render .node.narray .body .center-text .img-array.int{background-color:#1fe3af}.bue-render .node.narray .body .center-text .img-array.float{background-color:#a1ff45}.bue-render .node.narray .body .center-text .img-array.name{background-color:#cd82ff}.bue-render .node.narray .body .center-text .img-array.asset{background-color:#95ffff}.bue-render .node.narray .body .center-text .img-array.asset-class{background-color:#ff95ff}.bue-render .node.narray .body .center-text .img-array.delegate{background-color:#ff3838}.bue-render .node.narray .body .center-text .img-array.object{background-color:#00aaf5}.bue-render .node.narray .body .center-text .img-array.interface{background-color:#f1ffaa}.bue-render .node.narray .body .center-text .img-array.string{background-color:#ff00d4}.bue-render .node.narray .body .center-text .img-array.text{background-color:#e77caa}.bue-render .node.narray .body .center-text .img-array.struct{background-color:#0059cb}.bue-render .node.narray .body .center-text .img-array.wildcard{background-color:#7f7878}.bue-render .node.narray .body .center-text .img-array.vector{background-color:#ffca23}.bue-render .node.narray .body .center-text .img-array.rotator{background-color:#a0b4ff}.bue-render .node.narray .body .center-text .img-array.transform{background-color:#ff7300}.bue-render .node.narray .body .center-text .img-array.index{background-color:#1fe3af}.bue-render .node.narray .body .center-text .img-array.int64{background-color:#ace3af}.bue-render .node.narray .body .center-text .img-array.double,.bue-render .node.narray .body .center-text .img-array.real{background-color:#38d500}.bue-render .node.narray .body .center-text .img-array.soft-class{background-color:#ff95ff}.bue-render .node.narray .body .center-text .img-array.soft-object{background-color:#95ffff}.bue-render .node.narray .body .center-text .img-array.time{background-color:#95fefe}.bue-render .node.narray .body .center-text .img-array.wavetable{background-color:#c800eb}.bue-render .node.narray .body .round-bg{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAANCAQAAADC3sx5AAAAJklEQVR4AWP8Po3p8WGmdwwg9JYBynjPwPSJgekrA9MfBiYGEAIAHbwLxMfQ6vkAAAAASUVORK5CYII=) repeat-x left 1px;height:13px;left:14px;position:absolute;right:14px;top:0;z-index:-1}.bue-render .node.n_anim_state{background-color:rgba(90,90,90,.7)}.bue-render .node.n_anim_state.white_body{background-color:hsla(0,0%,100%,.7)}.bue-render .node.n_anim_state.round{border-radius:50%}.bue-render .node.n_anim_state.pad10{padding:10px}.bue-render .node.n_anim_state_reset_body .body{padding-top:0}.bue-render .node .n_anim_transition{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAfklEQVR4Ae3UAQbFMAzG8RyhN+gR0q/vAH33h8EA7AC7xOYboyCGhCJ/ApSf0lSybN06cKG1A0ANAcYYhcgzvZ+qWtyRn+qfwDS7CfGQ02whCAzIQIJvFBpl79t8guCE2FAUwnfO9z4f5j6Id4S4wS/CzZaIAFT+SURk2bLsBpAT3m02QqiKAAAAAElFTkSuQmCC);height:25px;width:25px}.bue-render .node.nmetasound{min-width:115px}.bue-render .node.nmetasound.input,.bue-render .node.nmetasound.output{min-width:inherit}.bue-render .node.nmetasound.icon-center.conv:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAMAAAC7IEhfAAAAOVBMVEUAAACfn5+jo6OmpqampqalpaWlpaWoqKilpaWlpaWmpqalpaWmpqampqampqanp6elpaWmpqampqY8GYeYAAAAEnRSTlMAEFBQX2Bvb3+Aj5Cvz9/f7++0HpSPAAAAd0lEQVQYGe3BQRKDIBAEwMFAVLKsOv9/bC4eFAbuVtmN10OE2TZys4ix6eDJIwZ+vFjRtfImoyOxMkFzVvYAJbHxhWJsGJTChkOhAIUCFGejQDE2DMrMRoQSDlYc2oeViI7MmwVdCy8yBpLzdEwYS1ZItzng9Qx/CjkV2kobT4gAAAAASUVORK5CYII=)}.bue-render .node.nmetasound.icon-center.math-add:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoBAMAAAB+0KVeAAAAGFBMVEUAAACmpqanp6enp6enp6empqampqampqbbGVCMAAAAB3RSTlMAX2B/n6+/htxmCwAAADFJREFUKM9jYIAA83IgKGRABaOCMJ4SBISDBEugHIZyLGBoCxpDQDqIUwrljCYGYgQBF2ytbluTjPsAAAAASUVORK5CYII=)}.bue-render .node.nmetasound.icon-center.math-divide:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAoCAMAAABDwLOoAAAAwFBMVEUAAAClpaX///+lpaWmpqalpaWmpqampqampqampqampqampqampqampqampqampqampqalpaWlpaWlpaWlpaWmpqalpaWlpaWlpaWmpqalpaWlpaWmpqalpaWlpaWlpaWmpqalpaWlpaWmpqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqY/NmPVAAAAP3RSTlMAAAABAQMMDxAREhQaGyQlKVhpbXBwcnd5eXp9fX5/gICBgoKOlpeanKGjrbjCy87b3urr7O3x8/T4+vv8/f5VuS84AAABEUlEQVQ4y73U2VaDMBAG4Eyi1hWtu1ZaiHXf627R//3fqhcGmDBDufE4N7ngOyGzJMb8Y1gZFML731UzAXnAd5gcAPK5JgMAIJtjUoRIdcMJkDrTRYChao7RYYh2fzgZKP9y/Skn2plX9t440XJfOp1wotWwd/T03SQNs3ry+MXISOnp2nhS8IxImIWN8+i4BySM27p+ZYV52abKEJUNOHtnmxSX4YMlMpXeeebkLqnrXpnDqEf3CUulNMOIPGxaaXIuPm/XrTSek4+rnpUm2mV6s2ylyTgpLhIrTTSY2F8UE2VcTPKydNzESY8U4mKTkmKscYPGMCgmvpJthl/tVsOeiHZDeU203ENPayLRXz2ZM8NQZca72xCEAAAAAElFTkSuQmCC);width:17px}.bue-render .node.nmetasound.icon-center.math-logarithm:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAEOklEQVRYR+2YOWhVQRSGkxj3DcUdEdziggquiFqkUBsLCxuNIC5go2ij2IiFYOGKKIgaQVxIAqIgghYStQgoopWKSxSjuAY3YjDGbP6f3AnHmzv3vXtf0mXg587cWc4//zlz5r6Xl9dduhXoViBWgfxc9SkrK+uwRElJSa7Lts/PiWAUObdyZ5FMTTCOXGeSLOg0X3TRQqkUzEa9zlIxkmBAYIqMrBJGCreFG0JjOLayJZs2Jn0unigyR4TdwlbhqLBJSKU4ama7kXCk+Agu18Bioa/AmHHCWmF4F4Wad9k4BfuYWSgHyV65EEyjoo9glCt515ILwTRzCz2TeO8j6bXDQcikEv32wJSXl8fy9hFkUluIZKvaIOfiNgHRtjbM+IvPxT0iFIw9wU6VtOnER9FHMOo9W41UMEwqW5KZwgHSPhdHEYRcB39EkcnGsFMsIvFPVx/5d5hwKglBF5cZY9AeFp+a2kRPLbRGz816ksIahFsBsZWBeEN9BKPiLVJBGeBKXCeQ3EnkGHognBWqhD/hHWnOUr07JEwTbG6dpHZTQA4OY+PSTEalZGiOBp0Q5gr2YBWpDYk9QqldSHP6qX1AmCWEhSC0epvxBUk+t/5LMzI0XgudFxaYHbu1WXcUKmkcHxy24L6phhwKfxB+CuEYb45LM2EF2a3d8YaQod9qvxG+GUODVN8lktaNG/XOXaO487CAq9nIl5DRwiRXHdecvepWqO3mE3c7AkOL9HxrDOFu3rkywWz0ner7dZDqhJuqV2ZLkHiKUtBuqL8xVKN6qYw0CM9V5zQ6d/FFNMYs9iPoo/+7gIqu1IaM5sdddWGCqNdsXr5SfbIA6SFCkVz5WE/W5DS6cGAOMeYKqs0O+hnHQavSXOYVh4w2JXExh8Qq+8QsNkL1q8Jp4Y6w0PS9V/2ZaeNGFyoDVb8kcvx2vSuQpG1p8BFkQU6XcxNPXNdoZl9QnZNHYR1ii69u4o0kTEG963L7JzPvjOpfgzYqc9pXC/OEsEdbfQSvaDBJlpNJjOC6c8SYM6T6I9UrBN65jbCecy3zWOOYIcen1i+1+QnhYpFumx1sqmnzxSDGtwmc1AECJ+yeNRTUuTNxNQrMFEgfuO+jQI48LkJOLTv9oBoPhZ0CeRQbiPFa4Eea+2nR0s48yQUfQZRYIpcR/HUCp/gz42LuYroRaLEwX3gqEIcIweGjvMyZYLafVhGbinwloarVwemmVCe56rK1kXqcyPGv02izQHOSPNjBcFL1RICkvUwgyZNuat0a6tuu9r6gz9mqbyeY9h+DhHJt0XiuRO5o8mOliNXryZfPDMHmWd5fzvhPQdThSaqc24TWuqY6mcHZdT8hbKiRZmqEvUJFRhenJeNRFrcuEQYHJMNngBR1X1gvvGCNjAQTujDT8JMawCcV//eQlvg4RU1UI19eFIhDUtW/FPUXk94eG6NQb9oAAAAASUVORK5CYII=)}.bue-render .node.nmetasound.icon-center.math-modulo:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAoCAYAAAB0HkOaAAAFZUlEQVRYhe2YS6xdUxjHf9/ae/e46lHVekZzRVuPiFcYECQMGEhQxVWSBi3qHSoYiDByibd6jExMOhDi0UH16VUqKRLUIx6pQb0aorR6zt57/Q3W3rf7nLvP2ceIgf/kJvuss9Zvf9+3/t93rknivyL3bwNUFQMsX74cAEmYGd57vPc45wyQmSGJLMvI8xznHFEUEUURZWSda36vQVlYsGBBgClVHGrOuYMB8963nXMHAUrT9DPvvZmZekGG1Ezgl0EL4pLYzEqgUUkXOedmAkcCJ0la4Zz7HhiPoshFUeR7X6JBBlwI7As8PBDGOYf3HjObAdwDnCFpTuWQhUmSTM3zfIaZPSpp6z+AOQCYJ2kJcAIQAQ/2hSnqY3/v/b1mdnXNuqmScM4tBUYk3TgkyB6EiNwOzC6ejRd/JwE5gHa7jaRTgbEh6uAG4NimRcDewEJJiyXNpfvmjgN31cIkSUKWZacSQjqMxho+nw5cDtwBnNJnzThw7ySYOI6dc26/IUEg5B7om6b5kq6VNNqwz/3AyV0wkszMfh2WxMy21D0GDgSuA24GTgKShq3WAXO6YAAPfAxkQ4D4LMtehElGFwEXALdKOqZpH2AN8CTwSheMglYB6xs28MBrWZat7yn06cAiSddIOroA66c2sBJ4AHgN2NkLA/A7IcTbikPrtF7Sc61Wq+q++wCXEIr15D7fq+od4BngfSCvfhBDVxF+C5wFPCVpu5mdCBwKfAi8CrwObI7jmDzPIURgTNIiYLQBYgfwLvA4sIqakoh7HwCfeu8XS/rDzC51zn0r6Tsz+7wAt8KtDwDmAbcCRzeAAGwEHgHerAOphSk69jdmZpKWFe5c7V8ipPcC4CZJs3v36FFaACwD3ibUTK0mYCQhicrhKnsWhFQWMDMJPnINzU7sCdd3vACpjUhZf3HvA+fcRCScc1UIgKmE1NxGxR8GaD3wLCFFk0DKfbMs64YBJmaUKkAFZE/giqJYZxNMrp92EiLxGMFPukDKPcuBLU3T3TBmNmFgfex9BnAxISJzB0CUep9gaG9Rub7VFyxBsiwjiqLdMAMgSs2XdC1weAPEX8CGAmQNRbHW7V1GxDlHq9XqhqmREYr1IuB64LgGEAg+8gAhRWm5j0LzAzgC+K3T6fxaRmRkZGQiK4NgEgofkTRMsa4BngbeA9IiFQmhvk6QdA4wamYvA6lz7tmRkREXRZHvqpkaTQMuk3Q1cFQDxC6CjzwMrDOzvLiZe5nZ5ZLOB84r1npJJ8ZxPNV7P8vMHmq3279Nuto9IGPAUnaPioO0gRCRDRTFWkRlnpndSUhNKUcYyuWcuzvP82nA9WVN1f3YGStGxdEGiB3AakJEVgI7S4MEDgOukjSrz3cNwHu/BDh3wuMqC+YCS4BbCN13UD1BuL7jhFrpSCLPczqdDsDxwOk0DFdFRJZmWRbRc+AxwH2S9m+AyAjOuoyQmk4ZZu996R+HlN7RJDM7Is/zCMirMGslxQyOSEroNeX1nTC0NE2rzfRHmkfO3n270rQdOBP4YcCX3iIMRh/QMxhlWYZzjiRJiKJoE/DnEBACVk+ZMkW9MACbgbNrgHYAbwAPASuojIrARFON47i8ST8V6wfKzL4EXojjkIy62/RFDdBGQtPr6jVVlSCFMsKvyG0DWL4GnnfOfTTIZ6pAawnReoJQtLvqFkuipmC3EEbY5wgD4mnFoV/lef5RkiTvSHoJ2DFMOyiBDmbAYFQFqmmIn0q6EpgFzE/TdFOSJLskfdLpdH5utVrbihG2EaYE+r4JBPp3fTP7WtLWNE3XFkP8tCRJtnc6Hd9ut2m1Wrunyf//p9dH/8P009+5QXLavrNkrQAAAABJRU5ErkJggg==);width:17px}.bue-render .node.nmetasound.icon-center.math-multiply:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoAgMAAADxkFD+AAAADFBMVEUAAAClpaWlpaWmpqb9WqD4AAAAA3RSTlMAf4C/aSLHAAAAp0lEQVQY0z3QsRWEIBQF0dGEwCIswRboTDujBUqgCAITnA0+bHLPCyZ6sD9AeDSW18uyfEx3faaHNsJLX8KiH+GtPrs6ONV2qJ2kvpda2dSvqBluVR3AGbMDKWYFtpgZZjxgxR1WXGHFGYBd9QHgUG0AXKovAEX1+6cRHzHbSiMuMeMHx+38wX46f7Am5w/mzfnDIDy1EyathJtmpveA6dlZpspyy4Q/I6PfIYQMZq0AAAAASUVORK5CYII=)}.bue-render .node.nmetasound.icon-center.math-power:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAADzklEQVRYR+2YSWgUQRSGJzHuuMSDejMquOKKK6gg4sUF9SISJGByUdyXiKBiVMQFNRpcLxFEE0QEBUEURURQjPshih4UETGI+xq3id8fqkNNpacz3RP1MgUf0/W6q+qvV69eFROLZUrGAxkPBHogK13/VFRUtKWPOTAJauB4fn7+3XT79dqnJRBx7ejoEMyG1hCHh1CEyBvNITI7aieIU9NC4z2JU1F/A6GM97lR+7bbRRZIJ4NgGbT0ETIc28r/JhDvdGTwndAriYgc7Av4bnK6IkPHoFnaNQxcYuIuSMNtXk6DGmIyktYoSzyakZamIE6ChsJayDETCy0ylEAG6cQIu6C7M1Id9efw3bG3oF4AM0MrMw1SFmg8oMAf5TPYG2za0RdAqcYuHahsgLwoXkxZIAOMh0Xg7tof2PYTYxfNcj51BCrO+8N6aBPWk1mVlZWBberqtHoxeeESjAB7Y+nlFZiFwPf6EC/N50dhoCRuly9UlkC5vWGaGj9bAoIwHtPSKre5u/4FtmJPnFFzlN8z4C51e2za/QO01N5yNzV+KkusY2w5KODtUkulFHG3HPtX6oq5R45d1d6wCSQ2pZI0D5oZ9jHe6Of0Ju/ISwUI/OyOZNrOxX4AFB52+WY8WZaKwiAPKoY2gkS65QkGBX0jcdaHJ3g+CL+dxrr9KI8OjizQeGAeHcwAdxIK9u1Qnex0MPaffLMF7vkI6YlNR6WOzMCiMzOhGHFDMK4CzdYu8sZJOOYZm8htH/lOG+w0dLY6UmgpbS2ErUEKGwk0s9rGbw+fhg+wlUBtiLNVaUh3Rk3YHk85UWlH6asqWX8Jy2e8oVlNBHcDfTDingXN2H1nBt6B/Y5Pu27YtNS5yVbCjS8dY4vBu4B6ff7i4Qho58bs2cbj8VgQpoN3/K6A145IOWEMKI1l+Yls8JK5AZ/lw7GO93Ra3ITp8CrE0iZoMYMrKyhZt3KEvtW84bzbf70HTWPNcKQjTq91EVgtcU6nUap7aHQd6s9Pq3TheTN0db3oLfEEXir2/C4C+7Ar0BOWNqw64xkttSb70qf9MGzFkLBxPYG6pdhpQO01y2ugWaclzhNjRFZR1ymio9IuEjYF8lyj6n19ZqRZ6iKg3dvcRSfMOJgK3j6QQ3RGJ9yCPA8q2yvze7Hxiefd4F4E0hZqvKgEvg6qQee6xtVt/Cok3Cc9gXt5cQ60ER5DKRxOW02SDozI+7xWoj4FypHloI0i5zQULyD1QRHo1qLZ6aqkm/JfK0bkZXat/oHQjUepRquYKRkPZDyQ8cC/9MAfnE8ywKQN2lcAAAAASUVORK5CYII=)}.bue-render .node.nmetasound.icon-center.math-subtract:after{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAPElEQVR4Ae3OAQ2AMAwAsEEu5O4vCycbIhaSJbQKGgEAwIeuc86OwVZVPTHYHcMJdgl2CXatzNwBAMBfvWLnCSNyx9s3AAAAAElFTkSuQmCC)}.bue-render .node.nmetasound.icon-center:after{background-size:cover;content:" ";height:20px;left:50%;position:absolute;top:50%;transform:translate(-50%,-50%);width:20px;z-index:-1}.bue-render .node.nmetasound.variable{background-color:hsla(0,0%,6%,.3);border-radius:15px}.bue-render .node.nmetasound.variable .body{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAApUlEQVQY02NgQAPfxb/5fy/73vK97/ssFIlP6p+rf5398/DPve/bP0x6VoQk9Trxx9lfd15NPREJg1CJJxyP8r+efbN2Z8y2SASESh4O+XT67rTFkagQLNWn92L75ckTI9EhUKpecHnevbX1kZgQKJnp9HhPSUxeJCZkiOSLi9o7ISESG2Tw151WFhqJHTJ4uR6ZExiJHTJ4hm7swinpEduch0sSANy8jegouf+HAAAAAElFTkSuQmCC) no-repeat left 1px,url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAANCAQAAAAz1Zf0AAAAnklEQVQY02P41v+19mvxp+j3Bh/5GNDBw9RXtV8Wfd/+bdPb9uv2t/hRJE9EwuDtoietp6L3GyBJbotEwB1RV6u2RG2w28YMlVwciQoPlyyMmu4ElZwYiQ63F/VF1RuBJesjMeHGipLYImGgZF4kJiyMyo2K9QBKJkRig1OLQhKD+RlCI7HDgFg3I4bASOwwIMrBD6dkYrxjDB5JhxQAFjKCyDrNoo8AAAAASUVORK5CYII=) no-repeat right 1px}.bue-render .node.nmetasound.variable .body .round-bg{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAANCAQAAADC3sx5AAAAJklEQVR4AWP8Po3p8WGmdwwg9JYBynjPwPSJgekrA9MfBiYGEAIAHbwLxMfQ6vkAAAAASUVORK5CYII=) repeat-x left 1px;font-weight:700;height:13px;left:14px;padding-top:7px;position:absolute;right:14px;text-align:center;top:0;z-index:-1}.bue-render .node.nmetasound.variable .header{padding:0}.bue-render .node.nmetasound .header{background:none;color:#a6e79c;padding:1px 3px;text-align:center}.bue-render .node.nmetasound .header .graph{color:#3dd9ff}.bue-render .node.nmetasound .header .native{color:#a6e79c}.bue-render .node.nmetasound .header .has-icon{margin:0}.bue-render .node.nmetasound .header .icon{display:unset;height:unset;position:unset;top:unset;width:unset}.bue-render .node.nmetasound .header .icon.graph:before{background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2EpIj48cGF0aCBkPSJNMTMuOSAxMS4yYTMuNSAzLjUgMCAxIDEtNyAwIDMuNSAzLjUgMCAwIDEgNyAweiIgc3Ryb2tlPSIjM0REOUZGIi8+PHBhdGggZD0iTTExLjk3MiA4Ljc2MmEuMzU4LjM1OCAwIDAgMS0uMzcuMzY2LjQyLjQyIDAgMCAxLS4yOC0uMTAyLjM0LjM0IDAgMCAxLS4xMTYtLjI2OWMwLS4xMS4wNDQtLjIwMi4xMzItLjI3M2EuMzk1LjM5NSAwIDAgMC0uMTE4LS4xODYuMjg4LjI4OCAwIDAgMC0uMjA1LS4wNzguMzEyLjMxMiAwIDAgMC0uMjQ5LjEwOC42NzIuNjcyIDAgMCAwLS4xMzIuMjUzIDEuMzQgMS4zNCAwIDAgMC0uMDUzLjMwOCA0LjU5MiA0LjU5MiAwIDAgMCAuMDEuNzM3Yy4wMTMuMTUzLjAyNy4zMDguMDQzLjQ2NGguOTU3di40NDVoLS44ODNsLjI1OCAyLjIzNi4wMi4yMjRhMS44NDMgMS44NDMgMCAwIDEtLjA1NC43MjggMS4zMDggMS4zMDggMCAwIDEtLjIxLjQ0IDEuMDE3IDEuMDE3IDAgMCAxLS44NDQuNDM0Ljk5Ljk5IDAgMCAxLS4zNzYtLjA3MyAxLjAzIDEuMDMgMCAwIDEtLjMxOC0uMTk1Ljk3OC45NzggMCAwIDEtLjIyLS4zMDMuODM4LjgzOCAwIDAgMS0uMDgzLS4zNzFjMC0uMTA4LjAzNi0uMTk2LjEwOC0uMjY0YS4zNjguMzY4IDAgMCAxIC4yNjQtLjEwMmMuMDQ4IDAgLjA5Ni4wMDguMTQxLjAyNGEuNDE3LjQxNyAwIDAgMSAuMjE1LjE5LjMyMy4zMjMgMCAwIDEgLjAzNC4xNDcuMzc0LjM3NCAwIDAgMS0uMTE3LjI3My4zOTYuMzk2IDAgMCAwIC4xMTcuMThjLjA1NS4wNTMuMTIuMDc5LjE5NS4wNzlhLjI5LjI5IDAgMCAwIC4yMTUtLjA4My41MjkuNTI5IDAgMCAwIC4xMzctLjE5NS44MzguODM4IDAgMCAwIC4wNjQtLjI0NCAxLjUgMS41IDAgMCAwIC4wMTktLjIyNWMwLS4xMjQtLjAwOC0uMjQ3LS4wMjQtLjM3MWE3LjI0NyA3LjI0NyAwIDAgMC0uMDUtLjM3MWwtLjAwNC0uMDA1LS4yNjQtMi4xNTNoLS43Mjd2LS40NDVoLjY3OGE3LjM4NCA3LjM4NCAwIDAgMS0uMDM5LS4zNjYgNi43ODUgNi43ODUgMCAwIDEtLjAxLS4zNjYgMi45IDIuOSAwIDAgMSAuMDU0LS41NTJjLjAzNi0uMTg1LjA5OC0uMzUyLjE4Ni0uNDk4LjA4OC0uMTUuMjAzLS4yNzIuMzQ2LS4zNjZhLjk5Ljk5IDAgMCAxIC41NDctLjE0MiAxLjAwNCAxLjAwNCAwIDAgMSAuNjk5LjI3OS45MzQuOTM0IDAgMCAxIC4yMjQuMzAyLjg4MS44ODEgMCAwIDEgLjA4My4zODF6TTE1LjIuOEgxMmEuOC44IDAgMCAwLS44LjhWNGEuOC44IDAgMCAwIC44LjhoMy4yQS44LjggMCAwIDAgMTYgNFYxLjZhLjguOCAwIDAgMC0uOC0uOHpNMCA1LjZWOGEuOC44IDAgMCAwIC44LjhINGEuOC44IDAgMCAwIC44LS44VjUuNmEuOC44IDAgMCAwLS44LS44SC44YS44LjggMCAwIDAtLjguOHoiIGZpbGw9IiMzREQ5RkYiLz48cGF0aCBvcGFjaXR5PSIuNSIgZD0iTTEyIDIuNEg4LjJhMSAxIDAgMCAwLTEgMXYzSDR2LjhoMy4ydjIuNjA4QTUuMzUgNS4zNSAwIDAgMSA4IDguNTZ2LTQuOGEuNTg0LjU4NCAwIDAgMSAuNTg0LS41NkgxMnYtLjh6IiBmaWxsPSIjM0REOUZGIi8+PC9nPjxkZWZzPjxjbGlwUGF0aCBpZD0iYSI+PHBhdGggZmlsbD0iIzNERDlGRiIgZD0iTTAgMGgxNnYxNkgweiIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==) no-repeat 0 0;background-size:100%;content:" ";display:inline-block;height:16px;margin-right:5px;position:relative;top:3px;width:16px}.bue-render .node.nmetasound .header .icon.native:before{background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSIxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNy4xNDUgMy4zMjRhLjcxNy43MTcgMCAwIDEtLjc0My43MzMuODQxLjg0MSAwIDAgMS0uNTU2LS4yMDUuNjguNjggMCAwIDEtLjIzNS0uNTM4YzAtLjIyLjA4OC0uNDAzLjI2NC0uNTQ2YS43OS43OSAwIDAgMC0uMjM0LS4zNzIuNTc2LjU3NiAwIDAgMC0uNDEtLjE1Ni42MjUuNjI1IDAgMCAwLS40OTkuMjE1IDEuMzQ0IDEuMzQ0IDAgMCAwLS4yNjMuNTA4Yy0uMDU5LjE5NS0uMDk1LjQtLjEwOC42MTVhOS4xNiA5LjE2IDAgMCAwIC4wMiAxLjQ3NWMuMDI2LjMwNi4wNTUuNjE1LjA4OC45MjdoMS45MTR2Ljg5SDQuNjE1bC41MTggNC40NzIuMDM5LjQ0OWEzLjcgMy43IDAgMCAxLS4xMDggMS40NTUgMi42MTggMi42MTggMCAwIDEtLjQyLjg3OWMtLjE4Mi4yNi0uNDE2LjQ2OS0uNzAzLjYyNS0uMjguMTYzLS42MDguMjQ0LS45ODYuMjQ0LS4yNiAwLS41MTEtLjA0OS0uNzUyLS4xNDZhMi4wNjUgMi4wNjUgMCAwIDEtLjYzNS0uMzkxIDEuOTU3IDEuOTU3IDAgMCAxLS40NC0uNjA1IDEuNjc2IDEuNjc2IDAgMCAxLS4xNjUtLjc0M2MwLS4yMTQuMDcyLS4zOS4yMTUtLjUyN2EuNzM1LjczNSAwIDAgMSAuNTI3LS4yMDVjLjA5OCAwIC4xOTIuMDE2LjI4My4wNDlhLjgzMi44MzIgMCAwIDEgLjI1NC4xNTYuNjQuNjQgMCAwIDEgLjE3Ni4yMjUuNjQ2LjY0NiAwIDAgMSAuMDY4LjI5My43NS43NSAwIDAgMS0uMjM0LjU0Ni43OTMuNzkzIDAgMCAwIC4yMzQuMzYyLjU1Mi41NTIgMCAwIDAgLjM5LjE1Ni41ODEuNTgxIDAgMCAwIC40My0uMTY2Yy4xMTgtLjEwNC4yMDktLjIzNC4yNzQtLjM5LjA2NS0uMTUuMTA3LS4zMTMuMTI3LS40ODkuMDI2LS4xNy4wNC0uMzE5LjA0LS40NWE1LjU5IDUuNTkgMCAwIDAtLjA1LS43NDEgMTQuNDg0IDE0LjQ4NCAwIDAgMC0uMDk3LS43NDNsLS4wMS0uMDEtLjUyNy00LjMwNkgxLjYwN1Y1Ljk4aDEuMzU4YTE0Ljc1OCAxNC43NTggMCAwIDEtLjA3OC0uNzMyIDEzLjU3IDEzLjU3IDAgMCAxLS4wMi0uNzMyYzAtLjM2NS4wMzYtLjczMy4xMDgtMS4xMDRhMy4wNCAzLjA0IDAgMCAxIC4zNy0uOTk2Yy4xNzYtLjMuNDA4LS41NDQuNjk0LS43MzIuMjkzLS4xOS42NTgtLjI4NCAxLjA5NC0uMjg0YTIuMDA4IDIuMDA4IDAgMCAxIDEuMzk2LjU1N2MuMTkuMTcuMzM5LjM3MS40NS42MDUuMTEuMjM1LjE2Ni40ODkuMTY2Ljc2MnoiIGZpbGw9IiNBNkU3OUMiLz48L3N2Zz4=) no-repeat 0 0;background-size:100%;content:" ";display:inline-block;height:16px;margin-right:5px;position:relative;top:3px;width:8px}.bue-render .node.nmetasound .header .icon.input{color:#72ffde}.bue-render .node.nmetasound .header .icon.input:before{background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTE0LjM2NCAxMkg0LjcyN0M0LjM2NCAxMiA0IDExLjY3MyA0IDExLjEyOVYxLjg3YzAtLjQzNC4yNzMtLjg3LjcyNy0uODdoOS41NDZjLjM2MyAwIC43MjcuMzI3LjcyNy44NzF2OS4yNThjMCAuNTQ0LS4yNzMuODcxLS42MzYuODcxeiIgc3Ryb2tlPSIjNzJGRkRFIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiLz48cGF0aCBkPSJNMy40OCA1LjE3MUgzVjcuODNoMy41ODlWMTBsLjc3Mi0uNjEzIDMuMTQtMi40OTFMMTEgNi41bC0uNDk5LS4zOTYtMy4xNC0yLjQ5TDYuNTkgM3YyLjE3MUgzLjQ4eiIgZmlsbD0iIzcyRkZERSIgc3Ryb2tlPSIjNzJGRkRFIi8+PC9zdmc+) no-repeat 0 0;background-size:100%;content:" ";display:inline-block;height:13px;margin-right:5px;position:relative;top:2px;width:16px}.bue-render .node.nmetasound .header .icon.output{color:#fdf071}.bue-render .node.nmetasound .header .icon.output:before{background:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEyLjM2NCAxMkgyLjcyN0MyLjM2NCAxMiAyIDExLjY3MyAyIDExLjEyOVYxLjg3YzAtLjQzNC4yNzMtLjg3LjcyNy0uODdoOS41NDZjLjM2MyAwIC43MjcuMzI3LjcyNy44NzF2OS4yNThjMCAuNTQ0LS4yNzMuODcxLS42MzYuODcxeiIgc3Ryb2tlPSIjRkRGMDcxIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiLz48cGF0aCBkPSJNNy40OCA1LjE3MUg3VjcuODNoMy41ODhWMTBsLjc3My0uNjEzIDMuMTQtMi40OTFMMTUgNi41bC0uNDk5LS4zOTYtMy4xNC0yLjQ5TDEwLjU4OCAzdjIuMTcxSDcuNDgxeiIgZmlsbD0iI0ZERjA3MSIgc3Ryb2tlPSIjRkRGMDcxIi8+PC9zdmc+) no-repeat 0 0;background-size:100%;content:" ";display:inline-block;height:13px;margin-right:5px;position:relative;top:2px;width:16px}.bue-render .node.nmetasound .body{align-items:center;display:flex;justify-content:space-between}.bue-render .node.nmetasound .body .left-col{align-self:flex-start;display:unset;float:unset;top:unset}.bue-render .node.nmetasound .body .right-col{display:unset;float:unset;top:unset}.bue-render .node .nmetasound-select{min-height:27px;width:191px}.bue-render .node .space-input-select{margin-bottom:5px}.bue-render .pin{cursor:default}.bue-render .pin .div-inside{display:inline-block}.bue-render .pin .div-inside:hover.default{background-color:hsla(37,48%,77%,.3)}.bue-render .pin .div-inside:hover.exec{background-color:hsla(0,0%,100%,.3)}.bue-render .pin .div-inside:hover.bool{background-color:rgba(149,0,0,.3)}.bue-render .pin .div-inside:hover.byte{background-color:rgba(0,111,101,.3)}.bue-render .pin .div-inside:hover.class{background-color:rgba(89,0,188,.3)}.bue-render .pin .div-inside:hover.int{background-color:rgba(31,227,175,.3)}.bue-render .pin .div-inside:hover.float{background-color:rgba(161,255,69,.3)}.bue-render .pin .div-inside:hover.name{background-color:rgba(205,130,255,.3)}.bue-render .pin .div-inside:hover.asset{background-color:rgba(149,255,255,.3)}.bue-render .pin .div-inside:hover.asset-class{background-color:rgba(255,149,255,.3)}.bue-render .pin .div-inside:hover.delegate{background-color:rgba(255,56,56,.3)}.bue-render .pin .div-inside:hover.object{background-color:rgba(0,170,245,.3)}.bue-render .pin .div-inside:hover.interface{background-color:rgba(241,255,170,.3)}.bue-render .pin .div-inside:hover.string{background-color:rgba(255,0,212,.3)}.bue-render .pin .div-inside:hover.text{background-color:rgba(231,124,170,.3)}.bue-render .pin .div-inside:hover.struct{background-color:rgba(0,89,203,.3)}.bue-render .pin .div-inside:hover.wildcard{background-color:hsla(0,3%,48%,.3)}.bue-render .pin .div-inside:hover.vector{background-color:rgba(255,202,35,.3)}.bue-render .pin .div-inside:hover.rotator{background-color:rgba(160,180,255,.3)}.bue-render .pin .div-inside:hover.transform{background-color:rgba(255,115,0,.3)}.bue-render .pin .div-inside:hover.index{background-color:rgba(31,227,175,.3)}.bue-render .pin .div-inside:hover.int64{background-color:rgba(172,227,175,.3)}.bue-render .pin .div-inside:hover.double,.bue-render .pin .div-inside:hover.real{background-color:rgba(56,213,0,.3)}.bue-render .pin .div-inside:hover.soft-class{background-color:rgba(255,149,255,.3)}.bue-render .pin .div-inside:hover.soft-object{background-color:rgba(149,255,255,.3)}.bue-render .pin .div-inside:hover.audio{background-color:rgba(253,148,253,.3)}.bue-render .pin .div-inside:hover.time{background-color:rgba(149,254,254,.3)}.bue-render .pin .div-inside:hover.trigger{background-color:hsla(0,0%,100%,.3)}.bue-render .pin .div-inside:hover.wavetable{background-color:rgba(200,0,235,.3)}.bue-render .pin .div-inside:hover.pcg-spatial-data{background-color:hsla(0,0%,100%,.3)}.bue-render .pin .div-inside:hover.pcg-attribute-set{background-color:rgba(200,129,28,.3)}.bue-render .pin .div-inside:hover.pcg-point-data{background-color:rgba(63,137,255,.3)}.bue-render .pin .div-inside:hover.pcg-poly-line-data{background-color:rgba(63,225,234,.3)}.bue-render .pin .div-inside:hover.pcg-landscape-data{background-color:rgba(212,212,75,.3)}.bue-render .pin .div-inside:hover.pcg-texture-data{background-color:rgba(230,80,25,.3)}.bue-render .pin .div-inside:hover.pcg-render-target-data{background-color:hsla(9,74%,64%,.3)}.bue-render .pin .div-inside:hover.pcg-surface-data{background-color:rgba(69,196,126,.3)}.bue-render .pin .div-inside:hover.pcg-volume-data{background-color:rgba(230,69,188,.3)}.bue-render .pin .div-inside:hover.pcg-primitive-data{background-color:rgba(129,63,255,.3)}.bue-render .pin .div-inside:hover.pcg-concrete-data{background-color:rgba(179,166,250,.3)}.bue-render .pin .div-inside:hover.pcg-any-data{background-color:hsla(0,0%,58%,.3)}.bue-render .pin .connector{background-color:#000;border:2px solid #000;border-radius:50px;box-sizing:content-box;cursor:crosshair;display:inline-block;height:8px;margin-right:5px;position:relative;top:1px;width:8px}.bue-render .pin .connector:after{border-bottom:3px solid transparent;border-left:3px solid #000;border-top:3px solid transparent;content:"";float:left;height:0;left:10px;position:relative;top:1px;width:0}.bue-render .pin .connector.filled{background-color:red}.bue-render .pin .connector.default{border-color:#e1ccaa}.bue-render .pin .connector.default:after{border-left:3px solid #e1ccaa}.bue-render .pin .connector.default.filled{background-color:#e1ccaa}.bue-render .pin .connector.exec{border-color:#fff}.bue-render .pin .connector.exec:after{border-left:3px solid #fff}.bue-render .pin .connector.exec.filled{background-color:#fff}.bue-render .pin .connector.bool{border-color:#950000}.bue-render .pin .connector.bool:after{border-left:3px solid #950000}.bue-render .pin .connector.bool.filled{background-color:#950000}.bue-render .pin .connector.byte{border-color:#006f65}.bue-render .pin .connector.byte:after{border-left:3px solid #006f65}.bue-render .pin .connector.byte.filled{background-color:#006f65}.bue-render .pin .connector.class{border-color:#5900bc}.bue-render .pin .connector.class:after{border-left:3px solid #5900bc}.bue-render .pin .connector.class.filled{background-color:#5900bc}.bue-render .pin .connector.int{border-color:#1fe3af}.bue-render .pin .connector.int:after{border-left:3px solid #1fe3af}.bue-render .pin .connector.int.filled{background-color:#1fe3af}.bue-render .pin .connector.float{border-color:#a1ff45}.bue-render .pin .connector.float:after{border-left:3px solid #a1ff45}.bue-render .pin .connector.float.filled{background-color:#a1ff45}.bue-render .pin .connector.name{border-color:#cd82ff}.bue-render .pin .connector.name:after{border-left:3px solid #cd82ff}.bue-render .pin .connector.name.filled{background-color:#cd82ff}.bue-render .pin .connector.asset{border-color:#95ffff}.bue-render .pin .connector.asset:after{border-left:3px solid #95ffff}.bue-render .pin .connector.asset.filled{background-color:#95ffff}.bue-render .pin .connector.asset-class{border-color:#ff95ff}.bue-render .pin .connector.asset-class:after{border-left:3px solid #ff95ff}.bue-render .pin .connector.asset-class.filled{background-color:#ff95ff}.bue-render .pin .connector.delegate{border-color:#ff3838;border-radius:3px}.bue-render .pin .connector.delegate:after{border-left:3px solid #ff3838;content:none}.bue-render .pin .connector.delegate.filled{background-color:#ff3838}.bue-render .pin .connector.object{border-color:#00aaf5}.bue-render .pin .connector.object:after{border-left:3px solid #00aaf5}.bue-render .pin .connector.object.filled{background-color:#00aaf5}.bue-render .pin .connector.interface{border-color:#f1ffaa}.bue-render .pin .connector.interface:after{border-left:3px solid #f1ffaa}.bue-render .pin .connector.interface.filled{background-color:#f1ffaa}.bue-render .pin .connector.string{border-color:#ff00d4}.bue-render .pin .connector.string:after{border-left:3px solid #ff00d4}.bue-render .pin .connector.string.filled{background-color:#ff00d4}.bue-render .pin .connector.text{border-color:#e77caa}.bue-render .pin .connector.text:after{border-left:3px solid #e77caa}.bue-render .pin .connector.text.filled{background-color:#e77caa}.bue-render .pin .connector.struct{border-color:#0059cb}.bue-render .pin .connector.struct:after{border-left:3px solid #0059cb}.bue-render .pin .connector.struct.filled{background-color:#0059cb}.bue-render .pin .connector.wildcard{border-color:#7f7878}.bue-render .pin .connector.wildcard:after{border-left:3px solid #7f7878}.bue-render .pin .connector.wildcard.filled{background-color:#7f7878}.bue-render .pin .connector.vector{border-color:#ffca23}.bue-render .pin .connector.vector:after{border-left:3px solid #ffca23}.bue-render .pin .connector.vector.filled{background-color:#ffca23}.bue-render .pin .connector.rotator{border-color:#a0b4ff}.bue-render .pin .connector.rotator:after{border-left:3px solid #a0b4ff}.bue-render .pin .connector.rotator.filled{background-color:#a0b4ff}.bue-render .pin .connector.transform{border-color:#ff7300}.bue-render .pin .connector.transform:after{border-left:3px solid #ff7300}.bue-render .pin .connector.transform.filled{background-color:#ff7300}.bue-render .pin .connector.index{border-color:#1fe3af}.bue-render .pin .connector.index:after{border-left:3px solid #1fe3af}.bue-render .pin .connector.index.filled{background-color:#1fe3af}.bue-render .pin .connector.materialinput{border-color:#fff}.bue-render .pin .connector.materialinput:after{border-left:3px solid #fff}.bue-render .pin .connector.materialinput.filled{background-color:#fff}.bue-render .pin .connector.int64{border-color:#ace3af}.bue-render .pin .connector.int64:after{border-left:3px solid #ace3af}.bue-render .pin .connector.int64.filled{background-color:#ace3af}.bue-render .pin .connector.double{border-color:#38d500}.bue-render .pin .connector.double:after{border-left:3px solid #38d500}.bue-render .pin .connector.double.filled{background-color:#38d500}.bue-render .pin .connector.real{border-color:#38d500}.bue-render .pin .connector.real:after{border-left:3px solid #38d500}.bue-render .pin .connector.real.filled{background-color:#38d500}.bue-render .pin .connector.soft-class{border-color:#ff95ff}.bue-render .pin .connector.soft-class:after{border-left:3px solid #ff95ff}.bue-render .pin .connector.soft-class.filled{background-color:#ff95ff}.bue-render .pin .connector.soft-object{border-color:#95ffff}.bue-render .pin .connector.soft-object:after{border-left:3px solid #95ffff}.bue-render .pin .connector.soft-object.filled{background-color:#95ffff}.bue-render .pin .connector.audio{border-color:#fd94fd}.bue-render .pin .connector.audio:after{border-left:3px solid #fd94fd}.bue-render .pin .connector.audio.filled{background-color:#fd94fd}.bue-render .pin .connector.time{border-color:#95fefe}.bue-render .pin .connector.time:after{border-left:3px solid #95fefe}.bue-render .pin .connector.time.filled{background-color:#95fefe}.bue-render .pin .connector.wavetable{border-color:#c800eb}.bue-render .pin .connector.wavetable:after{border-left:3px solid #c800eb}.bue-render .pin .connector.wavetable.filled{background-color:#c800eb}.bue-render .pin .connector.enum{border-color:#006f65}.bue-render .pin .connector.enum:after{border-left:3px solid #006f65}.bue-render .pin .connector.enum.filled{background-color:#006f65}.bue-render .pin .connector.pcg-spatial-data{border-color:#fff}.bue-render .pin .connector.pcg-spatial-data:after{border-left:3px solid #fff}.bue-render .pin .connector.pcg-spatial-data.filled{background-color:#fff}.bue-render .pin .connector.pcg-attribute-set{border-color:#c8811c}.bue-render .pin .connector.pcg-attribute-set:after{border-left:3px solid #c8811c}.bue-render .pin .connector.pcg-attribute-set.filled{background-color:#c8811c}.bue-render .pin .connector.pcg-point-data{border-color:#3f89ff}.bue-render .pin .connector.pcg-point-data:after{border-left:3px solid #3f89ff}.bue-render .pin .connector.pcg-point-data.filled{background-color:#3f89ff}.bue-render .pin .connector.pcg-poly-line-data{border-color:#3fe1ea}.bue-render .pin .connector.pcg-poly-line-data:after{border-left:3px solid #3fe1ea}.bue-render .pin .connector.pcg-poly-line-data.filled{background-color:#3fe1ea}.bue-render .pin .connector.pcg-landscape-data{border-color:#d4d44b}.bue-render .pin .connector.pcg-landscape-data:after{border-left:3px solid #d4d44b}.bue-render .pin .connector.pcg-landscape-data.filled{background-color:#d4d44b}.bue-render .pin .connector.pcg-texture-data{border-color:#e65019}.bue-render .pin .connector.pcg-texture-data:after{border-left:3px solid #e65019}.bue-render .pin .connector.pcg-texture-data.filled{background-color:#e65019}.bue-render .pin .connector.pcg-render-target-data{border-color:#e77661}.bue-render .pin .connector.pcg-render-target-data:after{border-left:3px solid #e77661}.bue-render .pin .connector.pcg-render-target-data.filled{background-color:#e77661}.bue-render .pin .connector.pcg-surface-data{border-color:#45c47e}.bue-render .pin .connector.pcg-surface-data:after{border-left:3px solid #45c47e}.bue-render .pin .connector.pcg-surface-data.filled{background-color:#45c47e}.bue-render .pin .connector.pcg-volume-data{border-color:#e645bc}.bue-render .pin .connector.pcg-volume-data:after{border-left:3px solid #e645bc}.bue-render .pin .connector.pcg-volume-data.filled{background-color:#e645bc}.bue-render .pin .connector.pcg-primitive-data{border-color:#813fff}.bue-render .pin .connector.pcg-primitive-data:after{border-left:3px solid #813fff}.bue-render .pin .connector.pcg-primitive-data.filled{background-color:#813fff}.bue-render .pin .connector.pcg-concrete-data{border-color:#b3a6fa}.bue-render .pin .connector.pcg-concrete-data:after{border-left:3px solid #b3a6fa}.bue-render .pin .connector.pcg-concrete-data.filled{background-color:#b3a6fa}.bue-render .pin .connector.pcg-any-data{border-color:#959595}.bue-render .pin .connector.pcg-any-data:after{border-left:3px solid #959595}.bue-render .pin .connector.pcg-any-data.filled{background-color:#959595}.bue-render .pin .connector.ref{border-radius:0;height:5px;transform:rotate(45deg);width:5px}.bue-render .pin .connector.ref:after{border:0}.bue-render .pin .connector.staticenum{background:transparent url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSIjMDA2RjY1IiBmaWxsPSJub25lIiBkPSJNMSA4cy41LTUuMyA0LjktNS4zYzIuMiAwIDQuNi44IDYuOSAyLjQgMi4zIDEuNSAzLjkgMyAzLjkgMy4xIDAgMC0xLjYgMS45LTMuNiAzLjEtMS45IDEuMi00LjMgMi4zLTYuOSAyLjNDMS4xIDEzLjYgMSA3LjkgMSA3LjkiLz48cGF0aCBzdHJva2U9IiMwMDZGNjUiIGZpbGw9Im5vbmUiIGQ9Ik00LjUgMTB2MmgzVjhoLTNWNC41aDN2MS43Ii8+PC9zdmc+) no-repeat;border:none;border-radius:unset;cursor:crosshair;display:inline-block;height:14px;margin-right:2px;position:relative;top:2px;width:17px}.bue-render .pin .connector.staticenum:after{border:none}.bue-render .pin .connector.staticenum.filled{background:transparent url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSIjMDA2RjY1IiBmaWxsPSIjMDA2RjY1IiBkPSJNMSA4cy41LTUuMyA0LjktNS4zYzIuMiAwIDQuNi44IDYuOSAyLjQgMi4zIDEuNSAzLjkgMyAzLjkgMy4xIDAgMC0xLjYgMS45LTMuNiAzLjEtMS45IDEuMi00LjMgMi4zLTYuOSAyLjNDMS4xIDEzLjYgMSA3LjkgMSA3LjkiLz48cGF0aCBzdHJva2U9IiMwMDAiIGZpbGw9Im5vbmUiIGQ9Ik00LjUgMTB2MmgzVjhoLTNWNC41aDN2MS43Ii8+PC9zdmc+) no-repeat}.bue-render .pin .connector.statictype-int{background:transparent url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSIjMUZFM0FGIiBmaWxsPSJub25lIiBkPSJNMSA4cy41LTUuMyA0LjktNS4zYzIuMiAwIDQuNi44IDYuOSAyLjQgMi4zIDEuNSAzLjkgMyAzLjkgMy4xIDAgMC0xLjYgMS45LTMuNiAzLjEtMS45IDEuMi00LjMgMi4zLTYuOSAyLjNDMS4xIDEzLjYgMSA3LjkgMSA3LjkiLz48cGF0aCBzdHJva2U9IiMxRkUzQUYiIGZpbGw9Im5vbmUiIGQ9Ik00LjUgMTB2MmgzVjhoLTNWNC41aDN2MS43Ii8+PC9zdmc+) no-repeat;border:none;border-radius:unset;cursor:crosshair;display:inline-block;height:14px;margin-right:2px;position:relative;top:2px;width:17px}.bue-render .pin .connector.statictype-int:after{border:none}.bue-render .pin .connector.statictype-int.filled{background:transparent url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSIjMUZFM0FGIiBmaWxsPSIjMUZFM0FGIiBkPSJNMSA4cy41LTUuMyA0LjktNS4zYzIuMiAwIDQuNi44IDYuOSAyLjQgMi4zIDEuNSAzLjkgMyAzLjkgMy4xIDAgMC0xLjYgMS45LTMuNiAzLjEtMS45IDEuMi00LjMgMi4zLTYuOSAyLjNDMS4xIDEzLjYgMSA3LjkgMSA3LjkiLz48cGF0aCBzdHJva2U9IiMwMDAiIGZpbGw9Im5vbmUiIGQ9Ik00LjUgMTB2MmgzVjhoLTNWNC41aDN2MS43Ii8+PC9zdmc+) no-repeat}.bue-render .pin .connector.statictype-bool{background:transparent url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSIjOTUwMDAwIiBmaWxsPSJub25lIiBkPSJNMSA4cy41LTUuMyA0LjktNS4zYzIuMiAwIDQuNi44IDYuOSAyLjQgMi4zIDEuNSAzLjkgMyAzLjkgMy4xIDAgMC0xLjYgMS45LTMuNiAzLjEtMS45IDEuMi00LjMgMi4zLTYuOSAyLjNDMS4xIDEzLjYgMSA3LjkgMSA3LjkiLz48cGF0aCBzdHJva2U9IiM5NTAwMDAiIGZpbGw9Im5vbmUiIGQ9Ik00LjUgMTB2MmgzVjhoLTNWNC41aDN2MS43Ii8+PC9zdmc+) no-repeat;border:none;border-radius:unset;cursor:crosshair;display:inline-block;height:14px;margin-right:2px;position:relative;top:2px;width:17px}.bue-render .pin .connector.statictype-bool:after{border:none}.bue-render .pin .connector.statictype-bool.filled{background:transparent url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggc3Ryb2tlPSIjOTUwMDAwIiBmaWxsPSIjOTUwMDAwIiBkPSJNMSA4cy41LTUuMyA0LjktNS4zYzIuMiAwIDQuNi44IDYuOSAyLjQgMi4zIDEuNSAzLjkgMyAzLjkgMy4xIDAgMC0xLjYgMS45LTMuNiAzLjEtMS45IDEuMi00LjMgMi4zLTYuOSAyLjNDMS4xIDEzLjYgMSA3LjkgMSA3LjkiLz48cGF0aCBzdHJva2U9IiMwMDAiIGZpbGw9Im5vbmUiIGQ9Ik00LjUgMTB2MmgzVjhoLTNWNC41aDN2MS43Ii8+PC9zdmc+) no-repeat}.bue-render .pin .connector-image.exec{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAQCAQAAACIaFaMAAAAY0lEQVR42mNgwAX++/1/+x8C3v73Q5Z4ciqaQQoE//v9f4Ik9f8/RBgEzyf8/w+XQpYA64JJoUog6UKXgOvClIBIkSKBwyi4u4hyLpIwKEjOJ8B9gBIkHv+fQwPx+X8PBsIAAN/VbnUHQrhKAAAAAElFTkSuQmCC) no-repeat;cursor:crosshair;display:inline-block;height:16px;margin-right:5px;position:relative;top:1px;width:12px}.bue-render .pin .connector-image.exec.filled{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAQCAQAAACIaFaMAAAAVklEQVR42mNgwAVORM/8D4MnopEkZv5/duc/GDy7M/P/yVAkCWSAJIUqgSSFLgGXwpSASmGTAEmRJoHDKByW43Auigcf34YIPr6NEiQnQxGBiCSMGwAA6HX4M2XGYHEAAAAASUVORK5CYII=) no-repeat}.bue-render .pin .connector-set{cursor:crosshair;display:inline-block;font-family:monospace;font-size:18px;font-weight:700;width:22px}.bue-render .pin .connector-set:after{content:"{}"}.bue-render .pin .connector-set.default{color:#e1ccaa}.bue-render .pin .connector-set.exec{color:#fff}.bue-render .pin .connector-set.bool{color:#950000}.bue-render .pin .connector-set.byte{color:#006f65}.bue-render .pin .connector-set.class{color:#5900bc}.bue-render .pin .connector-set.int{color:#1fe3af}.bue-render .pin .connector-set.float{color:#a1ff45}.bue-render .pin .connector-set.name{color:#cd82ff}.bue-render .pin .connector-set.asset{color:#95ffff}.bue-render .pin .connector-set.asset-class{color:#ff95ff}.bue-render .pin .connector-set.delegate{color:#ff3838}.bue-render .pin .connector-set.object{color:#00aaf5}.bue-render .pin .connector-set.interface{color:#f1ffaa}.bue-render .pin .connector-set.string{color:#ff00d4}.bue-render .pin .connector-set.text{color:#e77caa}.bue-render .pin .connector-set.struct{color:#0059cb}.bue-render .pin .connector-set.wildcard{color:#7f7878}.bue-render .pin .connector-set.vector{color:#ffca23}.bue-render .pin .connector-set.rotator{color:#a0b4ff}.bue-render .pin .connector-set.transform{color:#ff7300}.bue-render .pin .connector-set.index{color:#1fe3af}.bue-render .pin .connector-set.materialinput{color:#fff}.bue-render .pin .connector-set.int64{color:#ace3af}.bue-render .pin .connector-set.double,.bue-render .pin .connector-set.real{color:#38d500}.bue-render .pin .connector-set.soft-class{color:#ff95ff}.bue-render .pin .connector-set.soft-object{color:#95ffff}.bue-render .pin .connector-set.wavetable{color:#c800eb}.bue-render .pin .connector-array{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAJElEQVR4AWMQFRVFxv/x8Wmr+D+xGMNkTIyQp55iyt088OEMAMYGTpdQIyXgAAAAAElFTkSuQmCC) no-repeat;cursor:crosshair;display:inline-block;height:11px;margin-right:5px;width:11px}.bue-render .pin .connector-array.filled{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAG0lEQVR4AWMQFRVFxv/x8Wmr+D+xeNTNZCsGACg0RaB8zNMXAAAAAElFTkSuQmCC) no-repeat}.bue-render .pin .connector-array.default{background-color:#e1ccaa}.bue-render .pin .connector-array.exec{background-color:#fff}.bue-render .pin .connector-array.bool{background-color:#950000}.bue-render .pin .connector-array.byte{background-color:#006f65}.bue-render .pin .connector-array.class{background-color:#5900bc}.bue-render .pin .connector-array.int{background-color:#1fe3af}.bue-render .pin .connector-array.float{background-color:#a1ff45}.bue-render .pin .connector-array.name{background-color:#cd82ff}.bue-render .pin .connector-array.asset{background-color:#95ffff}.bue-render .pin .connector-array.asset-class{background-color:#ff95ff}.bue-render .pin .connector-array.delegate{background-color:#ff3838}.bue-render .pin .connector-array.object{background-color:#00aaf5}.bue-render .pin .connector-array.interface{background-color:#f1ffaa}.bue-render .pin .connector-array.string{background-color:#ff00d4}.bue-render .pin .connector-array.text{background-color:#e77caa}.bue-render .pin .connector-array.struct{background-color:#0059cb}.bue-render .pin .connector-array.wildcard{background-color:#7f7878}.bue-render .pin .connector-array.vector{background-color:#ffca23}.bue-render .pin .connector-array.rotator{background-color:#a0b4ff}.bue-render .pin .connector-array.transform{background-color:#ff7300}.bue-render .pin .connector-array.index{background-color:#1fe3af}.bue-render .pin .connector-array.int64{background-color:#ace3af}.bue-render .pin .connector-array.double,.bue-render .pin .connector-array.real{background-color:#38d500}.bue-render .pin .connector-array.soft-class{background-color:#ff95ff}.bue-render .pin .connector-array.soft-object{background-color:#95ffff}.bue-render .pin .connector-array.time{background-color:#95fefe}.bue-render .pin .connector-array.wavetable{background-color:#c800eb}.bue-render .pin .connector-map{cursor:crosshair;display:inline-block}.bue-render .pin .connector-map .key{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAOCAQAAACiY3WTAAAAF0lEQVR42mNgAIP/vAx4GKL/IZCB2ooBE+0VMQkh1i4AAAAASUVORK5CYII=) no-repeat;display:inline-block;height:14px;margin-right:2px;width:4px}.bue-render .pin .connector-map .value{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAOCAQAAABXnf4jAAAAGElEQVR42mNgoBb4x8so+p8IVYPTeAYGADzQBldIo2V4AAAAAElFTkSuQmCC) no-repeat;display:inline-block;height:14px;margin-right:5px;width:9px}.bue-render .pin .connector-map .key.default,.bue-render .pin .connector-map .value.default{background-color:#e1ccaa}.bue-render .pin .connector-map .key.exec,.bue-render .pin .connector-map .value.exec{background-color:#fff}.bue-render .pin .connector-map .key.bool,.bue-render .pin .connector-map .value.bool{background-color:#950000}.bue-render .pin .connector-map .key.byte,.bue-render .pin .connector-map .value.byte{background-color:#006f65}.bue-render .pin .connector-map .key.class,.bue-render .pin .connector-map .value.class{background-color:#5900bc}.bue-render .pin .connector-map .key.int,.bue-render .pin .connector-map .value.int{background-color:#1fe3af}.bue-render .pin .connector-map .key.float,.bue-render .pin .connector-map .value.float{background-color:#a1ff45}.bue-render .pin .connector-map .key.name,.bue-render .pin .connector-map .value.name{background-color:#cd82ff}.bue-render .pin .connector-map .key.asset,.bue-render .pin .connector-map .value.asset{background-color:#95ffff}.bue-render .pin .connector-map .key.asset-class,.bue-render .pin .connector-map .value.asset-class{background-color:#ff95ff}.bue-render .pin .connector-map .key.delegate,.bue-render .pin .connector-map .value.delegate{background-color:#ff3838}.bue-render .pin .connector-map .key.object,.bue-render .pin .connector-map .value.object{background-color:#00aaf5}.bue-render .pin .connector-map .key.interface,.bue-render .pin .connector-map .value.interface{background-color:#f1ffaa}.bue-render .pin .connector-map .key.string,.bue-render .pin .connector-map .value.string{background-color:#ff00d4}.bue-render .pin .connector-map .key.text,.bue-render .pin .connector-map .value.text{background-color:#e77caa}.bue-render .pin .connector-map .key.struct,.bue-render .pin .connector-map .value.struct{background-color:#0059cb}.bue-render .pin .connector-map .key.wildcard,.bue-render .pin .connector-map .value.wildcard{background-color:#7f7878}.bue-render .pin .connector-map .key.vector,.bue-render .pin .connector-map .value.vector{background-color:#ffca23}.bue-render .pin .connector-map .key.rotator,.bue-render .pin .connector-map .value.rotator{background-color:#a0b4ff}.bue-render .pin .connector-map .key.transform,.bue-render .pin .connector-map .value.transform{background-color:#ff7300}.bue-render .pin .connector-map .key.index,.bue-render .pin .connector-map .value.index{background-color:#1fe3af}.bue-render .pin .connector-map .key.int64,.bue-render .pin .connector-map .value.int64{background-color:#ace3af}.bue-render .pin .connector-map .key.double,.bue-render .pin .connector-map .key.real,.bue-render .pin .connector-map .value.double,.bue-render .pin .connector-map .value.real{background-color:#38d500}.bue-render .pin .connector-map .key.soft-class,.bue-render .pin .connector-map .value.soft-class{background-color:#ff95ff}.bue-render .pin .connector-map .key.soft-object,.bue-render .pin .connector-map .value.soft-object{background-color:#95ffff}.bue-render .pin .connector-map .key.time,.bue-render .pin .connector-map .value.time{background-color:#95fefe}.bue-render .pin .connector-map .key.wavetable,.bue-render .pin .connector-map .value.wavetable{background-color:#c800eb}.bue-render .pin .connector-trigger.trigger{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAAAx0lEQVR4AXVSARGDMBBrUVAJSMDBcMIk4IA5YA5qYVPAHCCBORgOuvzuO9LS5i4H6aeh/8UaQgjB4TGAHbiDT2vti+o9a5NtvocyNrCNAaxrmz04gJOa8xCfhGhqRJe3BK4xOPN7Q4mCudJaq/WPzsjo+0830K16H6UADO2Nh9CR968b8jpTx16tyNGTnuotbLR2aDIIboXNm9YmXetPM4MYQ3rvHlxobSXvojfj8qNe6WuMmaY/shbYQs8Xc0xbfuWdao614AvOEFYm+pLoCwAAAABJRU5ErkJggg==) no-repeat;cursor:crosshair;display:inline-block;height:12px;image-rendering:-webkit-optimize-contrast;margin-right:5px;position:relative;top:1px;width:16px}.bue-render .pin .connector-trigger.trigger.filled{background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAMCAYAAABr5z2BAAAAq0lEQVQokY2R0RGCMBBE31FBSrAEO5BOtAQ6QSuIJUgF2gElYAfQwfpBogcDY95Xdu5uL9kYDkkBOANHYAI6M3u5eu31AklXbTNIOmQDr0uGt0ziwiS5lhBX/RHnWMKoOSPSeZQUKmD5nn2C631nXRUO7yOpLXzC4Ga+ugJuhbvuabhO+uFv0fzZ3rvep6Q+B+pNLpr/d03r0m+8BrCNTE780u7MbHK14DXAB0WHarPGBdRjAAAAAElFTkSuQmCC) no-repeat}.bue-render .pin .label-text{display:inline-block;padding-right:5px;vertical-align:text-top}.bue-render .pin .label-text.icon-plus:before{content:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAQAAAD8fJRsAAAAMklEQVR42mNggIL/e////7+XARP8BwOKJMBmo4O9cJXoACSxHYv4duq6Ci6xHc1sXAAAMxZvZzucCzkAAAAASUVORK5CYII=);padding-left:5px}.bue-render .pin .tri-input-wrapper{margin-left:26px}.bue-render .pin span.fake-input{border:1px solid grey;border-radius:2px;color:#fff;display:inline-block;line-height:14px;min-height:14px;min-width:7px;padding-left:4px;padding-right:4px;padding-top:2px;vertical-align:text-top;white-space:pre}.bue-render .pin span.fake-input.axis{margin-right:3px}.bue-render .pin span.fake-input.axis-X:before{color:grey;content:"X";padding-right:5px}.bue-render .pin span.fake-input.axis-Y:before{color:grey;content:"Y";padding-right:5px}.bue-render .pin span.fake-input.axis-Z:before{color:grey;content:"Z";padding-right:5px}.bue-render .pin span.fake-input.axis-W:before{color:grey;content:"W";padding-right:5px}.bue-render .pin span.fake-input-colorpicker{background-color:transparent;border:1px inset grey;display:inline-block;height:16px;padding:0;vertical-align:text-top;width:16px}.bue-render .pin span.no-input{display:block;height:1px;width:1px}.bue-render .pin span.fake-input-select{background-color:#20221f;border:0;border-radius:2px;color:#fff;display:inline-block;font-size:11px;line-height:11px;margin-left:26px;min-height:14px;min-width:7px;padding-left:4px;padding-right:4px;padding-top:2px;vertical-align:text-top;white-space:pre}.bue-render .pin .checkbox{left:2px;padding:0;position:relative;top:2px}.bue-render .pin .dropdown{border-color:#909090 transparent transparent;border-style:solid;border-width:7px 6px 0;cursor:pointer;display:inline-block;height:0;margin-left:5px;width:0}.bue-render .pin .asset-browser{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAgElEQVR4AWP4//8/OhYC4m4gFsYix4AuIAjEF/5DAD8hDSJAfByq+AVIDJ8GXiA+8h8BPgOxNxDbI2E1mAYJID7zHx9AGGLOADaZeLAPpKGNBA1HYX6YRoTiH0DshBwCs5EkP2HxtBbM09g0vcUXrOh4E1STILEamIC4CxrcGPIAWhns4nl183oAAAAASUVORK5CYII=);margin-left:2px}.bue-render .pin .asset-browser,.bue-render .pin .browse{cursor:pointer;display:inline-block;height:12px;position:relative;top:3px;width:12px}.bue-render .pin .browse{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAQAAAD8fJRsAAAApklEQVQYGQXBsSoEAACA4T8hm0FsViWDpJsMXsDoAe4dGMxGWRTblYFJXeINLEbDTRgUg0nCJMvn+5IkAyMT9/YsSEmyj1eXbvFmXUmGODQvWTXxYzGZ9uZOkmQZB8mGb7uSJLn2kGz5si1JkpGnZMmnY0mSPLpIcubPmiQ5wmYy4xq/TuwYusOBMmeMK6defHj3bFfKDW7NyayBFUnK2LkpSZIk/QMfG7yjbyfEKQAAAABJRU5ErkJggg==);margin-left:4px}.bue-render .pin.hidden{display:none}.bue-render .pin .connector-pcg-attribute-set{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjMgOCAzMCAyMCI+PHBhdGggZD0iTTggMThjLTIuNSAwLTQuNS0yLTQuNS00LjVTNS41IDkgOCA5aDIwYzIuNSAwIDQuNSAyIDQuNSA0LjVTMzAuNSAxOCAyOCAxOEg4eiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMyMzEzMDEiLz48cGF0aCBkPSJNMjggOS41YzIuMiAwIDQgMS44IDQgNHMtMS44IDQtNCA0SDhjLTIuMiAwLTQtMS44LTQtNHMxLjgtNCA0LTRoMjBtMC0xSDhjLTIuOCAwLTUgMi4yLTUgNXMyLjIgNSA1IDVoMjBjMi44IDAgNS0yLjIgNS01cy0yLjItNS01LTV6IiBmaWxsPSIjYzg4MTFjIi8+PHBhdGggZD0iTTMxIDI3LjVIMTNjLS41IDAtMS0uNC0xLTF2LTRjMC0uNS40LTEgMS0xaDE4Yy41IDAgMSAuNCAxIDF2NGMwIC42LS40IDEtMSAxeiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNjODgxMWMiIHN0cm9rZT0iIzIzMTMwMSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9zdmc+) no-repeat;cursor:crosshair;display:inline-block;height:16px;margin-right:3px;position:relative;top:6px;width:18px}.bue-render .pin .connector-pcg-attribute-set.filled{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjMgOCAzMCAyMCI+PHBhdGggZD0iTTggMThjLTIuNSAwLTQuNS0yLTQuNS00LjVTNS41IDkgOCA5aDIwYzIuNSAwIDQuNSAyIDQuNSA0LjVTMzAuNSAxOCAyOCAxOEg4eiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNjODgxMWMiLz48cGF0aCBkPSJNMjggOS41YzIuMiAwIDQgMS44IDQgNHMtMS44IDQtNCA0SDhjLTIuMiAwLTQtMS44LTQtNHMxLjgtNCA0LTRoMjBtMC0xSDhjLTIuOCAwLTUgMi4yLTUgNXMyLjIgNSA1IDVoMjBjMi44IDAgNS0yLjIgNS01cy0yLjItNS01LTV6IiBmaWxsPSIjMjMxMzAxIi8+PHBhdGggZD0iTTMxIDI3LjVIMTNjLS41IDAtMS0uNC0xLTF2LTRjMC0uNS40LTEgMS0xaDE4Yy41IDAgMSAuNCAxIDF2NGMwIC42LS40IDEtMSAxeiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiNjODgxMWMiIHN0cm9rZT0iIzIzMTMwMSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9zdmc+) no-repeat}.bue-render .pin .connector-pcg-spatial-data{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQgMiAzMiAzMiI+PHBhdGggZD0iTTIwLjUgMzNoLTEwYy0yLjggMC01LTIuMi01LTVWOGMwLTIuOCAyLjItNSA1LTVoMTBjMi44IDAgNSAyLjIgNSA1djIwYzAgMi44LTIuMiA1LTUgNXoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSJncmF5IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PGNpcmNsZSBjeD0iMjMuNyIgY3k9IjE4IiByPSIxMCIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMyMDIwMjAiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiLz48L3N2Zz4=) no-repeat;cursor:crosshair;display:inline-block;height:18px;margin-right:3px;position:relative;top:4px;width:18px}.bue-render .pin .connector-pcg-spatial-data.filled{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjQgMiAzMiAzMiI+PGNpcmNsZSBjeD0iMTUiIGN5PSIyMy4zIiByPSI4IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZmlsbD0iI2MzYzNjMyIgc3Ryb2tlPSIjNDY0NjQ2Ii8+PHBhdGggZD0iTTIwLjUgMzNoLTEwYy0yLjggMC01LTIuMi01LTVWOGMwLTIuOCAyLjItNSA1LTVoMTBjMi44IDAgNSAyLjIgNSA1djIwYzAgMi44LTIuMiA1LTUgNXoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjODc4Nzg3IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PGNpcmNsZSBjeD0iMjMuNyIgY3k9IjE4IiByPSI5LjUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjZmZmIi8+PHBhdGggZD0iTTIzLjcgMjdjLTUgMC05LTQtOS05czQtOSA5LTkgOSA0IDkgOS00IDktOSA5bTAgMWM1LjUgMCAxMC00LjUgMTAtMTBzLTQuNS0xMC0xMC0xMC0xMCA0LjUtMTAgMTAgNC41IDEwIDEwIDEweiIgZmlsbD0iIzQ2NDY0NiIvPjwvc3ZnPg==) no-repeat}.bue-render .pin .connector-pcg-multiple-data-multiple-connection{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjMgMCAyOSAzNiI+PHN0eWxlPi5zdDR7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojMDIxYjFjO3N0cm9rZTojMGU0NzRhO3N0cm9rZS13aWR0aDoxLjV9PC9zdHlsZT48cGF0aCBkPSJNMjUuOCAzMi4yVjE3LjVjMC0xLjcgMS4zLTMuMSAzLTMuMXMzIDEuMyAzIDMuMXYxNC43YzAgMS44LTEuMyAzLjItMyAzLjItMS44LjEtMy0xLjQtMy0zLjJ6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZmlsbD0iIzFkNzY3YiIgc3Ryb2tlPSIjMGU0NzRhIiBzdHJva2UtbGluZWNhcD0icm91bmQiLz48cGF0aCBkPSJNMTguOCAzMC4xVjExLjhjMC0yLjQgMS44LTQuMyA0LTQuM3M0IDEuOSA0IDQuM3YxOC40YzAgMi40LTEuOCA0LjMtNCA0LjMtMi4zIDAtNC0yLTQtNC40eiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMyZWFjYjMiIHN0cm9rZT0iIzBlNDc0YSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PHBhdGggZD0iTTIxLjMgNi40djIxLjNjMCAzLjItMi40IDUuOC01LjUgNS44cy01LjUtMi41LTUuNS01LjhWNi4zYzAtMy4yIDIuNC01LjggNS41LTUuOCAzIDAgNS40IDIuNSA1LjUgNS45eiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMzZmUxZWEiLz48cGF0aCBkPSJNMTUuOCAzM2MtMi45IDAtNS0yLjMtNS01LjNWNi4zYzAtMyAyLjItNS4zIDUtNS4zczUgMi4zIDUgNS4zdjIxLjNjMCAzLTIuMiA1LjQtNSA1LjRtMCAxYzMuMyAwIDYtMi44IDYtNi4zVjYuM2MwLTMuNS0yLjYtNi4zLTYtNi4zcy02IDIuNy02IDYuM3YyMS4zYzAgMy41IDIuNiA2LjQgNiA2LjR6IiBmaWxsPSIjMGU0NzRhIi8+PGNpcmNsZSBjbGFzcz0ic3Q0IiBjeD0iMTAuMiIgY3k9IjkiIHI9IjYiLz48Y2lyY2xlIGNsYXNzPSJzdDQiIGN4PSIxMC4yIiBjeT0iMTciIHI9IjYiLz48Y2lyY2xlIGNsYXNzPSJzdDQiIGN4PSIxMC4yIiBjeT0iMjUiIHI9IjYiLz48L3N2Zz4=) no-repeat;cursor:crosshair;display:inline-block;height:20px;left:-2px;margin-top:-4px;position:relative;top:6px;width:18px}.bue-render .pin .connector-pcg-multiple-data-multiple-connection.filled{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjMgMCAyOSAzNiI+PHN0eWxlPi5zdDR7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojM2ZlMWVhO3N0cm9rZTojMGU0NzRhfTwvc3R5bGU+PHBhdGggZD0iTTI1LjggMzIuMlYxNy41YzAtMS43IDEuMy0zLjEgMy0zLjFzMyAxLjMgMyAzLjF2MTQuN2MwIDEuOC0xLjMgMy4yLTMgMy4yLTEuOC4xLTMtMS40LTMtMy4yeiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMxZDc2N2IiIHN0cm9rZT0iIzBlNDc0YSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PHBhdGggZD0iTTE4LjggMzAuMVYxMS44YzAtMi40IDEuOC00LjMgNC00LjNzNCAxLjkgNCA0LjN2MTguNGMwIDIuNC0xLjggNC4zLTQgNC4zLTIuMyAwLTQtMi00LTQuNHoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjMmVhY2IzIiBzdHJva2U9IiMwZTQ3NGEiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPjxwYXRoIGQ9Ik0yMS4zIDYuNHYyMS4zYzAgMy4yLTIuNCA1LjgtNS41IDUuOHMtNS41LTIuNS01LjUtNS44VjYuM2MwLTMuMiAyLjQtNS44IDUuNS01LjggMyAwIDUuNCAyLjUgNS41IDUuOXoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjM2ZlMWVhIi8+PHBhdGggZD0iTTE1LjggMzNjLTIuOSAwLTUtMi4zLTUtNS4zVjYuM2MwLTMgMi4yLTUuMyA1LTUuM3M1IDIuMyA1IDUuM3YyMS4zYzAgMy0yLjIgNS40LTUgNS40bTAgMWMzLjMgMCA2LTIuOCA2LTYuM1Y2LjNjMC0zLjUtMi42LTYuMy02LTYuM3MtNiAyLjctNiA2LjN2MjEuM2MwIDMuNSAyLjYgNi40IDYgNi40eiIgZmlsbD0iIzBlNDc0YSIvPjxjaXJjbGUgY2xhc3M9InN0NCIgY3g9IjEwLjIiIGN5PSI5IiByPSI2Ii8+PGNpcmNsZSBjbGFzcz0ic3Q0IiBjeD0iMTAuMiIgY3k9IjE3IiByPSI2Ii8+PGNpcmNsZSBjbGFzcz0ic3Q0IiBjeD0iMTAuMiIgY3k9IjI1IiByPSI2Ii8+PC9zdmc+) no-repeat}.bue-render .pin .connector-pcg-multiple-data-single-connection{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjkgMSAxOCAzNCI+PHN0eWxlPi5zdDJ7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojMDIxYjFjO3N0cm9rZTojMGU0NzRhO3N0cm9rZS13aWR0aDoxLjV9PC9zdHlsZT48cGF0aCBkPSJNMjEuMiAzNC41Yy0zLjEgMC01LjUtMi42LTUuNS01LjhWNy4zYzAtMy4zIDIuNC01LjggNS41LTUuOHM1LjUgMi42IDUuNSA1Ljh2MjEuM2MuMSAzLjMtMi40IDUuOS01LjUgNS45eiIgZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGZpbGw9IiMzZmUxZWEiLz48cGF0aCBkPSJNMjEuMiAyYzIuOCAwIDUgMi4zIDUgNS4zdjIxLjNjMCAzLTIuMiA1LjMtNSA1LjNzLTUtMi4zLTUtNS4zVjcuM2MwLTMgMi4zLTUuMyA1LTUuM20wLTFjLTMuNCAwLTYgMi44LTYgNi4zdjIxLjNjMCAzLjYgMi42IDYuMyA2IDYuM3M2LTIuOCA2LTYuM1Y3LjNjMC0zLjUtMi42LTYuMy02LTYuM3oiIGZpbGw9IiMwZTQ3NGEiLz48Y2lyY2xlIGNsYXNzPSJzdDIiIGN4PSIxNS44IiBjeT0iMTAiIHI9IjYiLz48Y2lyY2xlIGNsYXNzPSJzdDIiIGN4PSIxNS44IiBjeT0iMTgiIHI9IjYiLz48Y2lyY2xlIGNsYXNzPSJzdDIiIGN4PSIxNS44IiBjeT0iMjYiIHI9IjYiLz48L3N2Zz4=) no-repeat;cursor:crosshair;display:inline-block;height:20px;margin-right:3px;margin-top:-4px;position:relative;top:6px;width:12px}.bue-render .pin .connector-pcg-multiple-data-single-connection.filled{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjkgMSAxOCAzNCI+PHN0eWxlPi5zdDJ7ZmlsbC1ydWxlOmV2ZW5vZGQ7Y2xpcC1ydWxlOmV2ZW5vZGQ7ZmlsbDojM2ZlMWVhO3N0cm9rZTojMGU0NzRhfTwvc3R5bGU+PHBhdGggZD0iTTIxLjIgMzQuNWMtMy4xIDAtNS41LTIuNi01LjUtNS44VjcuM2MwLTMuMyAyLjQtNS44IDUuNS01LjhzNS41IDIuNiA1LjUgNS44djIxLjNjLjEgMy4zLTIuNCA1LjktNS41IDUuOXoiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBmaWxsPSIjM2ZlMWVhIi8+PHBhdGggZD0iTTIxLjIgMmMyLjggMCA1IDIuMyA1IDUuM3YyMS4zYzAgMy0yLjIgNS4zLTUgNS4zcy01LTIuMy01LTUuM1Y3LjNjMC0zIDIuMy01LjMgNS01LjNtMC0xYy0zLjQgMC02IDIuOC02IDYuM3YyMS4zYzAgMy42IDIuNiA2LjMgNiA2LjNzNi0yLjggNi02LjNWNy4zYzAtMy41LTIuNi02LjMtNi02LjN6IiBmaWxsPSIjMGU0NzRhIi8+PGNpcmNsZSBjbGFzcz0ic3QyIiBjeD0iMTUuOCIgY3k9IjEwIiByPSI2Ii8+PGNpcmNsZSBjbGFzcz0ic3QyIiBjeD0iMTUuOCIgY3k9IjE4IiByPSI2Ii8+PGNpcmNsZSBjbGFzcz0ic3QyIiBjeD0iMTUuOCIgY3k9IjI2IiByPSI2Ii8+PC9zdmc+) no-repeat}.bue-render .right-col .pin .connector-pcg-attribute-set,.bue-render .right-col .pin .connector-pcg-spatial-data{margin-right:0;transform:scaleX(-1)}.bue-render .right-col .pin .connector-pcg-multiple-data-multiple-connection{left:0;margin-right:0;transform:scaleX(-1)}.bue-render .right-col .pin .connector-pcg-multiple-data-single-connection{transform:scaleX(-1)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-any-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-any-data{filter:grayscale(1)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-point-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-point-data{filter:brightness(67%) hue-rotate(43deg) saturate(150%)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-landscape-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-landscape-data{filter:brightness(155%) hue-rotate(250deg) saturate(110%)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-texture-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-texture-data{filter:brightness(70%) hue-rotate(190deg) saturate(170%)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-render-target-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-render-target-data{filter:brightness(92%) hue-rotate(184deg) saturate(128%)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-surface-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-surface-data{filter:hue-rotate(326deg)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-volume-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-volume-data{filter:brightness(80%) hue-rotate(128deg) saturate(150%)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-primitive-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-primitive-data{filter:brightness(74%) hue-rotate(77deg) saturate(250%)}.bue-render .clink.connector-pcg-multiple-data-multiple-connection.pcg-concrete-data,.bue-render .clink.connector-pcg-multiple-data-single-connection.pcg-concrete-data{filter:hue-rotate(68deg)} \ No newline at end of file