inkcpp_rb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +84 -0
- data/LICENSE +7 -0
- data/README.md +3 -0
- data/Rakefile +16 -0
- data/bin/console +15 -0
- data/bin/setup +10 -0
- data/bin/tapioca +29 -0
- data/ext/inkcpp_rb/extconf.rb +19 -0
- data/ext/inkcpp_rb/inkcpp/.clang-format +99 -0
- data/ext/inkcpp_rb/inkcpp/.github/FUNDING.yml +1 -0
- data/ext/inkcpp_rb/inkcpp/.github/workflows/build.yml +344 -0
- data/ext/inkcpp_rb/inkcpp/.github/workflows/release.yml +49 -0
- data/ext/inkcpp_rb/inkcpp/.gitignore +25 -0
- data/ext/inkcpp_rb/inkcpp/.gitmodules +9 -0
- data/ext/inkcpp_rb/inkcpp/CMakeLists.txt +170 -0
- data/ext/inkcpp_rb/inkcpp/CODE_OF_CONDUCT.md +76 -0
- data/ext/inkcpp_rb/inkcpp/CONTRIBUTING.md +55 -0
- data/ext/inkcpp_rb/inkcpp/Config.cmake.in +2 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/CMakeLists.txt +13 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/main.c +38 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/main.cpp +40 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/test.ink +8 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/test.ink.json +1 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example.zip +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/InkCPP_DEMO.zip +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/CreateThread.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/HandleChoice.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/ListElementOf.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/MinimalRuntime.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/MinimalThread.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/ObseverChange.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/TagListGetValue.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/YieldResume.png +0 -0
- data/ext/inkcpp_rb/inkcpp/Doxyfile +2825 -0
- data/ext/inkcpp_rb/inkcpp/LICENSE.txt +22 -0
- data/ext/inkcpp_rb/inkcpp/Minimal.runsettings +8 -0
- data/ext/inkcpp_rb/inkcpp/README.md +192 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/CMakeLists.txt +67 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/array.h +481 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/avl_array.h +833 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/casting.h +93 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/choice.cpp +54 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/collections/restorable.cpp +124 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/collections/restorable.h +406 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/container_operations.cpp +52 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/container_operations.h +34 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/executioner.h +179 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/functional.cpp +86 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/functions.cpp +54 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/functions.h +40 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/globals_impl.cpp +289 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/globals_impl.h +149 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/header.cpp +44 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/choice.h +106 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/functional.h +327 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/globals.h +196 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/list.h +187 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/runner.h +291 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/snapshot.h +61 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/story.h +219 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/story_ptr.h +233 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/traits.h +270 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/include/types.h +169 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/list_impl.cpp +79 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/list_impl.h +39 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/list_operations.cpp +276 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/list_operations.h +356 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/list_table.cpp +841 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/list_table.h +450 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/numeric_operations.cpp +40 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/numeric_operations.h +529 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/operation_bases.h +164 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/operations.h +100 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/output.cpp +528 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/output.h +153 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/platform.h +22 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/random.h +38 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/runner_impl.cpp +1396 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/runner_impl.h +336 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/simple_restorable_stack.h +335 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/snapshot_impl.cpp +182 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/snapshot_impl.h +91 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/snapshot_interface.h +57 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/stack.cpp +618 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/stack.h +243 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/story_impl.cpp +361 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/story_impl.h +92 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/story_ptr.cpp +75 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/string_operations.cpp +125 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/string_operations.h +67 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/string_table.cpp +149 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/string_table.h +47 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/string_utils.h +207 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/system.cpp +39 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/tuple.hpp +151 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/value.cpp +279 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp/value.h +666 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/CMakeLists.txt +62 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/include/inkcpp.h +393 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/inkcpp.cpp +344 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/inkcpp_c.pc.in +10 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/ExternalFunction.c +56 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Globals.c +98 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Lists.c +73 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Observer.c +36 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Snapshot.c +65 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_cl/CMakeLists.txt +49 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_cl/inkcpp_cl.cpp +215 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_cl/test.cpp +209 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_cl/test.h +8 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/CMakeLists.txt +37 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_emitter.cpp +446 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_emitter.h +70 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_stream.cpp +166 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_stream.h +79 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/command.cpp +107 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/compiler.cpp +96 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/emitter.cpp +62 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/emitter.h +104 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/include/compilation_results.h +22 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/include/compiler.h +44 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/json.hpp +24596 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/json_compiler.cpp +411 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/json_compiler.h +62 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/list_data.cpp +47 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/list_data.h +70 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/reporter.cpp +107 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/reporter.h +55 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/CMakeLists.txt +19 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/example.py +78 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/src/module.cpp +317 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/conftest.py +53 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_ExternalFunctions.py +35 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Globals.py +40 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Lists.py +43 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Observer.py +27 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Snapshot.py +57 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_py/unreal_example.ink +71 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Array.cpp +115 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/CMakeLists.txt +117 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Callstack.cpp +392 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/EmptyStringForDivert.cpp +36 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ExternalFunctionsExecuteProperly.cpp +34 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/FallbackFunction.cpp +77 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Globals.cpp +73 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/InkyJson.cpp +34 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/LabelCondition.cpp +60 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Lists.cpp +144 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/LookaheadSafe.cpp +46 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Main.cpp +7 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/MoveTo.cpp +95 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/NewLines.cpp +76 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/NoEarlyTags.cpp +33 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Observer.cpp +245 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Pointer.cpp +191 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Restorable.cpp +294 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/SpaceAfterBracketChoice.cpp +45 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Stack.cpp +224 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Tags.cpp +131 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp +38 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/UTF8.cpp +56 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/Value.cpp +210 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/catch.hpp +17970 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/AHF.ink +7 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ChoiceBracketStory.ink +7 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/EmptyStringForDivert.ink +13 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ExternalFunctionsExecuteProperly.ink +11 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/FallBack.ink +15 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/GlobalStory.ink +9 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/LabelConditionStory.ink +5 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/LinesStory.ink +42 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ListLogicStory.ink +40 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ListStory.ink +8 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/LookaheadSafe.ink +14 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/MoveTo.ink +36 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/NoEarlyTags.ink +19 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ObserverStory.ink +8 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/SimpleStoryFlow.ink +65 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/TagsStory.ink +22 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/TheIntercept.ink +1686 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ThirdTierChoiceAfterBracketsStory.ink +13 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/UTF-8-demo.txt +212 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/UTF8Story.ink +218 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/simple-1.1.1-inklecate.json +154 -0
- data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/simple-1.1.1-inky.json +160 -0
- data/ext/inkcpp_rb/inkcpp/notes/ArchitectureNotes.md +54 -0
- data/ext/inkcpp_rb/inkcpp/notes/ListNotes.md +69 -0
- data/ext/inkcpp_rb/inkcpp/notes/OperationNotes.md +35 -0
- data/ext/inkcpp_rb/inkcpp/notes/TagsNotes.md +24 -0
- data/ext/inkcpp_rb/inkcpp/notes/WhitespaceNotes.md +28 -0
- data/ext/inkcpp_rb/inkcpp/proofing/README.md +3 -0
- data/ext/inkcpp_rb/inkcpp/proofing/inkcpp_runtime_driver +12 -0
- data/ext/inkcpp_rb/inkcpp/pyproject.toml +63 -0
- data/ext/inkcpp_rb/inkcpp/setup.py +166 -0
- data/ext/inkcpp_rb/inkcpp/shared/CMakeLists.txt +14 -0
- data/ext/inkcpp_rb/inkcpp/shared/private/command.h +172 -0
- data/ext/inkcpp_rb/inkcpp/shared/private/header.h +46 -0
- data/ext/inkcpp_rb/inkcpp/shared/public/config.h +53 -0
- data/ext/inkcpp_rb/inkcpp/shared/public/system.h +307 -0
- data/ext/inkcpp_rb/inkcpp/shared/public/version.h +14 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestAllSequenceTypes.ink +59 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestArithmetic.ink +17 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestBasicStringLiterals.ink +8 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestBasicTunnel.ink +10 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestBlanksInInlineSequences.ink +51 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestCallStackEvaluation.ink +15 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestChoiceCount.ink +15 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestChoiceDivertsToDone.ink +6 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestChoiceWithBracketsOnly.ink +9 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestCompareDivertTargets.ink +26 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestComplexTunnels.ink +22 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestConditionalChoiceInWeave.ink +19 -0
- data/ext/inkcpp_rb/inkcpp/tests/TestTunnelOnwardsAfterTunnel.ink +17 -0
- data/ext/inkcpp_rb/inkcpp/unreal/CMakeLists.txt +51 -0
- data/ext/inkcpp_rb/inkcpp/unreal/UE_example.ink +92 -0
- data/ext/inkcpp_rb/inkcpp/unreal/blueprint_filter.js +377 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Resources/Icon128.png +0 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkAsset.cpp +47 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkChoice.cpp +40 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkList.cpp +86 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkRuntime.cpp +265 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkThread.cpp +239 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkVar.cpp +143 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/TagList.cpp +95 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/inkcpp.cpp +13 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkAsset.h +50 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkChoice.h +58 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkDelegates.h +139 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkList.h +102 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkRuntime.h +177 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkSnapshot.h +30 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkThread.h +215 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkVar.h +245 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/TagList.h +77 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/inkcpp.h +217 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/inkcpp.Build.cs +62 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.cpp +237 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.h +43 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/inkcpp_editor.cpp +13 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/inklecate_cmd.cpp.in +24 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Public/inkcpp_editor.h +9 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/inkcpp_editor.Build.cs +61 -0
- data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/inkcpp.uplugin +44 -0
- data/ext/inkcpp_rb/inkcpp/unreal/render.css +1 -0
- data/ext/inkcpp_rb/inkcpp_rb.cpp +321 -0
- data/inkcpp_rb.gemspec +54 -0
- data/rbi/inkcpp_rb.rbi +211 -0
- data/sorbet/config +4 -0
- data/sorbet/rbi/annotations/.gitattributes +1 -0
- data/sorbet/rbi/annotations/minitest.rbi +119 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/benchmark@0.4.0.rbi +618 -0
- data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
- data/sorbet/rbi/gems/minitest@5.25.4.rbi +1547 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
- data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
- data/sorbet/rbi/gems/prism@1.3.0.rbi +40040 -0
- data/sorbet/rbi/gems/rake-compiler@1.2.8.rbi +9 -0
- data/sorbet/rbi/gems/rake@13.2.1.rbi +3033 -0
- data/sorbet/rbi/gems/rbi@0.2.2.rbi +4527 -0
- data/sorbet/rbi/gems/rice@4.3.3.rbi +44 -0
- data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
- data/sorbet/rbi/gems/tapioca@0.16.7.rbi +3611 -0
- data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- metadata +400 -0
|
Binary file
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* Copyright (c) 2024 Julian Benda
|
|
2
|
+
*
|
|
3
|
+
* This file is part of inkCPP which is released under MIT license.
|
|
4
|
+
* See file LICENSE.txt or go to
|
|
5
|
+
* https://github.com/JBenda/inkcpp for full license details.
|
|
6
|
+
*/
|
|
7
|
+
#include "InkAsset.h"
|
|
8
|
+
|
|
9
|
+
#include "Misc/FileHelper.h"
|
|
10
|
+
#if WITH_EDITORONLY_DATA
|
|
11
|
+
#include "EditorFramework/AssetImportData.h"
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
UInkAsset::UInkAsset()
|
|
15
|
+
: Super()
|
|
16
|
+
{
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void UInkAsset::Serialize(FStructuredArchive::FRecord Record)
|
|
20
|
+
{
|
|
21
|
+
Super::Serialize(Record);
|
|
22
|
+
|
|
23
|
+
// Write to archive?
|
|
24
|
+
Record.GetUnderlyingArchive() << CompiledStory;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#if WITH_EDITORONLY_DATA
|
|
28
|
+
void UInkAsset::PostInitProperties()
|
|
29
|
+
{
|
|
30
|
+
if (!HasAnyFlags(RF_ClassDefaultObject))
|
|
31
|
+
{
|
|
32
|
+
AssetImportData = NewObject<UAssetImportData>(this, TEXT("AssetImportData"));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Super::PostInitProperties();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
void UInkAsset::GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const
|
|
39
|
+
{
|
|
40
|
+
if (AssetImportData)
|
|
41
|
+
{
|
|
42
|
+
OutTags.Add(FAssetRegistryTag(SourceFileTagName(), AssetImportData->GetSourceData().ToJson(), FAssetRegistryTag::TT_Hidden));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
Super::GetAssetRegistryTags(OutTags);
|
|
46
|
+
}
|
|
47
|
+
#endif
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* Copyright (c) 2024 Julian Benda
|
|
2
|
+
*
|
|
3
|
+
* This file is part of inkCPP which is released under MIT license.
|
|
4
|
+
* See file LICENSE.txt or go to
|
|
5
|
+
* https://github.com/JBenda/inkcpp for full license details.
|
|
6
|
+
*/
|
|
7
|
+
#include "InkChoice.h"
|
|
8
|
+
|
|
9
|
+
#include "ink/choice.h"
|
|
10
|
+
|
|
11
|
+
FString UInkChoice::GetText() const
|
|
12
|
+
{
|
|
13
|
+
return data->text();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
UInkChoice::UInkChoice() {
|
|
17
|
+
tags = NewObject<UTagList>();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
int UInkChoice::GetIndex() const
|
|
21
|
+
{
|
|
22
|
+
return data->index();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const UTagList* UInkChoice::GetTags() const
|
|
26
|
+
{
|
|
27
|
+
return tags;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void UInkChoice::Initialize(const ink::runtime::choice* c)
|
|
31
|
+
{
|
|
32
|
+
data = c;
|
|
33
|
+
if (c->has_tags()) {
|
|
34
|
+
TArray<FString> fstring_tags{};
|
|
35
|
+
for(unsigned i = 0; i < c->num_tags(); ++i) {
|
|
36
|
+
fstring_tags.Add(FString(ANSI_TO_TCHAR(c->get_tag(i))));
|
|
37
|
+
}
|
|
38
|
+
tags->Initialize(fstring_tags);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Copyright (c) 2024 Julian Benda
|
|
2
|
+
*
|
|
3
|
+
* This file is part of inkCPP which is released under MIT license.
|
|
4
|
+
* See file LICENSE.txt or go to
|
|
5
|
+
* https://github.com/JBenda/inkcpp for full license details.
|
|
6
|
+
*/
|
|
7
|
+
#pragma once
|
|
8
|
+
|
|
9
|
+
#include "InkList.h"
|
|
10
|
+
#include <string>
|
|
11
|
+
#include "ink/list.h"
|
|
12
|
+
|
|
13
|
+
bool UInkList::ContainsFlag(const FString& flag_name) const
|
|
14
|
+
{
|
|
15
|
+
return list_data->contains(TCHAR_TO_ANSI(*flag_name));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
bool UInkList::ContainsEnum(const UEnum* Enum, const uint8& value) const
|
|
19
|
+
{
|
|
20
|
+
if (! Enum) {
|
|
21
|
+
UE_LOG(InkCpp, Warning, TEXT("No Enum provided for ContainsEnum, it will fail therfore!"));
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return list_data->contains(TCHAR_TO_ANSI(*Enum->GetDisplayNameTextByValue(value).ToString()));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
TArray<uint8> UInkList::ElementsOf(const UEnum* Enum) const
|
|
29
|
+
{
|
|
30
|
+
TArray<uint8> ret;
|
|
31
|
+
if (! Enum) {
|
|
32
|
+
UE_LOG(InkCpp, Warning, TEXT("Failed to provide enum for elements of!"));
|
|
33
|
+
return ret;
|
|
34
|
+
}
|
|
35
|
+
FString enumName = Enum->GetFName().ToString();
|
|
36
|
+
|
|
37
|
+
int num = Enum->NumEnums();
|
|
38
|
+
std::string str(TCHAR_TO_ANSI(*enumName));
|
|
39
|
+
for (auto itr = list_data->begin(str.c_str()); itr != list_data->end(); ++itr) {
|
|
40
|
+
bool hit = false;
|
|
41
|
+
const FString flag(ANSI_TO_TCHAR((*itr).flag_name));
|
|
42
|
+
for (int i = 0; i < num; ++i) {
|
|
43
|
+
FString enumStr = Enum->GetDisplayNameTextByIndex(i).ToString();
|
|
44
|
+
if (enumStr.EndsWith(flag)) {
|
|
45
|
+
ret.Add(Enum->GetValueByIndex(i));
|
|
46
|
+
hit = true;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (! hit) {
|
|
51
|
+
UE_LOG(
|
|
52
|
+
InkCpp, Warning, TEXT("Failed to find list value '%s' in enum '%s'"), *flag, *enumName
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return ret;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
TArray<FString> UInkList::ElementsOfAsString(const UEnum* Enum) const
|
|
61
|
+
{
|
|
62
|
+
TArray<FString> ret;
|
|
63
|
+
|
|
64
|
+
FString EnumName = Enum->GetFName().ToString();
|
|
65
|
+
for (auto itr = list_data->begin(TCHAR_TO_ANSI(*EnumName)); itr != list_data->end(); ++itr) {
|
|
66
|
+
ret.Add(FString((*itr).flag_name));
|
|
67
|
+
}
|
|
68
|
+
return ret;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
TArray<FListFlag> UInkList::Elements() const
|
|
72
|
+
{
|
|
73
|
+
TArray<FListFlag> ret;
|
|
74
|
+
for (auto itr = list_data->begin(); itr != list_data->end(); ++itr) {
|
|
75
|
+
ret.Add(FListFlag{
|
|
76
|
+
.list_name = FString((*itr).list_name),
|
|
77
|
+
.flag_name = FString((*itr).flag_name),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return ret;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
bool UInkList::ContainsList(const FString& name) const
|
|
84
|
+
{
|
|
85
|
+
return list_data->begin(TCHAR_TO_ANSI(*name)) != list_data->end();
|
|
86
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/* Copyright (c) 2024 Julian Benda
|
|
2
|
+
*
|
|
3
|
+
* This file is part of inkCPP which is released under MIT license.
|
|
4
|
+
* See file LICENSE.txt or go to
|
|
5
|
+
* https://github.com/JBenda/inkcpp for full license details.
|
|
6
|
+
*/
|
|
7
|
+
#include "InkRuntime.h"
|
|
8
|
+
|
|
9
|
+
// Game includes
|
|
10
|
+
#include "inkcpp.h"
|
|
11
|
+
#include "InkThread.h"
|
|
12
|
+
#include "TagList.h"
|
|
13
|
+
#include "InkAsset.h"
|
|
14
|
+
#include "InkVar.h"
|
|
15
|
+
|
|
16
|
+
// inkcpp includes
|
|
17
|
+
#include "ink/story.h"
|
|
18
|
+
#include "ink/globals.h"
|
|
19
|
+
#include "ink/snapshot.h"
|
|
20
|
+
#include "system.h"
|
|
21
|
+
#include "types.h"
|
|
22
|
+
|
|
23
|
+
namespace ink { using value = runtime::value; }
|
|
24
|
+
|
|
25
|
+
// Sets default values
|
|
26
|
+
AInkRuntime::AInkRuntime() : mpRuntime(nullptr)
|
|
27
|
+
{
|
|
28
|
+
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
|
29
|
+
PrimaryActorTick.bCanEverTick = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
AInkRuntime::~AInkRuntime()
|
|
33
|
+
{
|
|
34
|
+
if(mSnapshot) { delete mpSnapshot; }
|
|
35
|
+
mSnapshot.Reset();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Called when the game starts or when spawned
|
|
39
|
+
void AInkRuntime::BeginPlay()
|
|
40
|
+
{
|
|
41
|
+
// Create the CPU for the story
|
|
42
|
+
if (InkAsset != nullptr)
|
|
43
|
+
{
|
|
44
|
+
// TODO: Better error handling? What if load fails.
|
|
45
|
+
mpRuntime = ink::runtime::story::from_binary(reinterpret_cast<unsigned char*>(InkAsset->CompiledStory.GetData()), InkAsset->CompiledStory.Num(), false);
|
|
46
|
+
UE_LOG(InkCpp, Display, TEXT("Loaded Ink asset"));
|
|
47
|
+
|
|
48
|
+
// create globals
|
|
49
|
+
if (mSnapshot) {
|
|
50
|
+
LoadSnapshot(*mSnapshot);
|
|
51
|
+
} else {
|
|
52
|
+
mpGlobals = mpRuntime->new_globals();
|
|
53
|
+
}
|
|
54
|
+
// initialize globals
|
|
55
|
+
mpRuntime->new_runner(mpGlobals);
|
|
56
|
+
}
|
|
57
|
+
else
|
|
58
|
+
{
|
|
59
|
+
UE_LOG(InkCpp, Warning, TEXT("No story asset assigned."));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
Super::BeginPlay();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Called every frame
|
|
66
|
+
void AInkRuntime::Tick(float DeltaTime)
|
|
67
|
+
{
|
|
68
|
+
Super::Tick(DeltaTime);
|
|
69
|
+
|
|
70
|
+
// Early out: no threads.
|
|
71
|
+
if (mThreads.Num() == 0)
|
|
72
|
+
return;
|
|
73
|
+
|
|
74
|
+
// Special: If we're in exclusive mode, only execute the thread at the
|
|
75
|
+
// top of the exclusive stack
|
|
76
|
+
while (mExclusiveStack.Num() > 0)
|
|
77
|
+
{
|
|
78
|
+
// Make sure top thread is active
|
|
79
|
+
UInkThread* top = mExclusiveStack.Top();
|
|
80
|
+
|
|
81
|
+
// If it can't execute, we're not doing anything else
|
|
82
|
+
if (!top->CanExecute())
|
|
83
|
+
return;
|
|
84
|
+
|
|
85
|
+
// Execute it
|
|
86
|
+
if (top->Execute())
|
|
87
|
+
{
|
|
88
|
+
mExclusiveStack.Remove(top);
|
|
89
|
+
mThreads.Remove(top);
|
|
90
|
+
|
|
91
|
+
// execute next exclusive thread
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Nothing more to do
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Execute other available threads
|
|
100
|
+
for (auto iter = mThreads.CreateIterator(); iter; iter++)
|
|
101
|
+
{
|
|
102
|
+
UInkThread* pNextThread = *iter;
|
|
103
|
+
|
|
104
|
+
// Ignore threads that aren't eligable for execution
|
|
105
|
+
if (!pNextThread->CanExecute())
|
|
106
|
+
continue;
|
|
107
|
+
|
|
108
|
+
// Execute
|
|
109
|
+
if (pNextThread->Execute())
|
|
110
|
+
{
|
|
111
|
+
// If the thread has finished, destroy it
|
|
112
|
+
iter.RemoveCurrent();
|
|
113
|
+
mExclusiveStack.Remove(pNextThread);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void AInkRuntime::HandleTagFunction(UInkThread* Caller, const TArray<FString>& Params)
|
|
119
|
+
{
|
|
120
|
+
// Look for method and execute with parameters
|
|
121
|
+
FGlobalTagFunctionMulticastDelegate* function = mGlobalTagFunctions.Find(FName(*Params[0]));
|
|
122
|
+
if (function != nullptr)
|
|
123
|
+
{
|
|
124
|
+
function->Broadcast(Caller, Params);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
void AInkRuntime::RegisterTagFunction(FName functionName, const FTagFunctionDelegate & function)
|
|
129
|
+
{
|
|
130
|
+
// Register tag function
|
|
131
|
+
mGlobalTagFunctions.FindOrAdd(functionName).Add(function);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
UInkThread* AInkRuntime::Start(TSubclassOf<class UInkThread> type, FString path, bool startImmediately)
|
|
135
|
+
{
|
|
136
|
+
UE_LOG(InkCpp, Display, TEXT("Start"));
|
|
137
|
+
if (mpRuntime == nullptr || type == nullptr)
|
|
138
|
+
{
|
|
139
|
+
UE_LOG(InkCpp, Warning, TEXT("failed to start"));
|
|
140
|
+
return nullptr;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Instantiate the thread
|
|
144
|
+
UInkThread* pThread = NewObject<UInkThread>(this, type);
|
|
145
|
+
|
|
146
|
+
// Startup
|
|
147
|
+
return StartExisting(pThread, path, startImmediately);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
FInkSnapshot AInkRuntime::Snapshot()
|
|
151
|
+
{
|
|
152
|
+
ink::runtime::snapshot* inkSnapshot = mpGlobals->create_snapshot();
|
|
153
|
+
FInkSnapshot snapshot(reinterpret_cast<const char*>(inkSnapshot->get_data()), inkSnapshot->get_data_len());
|
|
154
|
+
delete inkSnapshot;
|
|
155
|
+
return snapshot;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
void AInkRuntime::LoadSnapshot(const FInkSnapshot& snapshot) {
|
|
159
|
+
mSnapshot = snapshot;
|
|
160
|
+
mpSnapshot = ink::runtime::snapshot::from_binary(reinterpret_cast<unsigned char*>(mSnapshot->data.GetData()), mSnapshot->data.Num(), false);
|
|
161
|
+
mpGlobals = mpRuntime->new_globals_from_snapshot(*mpSnapshot);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
UInkThread* AInkRuntime::StartExisting(UInkThread* thread, FString path, bool startImmediately /*= true*/)
|
|
165
|
+
{
|
|
166
|
+
if (mpRuntime == nullptr)
|
|
167
|
+
{
|
|
168
|
+
UE_LOG(InkCpp, Warning, TEXT("Failed to start existing"));
|
|
169
|
+
return nullptr;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// remove handle if it still exists
|
|
173
|
+
mThreads.Remove(thread);
|
|
174
|
+
mExclusiveStack.Remove(thread);
|
|
175
|
+
|
|
176
|
+
// Initialize thread with new runner
|
|
177
|
+
ink::runtime::runner runner;
|
|
178
|
+
if (mSnapshot && path.IsEmpty()) {
|
|
179
|
+
if (mpSnapshot->num_runners() == mThreads.Num()) {
|
|
180
|
+
UE_LOG(InkCpp, Warning, TEXT("Already created all Threads from Snapshot!, will not create more. You can Still create new Threads with entering the starting Path."));
|
|
181
|
+
return nullptr;
|
|
182
|
+
}
|
|
183
|
+
runner = mpRuntime->new_runner_from_snapshot(*mpSnapshot, mpGlobals, mThreads.Num());
|
|
184
|
+
} else {
|
|
185
|
+
runner = mpRuntime->new_runner(mpGlobals);
|
|
186
|
+
}
|
|
187
|
+
thread->Initialize(path, this, runner);
|
|
188
|
+
|
|
189
|
+
// If we're not starting immediately, just queue
|
|
190
|
+
if (!startImmediately ||
|
|
191
|
+
// Even if we want to start immediately, don't if there's an exclusive thread and it's not us
|
|
192
|
+
(mExclusiveStack.Num() > 0 && mExclusiveStack.Top() != thread))
|
|
193
|
+
{
|
|
194
|
+
mThreads.Add(thread);
|
|
195
|
+
return thread;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Execute the newly created thread
|
|
199
|
+
if (!thread->Execute())
|
|
200
|
+
{
|
|
201
|
+
// If it hasn't finished immediately, add it to the threads list
|
|
202
|
+
mThreads.Add(thread);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return thread;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
void AInkRuntime::PushExclusiveThread(UInkThread* Thread)
|
|
209
|
+
{
|
|
210
|
+
// If we're already on the stack, ignore
|
|
211
|
+
if (mExclusiveStack.Find(Thread) != INDEX_NONE)
|
|
212
|
+
return;
|
|
213
|
+
|
|
214
|
+
// Push
|
|
215
|
+
mExclusiveStack.Push(Thread);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
void AInkRuntime::PopExclusiveThread(UInkThread* Thread)
|
|
219
|
+
{
|
|
220
|
+
// Remove from the stack
|
|
221
|
+
mExclusiveStack.Remove(Thread);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
FInkVar AInkRuntime::GetGlobalVariable(const FString& name) {
|
|
225
|
+
ink::optional<ink::value> var = mpGlobals->get<ink::value>(TCHAR_TO_ANSI(*name));
|
|
226
|
+
if(var) { return FInkVar(*var); }
|
|
227
|
+
else { UE_LOG(InkCpp, Warning, TEXT("Failed to find global variable with name: %s"), *name); }
|
|
228
|
+
return FInkVar{};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void AInkRuntime::SetGlobalVariable(const FString& name, const FInkVar& value) {
|
|
232
|
+
bool success = mpGlobals->set<ink::value>(TCHAR_TO_ANSI(*name), value.to_value());
|
|
233
|
+
if(!success) {
|
|
234
|
+
UE_LOG(InkCpp, Warning, TEXT("Filed to set global variable with name: %s"), *name);
|
|
235
|
+
ink::optional<ink::value> var = mpGlobals->get<ink::value>(TCHAR_TO_ANSI(*name));
|
|
236
|
+
if(var) {
|
|
237
|
+
UE_LOG(InkCpp, Warning,
|
|
238
|
+
TEXT("Reason: wrong type!, got: %i, expected: %i"),
|
|
239
|
+
static_cast<int>(value.to_value().type),
|
|
240
|
+
static_cast<int>(var->type) );
|
|
241
|
+
} else {
|
|
242
|
+
UE_LOG(InkCpp, Warning, TEXT("Reason: no variable with this name exists! '%s'"),
|
|
243
|
+
*name);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
void AInkRuntime::ObserverVariable(const FString& name, const FVariableCallbackDelegate& callback) {
|
|
248
|
+
mpGlobals->observe(TCHAR_TO_ANSI(*name), [callback](){callback.Execute();});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
void AInkRuntime::ObserverVariableEvent(const FString& name, const FVariableCallbackDelegateNewValue& callback) {
|
|
252
|
+
mpGlobals->observe(TCHAR_TO_ANSI(*name), [callback](ink::runtime::value x){callback.Execute(FInkVar(x));});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
void AInkRuntime::ObserverVariableChange(const FString& name, const FVariableCallbackDelegateNewOldValue& callback) {
|
|
256
|
+
mpGlobals->observe(TCHAR_TO_ANSI(*name),
|
|
257
|
+
[callback](ink::runtime::value x, ink::optional<ink::runtime::value> y){
|
|
258
|
+
if (y.has_value()) {
|
|
259
|
+
callback.Execute(FInkVar(x), FInkVar(y.value()));
|
|
260
|
+
} else {
|
|
261
|
+
callback.Execute(FInkVar(x), FInkVar());
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
);
|
|
265
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/* Copyright (c) 2024 Julian Benda
|
|
2
|
+
*
|
|
3
|
+
* This file is part of inkCPP which is released under MIT license.
|
|
4
|
+
* See file LICENSE.txt or go to
|
|
5
|
+
* https://github.com/JBenda/inkcpp for full license details.
|
|
6
|
+
*/
|
|
7
|
+
#include "InkThread.h"
|
|
8
|
+
|
|
9
|
+
#include "inkcpp.h"
|
|
10
|
+
#include "InkRuntime.h"
|
|
11
|
+
#include "TagList.h"
|
|
12
|
+
#include "InkChoice.h"
|
|
13
|
+
#include "ink/runner.h"
|
|
14
|
+
|
|
15
|
+
// Unreal includes
|
|
16
|
+
#include "Internationalization/Regex.h"
|
|
17
|
+
|
|
18
|
+
UInkThread::UInkThread()
|
|
19
|
+
: mbHasRun(false)
|
|
20
|
+
, mnChoiceToChoose(-1)
|
|
21
|
+
, mnYieldCounter(0)
|
|
22
|
+
, mbKill(false)
|
|
23
|
+
{
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
UInkThread::~UInkThread() {}
|
|
27
|
+
|
|
28
|
+
void UInkThread::Yield() { mnYieldCounter++; }
|
|
29
|
+
|
|
30
|
+
bool UInkThread::IsYielding() { return mnYieldCounter > 0; }
|
|
31
|
+
|
|
32
|
+
void UInkThread::Resume() { mnYieldCounter--; }
|
|
33
|
+
|
|
34
|
+
void UInkThread::RegisterTagFunction(FName functionName, const FTagFunctionDelegate& function)
|
|
35
|
+
{
|
|
36
|
+
// Register tag function
|
|
37
|
+
mTagFunctions.FindOrAdd(functionName).Add(function);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void UInkThread::RegisterExternalFunction(
|
|
41
|
+
const FString& functionName, const FExternalFunctionDelegate& function, bool lookaheadSafe
|
|
42
|
+
)
|
|
43
|
+
{
|
|
44
|
+
mpRunner->bind_delegate(ink::hash_string(TCHAR_TO_ANSI(*functionName)), function, lookaheadSafe);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void UInkThread::RegisterExternalEvent(
|
|
48
|
+
const FString& functionName, const FExternalFunctionVoidDelegate& function, bool lookaheadSafe
|
|
49
|
+
)
|
|
50
|
+
{
|
|
51
|
+
mpRunner->bind_delegate(ink::hash_string(TCHAR_TO_ANSI(*functionName)), function, lookaheadSafe);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void UInkThread::Initialize(FString path, AInkRuntime* runtime, ink::runtime::runner thread)
|
|
55
|
+
{
|
|
56
|
+
inkAssert(
|
|
57
|
+
! thread->has_choices() || path.IsEmpty(),
|
|
58
|
+
"Snapshot recovery does not work with starting path if currently at choice."
|
|
59
|
+
);
|
|
60
|
+
mStartPath = path;
|
|
61
|
+
mpRuntime = runtime;
|
|
62
|
+
mbInitialized = true;
|
|
63
|
+
mpRunner = thread;
|
|
64
|
+
mpTags = NewObject<UTagList>();
|
|
65
|
+
mTagFunctions.Reset();
|
|
66
|
+
mCurrentChoices.Reset();
|
|
67
|
+
mnChoiceToChoose = -1;
|
|
68
|
+
mbHasRun = false;
|
|
69
|
+
mbInChoice = thread->has_choices();
|
|
70
|
+
|
|
71
|
+
OnStartup();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
bool UInkThread::ExecuteInternal()
|
|
75
|
+
{
|
|
76
|
+
// Kill thread
|
|
77
|
+
if (mbKill)
|
|
78
|
+
return true;
|
|
79
|
+
|
|
80
|
+
// If this is the first time we're running, start us off at our starting path
|
|
81
|
+
if (! mbHasRun) {
|
|
82
|
+
if (! ensureMsgf(mbInitialized, TEXT("Thread executing without call to ::Initialize")))
|
|
83
|
+
return true;
|
|
84
|
+
mbHasRun = true;
|
|
85
|
+
if (mStartPath.Len()) {
|
|
86
|
+
mpRunner->move_to(ink::hash_string(TCHAR_TO_ANSI(*mStartPath)));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (mbInChoice) {
|
|
90
|
+
for (ink::size_t i = 0; i < mpRunner->num_choices(); i++) {
|
|
91
|
+
UInkChoice* choice = NewObject<UInkChoice>(this);
|
|
92
|
+
choice->Initialize(mpRunner->get_choice(i));
|
|
93
|
+
mCurrentChoices.Add(choice);
|
|
94
|
+
}
|
|
95
|
+
OnChoice(mCurrentChoices);
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Execution loop
|
|
101
|
+
while (true) {
|
|
102
|
+
// Handle pending choice
|
|
103
|
+
if (mnChoiceToChoose != -1) {
|
|
104
|
+
if (ensure(mpRunner->num_choices() > 0)) {
|
|
105
|
+
mpRunner->choose(mnChoiceToChoose);
|
|
106
|
+
}
|
|
107
|
+
mnChoiceToChoose = -1;
|
|
108
|
+
mCurrentChoices.Empty();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Execute until story yields or finishes
|
|
112
|
+
while (mnYieldCounter == 0 && mpRunner->can_continue()) {
|
|
113
|
+
// Handle text
|
|
114
|
+
FString line = mpRunner->getline();
|
|
115
|
+
// Special: Line begins with >> marker
|
|
116
|
+
if (line.StartsWith(TEXT(">>"))) {
|
|
117
|
+
// This is a special version of the tag function call
|
|
118
|
+
// Expected: >> MyTagFunction(Arg1, Arg2, Arg3)
|
|
119
|
+
FRegexPattern pattern
|
|
120
|
+
= FRegexPattern(TEXT("^>>\\s*(\\w+)(\\((\\s*(\\w+)\\s*(,\\s*(\\w+)\\s*)*)?\\))?$"));
|
|
121
|
+
FRegexMatcher matcher = FRegexMatcher(pattern, line);
|
|
122
|
+
if (matcher.FindNext()) {
|
|
123
|
+
// Get name of function
|
|
124
|
+
FString functionName = matcher.GetCaptureGroup(1);
|
|
125
|
+
|
|
126
|
+
// Get arguments
|
|
127
|
+
TArray<FString> Arguments;
|
|
128
|
+
Arguments.Add(functionName);
|
|
129
|
+
int groupIndex = 4;
|
|
130
|
+
while (matcher.GetCaptureGroupBeginning(groupIndex) != -1) {
|
|
131
|
+
Arguments.Add(matcher.GetCaptureGroup(groupIndex).TrimStartAndEnd());
|
|
132
|
+
groupIndex += 2;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Call tag method
|
|
136
|
+
ExecuteTagMethod(Arguments);
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
// Forward to handler
|
|
140
|
+
// Get tags
|
|
141
|
+
TArray<FString> tags;
|
|
142
|
+
for (size_t i = 0; i < mpRunner->num_tags(); ++i) {
|
|
143
|
+
tags.Add(FString(mpRunner->get_tag(i)));
|
|
144
|
+
}
|
|
145
|
+
mpTags->Initialize(tags);
|
|
146
|
+
OnLineWritten(line, mpTags);
|
|
147
|
+
|
|
148
|
+
// Handle tags/tag methods post-line
|
|
149
|
+
for (auto it = tags.CreateConstIterator(); it; ++it) {
|
|
150
|
+
// Generic tag handler
|
|
151
|
+
OnTag(*it);
|
|
152
|
+
|
|
153
|
+
// Tag methods
|
|
154
|
+
TArray<FString> params;
|
|
155
|
+
it->ParseIntoArray(params, TEXT("_"));
|
|
156
|
+
ExecuteTagMethod(params);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Handle choice block
|
|
162
|
+
if (mnYieldCounter == 0 && mpRunner->num_choices() > 0) {
|
|
163
|
+
mbInChoice = true;
|
|
164
|
+
|
|
165
|
+
// Forward to handler
|
|
166
|
+
for (ink::size_t i = 0; i < mpRunner->num_choices(); i++) {
|
|
167
|
+
UInkChoice* choice = NewObject<UInkChoice>(this);
|
|
168
|
+
choice->Initialize(mpRunner->get_choice(i));
|
|
169
|
+
mCurrentChoices.Add(choice);
|
|
170
|
+
}
|
|
171
|
+
OnChoice(mCurrentChoices);
|
|
172
|
+
|
|
173
|
+
// If we've chosen a choice already, go back up to handle it.
|
|
174
|
+
if (mnChoiceToChoose != -1)
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Have we reached the end? If so, destroy the thread
|
|
182
|
+
if (! mpRunner->can_continue() && mnYieldCounter == 0 && mpRunner->num_choices() == 0) {
|
|
183
|
+
UE_LOG(InkCpp, Display, TEXT("Destroying thread"));
|
|
184
|
+
|
|
185
|
+
// TODO: Event for ending?
|
|
186
|
+
|
|
187
|
+
// TODO: Destroy ourselves?
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// There's more to go. Return false to put us on the waiting list.
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
void UInkThread::ExecuteTagMethod(const TArray<FString>& Params)
|
|
196
|
+
{
|
|
197
|
+
// Look for method and execute with parameters
|
|
198
|
+
FTagFunctionMulticastDelegate* function = mTagFunctions.Find(FName(*Params[0]));
|
|
199
|
+
if (function != nullptr) {
|
|
200
|
+
function->Broadcast(this, Params);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Forward to runtime
|
|
204
|
+
mpRuntime->HandleTagFunction(this, Params);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
bool UInkThread::Execute()
|
|
208
|
+
{
|
|
209
|
+
// Execute thread
|
|
210
|
+
bool finished = ExecuteInternal();
|
|
211
|
+
|
|
212
|
+
// If we've finished, run callback
|
|
213
|
+
if (finished) {
|
|
214
|
+
// Allow outsiders to subscribe
|
|
215
|
+
// TODO: OnThreadShutdown.Broadcast();
|
|
216
|
+
OnShutdown();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Return result
|
|
220
|
+
return finished;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
bool UInkThread::PickChoice(int index)
|
|
224
|
+
{
|
|
225
|
+
if (index >= mCurrentChoices.Num() || index < 0) {
|
|
226
|
+
UE_LOG(
|
|
227
|
+
InkCpp, Warning, TEXT("PickChoice: index(%i) out of range [0-%i)"), index,
|
|
228
|
+
mCurrentChoices.Num()
|
|
229
|
+
);
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
mnChoiceToChoose = index;
|
|
233
|
+
mbInChoice = false;
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
bool UInkThread::CanExecute() const { return (mnYieldCounter == 0 && ! mbInChoice) || ! mbHasRun; }
|
|
238
|
+
|
|
239
|
+
void UInkThread::Stop() { mbKill = true; }
|