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.
Files changed (273) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +1 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +84 -0
  6. data/LICENSE +7 -0
  7. data/README.md +3 -0
  8. data/Rakefile +16 -0
  9. data/bin/console +15 -0
  10. data/bin/setup +10 -0
  11. data/bin/tapioca +29 -0
  12. data/ext/inkcpp_rb/extconf.rb +19 -0
  13. data/ext/inkcpp_rb/inkcpp/.clang-format +99 -0
  14. data/ext/inkcpp_rb/inkcpp/.github/FUNDING.yml +1 -0
  15. data/ext/inkcpp_rb/inkcpp/.github/workflows/build.yml +344 -0
  16. data/ext/inkcpp_rb/inkcpp/.github/workflows/release.yml +49 -0
  17. data/ext/inkcpp_rb/inkcpp/.gitignore +25 -0
  18. data/ext/inkcpp_rb/inkcpp/.gitmodules +9 -0
  19. data/ext/inkcpp_rb/inkcpp/CMakeLists.txt +170 -0
  20. data/ext/inkcpp_rb/inkcpp/CODE_OF_CONDUCT.md +76 -0
  21. data/ext/inkcpp_rb/inkcpp/CONTRIBUTING.md +55 -0
  22. data/ext/inkcpp_rb/inkcpp/Config.cmake.in +2 -0
  23. data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/CMakeLists.txt +13 -0
  24. data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/main.c +38 -0
  25. data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/main.cpp +40 -0
  26. data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/test.ink +8 -0
  27. data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example/test.ink.json +1 -0
  28. data/ext/inkcpp_rb/inkcpp/Documentation/cmake_example.zip +0 -0
  29. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/InkCPP_DEMO.zip +0 -0
  30. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/CreateThread.png +0 -0
  31. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/HandleChoice.png +0 -0
  32. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/ListElementOf.png +0 -0
  33. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/MinimalRuntime.png +0 -0
  34. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/MinimalThread.png +0 -0
  35. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/ObseverChange.png +0 -0
  36. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/TagListGetValue.png +0 -0
  37. data/ext/inkcpp_rb/inkcpp/Documentation/unreal/imgs/YieldResume.png +0 -0
  38. data/ext/inkcpp_rb/inkcpp/Doxyfile +2825 -0
  39. data/ext/inkcpp_rb/inkcpp/LICENSE.txt +22 -0
  40. data/ext/inkcpp_rb/inkcpp/Minimal.runsettings +8 -0
  41. data/ext/inkcpp_rb/inkcpp/README.md +192 -0
  42. data/ext/inkcpp_rb/inkcpp/inkcpp/CMakeLists.txt +67 -0
  43. data/ext/inkcpp_rb/inkcpp/inkcpp/array.h +481 -0
  44. data/ext/inkcpp_rb/inkcpp/inkcpp/avl_array.h +833 -0
  45. data/ext/inkcpp_rb/inkcpp/inkcpp/casting.h +93 -0
  46. data/ext/inkcpp_rb/inkcpp/inkcpp/choice.cpp +54 -0
  47. data/ext/inkcpp_rb/inkcpp/inkcpp/collections/restorable.cpp +124 -0
  48. data/ext/inkcpp_rb/inkcpp/inkcpp/collections/restorable.h +406 -0
  49. data/ext/inkcpp_rb/inkcpp/inkcpp/container_operations.cpp +52 -0
  50. data/ext/inkcpp_rb/inkcpp/inkcpp/container_operations.h +34 -0
  51. data/ext/inkcpp_rb/inkcpp/inkcpp/executioner.h +179 -0
  52. data/ext/inkcpp_rb/inkcpp/inkcpp/functional.cpp +86 -0
  53. data/ext/inkcpp_rb/inkcpp/inkcpp/functions.cpp +54 -0
  54. data/ext/inkcpp_rb/inkcpp/inkcpp/functions.h +40 -0
  55. data/ext/inkcpp_rb/inkcpp/inkcpp/globals_impl.cpp +289 -0
  56. data/ext/inkcpp_rb/inkcpp/inkcpp/globals_impl.h +149 -0
  57. data/ext/inkcpp_rb/inkcpp/inkcpp/header.cpp +44 -0
  58. data/ext/inkcpp_rb/inkcpp/inkcpp/include/choice.h +106 -0
  59. data/ext/inkcpp_rb/inkcpp/inkcpp/include/functional.h +327 -0
  60. data/ext/inkcpp_rb/inkcpp/inkcpp/include/globals.h +196 -0
  61. data/ext/inkcpp_rb/inkcpp/inkcpp/include/list.h +187 -0
  62. data/ext/inkcpp_rb/inkcpp/inkcpp/include/runner.h +291 -0
  63. data/ext/inkcpp_rb/inkcpp/inkcpp/include/snapshot.h +61 -0
  64. data/ext/inkcpp_rb/inkcpp/inkcpp/include/story.h +219 -0
  65. data/ext/inkcpp_rb/inkcpp/inkcpp/include/story_ptr.h +233 -0
  66. data/ext/inkcpp_rb/inkcpp/inkcpp/include/traits.h +270 -0
  67. data/ext/inkcpp_rb/inkcpp/inkcpp/include/types.h +169 -0
  68. data/ext/inkcpp_rb/inkcpp/inkcpp/list_impl.cpp +79 -0
  69. data/ext/inkcpp_rb/inkcpp/inkcpp/list_impl.h +39 -0
  70. data/ext/inkcpp_rb/inkcpp/inkcpp/list_operations.cpp +276 -0
  71. data/ext/inkcpp_rb/inkcpp/inkcpp/list_operations.h +356 -0
  72. data/ext/inkcpp_rb/inkcpp/inkcpp/list_table.cpp +841 -0
  73. data/ext/inkcpp_rb/inkcpp/inkcpp/list_table.h +450 -0
  74. data/ext/inkcpp_rb/inkcpp/inkcpp/numeric_operations.cpp +40 -0
  75. data/ext/inkcpp_rb/inkcpp/inkcpp/numeric_operations.h +529 -0
  76. data/ext/inkcpp_rb/inkcpp/inkcpp/operation_bases.h +164 -0
  77. data/ext/inkcpp_rb/inkcpp/inkcpp/operations.h +100 -0
  78. data/ext/inkcpp_rb/inkcpp/inkcpp/output.cpp +528 -0
  79. data/ext/inkcpp_rb/inkcpp/inkcpp/output.h +153 -0
  80. data/ext/inkcpp_rb/inkcpp/inkcpp/platform.h +22 -0
  81. data/ext/inkcpp_rb/inkcpp/inkcpp/random.h +38 -0
  82. data/ext/inkcpp_rb/inkcpp/inkcpp/runner_impl.cpp +1396 -0
  83. data/ext/inkcpp_rb/inkcpp/inkcpp/runner_impl.h +336 -0
  84. data/ext/inkcpp_rb/inkcpp/inkcpp/simple_restorable_stack.h +335 -0
  85. data/ext/inkcpp_rb/inkcpp/inkcpp/snapshot_impl.cpp +182 -0
  86. data/ext/inkcpp_rb/inkcpp/inkcpp/snapshot_impl.h +91 -0
  87. data/ext/inkcpp_rb/inkcpp/inkcpp/snapshot_interface.h +57 -0
  88. data/ext/inkcpp_rb/inkcpp/inkcpp/stack.cpp +618 -0
  89. data/ext/inkcpp_rb/inkcpp/inkcpp/stack.h +243 -0
  90. data/ext/inkcpp_rb/inkcpp/inkcpp/story_impl.cpp +361 -0
  91. data/ext/inkcpp_rb/inkcpp/inkcpp/story_impl.h +92 -0
  92. data/ext/inkcpp_rb/inkcpp/inkcpp/story_ptr.cpp +75 -0
  93. data/ext/inkcpp_rb/inkcpp/inkcpp/string_operations.cpp +125 -0
  94. data/ext/inkcpp_rb/inkcpp/inkcpp/string_operations.h +67 -0
  95. data/ext/inkcpp_rb/inkcpp/inkcpp/string_table.cpp +149 -0
  96. data/ext/inkcpp_rb/inkcpp/inkcpp/string_table.h +47 -0
  97. data/ext/inkcpp_rb/inkcpp/inkcpp/string_utils.h +207 -0
  98. data/ext/inkcpp_rb/inkcpp/inkcpp/system.cpp +39 -0
  99. data/ext/inkcpp_rb/inkcpp/inkcpp/tuple.hpp +151 -0
  100. data/ext/inkcpp_rb/inkcpp/inkcpp/value.cpp +279 -0
  101. data/ext/inkcpp_rb/inkcpp/inkcpp/value.h +666 -0
  102. data/ext/inkcpp_rb/inkcpp/inkcpp_c/CMakeLists.txt +62 -0
  103. data/ext/inkcpp_rb/inkcpp/inkcpp_c/include/inkcpp.h +393 -0
  104. data/ext/inkcpp_rb/inkcpp/inkcpp_c/inkcpp.cpp +344 -0
  105. data/ext/inkcpp_rb/inkcpp/inkcpp_c/inkcpp_c.pc.in +10 -0
  106. data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/ExternalFunction.c +56 -0
  107. data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Globals.c +98 -0
  108. data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Lists.c +73 -0
  109. data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Observer.c +36 -0
  110. data/ext/inkcpp_rb/inkcpp/inkcpp_c/tests/Snapshot.c +65 -0
  111. data/ext/inkcpp_rb/inkcpp/inkcpp_cl/CMakeLists.txt +49 -0
  112. data/ext/inkcpp_rb/inkcpp/inkcpp_cl/inkcpp_cl.cpp +215 -0
  113. data/ext/inkcpp_rb/inkcpp/inkcpp_cl/test.cpp +209 -0
  114. data/ext/inkcpp_rb/inkcpp/inkcpp_cl/test.h +8 -0
  115. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/CMakeLists.txt +37 -0
  116. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_emitter.cpp +446 -0
  117. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_emitter.h +70 -0
  118. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_stream.cpp +166 -0
  119. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/binary_stream.h +79 -0
  120. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/command.cpp +107 -0
  121. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/compiler.cpp +96 -0
  122. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/emitter.cpp +62 -0
  123. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/emitter.h +104 -0
  124. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/include/compilation_results.h +22 -0
  125. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/include/compiler.h +44 -0
  126. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/json.hpp +24596 -0
  127. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/json_compiler.cpp +411 -0
  128. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/json_compiler.h +62 -0
  129. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/list_data.cpp +47 -0
  130. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/list_data.h +70 -0
  131. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/reporter.cpp +107 -0
  132. data/ext/inkcpp_rb/inkcpp/inkcpp_compiler/reporter.h +55 -0
  133. data/ext/inkcpp_rb/inkcpp/inkcpp_py/CMakeLists.txt +19 -0
  134. data/ext/inkcpp_rb/inkcpp/inkcpp_py/example.py +78 -0
  135. data/ext/inkcpp_rb/inkcpp/inkcpp_py/src/module.cpp +317 -0
  136. data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/conftest.py +53 -0
  137. data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_ExternalFunctions.py +35 -0
  138. data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Globals.py +40 -0
  139. data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Lists.py +43 -0
  140. data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Observer.py +27 -0
  141. data/ext/inkcpp_rb/inkcpp/inkcpp_py/tests/test_Snapshot.py +57 -0
  142. data/ext/inkcpp_rb/inkcpp/inkcpp_py/unreal_example.ink +71 -0
  143. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Array.cpp +115 -0
  144. data/ext/inkcpp_rb/inkcpp/inkcpp_test/CMakeLists.txt +117 -0
  145. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Callstack.cpp +392 -0
  146. data/ext/inkcpp_rb/inkcpp/inkcpp_test/EmptyStringForDivert.cpp +36 -0
  147. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ExternalFunctionsExecuteProperly.cpp +34 -0
  148. data/ext/inkcpp_rb/inkcpp/inkcpp_test/FallbackFunction.cpp +77 -0
  149. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Globals.cpp +73 -0
  150. data/ext/inkcpp_rb/inkcpp/inkcpp_test/InkyJson.cpp +34 -0
  151. data/ext/inkcpp_rb/inkcpp/inkcpp_test/LabelCondition.cpp +60 -0
  152. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Lists.cpp +144 -0
  153. data/ext/inkcpp_rb/inkcpp/inkcpp_test/LookaheadSafe.cpp +46 -0
  154. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Main.cpp +7 -0
  155. data/ext/inkcpp_rb/inkcpp/inkcpp_test/MoveTo.cpp +95 -0
  156. data/ext/inkcpp_rb/inkcpp/inkcpp_test/NewLines.cpp +76 -0
  157. data/ext/inkcpp_rb/inkcpp/inkcpp_test/NoEarlyTags.cpp +33 -0
  158. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Observer.cpp +245 -0
  159. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Pointer.cpp +191 -0
  160. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Restorable.cpp +294 -0
  161. data/ext/inkcpp_rb/inkcpp/inkcpp_test/SpaceAfterBracketChoice.cpp +45 -0
  162. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Stack.cpp +224 -0
  163. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Tags.cpp +131 -0
  164. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ThirdTierChoiceAfterBrackets.cpp +38 -0
  165. data/ext/inkcpp_rb/inkcpp/inkcpp_test/UTF8.cpp +56 -0
  166. data/ext/inkcpp_rb/inkcpp/inkcpp_test/Value.cpp +210 -0
  167. data/ext/inkcpp_rb/inkcpp/inkcpp_test/catch.hpp +17970 -0
  168. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/AHF.ink +7 -0
  169. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ChoiceBracketStory.ink +7 -0
  170. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/EmptyStringForDivert.ink +13 -0
  171. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ExternalFunctionsExecuteProperly.ink +11 -0
  172. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/FallBack.ink +15 -0
  173. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/GlobalStory.ink +9 -0
  174. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/LabelConditionStory.ink +5 -0
  175. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/LinesStory.ink +42 -0
  176. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ListLogicStory.ink +40 -0
  177. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ListStory.ink +8 -0
  178. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/LookaheadSafe.ink +14 -0
  179. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/MoveTo.ink +36 -0
  180. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/NoEarlyTags.ink +19 -0
  181. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ObserverStory.ink +8 -0
  182. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/SimpleStoryFlow.ink +65 -0
  183. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/TagsStory.ink +22 -0
  184. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/TheIntercept.ink +1686 -0
  185. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/ThirdTierChoiceAfterBracketsStory.ink +13 -0
  186. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/UTF-8-demo.txt +212 -0
  187. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/UTF8Story.ink +218 -0
  188. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/simple-1.1.1-inklecate.json +154 -0
  189. data/ext/inkcpp_rb/inkcpp/inkcpp_test/ink/simple-1.1.1-inky.json +160 -0
  190. data/ext/inkcpp_rb/inkcpp/notes/ArchitectureNotes.md +54 -0
  191. data/ext/inkcpp_rb/inkcpp/notes/ListNotes.md +69 -0
  192. data/ext/inkcpp_rb/inkcpp/notes/OperationNotes.md +35 -0
  193. data/ext/inkcpp_rb/inkcpp/notes/TagsNotes.md +24 -0
  194. data/ext/inkcpp_rb/inkcpp/notes/WhitespaceNotes.md +28 -0
  195. data/ext/inkcpp_rb/inkcpp/proofing/README.md +3 -0
  196. data/ext/inkcpp_rb/inkcpp/proofing/inkcpp_runtime_driver +12 -0
  197. data/ext/inkcpp_rb/inkcpp/pyproject.toml +63 -0
  198. data/ext/inkcpp_rb/inkcpp/setup.py +166 -0
  199. data/ext/inkcpp_rb/inkcpp/shared/CMakeLists.txt +14 -0
  200. data/ext/inkcpp_rb/inkcpp/shared/private/command.h +172 -0
  201. data/ext/inkcpp_rb/inkcpp/shared/private/header.h +46 -0
  202. data/ext/inkcpp_rb/inkcpp/shared/public/config.h +53 -0
  203. data/ext/inkcpp_rb/inkcpp/shared/public/system.h +307 -0
  204. data/ext/inkcpp_rb/inkcpp/shared/public/version.h +14 -0
  205. data/ext/inkcpp_rb/inkcpp/tests/TestAllSequenceTypes.ink +59 -0
  206. data/ext/inkcpp_rb/inkcpp/tests/TestArithmetic.ink +17 -0
  207. data/ext/inkcpp_rb/inkcpp/tests/TestBasicStringLiterals.ink +8 -0
  208. data/ext/inkcpp_rb/inkcpp/tests/TestBasicTunnel.ink +10 -0
  209. data/ext/inkcpp_rb/inkcpp/tests/TestBlanksInInlineSequences.ink +51 -0
  210. data/ext/inkcpp_rb/inkcpp/tests/TestCallStackEvaluation.ink +15 -0
  211. data/ext/inkcpp_rb/inkcpp/tests/TestChoiceCount.ink +15 -0
  212. data/ext/inkcpp_rb/inkcpp/tests/TestChoiceDivertsToDone.ink +6 -0
  213. data/ext/inkcpp_rb/inkcpp/tests/TestChoiceWithBracketsOnly.ink +9 -0
  214. data/ext/inkcpp_rb/inkcpp/tests/TestCompareDivertTargets.ink +26 -0
  215. data/ext/inkcpp_rb/inkcpp/tests/TestComplexTunnels.ink +22 -0
  216. data/ext/inkcpp_rb/inkcpp/tests/TestConditionalChoiceInWeave.ink +19 -0
  217. data/ext/inkcpp_rb/inkcpp/tests/TestTunnelOnwardsAfterTunnel.ink +17 -0
  218. data/ext/inkcpp_rb/inkcpp/unreal/CMakeLists.txt +51 -0
  219. data/ext/inkcpp_rb/inkcpp/unreal/UE_example.ink +92 -0
  220. data/ext/inkcpp_rb/inkcpp/unreal/blueprint_filter.js +377 -0
  221. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Resources/Icon128.png +0 -0
  222. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkAsset.cpp +47 -0
  223. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkChoice.cpp +40 -0
  224. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkList.cpp +86 -0
  225. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkRuntime.cpp +265 -0
  226. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkThread.cpp +239 -0
  227. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/InkVar.cpp +143 -0
  228. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/TagList.cpp +95 -0
  229. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Private/inkcpp.cpp +13 -0
  230. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkAsset.h +50 -0
  231. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkChoice.h +58 -0
  232. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkDelegates.h +139 -0
  233. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkList.h +102 -0
  234. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkRuntime.h +177 -0
  235. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkSnapshot.h +30 -0
  236. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkThread.h +215 -0
  237. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/InkVar.h +245 -0
  238. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/TagList.h +77 -0
  239. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/Public/inkcpp.h +217 -0
  240. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp/inkcpp.Build.cs +62 -0
  241. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.cpp +237 -0
  242. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/InkAssetFactory.h +43 -0
  243. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/inkcpp_editor.cpp +13 -0
  244. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Private/inklecate_cmd.cpp.in +24 -0
  245. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/Public/inkcpp_editor.h +9 -0
  246. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/Source/inkcpp_editor/inkcpp_editor.Build.cs +61 -0
  247. data/ext/inkcpp_rb/inkcpp/unreal/inkcpp/inkcpp.uplugin +44 -0
  248. data/ext/inkcpp_rb/inkcpp/unreal/render.css +1 -0
  249. data/ext/inkcpp_rb/inkcpp_rb.cpp +321 -0
  250. data/inkcpp_rb.gemspec +54 -0
  251. data/rbi/inkcpp_rb.rbi +211 -0
  252. data/sorbet/config +4 -0
  253. data/sorbet/rbi/annotations/.gitattributes +1 -0
  254. data/sorbet/rbi/annotations/minitest.rbi +119 -0
  255. data/sorbet/rbi/gems/.gitattributes +1 -0
  256. data/sorbet/rbi/gems/benchmark@0.4.0.rbi +618 -0
  257. data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
  258. data/sorbet/rbi/gems/minitest@5.25.4.rbi +1547 -0
  259. data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
  260. data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
  261. data/sorbet/rbi/gems/prism@1.3.0.rbi +40040 -0
  262. data/sorbet/rbi/gems/rake-compiler@1.2.8.rbi +9 -0
  263. data/sorbet/rbi/gems/rake@13.2.1.rbi +3033 -0
  264. data/sorbet/rbi/gems/rbi@0.2.2.rbi +4527 -0
  265. data/sorbet/rbi/gems/rice@4.3.3.rbi +44 -0
  266. data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
  267. data/sorbet/rbi/gems/tapioca@0.16.7.rbi +3611 -0
  268. data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
  269. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  270. data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
  271. data/sorbet/tapioca/config.yml +13 -0
  272. data/sorbet/tapioca/require.rb +4 -0
  273. metadata +400 -0
@@ -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; }