diff --git a/OmegaGameFramework/BuildingNotes.md b/OmegaGameFramework/BuildingNotes.md new file mode 100644 index 00000000..5ca0187d --- /dev/null +++ b/OmegaGameFramework/BuildingNotes.md @@ -0,0 +1,54 @@ +# Building Lua static library for Mac + +```sh +# edit src/Makefile and set MYCFLAGS to -mmacosx-version-min=10.12 -arch arm64 -arch x86_64 +make macosx +``` + +# Building Lua static library for Linux x86_64 + +```sh +# after having added -fPIC to MYCFLAGS in src/Makefile +make linux +``` + +# Building Lua static library for Win64 + +```sh +# open visual studio shell for x64 and move to the src/ directory (change cl.exe and lib.exe with their arm64 version for hololens) +cl /MD /O2 /c /DLUA_BUILD_AS_DLL /DLUA_COMPAT_5_2 *.c +del lua.obj +del luac.obj +lib /OUT:liblua53_win64.lib *.obj +``` + +# Building Lua static library for Android + +```sh +# assume ndk is installed in home with api 24 +~/ndk/bin/clang -O2 -Wall -Werror -Wextra -DLUA_USE_POSIX -DLUA_USEDLOPEN -DLUA_COMPAT_5_2 -std=gnu99 -c *.c +rm lua.o +rm luac.o + ~/ndk/bin/arm-linux-androideabi-ar.exe rcu liblua53_android.a *.o +``` + +# Building Lua static library for iOS + +Comment the os_execute function in loslib.c and its mapping in the syslib array + +```sh +clang -arch arm64 -mios-version-min=7.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/ -O2 -Wall -Werror -Wextra -DLUA_USE_POSIX -DLUA_USEDLOPEN -DLUA_COMPAT_5_2 -std=gnu99 -c *.c +rm lua.o luac.o + ar rcu liblua53_ios.a *.o +``` + + +# Building Lua static library for Linux AArch64 + +```sh +# assume cross compiler for aarch64 is available +aarch64-linux-gnu-gcc -O2 -Wall -Werror -Wextra -DLUA_USE_POSIX -DLUA_USEDLOPEN -DLUA_COMPAT_5_2 -std=gnu99 -c *.c +rm lua.o +rm luac.o +aarch64-linux-gnu-ar rcD liblua53_linux_aarch64.a *.o +``` diff --git a/OmegaGameFramework/Content/Blueprints/Actors/LevelBuilder/LevelBuilder_AdvRoom.uasset b/OmegaGameFramework/Content/Blueprints/Actors/LevelBuilder/LevelBuilder_AdvRoom.uasset new file mode 100644 index 00000000..986939d3 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Actors/LevelBuilder/LevelBuilder_AdvRoom.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Actors/LevelImport/OmegaLevelImporter_Godot.uasset b/OmegaGameFramework/Content/Blueprints/Actors/LevelImport/OmegaLevelImporter_Godot.uasset new file mode 100644 index 00000000..7306a854 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Actors/LevelImport/OmegaLevelImporter_Godot.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Actors/OmegaBulletBase.uasset b/OmegaGameFramework/Content/Blueprints/Actors/OmegaBulletBase.uasset index 413f859b..5e56822e 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Actors/OmegaBulletBase.uasset and b/OmegaGameFramework/Content/Blueprints/Actors/OmegaBulletBase.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Actors/OmegaLevelImporter.uasset b/OmegaGameFramework/Content/Blueprints/Actors/OmegaLevelImporter.uasset new file mode 100644 index 00000000..97261995 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Actors/OmegaLevelImporter.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Actors/OmegaPickup.uasset b/OmegaGameFramework/Content/Blueprints/Actors/OmegaPickup.uasset index 5d302f04..07161dba 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Actors/OmegaPickup.uasset and b/OmegaGameFramework/Content/Blueprints/Actors/OmegaPickup.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/AnimNotify/AnimNotifyWindow_ActorTag.uasset b/OmegaGameFramework/Content/Blueprints/AnimNotify/AnimNotifyWindow_ActorTag.uasset new file mode 100644 index 00000000..477af129 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/AnimNotify/AnimNotifyWindow_ActorTag.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/AnimNotify/AnimNotifyWindow_Combatant_TrackTarget.uasset b/OmegaGameFramework/Content/Blueprints/AnimNotify/AnimNotifyWindow_Combatant_TrackTarget.uasset new file mode 100644 index 00000000..f69e848a Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/AnimNotify/AnimNotifyWindow_Combatant_TrackTarget.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/AssetCooldown.uasset b/OmegaGameFramework/Content/Blueprints/Components/AssetCooldown.uasset index 194966f6..4684ffbd 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/AssetCooldown.uasset and b/OmegaGameFramework/Content/Blueprints/Components/AssetCooldown.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/BulletSpawner.uasset b/OmegaGameFramework/Content/Blueprints/Components/BulletSpawner.uasset index 74cde875..8821f436 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/BulletSpawner.uasset and b/OmegaGameFramework/Content/Blueprints/Components/BulletSpawner.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Character_AdvancedJump.uasset b/OmegaGameFramework/Content/Blueprints/Components/Character_AdvancedJump.uasset index 94a123d2..e14c52a7 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Character_AdvancedJump.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Character_AdvancedJump.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Child_AutoSnaptoParent.uasset b/OmegaGameFramework/Content/Blueprints/Components/Child_AutoSnaptoParent.uasset new file mode 100644 index 00000000..a910eacc Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/Child_AutoSnaptoParent.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Child_SnapToParentSlot.uasset b/OmegaGameFramework/Content/Blueprints/Components/Child_SnapToParentSlot.uasset new file mode 100644 index 00000000..d320d721 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/Child_SnapToParentSlot.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/ComboManager.uasset b/OmegaGameFramework/Content/Blueprints/Components/ComboManager.uasset index f3cc767f..614cfa34 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/ComboManager.uasset and b/OmegaGameFramework/Content/Blueprints/Components/ComboManager.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Control_BasicMovement.uasset b/OmegaGameFramework/Content/Blueprints/Components/Control_BasicMovement.uasset index fd5e4c58..19019aca 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Control_BasicMovement.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Control_BasicMovement.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Control_Rotation.uasset b/OmegaGameFramework/Content/Blueprints/Components/Control_Rotation.uasset index a03bad96..30003527 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Control_Rotation.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Control_Rotation.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/DodgeAndDash.uasset b/OmegaGameFramework/Content/Blueprints/Components/DodgeAndDash.uasset index 5515aa58..53e67e87 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/DodgeAndDash.uasset and b/OmegaGameFramework/Content/Blueprints/Components/DodgeAndDash.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/InputActionComponent.uasset b/OmegaGameFramework/Content/Blueprints/Components/InputActionComponent.uasset deleted file mode 100644 index b71c396b..00000000 Binary files a/OmegaGameFramework/Content/Blueprints/Components/InputActionComponent.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Input_Simple.uasset b/OmegaGameFramework/Content/Blueprints/Components/Input_Simple.uasset new file mode 100644 index 00000000..09964f2a Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/Input_Simple.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Interpolator.uasset b/OmegaGameFramework/Content/Blueprints/Components/Interpolator.uasset index acbc6d55..7c7df548 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Interpolator.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Interpolator.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/LookAtActor.uasset b/OmegaGameFramework/Content/Blueprints/Components/LookAtActor.uasset new file mode 100644 index 00000000..cfcdc498 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/LookAtActor.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/MouseOverActor.uasset b/OmegaGameFramework/Content/Blueprints/Components/MouseOverActor.uasset new file mode 100644 index 00000000..6e9e96b5 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/MouseOverActor.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Move_AlongSpline.uasset b/OmegaGameFramework/Content/Blueprints/Components/Move_AlongSpline.uasset index b53bfa36..4c753b59 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Move_AlongSpline.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Move_AlongSpline.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Move_MouseCursor.uasset b/OmegaGameFramework/Content/Blueprints/Components/Move_MouseCursor.uasset index 9d1c9871..da981349 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Move_MouseCursor.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Move_MouseCursor.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Movement_Auto.uasset b/OmegaGameFramework/Content/Blueprints/Components/Movement_Auto.uasset index 8fe5a845..dc7da059 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Movement_Auto.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Movement_Auto.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/OmegaPickup.uasset b/OmegaGameFramework/Content/Blueprints/Components/OmegaPickup.uasset index 47a30368..0ccaa512 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/OmegaPickup.uasset and b/OmegaGameFramework/Content/Blueprints/Components/OmegaPickup.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/PawnSpeedAccelerator.uasset b/OmegaGameFramework/Content/Blueprints/Components/PawnSpeedAccelerator.uasset index 77ee6ff1..78b63bb3 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/PawnSpeedAccelerator.uasset and b/OmegaGameFramework/Content/Blueprints/Components/PawnSpeedAccelerator.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Pawn_RotationSyncing.uasset b/OmegaGameFramework/Content/Blueprints/Components/Pawn_RotationSyncing.uasset index 4af99958..8e5e29cb 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Pawn_RotationSyncing.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Pawn_RotationSyncing.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/PhysicsImpact.uasset b/OmegaGameFramework/Content/Blueprints/Components/PhysicsImpact.uasset new file mode 100644 index 00000000..cd55577c Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/PhysicsImpact.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Player_HUD.uasset b/OmegaGameFramework/Content/Blueprints/Components/Player_HUD.uasset index 5e18a38e..4b132c05 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Player_HUD.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Player_HUD.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Spline_4Connector.uasset b/OmegaGameFramework/Content/Blueprints/Components/Spline_4Connector.uasset index ea5bbd08..ebd0fe05 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Spline_4Connector.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Spline_4Connector.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Spline_MeshesAtPoints.uasset b/OmegaGameFramework/Content/Blueprints/Components/Spline_MeshesAtPoints.uasset index 00dc1087..dc5e11d5 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Spline_MeshesAtPoints.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Spline_MeshesAtPoints.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/TagEvent_WaitFor.uasset b/OmegaGameFramework/Content/Blueprints/Components/TagEvent_WaitFor.uasset index 5215037b..04067877 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/TagEvent_WaitFor.uasset and b/OmegaGameFramework/Content/Blueprints/Components/TagEvent_WaitFor.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/Timecode/TimecodeComponent.uasset b/OmegaGameFramework/Content/Blueprints/Components/Timecode/TimecodeComponent.uasset index 4e958def..5d150bc8 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/Timecode/TimecodeComponent.uasset and b/OmegaGameFramework/Content/Blueprints/Components/Timecode/TimecodeComponent.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/VisibilityOnAssetCollected.uasset b/OmegaGameFramework/Content/Blueprints/Components/VisibilityOnAssetCollected.uasset index efaf4dc2..a874ffaf 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/VisibilityOnAssetCollected.uasset and b/OmegaGameFramework/Content/Blueprints/Components/VisibilityOnAssetCollected.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/ReplicateTagEvents.uasset b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/ReplicateTagEvents.uasset new file mode 100644 index 00000000..e38e909d Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/ReplicateTagEvents.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoActivate.uasset b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoActivate.uasset index 60fd371b..369ee5e7 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoActivate.uasset and b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoActivate.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoActivate_Closest.uasset b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoActivate_Closest.uasset new file mode 100644 index 00000000..dccfb7d9 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoActivate_Closest.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoRegister.uasset b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoRegister.uasset index 753e220b..5ffef772 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoRegister.uasset and b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_AutoRegister.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_CameraPull.uasset b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_CameraPull.uasset new file mode 100644 index 00000000..2e1b9756 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_CameraPull.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_LockOn.uasset b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_LockOn.uasset new file mode 100644 index 00000000..ced6795d Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_LockOn.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_RotateTo.uasset b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_RotateTo.uasset index ef7e2d99..e28680a6 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_RotateTo.uasset and b/OmegaGameFramework/Content/Blueprints/Components/_Combatant/Target_RotateTo.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/Macros_DataWidget.uasset b/OmegaGameFramework/Content/Blueprints/Macros/Macros_DataWidget.uasset index 8cb040fb..3345f7fa 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Macros/Macros_DataWidget.uasset and b/OmegaGameFramework/Content/Blueprints/Macros/Macros_DataWidget.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/Macros_GameplayEffects.uasset b/OmegaGameFramework/Content/Blueprints/Macros/Macros_GameplayEffects.uasset new file mode 100644 index 00000000..0b5c9a63 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Macros/Macros_GameplayEffects.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/Macros_UserWidgets.uasset b/OmegaGameFramework/Content/Blueprints/Macros/Macros_UserWidgets.uasset index 43023e85..cd751602 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Macros/Macros_UserWidgets.uasset and b/OmegaGameFramework/Content/Blueprints/Macros/Macros_UserWidgets.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Actor.uasset b/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Actor.uasset index 577959cd..95a569cb 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Actor.uasset and b/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Actor.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Object.uasset b/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Object.uasset index 185125d7..815b3a11 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Object.uasset and b/OmegaGameFramework/Content/Blueprints/Macros/OmegaMacros_Object.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/mac_Assets.uasset b/OmegaGameFramework/Content/Blueprints/Macros/mac_Assets.uasset index 3c9433ca..443c43b8 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Macros/mac_Assets.uasset and b/OmegaGameFramework/Content/Blueprints/Macros/mac_Assets.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/mac_Component.uasset b/OmegaGameFramework/Content/Blueprints/Macros/mac_Component.uasset index 4aab1ff6..1b0b2077 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Macros/mac_Component.uasset and b/OmegaGameFramework/Content/Blueprints/Macros/mac_Component.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Macros/macros_Ability.uasset b/OmegaGameFramework/Content/Blueprints/Macros/macros_Ability.uasset index 21015bcb..b51bf573 100644 Binary files a/OmegaGameFramework/Content/Blueprints/Macros/macros_Ability.uasset and b/OmegaGameFramework/Content/Blueprints/Macros/macros_Ability.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/OmegaFunctions_Json.uasset b/OmegaGameFramework/Content/Blueprints/OmegaFunctions_Json.uasset new file mode 100644 index 00000000..a015ef36 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/OmegaFunctions_Json.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/OmegaGameFunctions.uasset b/OmegaGameFramework/Content/Blueprints/OmegaGameFunctions.uasset index f849948d..fe038765 100644 Binary files a/OmegaGameFramework/Content/Blueprints/OmegaGameFunctions.uasset and b/OmegaGameFramework/Content/Blueprints/OmegaGameFunctions.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/OmegaJsonInterface.uasset b/OmegaGameFramework/Content/Blueprints/OmegaJsonInterface.uasset new file mode 100644 index 00000000..01d271ae Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/OmegaJsonInterface.uasset differ diff --git a/OmegaGameFramework/Content/Blueprints/Widget/Button_Empty.uasset b/OmegaGameFramework/Content/Blueprints/Widget/Button_Empty.uasset new file mode 100644 index 00000000..a4a9b9f9 Binary files /dev/null and b/OmegaGameFramework/Content/Blueprints/Widget/Button_Empty.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_CommandAction.uasset b/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_CommandAction.uasset new file mode 100644 index 00000000..2b04fcdb Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_CommandAction.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_Jump.uasset b/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_Jump.uasset index 1d167150..5f42cb0a 100644 Binary files a/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_Jump.uasset and b/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_Jump.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_MontageAction.uasset b/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_MontageAction.uasset new file mode 100644 index 00000000..ea6ff110 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Abilities/DemoAbility_MontageAction.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Actor/DemoActor_Gun.uasset b/OmegaGameFramework/Content/DEMO/Actor/DemoActor_Gun.uasset new file mode 100644 index 00000000..dcba1464 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Actor/DemoActor_Gun.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Animation/AT_Saccade.uasset b/OmegaGameFramework/Content/DEMO/Animation/AT_Saccade.uasset new file mode 100644 index 00000000..7d834fca Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Animation/AT_Saccade.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Attributes/DemoAtb_Health.uasset b/OmegaGameFramework/Content/DEMO/Attributes/DemoAtb_Health.uasset index 2f6d1bad..a33c11f0 100644 Binary files a/OmegaGameFramework/Content/DEMO/Attributes/DemoAtb_Health.uasset and b/OmegaGameFramework/Content/DEMO/Attributes/DemoAtb_Health.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_CUstomCurve.uasset b/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_CUstomCurve.uasset new file mode 100644 index 00000000..0509460f Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_CUstomCurve.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_Flat.uasset b/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_Flat.uasset new file mode 100644 index 00000000..1f7a2269 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_Flat.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_FloatCurve.uasset b/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_FloatCurve.uasset new file mode 100644 index 00000000..da6d867e Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Attributes/Scripts/AttributeScript_FloatCurve.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Characters/DemoCharacter_FPS.uasset b/OmegaGameFramework/Content/DEMO/Characters/DemoCharacter_FPS.uasset new file mode 100644 index 00000000..fe575832 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Characters/DemoCharacter_FPS.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Characters/DemoCharacter_Third.uasset b/OmegaGameFramework/Content/DEMO/Characters/DemoCharacter_Third.uasset new file mode 100644 index 00000000..7752dc82 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Characters/DemoCharacter_Third.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/ControlRig/CR_Look.uasset b/OmegaGameFramework/Content/DEMO/ControlRig/CR_Look.uasset new file mode 100644 index 00000000..12c98ac1 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/ControlRig/CR_Look.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/ControlRig/DriverRig_Mannequin.uasset b/OmegaGameFramework/Content/DEMO/ControlRig/DriverRig_Mannequin.uasset new file mode 100644 index 00000000..a8c72463 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/ControlRig/DriverRig_Mannequin.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/ControlRig/Mannequin_ControlRig.uasset b/OmegaGameFramework/Content/DEMO/ControlRig/Mannequin_ControlRig.uasset new file mode 100644 index 00000000..9f3372d2 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/ControlRig/Mannequin_ControlRig.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/DemoSky.uasset b/OmegaGameFramework/Content/DEMO/DemoSky.uasset index 8551fcc4..07db8172 100644 Binary files a/OmegaGameFramework/Content/DEMO/DemoSky.uasset and b/OmegaGameFramework/Content/DEMO/DemoSky.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/EquipScript/EquipScript_Asset.uasset b/OmegaGameFramework/Content/DEMO/EquipScript/EquipScript_Asset.uasset new file mode 100644 index 00000000..f3ad58ab Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/EquipScript/EquipScript_Asset.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Flow/FN_Lua_Function.uasset b/OmegaGameFramework/Content/DEMO/Flow/FN_Lua_Function.uasset new file mode 100644 index 00000000..078e6287 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Flow/FN_Lua_Function.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Flow/FN_Lua_branch.uasset b/OmegaGameFramework/Content/DEMO/Flow/FN_Lua_branch.uasset new file mode 100644 index 00000000..ed9f23b8 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Flow/FN_Lua_branch.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Book/OmegaDemo_Book.uasset b/OmegaGameFramework/Content/DEMO/Game/Book/OmegaDemo_Book.uasset index 1e3d5140..e74fad42 100644 Binary files a/OmegaGameFramework/Content/DEMO/Game/Book/OmegaDemo_Book.uasset and b/OmegaGameFramework/Content/DEMO/Game/Book/OmegaDemo_Book.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Death/OmegaDemo_Death.uasset b/OmegaGameFramework/Content/DEMO/Game/Death/OmegaDemo_Death.uasset deleted file mode 100644 index d56ae9da..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Game/Death/OmegaDemo_Death.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog.uasset b/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog.uasset deleted file mode 100644 index 4a48bd78..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog_Component.uasset b/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog_Component.uasset index 10a34bb0..10e6423b 100644 Binary files a/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog_Component.uasset and b/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog_Component.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog_HUD.uasset b/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog_HUD.uasset deleted file mode 100644 index eae8985c..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Game/Dialog/OmegaDemo_Dialog_HUD.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Explore/OmegaDemo_Exploration.uasset b/OmegaGameFramework/Content/DEMO/Game/Explore/OmegaDemo_Exploration.uasset deleted file mode 100644 index 640bcccf..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Game/Explore/OmegaDemo_Exploration.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Maps/OmegaDemoMap_FPS.umap b/OmegaGameFramework/Content/DEMO/Game/Maps/OmegaDemoMap_FPS.umap new file mode 100644 index 00000000..6c84ff61 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Game/Maps/OmegaDemoMap_FPS.umap differ diff --git a/OmegaGameFramework/Content/DEMO/Game/OmegaDemoMap.umap b/OmegaGameFramework/Content/DEMO/Game/OmegaDemoMap.umap index 6a2d306a..aeef6b19 100644 Binary files a/OmegaGameFramework/Content/DEMO/Game/OmegaDemoMap.umap and b/OmegaGameFramework/Content/DEMO/Game/OmegaDemoMap.umap differ diff --git a/OmegaGameFramework/Content/DEMO/Game/OmegaDemo_Pause.uasset b/OmegaGameFramework/Content/DEMO/Game/OmegaDemo_Pause.uasset deleted file mode 100644 index 95c6fbdd..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Game/OmegaDemo_Pause.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Game/OmegaDemo_PlayerCharacter.uasset b/OmegaGameFramework/Content/DEMO/Game/OmegaDemo_PlayerCharacter.uasset index 98116838..95c1914f 100644 Binary files a/OmegaGameFramework/Content/DEMO/Game/OmegaDemo_PlayerCharacter.uasset and b/OmegaGameFramework/Content/DEMO/Game/OmegaDemo_PlayerCharacter.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Game/Pause/OmegaDemo_PauseMenu.uasset b/OmegaGameFramework/Content/DEMO/Game/Pause/OmegaDemo_PauseMenu.uasset index a08417c5..ed05dbae 100644 Binary files a/OmegaGameFramework/Content/DEMO/Game/Pause/OmegaDemo_PauseMenu.uasset and b/OmegaGameFramework/Content/DEMO/Game/Pause/OmegaDemo_PauseMenu.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/HUD/HUD_Demo_Dialog.uasset b/OmegaGameFramework/Content/DEMO/HUD/HUD_Demo_Dialog.uasset new file mode 100644 index 00000000..66eb523c Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/HUD/HUD_Demo_Dialog.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/HUD/HUD_Demo_TurnBased.uasset b/OmegaGameFramework/Content/DEMO/HUD/HUD_Demo_TurnBased.uasset new file mode 100644 index 00000000..c7f7c79d Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/HUD/HUD_Demo_TurnBased.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Input/InputMode_Full.uasset b/OmegaGameFramework/Content/DEMO/Input/InputMode_Full.uasset new file mode 100644 index 00000000..31d09c03 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Input/InputMode_Full.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/LinearEvents/LE_BGM_Play.uasset b/OmegaGameFramework/Content/DEMO/LinearEvents/LE_BGM_Play.uasset index dc79675d..1a6cab18 100644 Binary files a/OmegaGameFramework/Content/DEMO/LinearEvents/LE_BGM_Play.uasset and b/OmegaGameFramework/Content/DEMO/LinearEvents/LE_BGM_Play.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/ReflectionMetaTable.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/ReflectionMetaTable.uasset new file mode 100644 index 00000000..07fce419 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/ReflectionMetaTable.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/TestActorCode.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/TestActorCode.uasset new file mode 100644 index 00000000..b69033fc Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/TestActorCode.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/TestBrokenCode.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/TestBrokenCode.uasset new file mode 100644 index 00000000..4feae3aa Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/TestBrokenCode.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/TestCoroutines.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/TestCoroutines.uasset new file mode 100644 index 00000000..d945916f Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/TestCoroutines.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/TestDummyCode.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/TestDummyCode.uasset new file mode 100644 index 00000000..96792693 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/TestDummyCode.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/TestMainCode.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/TestMainCode.uasset new file mode 100644 index 00000000..7d450027 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/TestMainCode.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/TestProxyCall.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/TestProxyCall.uasset new file mode 100644 index 00000000..255dde60 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/TestProxyCall.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Hooks.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Hooks.uasset new file mode 100644 index 00000000..0f9efcab Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Hooks.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Loc.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Loc.uasset new file mode 100644 index 00000000..515e1683 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Loc.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Util.uasset b/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Util.uasset new file mode 100644 index 00000000..e04de824 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/Code/lib_Util.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/LuaReflectionTestState.uasset b/OmegaGameFramework/Content/DEMO/Lua/LuaReflectionTestState.uasset new file mode 100644 index 00000000..58d8fe65 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/LuaReflectionTestState.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/OmegaLuaObject.uasset b/OmegaGameFramework/Content/DEMO/Lua/OmegaLuaObject.uasset new file mode 100644 index 00000000..a846d43b Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/OmegaLuaObject.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/OmegaLua_State.uasset b/OmegaGameFramework/Content/DEMO/Lua/OmegaLua_State.uasset new file mode 100644 index 00000000..82fb0bcd Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/OmegaLua_State.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/OmegaMod_Lua.uasset b/OmegaGameFramework/Content/DEMO/Lua/OmegaMod_Lua.uasset new file mode 100644 index 00000000..a50f9e03 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/OmegaMod_Lua.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Lua/macros_OmegaLua.uasset b/OmegaGameFramework/Content/DEMO/Lua/macros_OmegaLua.uasset new file mode 100644 index 00000000..9c896af3 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Lua/macros_OmegaLua.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Run.uasset b/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Run.uasset index 6e45d5ba..f079d07a 100644 Binary files a/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Run.uasset and b/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Run.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Walk.uasset b/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Walk.uasset index fbf5ad0e..e5c5e7bb 100644 Binary files a/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Walk.uasset and b/OmegaGameFramework/Content/DEMO/Mannequin/Animations/a_OmegaDemo_Walk.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Mannequin/Animations/arms/abs_arms_idle-run.uasset b/OmegaGameFramework/Content/DEMO/Mannequin/Animations/arms/abs_arms_idle-run.uasset index a77712df..efead54c 100644 Binary files a/OmegaGameFramework/Content/DEMO/Mannequin/Animations/arms/abs_arms_idle-run.uasset and b/OmegaGameFramework/Content/DEMO/Mannequin/Animations/arms/abs_arms_idle-run.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/SK_MannequinDemo_Female_blank.uasset b/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/SK_MannequinDemo_Female_blank.uasset new file mode 100644 index 00000000..4615ab28 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/SK_MannequinDemo_Female_blank.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/SK_MannequinDemo_Male_blank.uasset b/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/SK_MannequinDemo_Male_blank.uasset new file mode 100644 index 00000000..190e50df Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/SK_MannequinDemo_Male_blank.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/UE4_Mannequin_DEMOSkeleton.uasset b/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/UE4_Mannequin_DEMOSkeleton.uasset index ca102233..4295801c 100644 Binary files a/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/UE4_Mannequin_DEMOSkeleton.uasset and b/OmegaGameFramework/Content/DEMO/Mannequin/Mesh/UE4_Mannequin_DEMOSkeleton.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Mannequin/Rig/IK-Rig_Mannequin.uasset b/OmegaGameFramework/Content/DEMO/Mannequin/Rig/IK-Rig_Mannequin.uasset new file mode 100644 index 00000000..0c824778 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Mannequin/Rig/IK-Rig_Mannequin.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal-crate_1.uasset b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal-crate_1.uasset new file mode 100644 index 00000000..887a379d Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal-crate_1.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal1.uasset b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal1.uasset new file mode 100644 index 00000000..ae852542 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal1.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal2.uasset b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal2.uasset new file mode 100644 index 00000000..db77962f Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal2.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal3.uasset b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal3.uasset new file mode 100644 index 00000000..e9cd6e5a Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Materials/m_demo_metal3.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Menus/DemoMenu_BattleCommand.uasset b/OmegaGameFramework/Content/DEMO/Menus/DemoMenu_BattleCommand.uasset new file mode 100644 index 00000000..9ccd8f21 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Menus/DemoMenu_BattleCommand.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Choice.uasset b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Choice.uasset new file mode 100644 index 00000000..95147316 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Choice.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Confirmation.uasset b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Confirmation.uasset new file mode 100644 index 00000000..7263c123 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Confirmation.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Generic.uasset b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Generic.uasset new file mode 100644 index 00000000..16fa23b5 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Generic.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Info.uasset b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Info.uasset new file mode 100644 index 00000000..242964b7 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_Info.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_SaveLoad.uasset b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_SaveLoad.uasset new file mode 100644 index 00000000..40090005 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Menus/OmegaMenu_SaveLoad.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Message/log/OmegaDemo_Message_LogEntry.uasset b/OmegaGameFramework/Content/DEMO/Message/log/OmegaDemo_Message_LogEntry.uasset index 1cc6b150..98ef1c06 100644 Binary files a/OmegaGameFramework/Content/DEMO/Message/log/OmegaDemo_Message_LogEntry.uasset and b/OmegaGameFramework/Content/DEMO/Message/log/OmegaDemo_Message_LogEntry.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/OmegaDemoCharacter.uasset b/OmegaGameFramework/Content/DEMO/OmegaDemoCharacter.uasset index 83937627..92829434 100644 Binary files a/OmegaGameFramework/Content/DEMO/OmegaDemoCharacter.uasset and b/OmegaGameFramework/Content/DEMO/OmegaDemoCharacter.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/OmegaGameMode_Demo.uasset b/OmegaGameFramework/Content/DEMO/OmegaGameMode_Demo.uasset index d85d50ff..eec61ed9 100644 Binary files a/OmegaGameFramework/Content/DEMO/OmegaGameMode_Demo.uasset and b/OmegaGameFramework/Content/DEMO/OmegaGameMode_Demo.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Rig/DriverRig_Looking.uasset b/OmegaGameFramework/Content/DEMO/Rig/DriverRig_Looking.uasset deleted file mode 100644 index a5b57aea..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Rig/DriverRig_Looking.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Rig/DriverRig_Mannequin.uasset b/OmegaGameFramework/Content/DEMO/Rig/DriverRig_Mannequin.uasset deleted file mode 100644 index b6cc3593..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Rig/DriverRig_Mannequin.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Rig/Mannequin_ControlRig.uasset b/OmegaGameFramework/Content/DEMO/Rig/Mannequin_ControlRig.uasset deleted file mode 100644 index 55e2b37b..00000000 Binary files a/OmegaGameFramework/Content/DEMO/Rig/Mannequin_ControlRig.uasset and /dev/null differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/OmegaDemo_Dialog.uasset b/OmegaGameFramework/Content/DEMO/Systems/OmegaDemo_Dialog.uasset new file mode 100644 index 00000000..0d43e7a6 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/OmegaDemo_Dialog.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/OmegaDemo_Exploration.uasset b/OmegaGameFramework/Content/DEMO/Systems/OmegaDemo_Exploration.uasset new file mode 100644 index 00000000..22ed3cee Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/OmegaDemo_Exploration.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Death.uasset b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Death.uasset new file mode 100644 index 00000000..ccee6cac Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Death.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Dialog.uasset b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Dialog.uasset new file mode 100644 index 00000000..a5d8c0a9 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Dialog.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Exploration.uasset b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Exploration.uasset new file mode 100644 index 00000000..a3edb354 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Exploration.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Menu.uasset b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Menu.uasset new file mode 100644 index 00000000..3b15feb1 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Menu.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Pause.uasset b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Pause.uasset new file mode 100644 index 00000000..1029c242 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_Pause.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/system_Demo_TabCombat.uasset b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_TabCombat.uasset new file mode 100644 index 00000000..0322099d Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_TabCombat.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Systems/system_Demo_TurnBasedCombat.uasset b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_TurnBasedCombat.uasset new file mode 100644 index 00000000..52d66555 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Systems/system_Demo_TurnBasedCombat.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Box.uasset b/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Box.uasset new file mode 100644 index 00000000..efddc984 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Box.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Line.uasset b/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Line.uasset new file mode 100644 index 00000000..e5cfa7b2 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Line.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Sphere.uasset b/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Sphere.uasset new file mode 100644 index 00000000..3af3fb2a Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/Traces/CustomTrace_Sphere.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/widget/DataWidgets/dw_omega_option_default.uasset b/OmegaGameFramework/Content/DEMO/widget/DataWidgets/dw_omega_option_default.uasset new file mode 100644 index 00000000..809e27fe Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/widget/DataWidgets/dw_omega_option_default.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/widget/DataWidgets/dw_omega_option_minimal.uasset b/OmegaGameFramework/Content/DEMO/widget/DataWidgets/dw_omega_option_minimal.uasset new file mode 100644 index 00000000..6aca3645 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/widget/DataWidgets/dw_omega_option_minimal.uasset differ diff --git a/OmegaGameFramework/Content/DEMO/widget/text/OmegaText_Style_1.uasset b/OmegaGameFramework/Content/DEMO/widget/text/OmegaText_Style_1.uasset new file mode 100644 index 00000000..5527ba44 Binary files /dev/null and b/OmegaGameFramework/Content/DEMO/widget/text/OmegaText_Style_1.uasset differ diff --git a/OmegaGameFramework/Content/Editor/OmegaEditor_Level.uasset b/OmegaGameFramework/Content/Editor/OmegaEditor_Level.uasset new file mode 100644 index 00000000..9f30ab9e Binary files /dev/null and b/OmegaGameFramework/Content/Editor/OmegaEditor_Level.uasset differ diff --git a/OmegaGameFramework/Content/Materials/Functions/MR_AlphaWeightColorTint.uasset b/OmegaGameFramework/Content/Materials/Functions/MR_AlphaWeightColorTint.uasset new file mode 100644 index 00000000..5a9a35a8 Binary files /dev/null and b/OmegaGameFramework/Content/Materials/Functions/MR_AlphaWeightColorTint.uasset differ diff --git a/OmegaGameFramework/Content/Materials/LayerBlend/MLB_VertexNormal.uasset b/OmegaGameFramework/Content/Materials/LayerBlend/MLB_VertexNormal.uasset new file mode 100644 index 00000000..959bcc47 Binary files /dev/null and b/OmegaGameFramework/Content/Materials/LayerBlend/MLB_VertexNormal.uasset differ diff --git a/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat.uasset b/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat.uasset index 90ca818f..8c056ef6 100644 Binary files a/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat.uasset and b/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat.uasset differ diff --git a/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat_blue.uasset b/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat_blue.uasset index 99e4a29b..43abe553 100644 Binary files a/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat_blue.uasset and b/OmegaGameFramework/Content/Materials/Shaders/Flats/M_Flat_blue.uasset differ diff --git a/OmegaGameFramework/Content/Materials/Shaders/M_SoftPoint.uasset b/OmegaGameFramework/Content/Materials/Shaders/M_SoftPoint.uasset new file mode 100644 index 00000000..c5b76712 Binary files /dev/null and b/OmegaGameFramework/Content/Materials/Shaders/M_SoftPoint.uasset differ diff --git a/OmegaGameFramework/Content/Materials/Shaders/M_Static.uasset b/OmegaGameFramework/Content/Materials/Shaders/M_Static.uasset new file mode 100644 index 00000000..58950cf0 Binary files /dev/null and b/OmegaGameFramework/Content/Materials/Shaders/M_Static.uasset differ diff --git a/OmegaGameFramework/Content/Materials/Shaders/static/M_Static_blue.uasset b/OmegaGameFramework/Content/Materials/Shaders/static/M_Static_blue.uasset new file mode 100644 index 00000000..d72e750f Binary files /dev/null and b/OmegaGameFramework/Content/Materials/Shaders/static/M_Static_blue.uasset differ diff --git a/OmegaGameFramework/Content/Materials/UI/M_ui_ColorCurveDisplay.uasset b/OmegaGameFramework/Content/Materials/UI/M_ui_ColorCurveDisplay.uasset new file mode 100644 index 00000000..ed673f10 Binary files /dev/null and b/OmegaGameFramework/Content/Materials/UI/M_ui_ColorCurveDisplay.uasset differ diff --git a/OmegaGameFramework/Content/Materials/UI/m_Omega_Border_Round.uasset b/OmegaGameFramework/Content/Materials/UI/m_Omega_Border_Round.uasset new file mode 100644 index 00000000..70814fd9 Binary files /dev/null and b/OmegaGameFramework/Content/Materials/UI/m_Omega_Border_Round.uasset differ diff --git a/OmegaGameFramework/Content/Materials/m_Blank.uasset b/OmegaGameFramework/Content/Materials/m_Blank.uasset new file mode 100644 index 00000000..57b7e359 Binary files /dev/null and b/OmegaGameFramework/Content/Materials/m_Blank.uasset differ diff --git a/OmegaGameFramework/Content/Materials/m_OmegaShader.uasset b/OmegaGameFramework/Content/Materials/m_OmegaShader.uasset index 03850f51..1b45e839 100644 Binary files a/OmegaGameFramework/Content/Materials/m_OmegaShader.uasset and b/OmegaGameFramework/Content/Materials/m_OmegaShader.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_grating_albedo.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_grating_albedo.uasset new file mode 100644 index 00000000..1710dde6 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_grating_albedo.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_grating_alpha.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_grating_alpha.uasset new file mode 100644 index 00000000..857f1b1c Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_grating_alpha.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_grating_normal.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_grating_normal.uasset new file mode 100644 index 00000000..f2822679 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_grating_normal.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_box1.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box1.uasset new file mode 100644 index 00000000..51f800d2 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box1.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_box2.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box2.uasset new file mode 100644 index 00000000..6ffbf31e Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box2.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_box3.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box3.uasset new file mode 100644 index 00000000..5b40cf83 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box3.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_box4.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box4.uasset new file mode 100644 index 00000000..5bdf4f2b Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box4.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_box5.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box5.uasset new file mode 100644 index 00000000..bf8bab3f Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box5.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_box6.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box6.uasset new file mode 100644 index 00000000..b6f47a34 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_box6.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling.uasset new file mode 100644 index 00000000..096fee4d Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling1.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling1.uasset new file mode 100644 index 00000000..473f57b9 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling1.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling3.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling3.uasset new file mode 100644 index 00000000..b3f04bf1 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_ceiling3.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor1.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor1.uasset new file mode 100644 index 00000000..92fedb62 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor1.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor2.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor2.uasset new file mode 100644 index 00000000..face899f Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor2.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor3.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor3.uasset new file mode 100644 index 00000000..c7489af9 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_floor3.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall0.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall0.uasset new file mode 100644 index 00000000..a8654ad6 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall0.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall1.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall1.uasset new file mode 100644 index 00000000..b7c6d7bf Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall1.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall2.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall2.uasset new file mode 100644 index 00000000..28d801d7 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall2.uasset differ diff --git a/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall3.uasset b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall3.uasset new file mode 100644 index 00000000..ebf9ea5f Binary files /dev/null and b/OmegaGameFramework/Content/Textures/World/t_omega_metal_wall3.uasset differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_cone.psd b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_cone.psd new file mode 100644 index 00000000..2a5053a7 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_cone.psd differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_cone.uasset b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_cone.uasset new file mode 100644 index 00000000..7cb326ad Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_cone.uasset differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_move.png b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_move.png new file mode 100644 index 00000000..79ae3ac6 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_move.png differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_move.uasset b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_move.uasset new file mode 100644 index 00000000..58fe9f9d Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_move.uasset differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphere.psd b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphere.psd new file mode 100644 index 00000000..16d18e38 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphere.psd differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphere.uasset b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphere.uasset new file mode 100644 index 00000000..d33c0189 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphere.uasset differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphereBounds.png b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphereBounds.png new file mode 100644 index 00000000..3b3f8df0 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphereBounds.png differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphereBounds.uasset b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphereBounds.uasset new file mode 100644 index 00000000..9e8d7f3a Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_sphereBounds.uasset differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_square.psd b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_square.psd new file mode 100644 index 00000000..2826bf14 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_square.psd differ diff --git a/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_square.uasset b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_square.uasset new file mode 100644 index 00000000..f9dbe537 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/aoe/t_aoeShape_square.uasset differ diff --git a/OmegaGameFramework/Content/Textures/masks/t_LightPointMask.png b/OmegaGameFramework/Content/Textures/masks/t_LightPointMask.png new file mode 100644 index 00000000..ce143181 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/t_LightPointMask.png differ diff --git a/OmegaGameFramework/Content/Textures/masks/t_mask_softPoint.uasset b/OmegaGameFramework/Content/Textures/masks/t_mask_softPoint.uasset new file mode 100644 index 00000000..a13762f7 Binary files /dev/null and b/OmegaGameFramework/Content/Textures/masks/t_mask_softPoint.uasset differ diff --git a/OmegaGameFramework/OmegaGameFramework.uplugin b/OmegaGameFramework/OmegaGameFramework.uplugin index a0c25803..904d2009 100644 --- a/OmegaGameFramework/OmegaGameFramework.uplugin +++ b/OmegaGameFramework/OmegaGameFramework.uplugin @@ -14,6 +14,29 @@ "CanContainContent": true, "Installed": true, "Modules": [ + { + "Name": "LuaMachine", + "Type": "Runtime", + "LoadingPhase": "PreDefault", + "WhitelistPlatforms": [ + "Mac", + "Win64", + "Linux", + "LinuxArm64", + "Android", + "IOS", + ] + }, + { + "Name": "LuaMachineEditor", + "Type": "Editor", + "LoadingPhase": "Default", + "WhitelistPlatforms": [ + "Linux", + "Mac", + "Win64" + ] + }, { "Name": "FileSDK", "Type": "Runtime", diff --git a/OmegaGameFramework/Resources/Icons/OmegaComponent.png b/OmegaGameFramework/Resources/Icons/OmegaComponent.png new file mode 100644 index 00000000..695d181f Binary files /dev/null and b/OmegaGameFramework/Resources/Icons/OmegaComponent.png differ diff --git a/OmegaGameFramework/Resources/Icons/OmegaComponent_16.png b/OmegaGameFramework/Resources/Icons/OmegaComponent_16.png new file mode 100644 index 00000000..fbdd4da1 Binary files /dev/null and b/OmegaGameFramework/Resources/Icons/OmegaComponent_16.png differ diff --git a/OmegaGameFramework/Resources/ico_LuaAsset.png b/OmegaGameFramework/Resources/ico_LuaAsset.png new file mode 100644 index 00000000..6f0648f3 Binary files /dev/null and b/OmegaGameFramework/Resources/ico_LuaAsset.png differ diff --git a/OmegaGameFramework/Resources/ico_LuaTable.png b/OmegaGameFramework/Resources/ico_LuaTable.png new file mode 100644 index 00000000..19236c0f Binary files /dev/null and b/OmegaGameFramework/Resources/ico_LuaTable.png differ diff --git a/OmegaGameFramework/Source/LuaMachine/LuaMachine.Build.cs b/OmegaGameFramework/Source/LuaMachine/LuaMachine.Build.cs new file mode 100644 index 00000000..073403d4 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/LuaMachine.Build.cs @@ -0,0 +1,102 @@ +// Copyright 2018-2023 - Roberto De Ioris + +using UnrealBuildTool; + +public class LuaMachine : ModuleRules +{ + public LuaMachine(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + bUseUnity = false; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "HTTP", + "Json", + "DeveloperSettings", + "PakFile" + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "UMG", + "InputCore", + // ... add private dependencies that you statically link with here ... + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + + if (Target.bBuildEditor) + { + PrivateDependencyModuleNames.AddRange(new string[]{ + "UnrealEd", + "Projects" + }); + } + + string ThirdPartyDirectory = System.IO.Path.Combine(ModuleDirectory, "..", "ThirdParty"); + + if (Target.Platform == UnrealTargetPlatform.Win64) + { + PublicAdditionalLibraries.Add(System.IO.Path.Combine(ThirdPartyDirectory, "x64", "liblua53_win64.lib")); + } + + else if (Target.Platform == UnrealTargetPlatform.Mac) + { + PublicAdditionalLibraries.Add(System.IO.Path.Combine(ThirdPartyDirectory, "x64", "liblua53_mac.a")); + } + + else if (Target.Platform == UnrealTargetPlatform.Linux) + { + PublicAdditionalLibraries.Add(System.IO.Path.Combine(ThirdPartyDirectory, "x64", "liblua53_linux64.a")); + } + + else if (Target.Platform == UnrealTargetPlatform.LinuxArm64) + { + PublicAdditionalLibraries.Add(System.IO.Path.Combine(ThirdPartyDirectory, "ARM64", "liblua53_linux_aarch64.a")); + } + + else if (Target.Platform == UnrealTargetPlatform.Android) + { + PublicAdditionalLibraries.Add(System.IO.Path.Combine(ThirdPartyDirectory, "ARMv7", "liblua53_android.a")); + PublicAdditionalLibraries.Add(System.IO.Path.Combine(ThirdPartyDirectory, "ARM64", "liblua53_android64.a")); + } + + else if (Target.Platform == UnrealTargetPlatform.IOS) + { + PublicAdditionalLibraries.Add(System.IO.Path.Combine(ThirdPartyDirectory, "ARM64", "liblua53_ios.a")); + } + + } +} diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaBlueprintFunctionLibrary.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaBlueprintFunctionLibrary.cpp new file mode 100644 index 00000000..13154f12 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaBlueprintFunctionLibrary.cpp @@ -0,0 +1,1985 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaBlueprintFunctionLibrary.h" +#include "LuaComponent.h" +#include "LuaMachine.h" +#include "Runtime/Online/HTTP/Public/Interfaces/IHttpResponse.h" +#include "Runtime/Core/Public/Math/BigInt.h" +#include "Runtime/Core/Public/Misc/Base64.h" +#include "Runtime/Core/Public/Misc/SecureHash.h" +#include "Serialization/JsonSerializer.h" +#include "Engine/Texture2D.h" +#include "IImageWrapper.h" +#include "IImageWrapperModule.h" +#include "IPlatformFilePak.h" +#if ENGINE_MAJOR_VERSION >= 5 +#include "HAL/PlatformFileManager.h" +#else +#include "HAL/PlatformFilemanager.h" +#endif +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 0 +#include "AssetRegistry/IAssetRegistry.h" +#include "AssetRegistry/AssetRegistryModule.h" +#else +#include "IAssetRegistry.h" +#include "AssetRegistryModule.h" +#endif +#include "Misc/FileHelper.h" +#include "Serialization/ArrayReader.h" +#include "TextureResource.h" + + + +ULuaState* ULuaBlueprintFunctionLibrary::LOCAL_getLuaState(UObject* WorldContextObject, + TSubclassOf StateClass) +{ + TSubclassOf local_state = GetDefaultLuaState(); + if(StateClass) + { + local_state=StateClass; + } + return FLuaMachineModule::Get().GetLuaState(local_state, WorldContextObject->GetWorld()); +} + +TSubclassOf ULuaBlueprintFunctionLibrary::GetDefaultLuaState() +{ + return GetMutableDefault()->DefaultState.LoadSynchronous(); + +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateNil() +{ + return FLuaValue(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateString(const FString& String) +{ + return FLuaValue(String); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateNumber(const float Value) +{ + return FLuaValue(Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateInteger(const int32 Value) +{ + return FLuaValue(Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateBool(const bool bInBool) +{ + return FLuaValue(bInBool); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateObject(UObject* InObject) +{ + return FLuaValue(InObject); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateUFunction(UObject* InObject, const FString& FunctionName) +{ + if (InObject && InObject->FindFunction(FName(*FunctionName))) + { + FLuaValue Value = FLuaValue::Function(FName(*FunctionName)); + Value.Object = InObject; + return Value; + } + + return FLuaValue(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateTable(UObject* WorldContextObject, TSubclassOf State) +{ + FLuaValue LuaValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return LuaValue; + + return L->CreateLuaTable(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateLazyTable(UObject* WorldContextObject, TSubclassOf State) +{ + FLuaValue LuaValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return LuaValue; + + return L->CreateLuaLazyTable(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateThread(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value) +{ + FLuaValue LuaValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return LuaValue; + + return L->CreateLuaThread(Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaCreateObjectInState(UObject* WorldContextObject, TSubclassOf State, UObject* InObject) +{ + FLuaValue LuaValue; + if (!InObject) + return LuaValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return LuaValue; + + LuaValue = FLuaValue(InObject); + LuaValue.LuaState = L; + return LuaValue; +} + +void ULuaBlueprintFunctionLibrary::LuaStateDestroy(UObject* WorldContextObject, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + FLuaMachineModule::Get().UnregisterLuaState(L); +} + +void ULuaBlueprintFunctionLibrary::LuaStateReload(UObject* WorldContextObject, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + FLuaMachineModule::Get().UnregisterLuaState(L); + LOCAL_getLuaState(WorldContextObject,State); +} + +FString ULuaBlueprintFunctionLibrary::Conv_LuaValueToString(const FLuaValue& Value) +{ + return Value.ToString(); +} + +FVector ULuaBlueprintFunctionLibrary::Conv_LuaValueToFVector(const FLuaValue& Value) +{ + return LuaTableToVector(Value); +} + +FName ULuaBlueprintFunctionLibrary::Conv_LuaValueToName(const FLuaValue& Value) +{ + return FName(*Value.ToString()); +} + +FText ULuaBlueprintFunctionLibrary::Conv_LuaValueToText(const FLuaValue& Value) +{ + return FText::FromString(Value.ToString()); +} + +UObject* ULuaBlueprintFunctionLibrary::Conv_LuaValueToObject(const FLuaValue& Value) +{ + if (Value.Type == ELuaValueType::UObject) + { + return Value.Object; + } + return nullptr; +} + +UClass* ULuaBlueprintFunctionLibrary::Conv_LuaValueToClass(const FLuaValue& Value) +{ + if (Value.Type == ELuaValueType::UObject) + { + UClass* Class = Cast(Value.Object); + if (Class) + return Class; + UBlueprint* Blueprint = Cast(Value.Object); + if (Blueprint) + return Blueprint->GeneratedClass; + } + return nullptr; +} + +FLuaValue ULuaBlueprintFunctionLibrary::Conv_ObjectToLuaValue(UObject* Object) +{ + return FLuaValue(Object); +} + + +FLuaValue ULuaBlueprintFunctionLibrary::Conv_FloatToLuaValue(const float Value) +{ + return FLuaValue(Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::Conv_BoolToLuaValue(const bool Value) +{ + return FLuaValue(Value); +} + +int32 ULuaBlueprintFunctionLibrary::Conv_LuaValueToInt(const FLuaValue& Value) +{ + return Value.ToInteger(); +} + +float ULuaBlueprintFunctionLibrary::Conv_LuaValueToFloat(const FLuaValue& Value) +{ + return Value.ToFloat(); +} + +bool ULuaBlueprintFunctionLibrary::Conv_LuaValueToBool(const FLuaValue& Value) +{ + return Value.ToBool(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::Conv_IntToLuaValue(const int32 Value) +{ + return FLuaValue(Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::Conv_StringToLuaValue(const FString& Value) +{ + return FLuaValue(Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::Conv_TextToLuaValue(const FText& Value) +{ + return FLuaValue(Value.ToString()); +} + +FLuaValue ULuaBlueprintFunctionLibrary::Conv_NameToLuaValue(const FName Value) +{ + return FLuaValue(Value.ToString()); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaGetGlobal(UObject* WorldContextObject, TSubclassOf State, const FString& Name) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return FLuaValue(); + + uint32 ItemsToPop = L->GetFieldFromTree(Name); + FLuaValue ReturnValue = L->ToLuaValue(-1); + L->Pop(ItemsToPop); + return ReturnValue; +} + +int64 ULuaBlueprintFunctionLibrary::LuaValueToPointer(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return 0; + + L->FromLuaValue(Value); + const void* Ptr = L->ToPointer(-1); + L->Pop(); + + return (int64)Ptr; +} + +FString ULuaBlueprintFunctionLibrary::LuaValueToHexPointer(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value) +{ + int64 Ptr = LuaValueToPointer(WorldContextObject, State, Value); + if (FGenericPlatformProperties::IsLittleEndian()) + { + uint8 BEPtr[8] = + { + (uint8)((Ptr >> 56) & 0xff), + (uint8)((Ptr >> 48) & 0xff), + (uint8)((Ptr >> 40) & 0xff), + (uint8)((Ptr >> 32) & 0xff), + (uint8)((Ptr >> 24) & 0xff), + (uint8)((Ptr >> 16) & 0xff), + (uint8)((Ptr >> 8) & 0xff), + (uint8)((Ptr) & 0xff), + }; + return BytesToHex((const uint8*)BEPtr, sizeof(int64)); + } + return BytesToHex((const uint8*)&Ptr, sizeof(int64)); +} + +FString ULuaBlueprintFunctionLibrary::LuaValueToBase64(const FLuaValue& Value) +{ + return Value.ToBase64(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaValueFromBase64(const FString& Base64) +{ + return FLuaValue::FromBase64(Base64); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaValueFromUTF16(const FString& String) +{ + TArray Bytes; + if (FGenericPlatformProperties::IsLittleEndian()) + { + for (int32 Index = 0; Index < String.Len(); Index++) + { + uint16 UTF16Char = (uint16)String[Index]; + Bytes.Add((uint8)(UTF16Char & 0xFF)); + Bytes.Add((uint8)((UTF16Char >> 8) & 0xFF)); + } + } + else + { + for (int32 Index = 0; Index < String.Len(); Index++) + { + uint16 UTF16Char = (uint16)String[Index]; + Bytes.Add((uint8)((UTF16Char >> 8) & 0xFF)); + Bytes.Add((uint8)(UTF16Char & 0xFF)); + } + } + return FLuaValue(Bytes); +} + +FString ULuaBlueprintFunctionLibrary::LuaValueToUTF16(const FLuaValue& Value) +{ + FString ReturnValue; + TArray Bytes = Value.ToBytes(); + if (Bytes.Num() % 2 != 0) + { + return ReturnValue; + } + + if (FGenericPlatformProperties::IsLittleEndian()) + { + for (int32 Index = 0; Index < Bytes.Num(); Index += 2) + { + uint16 UTF16Low = Bytes[Index]; + uint16 UTF16High = Bytes[Index + 1]; + ReturnValue.AppendChar((TCHAR)((UTF16High << 8) | UTF16Low)); + } + } + else + { + for (int32 Index = 0; Index < Bytes.Num(); Index += 2) + { + uint16 UTF16High = Bytes[Index]; + uint16 UTF16Low = Bytes[Index + 1]; + ReturnValue.AppendChar((TCHAR)((UTF16High << 8) | UTF16Low)); + } + } + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaValueFromUTF8(const FString& String) +{ + FTCHARToUTF8 UTF8String(*String); + return FLuaValue((const char*)UTF8String.Get(), UTF8String.Length()); +} + +FString ULuaBlueprintFunctionLibrary::LuaValueToUTF8(const FLuaValue& Value) +{ + FString ReturnValue; + TArray Bytes = Value.ToBytes(); + Bytes.Add(0); + return FString(UTF8_TO_TCHAR(Bytes.GetData())); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaValueFromUTF32(const FString& String) +{ +#if ENGINE_MINOR_VERSION >= 25 + FTCHARToUTF32 UTF32String(*String); + return FLuaValue((const char*)UTF32String.Get(), UTF32String.Length()); +#else + UE_LOG(LogLuaMachine, Error, TEXT("UTF32 not supported in this engine version")); + return FLuaValue(); +#endif +} + +FString ULuaBlueprintFunctionLibrary::LuaValueToUTF32(const FLuaValue& Value) +{ +#if ENGINE_MINOR_VERSION >= 25 + FString ReturnValue; + TArray Bytes = Value.ToBytes(); + Bytes.Add(0); + Bytes.Add(0); + Bytes.Add(0); + Bytes.Add(0); + return FString(FUTF32ToTCHAR((const UTF32CHAR*)Bytes.GetData(), Bytes.Num() / 4).Get()); +#else + UE_LOG(LogLuaMachine, Error, TEXT("UTF32 not supported in this engine version")); + return FString(""); +#endif +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaRunFile(UObject* WorldContextObject, TSubclassOf State, const FString& Filename, const bool bIgnoreNonExistent) +{ + FLuaValue ReturnValue; + + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + if (!L->RunFile(Filename, bIgnoreNonExistent, 1)) + { + if (L->bLogError) + L->LogError(L->LastError); + L->ReceiveLuaError(L->LastError); + } + else + { + ReturnValue = L->ToLuaValue(-1); + } + + L->Pop(); + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaRunNonContentFile(UObject* WorldContextObject, TSubclassOf State, const FString& Filename, const bool bIgnoreNonExistent) +{ + FLuaValue ReturnValue; + + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + if (!L->RunFile(Filename, bIgnoreNonExistent, 1, true)) + { + if (L->bLogError) + L->LogError(L->LastError); + L->ReceiveLuaError(L->LastError); + } + else + { + ReturnValue = L->ToLuaValue(-1); + } + + L->Pop(); + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaRunString(UObject* WorldContextObject, TSubclassOf State, const FString& CodeString, FString CodePath) +{ + FLuaValue ReturnValue; + + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + { + return ReturnValue; + } + + return L->RunString(CodeString, CodePath); +} + +ELuaThreadStatus ULuaBlueprintFunctionLibrary::LuaThreadGetStatus(FLuaValue Value) +{ + if (Value.Type != ELuaValueType::Thread || !Value.LuaState.IsValid()) + return ELuaThreadStatus::Invalid; + + return Value.LuaState->GetLuaThreadStatus(Value); +} + +int32 ULuaBlueprintFunctionLibrary::LuaThreadGetStackTop(FLuaValue Value) +{ + if (Value.Type != ELuaValueType::Thread || !Value.LuaState.IsValid()) + return MIN_int32; + + return Value.LuaState->GetLuaThreadStackTop(Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaRunCodeAsset(UObject* WorldContextObject, TSubclassOf State, ULuaCode* CodeAsset) +{ + FLuaValue ReturnValue; + + if (!CodeAsset) + return ReturnValue; + + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + if (!L->RunCodeAsset(CodeAsset, 1)) + { + if (L->bLogError) + L->LogError(L->LastError); + L->ReceiveLuaError(L->LastError); + } + else { + ReturnValue = L->ToLuaValue(-1); + } + L->Pop(); + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaRunByteCode(UObject* WorldContextObject, TSubclassOf State, const TArray& ByteCode, const FString& CodePath) +{ + FLuaValue ReturnValue; + + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + if (!L->RunCode(ByteCode, CodePath, 1)) + { + if (L->bLogError) + L->LogError(L->LastError); + L->ReceiveLuaError(L->LastError); + } + else + { + ReturnValue = L->ToLuaValue(-1); + } + L->Pop(); + return ReturnValue; +} + +UTexture2D* ULuaBlueprintFunctionLibrary::LuaValueToTransientTexture(int32 Width, int32 Height, const FLuaValue& Value, EPixelFormat PixelFormat, bool bDetectFormat) +{ + if (Value.Type != ELuaValueType::String) + { + return nullptr; + } + + IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked(TEXT("ImageWrapper")); + + TArray Bytes = Value.ToBytes(); + + if (bDetectFormat) + { + EImageFormat ImageFormat = ImageWrapperModule.DetectImageFormat(Bytes.GetData(), Bytes.Num()); + if (ImageFormat == EImageFormat::Invalid) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to detect image format")); + return nullptr; + } + + TSharedPtr ImageWrapper = ImageWrapperModule.CreateImageWrapper(ImageFormat); + if (!ImageWrapper.IsValid()) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to create ImageWrapper")); + return nullptr; + } + + if (!ImageWrapper->SetCompressed(Bytes.GetData(), Bytes.Num())) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to parse image data")); + return nullptr; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + TArray UncompressedBytes; +#else + const TArray* UncompressedBytes = nullptr; +#endif + if (!ImageWrapper->GetRaw(ERGBFormat::BGRA, 8, UncompressedBytes)) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to get raw image data")); + return nullptr; + } + PixelFormat = EPixelFormat::PF_B8G8R8A8; + Width = ImageWrapper->GetWidth(); + Height = ImageWrapper->GetHeight(); +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + Bytes = UncompressedBytes; +#else + Bytes = *UncompressedBytes; +#endif + } + + UTexture2D* Texture = UTexture2D::CreateTransient(Width, Height, PixelFormat); + if (!Texture) + { + return nullptr; + } + +#if ENGINE_MAJOR_VERSION > 4 + FTexture2DMipMap& Mip = Texture->GetPlatformData()->Mips[0]; +#else + FTexture2DMipMap& Mip = Texture->PlatformData->Mips[0]; +#endif + void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE); + FMemory::Memcpy(Data, Bytes.GetData(), Bytes.Num()); + Mip.BulkData.Unlock(); + Texture->UpdateResource(); + + return Texture; +} + +void ULuaBlueprintFunctionLibrary::LuaHttpRequest(UObject* WorldContextObject, TSubclassOf State, const FString& Method, const FString& URL, TMap Headers, FLuaValue Body, FLuaValue Context, const FLuaHttpResponseReceived& ResponseReceived, const FLuaHttpError& Error) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 26 + TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); +#else + TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); +#endif + HttpRequest->SetVerb(Method); + HttpRequest->SetURL(URL); + for (TPair Header : Headers) + { + HttpRequest->AppendToHeader(Header.Key, Header.Value); + } + HttpRequest->SetContent(Body.ToBytes()); + + TSharedRef ContextSmartRef = L->AddLuaSmartReference(Context); + + HttpRequest->OnProcessRequestComplete().BindStatic(&ULuaBlueprintFunctionLibrary::HttpGenericRequestDone, TWeakPtr(ContextSmartRef), ResponseReceived, Error); + HttpRequest->ProcessRequest(); +} + +void ULuaBlueprintFunctionLibrary::HttpGenericRequestDone(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, TWeakPtr Context, FLuaHttpResponseReceived ResponseReceived, FLuaHttpError Error) +{ + // if the context is invalid, the LuaState is already dead + if (!Context.IsValid()) + return; + + TSharedRef SmartContext = Context.Pin().ToSharedRef(); + + SmartContext->LuaState->RemoveLuaSmartReference(SmartContext); + + if (!bWasSuccessful) + { + Error.ExecuteIfBound(SmartContext->Value); + return; + } + + FLuaValue StatusCode = FLuaValue(Response->GetResponseCode()); + FLuaValue Headers = SmartContext->LuaState->CreateLuaTable(); + for (auto HeaderLine : Response->GetAllHeaders()) + { + int32 Index; + if (HeaderLine.Len() > 2 && HeaderLine.FindChar(':', Index)) + { + FString Key; + if (Index > 0) + Key = HeaderLine.Left(Index); + FString Value = HeaderLine.Right(HeaderLine.Len() - (Index + 2)); + Headers.SetField(Key, FLuaValue(Value)); + } + } + FLuaValue Content = FLuaValue(Response->GetContent()); + FLuaValue LuaHttpResponse = SmartContext->LuaState->CreateLuaTable(); + LuaHttpResponse.SetFieldByIndex(1, StatusCode); + LuaHttpResponse.SetFieldByIndex(2, Headers); + LuaHttpResponse.SetFieldByIndex(3, Content); + ResponseReceived.ExecuteIfBound(SmartContext->Value, LuaHttpResponse); +} + +void ULuaBlueprintFunctionLibrary::LuaRunURL(UObject* WorldContextObject, TSubclassOf State, const FString& URL, TMap Headers, const FString& SecurityHeader, const FString& SignaturePublicExponent, const FString& SignatureModulus, FLuaHttpSuccess Completed) +{ + + // Security CHECK + if (!SecurityHeader.IsEmpty() || !SignaturePublicExponent.IsEmpty() || !SignatureModulus.IsEmpty()) + { + if (SecurityHeader.IsEmpty() || SignaturePublicExponent.IsEmpty() || SignatureModulus.IsEmpty()) + { + UE_LOG(LogLuaMachine, Error, TEXT("For secure LuaRunURL() you need to specify the Security HTTP Header, the Signature Public Exponent and the Signature Modulus")); + return; + } + } +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 26 + TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); +#else + TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); +#endif + HttpRequest->SetURL(URL); + for (TPair Header : Headers) + { + HttpRequest->AppendToHeader(Header.Key, Header.Value); + } + HttpRequest->OnProcessRequestComplete().BindStatic(&ULuaBlueprintFunctionLibrary::HttpRequestDone, State, TWeakObjectPtr(WorldContextObject->GetWorld()), SecurityHeader, SignaturePublicExponent, SignatureModulus, Completed); + HttpRequest->ProcessRequest(); +} + +void ULuaBlueprintFunctionLibrary::HttpRequestDone(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, TSubclassOf LuaState, TWeakObjectPtr World, const FString SecurityHeader, const FString SignaturePublicExponent, const FString SignatureModulus, FLuaHttpSuccess Completed) +{ + FLuaValue ReturnValue; + int32 StatusCode = -1; + + if (!bWasSuccessful) + { + UE_LOG(LogLuaMachine, Error, TEXT("HTTP session failed for \"%s %s\""), *Request->GetVerb(), *Request->GetURL()); + } + + else if (!World.IsValid()) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to access LuaState as the World object is no more available (\"%s %s\")"), *Request->GetVerb(), *Request->GetURL()); + } + else + { + // Check signature + if (!SecurityHeader.IsEmpty()) + { + // check code size + if (Response->GetContentLength() <= 0) + { + UE_LOG(LogLuaMachine, Error, TEXT("[Security] Invalid Content Size")); + Completed.ExecuteIfBound(ReturnValue, bWasSuccessful, StatusCode); + return; + } + FString EncryptesSignatureBase64 = Response->GetHeader(SecurityHeader); + if (EncryptesSignatureBase64.IsEmpty()) + { + UE_LOG(LogLuaMachine, Error, TEXT("[Security] Invalid Security HTTP Header")); + Completed.ExecuteIfBound(ReturnValue, bWasSuccessful, StatusCode); + return; + } + + const uint32 KeySize = 64; + + TArray Signature; + FBase64::Decode(EncryptesSignatureBase64, Signature); + + if (Signature.Num() != KeySize) + { + UE_LOG(LogLuaMachine, Error, TEXT("[Security] Invalid Signature")); + Completed.ExecuteIfBound(ReturnValue, bWasSuccessful, StatusCode); + return; + } + TEncryptionInt SignatureValue = TEncryptionInt((uint32*)&Signature[0]); + + TArray PublicExponent; + FBase64::Decode(SignaturePublicExponent, PublicExponent); + if (PublicExponent.Num() != KeySize) + { + UE_LOG(LogLuaMachine, Error, TEXT("[Security] Invalid Signature Public Exponent")); + Completed.ExecuteIfBound(ReturnValue, bWasSuccessful, StatusCode); + return; + } + + TArray Modulus; + FBase64::Decode(SignatureModulus, Modulus); + if (Modulus.Num() != KeySize) + { + UE_LOG(LogLuaMachine, Error, TEXT("[Security] Invalid Signature Modulus")); + Completed.ExecuteIfBound(ReturnValue, bWasSuccessful, StatusCode); + return; + } + + TEncryptionInt PublicKey = TEncryptionInt((uint32*)&PublicExponent[0]); + TEncryptionInt ModulusValue = TEncryptionInt((uint32*)&Modulus[0]); + + TEncryptionInt ShaHash; + FSHA1::HashBuffer(Response->GetContent().GetData(), Response->GetContentLength(), (uint8*)&ShaHash); + + TEncryptionInt DecryptedSignature = FEncryption::ModularPow(SignatureValue, PublicKey, ModulusValue); + if (DecryptedSignature != ShaHash) + { + UE_LOG(LogLuaMachine, Error, TEXT("[Security] Signature check failed")); + Completed.ExecuteIfBound(ReturnValue, bWasSuccessful, StatusCode); + return; + } + } + + ReturnValue = LuaRunString(World.Get(), LuaState, Response->GetContentAsString()); + StatusCode = Response->GetResponseCode(); + } + + Completed.ExecuteIfBound(ReturnValue, bWasSuccessful, StatusCode); +} + +void ULuaBlueprintFunctionLibrary::LuaTableFillObject(FLuaValue InTable, UObject* InObject) +{ + if (InTable.Type != ELuaValueType::Table || !InObject) + return; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return; + + UStruct* Class = Cast(InObject); + if (!Class) + Class = InObject->GetClass(); + + L->FromLuaValue(InTable); + L->PushNil(); // first key + while (L->Next(-2)) + { + FLuaValue Key = L->ToLuaValue(-2); + FLuaValue Value = L->ToLuaValue(-1); + L->SetPropertyFromLuaValue(InObject, Key.ToString(), Value); + L->Pop(); // pop the value + } + + L->Pop(); // pop the table +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableGetField(FLuaValue Table, const FString& Key) +{ + ULuaState* L = Table.LuaState.Get(); + if (!L) + return FLuaValue(); + + return Table.GetField(Key); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaComponentGetField(FLuaValue LuaComponent, const FString& Key) +{ + FLuaValue ReturnValue; + if (LuaComponent.Type != ELuaValueType::UObject) + return ReturnValue; + + ULuaState* L = LuaComponent.LuaState.Get(); + if (!L) + return ReturnValue; + + ULuaComponent* Component = Cast(LuaComponent.Object); + + FLuaValue* LuaValue = Component->Table.Find(Key); + if (LuaValue) + { + return *LuaValue; + } + + return ReturnValue; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsNil(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::Nil; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsOwned(const FLuaValue& Value) +{ + return Value.LuaState != nullptr; +} + +TSubclassOf ULuaBlueprintFunctionLibrary::LuaValueGetOwner(const FLuaValue& Value) +{ + if (!Value.LuaState.IsValid()) + { + return nullptr; + } + return Value.LuaState->GetClass(); +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsNotNil(const FLuaValue& Value) +{ + return Value.Type != ELuaValueType::Nil; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsTable(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::Table; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsBoolean(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::Bool; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsThread(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::Thread; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsFunction(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::Function; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsNumber(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::Number; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsInteger(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::Integer; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsString(const FLuaValue& Value) +{ + return Value.Type == ELuaValueType::String; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableGetByIndex(FLuaValue Table, int32 Index) +{ + if (Table.Type != ELuaValueType::Table) + return FLuaValue(); + + ULuaState* L = Table.LuaState.Get(); + if (!L) + return FLuaValue(); + + return Table.GetFieldByIndex(Index); +} + +FLuaValue ULuaBlueprintFunctionLibrary::AssignLuaValueToLuaState(UObject* WorldContextObject, FLuaValue Value, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return Value; + Value.LuaState = L; + return Value; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableSetByIndex(FLuaValue Table, int32 Index, FLuaValue Value) +{ + if (Table.Type != ELuaValueType::Table) + return FLuaValue(); + + ULuaState* L = Table.LuaState.Get(); + if (!L) + return FLuaValue(); + + return Table.SetFieldByIndex(Index, Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableSetField(FLuaValue Table, const FString& Key, FLuaValue Value) +{ + FLuaValue ReturnValue; + if (Table.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = Table.LuaState.Get(); + if (!L) + return ReturnValue; + + return Table.SetField(Key, Value); +} + +FLuaValue ULuaBlueprintFunctionLibrary::GetLuaComponentAsLuaValue(AActor* Actor) +{ + if (!Actor) + return FLuaValue(); + + return FLuaValue(Actor->GetComponentByClass(ULuaComponent::StaticClass())); +} + +FLuaValue ULuaBlueprintFunctionLibrary::GetLuaComponentByStateAsLuaValue(AActor* Actor, TSubclassOf State) +{ + if (!Actor) + return FLuaValue(); +#if ENGINE_MAJOR_VERSION < 5 && ENGINE_MINOR_VERSION < 24 + TArray Components = Actor->GetComponentsByClass(ULuaComponent::StaticClass()); +#else + TArray Components; + Actor->GetComponents(Components); +#endif + for (UActorComponent* Component : Components) + { + ULuaComponent* LuaComponent = Cast(Component); + if (LuaComponent) + { + if (LuaComponent->LuaState == State) + { + return FLuaValue(LuaComponent); + } + } + } + + return FLuaValue(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::GetLuaComponentByNameAsLuaValue(AActor* Actor, const FString& Name) +{ + if (!Actor) + return FLuaValue(); + +#if ENGINE_MAJOR_VERSION < 5 && ENGINE_MINOR_VERSION < 24 + TArray Components = Actor->GetComponentsByClass(ULuaComponent::StaticClass()); +#else + TArray Components; + Actor->GetComponents(Components); +#endif + for (UActorComponent* Component : Components) + { + ULuaComponent* LuaComponent = Cast(Component); + if (LuaComponent) + { + if (LuaComponent->GetName() == Name) + { + return FLuaValue(LuaComponent); + } + } + } + + return FLuaValue(); +} + +FLuaValue ULuaBlueprintFunctionLibrary::GetLuaComponentByStateAndNameAsLuaValue(AActor* Actor, TSubclassOf State, const FString& Name) +{ + if (!Actor) + return FLuaValue(); + +#if ENGINE_MAJOR_VERSION < 5 && ENGINE_MINOR_VERSION < 24 + TArray Components = Actor->GetComponentsByClass(ULuaComponent::StaticClass()); +#else + TArray Components; + Actor->GetComponents(Components); +#endif + for (UActorComponent* Component : Components) + { + ULuaComponent* LuaComponent = Cast(Component); + if (LuaComponent) + { + if (LuaComponent->LuaState == State && LuaComponent->GetName() == Name) + { + return FLuaValue(LuaComponent); + } + } + } + + return FLuaValue(); +} + +int32 ULuaBlueprintFunctionLibrary::LuaGetTop(UObject* WorldContextObject, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return MIN_int32; + return L->GetTop(); +} + +void ULuaBlueprintFunctionLibrary::LuaSetGlobal(UObject* WorldContextObject, TSubclassOf State, const FString& Name, FLuaValue Value) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + L->SetFieldFromTree(Name, Value, true); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaGlobalCall(UObject* WorldContextObject, TSubclassOf State, const FString& Name, TArray Args) +{ + FLuaValue ReturnValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + int32 ItemsToPop = L->GetFieldFromTree(Name); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + L->PCall(NArgs, ReturnValue); + + // we have the return value and the function has been removed, so we do not need to change ItemsToPop + L->Pop(ItemsToPop); + + return ReturnValue; +} + +TArray ULuaBlueprintFunctionLibrary::LuaGlobalCallMulti(UObject* WorldContextObject, TSubclassOf State, const FString& Name, TArray Args) +{ + TArray ReturnValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + int32 ItemsToPop = L->GetFieldFromTree(Name); + + int32 StackTop = L->GetTop(); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + FLuaValue LastReturnValue; + if (L->PCall(NArgs, LastReturnValue, LUA_MULTRET)) + { + + int32 NumOfReturnValues = (L->GetTop() - StackTop) + 1; + if (NumOfReturnValues > 0) + { + for (int32 i = -1; i >= -(NumOfReturnValues); i--) + { + ReturnValue.Insert(L->ToLuaValue(i), 0); + } + L->Pop(NumOfReturnValues - 1); + } + + } + + // we have the return value and the function has been removed, so we do not need to change ItemsToPop + L->Pop(ItemsToPop); + + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaGlobalCallValue(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value, TArray Args) +{ + FLuaValue ReturnValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + L->FromLuaValue(Value); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + L->PCall(NArgs, ReturnValue); + + L->Pop(); + + return ReturnValue; +} + +TArray ULuaBlueprintFunctionLibrary::LuaGlobalCallValueMulti(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value, TArray Args) +{ + TArray ReturnValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + L->FromLuaValue(Value); + + int32 StackTop = L->GetTop(); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + FLuaValue LastReturnValue; + if (L->PCall(NArgs, LastReturnValue, LUA_MULTRET)) + { + + int32 NumOfReturnValues = (L->GetTop() - StackTop) + 1; + if (NumOfReturnValues > 0) + { + for (int32 i = -1; i >= -(NumOfReturnValues); i--) + { + ReturnValue.Insert(L->ToLuaValue(i), 0); + } + L->Pop(NumOfReturnValues - 1); + } + + } + + L->Pop(); + + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaValueCall(FLuaValue Value, TArray Args) +{ + FLuaValue ReturnValue; + + ULuaState* L = Value.LuaState.Get(); + if (!L) + return ReturnValue; + + L->FromLuaValue(Value); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + L->PCall(NArgs, ReturnValue); + + L->Pop(); + + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaValueCallIfNotNil(FLuaValue Value, TArray Args) +{ + FLuaValue ReturnValue; + if (Value.Type != ELuaValueType::Nil) + ReturnValue = LuaValueCall(Value, Args); + + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableKeyCall(FLuaValue InTable, const FString& Key, TArray Args) +{ + FLuaValue ReturnValue; + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + FLuaValue Value = InTable.GetField(Key); + if (Value.Type == ELuaValueType::Nil) + return ReturnValue; + + return LuaValueCall(Value, Args); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableKeyCallWithSelf(FLuaValue InTable, const FString& Key, TArray Args) +{ + FLuaValue ReturnValue; + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + FLuaValue Value = InTable.GetField(Key); + if (Value.Type == ELuaValueType::Nil) + return ReturnValue; + + Args.Insert(InTable, 0); + + return LuaValueCall(Value, Args); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableIndexCall(FLuaValue InTable, int32 Index, TArray Args) +{ + FLuaValue ReturnValue; + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + FLuaValue Value = InTable.GetFieldByIndex(Index); + if (Value.Type == ELuaValueType::Nil) + return ReturnValue; + + return LuaValueCall(Value, Args); +} + +TArray ULuaBlueprintFunctionLibrary::LuaTableUnpack(FLuaValue InTable) +{ + TArray ReturnValue; + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + int32 Index = 1; + for (;;) + { + FLuaValue Item = InTable.GetFieldByIndex(Index++); + if (Item.Type == ELuaValueType::Nil) + break; + ReturnValue.Add(Item); + } + + return ReturnValue; +} + +TArray ULuaBlueprintFunctionLibrary::LuaTableMergeUnpack(FLuaValue InTable1, FLuaValue InTable2) +{ + TArray ReturnValue; + if (InTable1.Type != ELuaValueType::Table) + return ReturnValue; + + if (InTable2.Type != ELuaValueType::Table) + return ReturnValue; + + int32 Index = 1; + for (;;) + { + FLuaValue Item = InTable1.GetFieldByIndex(Index++); + if (Item.Type == ELuaValueType::Nil) + break; + ReturnValue.Add(Item); + } + + for (;;) + { + FLuaValue Item = InTable2.GetFieldByIndex(Index++); + if (Item.Type == ELuaValueType::Nil) + break; + ReturnValue.Add(Item); + } + + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTablePack(UObject* WorldContextObject, TSubclassOf State, TArray Values) +{ + FLuaValue ReturnValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + ReturnValue = L->CreateLuaTable(); + + int32 Index = 1; + + for (FLuaValue& Value : Values) + { + ReturnValue.SetFieldByIndex(Index++, Value); + } + + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableMergePack(UObject* WorldContextObject, TSubclassOf State, TArray Values1, TArray Values2) +{ + FLuaValue ReturnValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + ReturnValue = L->CreateLuaTable(); + + int32 Index = 1; + + for (FLuaValue& Value : Values1) + { + ReturnValue.SetFieldByIndex(Index++, Value); + } + + for (FLuaValue& Value : Values2) + { + ReturnValue.SetFieldByIndex(Index++, Value); + } + + return ReturnValue; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableFromMap(UObject* WorldContextObject, TSubclassOf State, TMap Map) +{ + FLuaValue ReturnValue; + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return ReturnValue; + + ReturnValue = L->CreateLuaTable(); + + for (TPair& Pair : Map) + { + ReturnValue.SetField(Pair.Key, Pair.Value); + } + + return ReturnValue; +} + +TArray ULuaBlueprintFunctionLibrary::LuaTableRange(FLuaValue InTable, int32 First, int32 Last) +{ + TArray ReturnValue; + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + for (int32 i = First; i <= Last; i++) + { + ReturnValue.Add(InTable.GetFieldByIndex(i)); + } + + return ReturnValue; +} + +TArray ULuaBlueprintFunctionLibrary::LuaValueArrayMerge(TArray Array1, TArray Array2) +{ + TArray NewArray = Array1; + NewArray.Append(Array2); + return NewArray; +} + +TArray ULuaBlueprintFunctionLibrary::LuaValueArrayAppend(TArray Array, FLuaValue Value) +{ + TArray NewArray = Array; + NewArray.Add(Value); + return NewArray; +} + +TArray ULuaBlueprintFunctionLibrary::LuaValueCallMulti(FLuaValue Value, TArray Args) +{ + TArray ReturnValue; + + ULuaState* L = Value.LuaState.Get(); + if (!L) + return ReturnValue; + + L->FromLuaValue(Value); + + int32 StackTop = L->GetTop(); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + FLuaValue LastReturnValue; + if (L->PCall(NArgs, LastReturnValue, LUA_MULTRET)) + { + + int32 NumOfReturnValues = (L->GetTop() - StackTop) + 1; + if (NumOfReturnValues > 0) + { + for (int32 i = -1; i >= -(NumOfReturnValues); i--) + { + ReturnValue.Insert(L->ToLuaValue(i), 0); + } + L->Pop(NumOfReturnValues - 1); + } + + } + + L->Pop(); + + return ReturnValue; +} + +void ULuaBlueprintFunctionLibrary::LuaValueYield(FLuaValue Value, TArray Args) +{ + if (Value.Type != ELuaValueType::Thread) + return; + + ULuaState* L = Value.LuaState.Get(); + if (!L) + return; + + L->FromLuaValue(Value); + + int32 StackTop = L->GetTop(); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + L->Yield(-1 - NArgs, NArgs); + + L->Pop(); +} + +TArray ULuaBlueprintFunctionLibrary::LuaValueResumeMulti(FLuaValue Value, TArray Args) +{ + TArray ReturnValue; + + if (Value.Type != ELuaValueType::Thread) + return ReturnValue; + + ULuaState* L = Value.LuaState.Get(); + if (!L) + return ReturnValue; + + L->FromLuaValue(Value); + + int32 StackTop = L->GetTop(); + + int NArgs = 0; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + L->Resume(-1 - NArgs, NArgs); + + int32 NumOfReturnValues = (L->GetTop() - StackTop); + if (NumOfReturnValues > 0) + { + for (int32 i = -1; i >= -(NumOfReturnValues); i--) + { + ReturnValue.Insert(L->ToLuaValue(i), 0); + } + L->Pop(NumOfReturnValues); + } + + L->Pop(); + + return ReturnValue; +} + +FVector ULuaBlueprintFunctionLibrary::LuaTableToVector(FLuaValue Value) +{ + if (Value.Type != ELuaValueType::Table) + return FVector(NAN); + + auto GetVectorField = [](FLuaValue& Table, const char* Field_n, const char* Field_N, int32 Index) -> FLuaValue + { + FLuaValue N = Table.GetField(Field_n); + if (N.IsNil()) + { + N = Table.GetField(Field_N); + if (N.IsNil()) + { + N = Table.GetFieldByIndex(Index); + if (N.IsNil()) + N = FLuaValue(NAN); + } + } + return N; + }; + + FLuaValue X = GetVectorField(Value, "x", "X", 1); + FLuaValue Y = GetVectorField(Value, "y", "Y", 2); + FLuaValue Z = GetVectorField(Value, "z", "Z", 3); + + return FVector(X.ToFloat(), Y.ToFloat(), Z.ToFloat()); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableSetMetaTable(FLuaValue InTable, FLuaValue InMetaTable) +{ + FLuaValue ReturnValue; + if (InTable.Type != ELuaValueType::Table || InMetaTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + return InTable.SetMetaTable(InMetaTable); +} + +int32 ULuaBlueprintFunctionLibrary::LuaValueLength(FLuaValue Value) +{ + + ULuaState* L = Value.LuaState.Get(); + if (!L) + return 0; + + L->FromLuaValue(Value); + L->Len(-1); + int32 Length = L->ToInteger(-1); + L->Pop(2); + + return Length; +} + +TArray ULuaBlueprintFunctionLibrary::LuaTableGetKeys(FLuaValue Table) +{ + TArray Keys; + + if (Table.Type != ELuaValueType::Table) + return Keys; + + ULuaState* L = Table.LuaState.Get(); + if (!L) + return Keys; + + L->FromLuaValue(Table); + L->PushNil(); // first key + while (L->Next(-2)) + { + Keys.Add(L->ToLuaValue(-2)); // add key + L->Pop(); // pop the value + } + + L->Pop(); // pop the table + + return Keys; +} + +TArray ULuaBlueprintFunctionLibrary::LuaTableGetValues(FLuaValue Table) +{ + TArray Keys; + + if (Table.Type != ELuaValueType::Table) + return Keys; + + ULuaState* L = Table.LuaState.Get(); + if (!L) + return Keys; + + L->FromLuaValue(Table); + L->PushNil(); // first key + while (L->Next(-2)) + { + Keys.Add(L->ToLuaValue(-1)); // add value + L->Pop(); // pop the value + } + + L->Pop(); // pop the table + + return Keys; +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaTableAssetToLuaTable(UObject* WorldContextObject, TSubclassOf State, ULuaTableAsset* TableAsset) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return FLuaValue(); + + return TableAsset->ToLuaTable(L); +} + +FLuaValue ULuaBlueprintFunctionLibrary::LuaNewLuaUserDataObject(UObject* WorldContextObject, TSubclassOf State, TSubclassOf UserDataObjectClass, bool bTrackObject) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return FLuaValue(); + + return L->NewLuaUserDataObject(UserDataObjectClass, bTrackObject); +} + +ULuaState* ULuaBlueprintFunctionLibrary::LuaGetState(UObject* WorldContextObject, TSubclassOf State) +{ + return LOCAL_getLuaState(WorldContextObject,State); +} + +bool ULuaBlueprintFunctionLibrary::LuaTableImplements(FLuaValue Table, ULuaTableAsset* TableAsset) +{ + if (Table.Type != ELuaValueType::Table) + return false; + + ULuaState* L = Table.LuaState.Get(); + if (!L) + return false; + + for (TPair& Pair : TableAsset->Table) + { + FLuaValue Item = Table.GetField(Pair.Key); + if (Item.Type == ELuaValueType::Nil) + return false; + if (Item.Type != Pair.Value.Type) + return false; + } + + return true; +} + +bool ULuaBlueprintFunctionLibrary::LuaTableImplementsAll(FLuaValue Table, TArray TableAssets) +{ + for (ULuaTableAsset* TableAsset : TableAssets) + { + if (!LuaTableImplements(Table, TableAsset)) + return false; + } + return true; +} + +bool ULuaBlueprintFunctionLibrary::LuaTableImplementsAny(FLuaValue Table, TArray TableAssets) +{ + for (ULuaTableAsset* TableAsset : TableAssets) + { + if (LuaTableImplements(Table, TableAsset)) + return true; + } + return false; +} + +int32 ULuaBlueprintFunctionLibrary::LuaGetUsedMemory(UObject* WorldContextObject, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return -1; + + return L->GC(LUA_GCCOUNT); +} + +void ULuaBlueprintFunctionLibrary::LuaGCCollect(UObject* WorldContextObject, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + + L->GC(LUA_GCCOLLECT); +} + +void ULuaBlueprintFunctionLibrary::LuaGCStop(UObject* WorldContextObject, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + + L->GC(LUA_GCSTOP); +} + +void ULuaBlueprintFunctionLibrary::LuaGCRestart(UObject* WorldContextObject, TSubclassOf State) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + + L->GC(LUA_GCRESTART); +} + +void ULuaBlueprintFunctionLibrary::LuaSetUserDataMetaTable(UObject* WorldContextObject, TSubclassOf State, FLuaValue MetaTable) +{ + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return; + L->SetUserDataMetaTable(MetaTable); +} + +bool ULuaBlueprintFunctionLibrary::LuaValueIsReferencedInLuaRegistry(FLuaValue Value) +{ + return Value.IsReferencedInLuaRegistry(); +} + +UClass* ULuaBlueprintFunctionLibrary::LuaValueToBlueprintGeneratedClass(const FLuaValue& Value) +{ + UObject* LoadedObject = nullptr; + if (Value.Type == ELuaValueType::String) + { + LoadedObject = StaticLoadObject(UBlueprint::StaticClass(), nullptr, *Value.ToString()); + } + else if (Value.Type == ELuaValueType::UObject) + { + LoadedObject = Value.Object; + } + + if (!LoadedObject) + return nullptr; + + UBlueprint* Blueprint = Cast(LoadedObject); + if (!Blueprint) + return nullptr; + return Cast(Blueprint->GeneratedClass); +} + +UClass* ULuaBlueprintFunctionLibrary::LuaValueLoadClass(const FLuaValue& Value, bool bDetectBlueprintGeneratedClass) +{ + UObject* LoadedObject = nullptr; + if (Value.Type == ELuaValueType::String) + { + LoadedObject = StaticLoadObject(UObject::StaticClass(), nullptr, *Value.ToString()); + } + else if (Value.Type == ELuaValueType::UObject) + { + LoadedObject = Value.Object; + } + + if (!LoadedObject) + return nullptr; + + if (bDetectBlueprintGeneratedClass) + { + UBlueprint* Blueprint = Cast(LoadedObject); + if (Blueprint) + return Cast(Blueprint->GeneratedClass); + } + + return Cast(LoadedObject); +} + +UObject* ULuaBlueprintFunctionLibrary::LuaValueLoadObject(const FLuaValue& Value) +{ + UObject* LoadedObject = nullptr; + if (Value.Type == ELuaValueType::String) + { + LoadedObject = StaticLoadObject(UObject::StaticClass(), nullptr, *Value.ToString()); + } + else if (Value.Type == ELuaValueType::UObject) + { + LoadedObject = Value.Object; + } + + return LoadedObject; +} + +bool ULuaBlueprintFunctionLibrary::LuaValueFromJson(UObject* WorldContextObject, TSubclassOf State, const FString& Json, FLuaValue& LuaValue) +{ + // default to nil + LuaValue = FLuaValue(); + + ULuaState* L = LOCAL_getLuaState(WorldContextObject,State); + if (!L) + return false; + + TSharedPtr JsonValue; + TSharedRef< TJsonReader > JsonReader = TJsonReaderFactory::Create(Json); + if (!FJsonSerializer::Deserialize(JsonReader, JsonValue)) + { + return false; + } + + LuaValue = FLuaValue::FromJsonValue(L, *JsonValue); + return true; +} + +FString ULuaBlueprintFunctionLibrary::LuaValueToJson(FLuaValue Value) +{ + FString Json; + TSharedRef> JsonWriter = TJsonWriterFactory<>::Create(&Json); + FJsonSerializer::Serialize(Value.ToJsonValue(), "", JsonWriter); + return Json; +} + +bool ULuaBlueprintFunctionLibrary::LuaLoadPakFile(const FString& Filename, FString Mountpoint, TArray& Assets, FString ContentPath, FString AssetRegistryPath) +{ + if (!Mountpoint.StartsWith("/") || !Mountpoint.EndsWith("/")) + { + UE_LOG(LogLuaMachine, Error, TEXT("Invalid Mountpoint, must be in the format /Name/")); + return false; + } + + IPlatformFile& TopPlatformFile = FPlatformFileManager::Get().GetPlatformFile(); + bool bCustomPakPlatformFile = false; + + FPakPlatformFile* PakPlatformFile = (FPakPlatformFile*)FPlatformFileManager::Get().FindPlatformFile(TEXT("PakFile")); + if (!PakPlatformFile) + { + PakPlatformFile = new FPakPlatformFile(); + if (!PakPlatformFile->Initialize(&TopPlatformFile, TEXT(""))) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to setup PakPlatformFile")); + delete(PakPlatformFile); + return false; + } + FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile); + bCustomPakPlatformFile = true; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 26 + TRefCountPtr PakFile = new FPakFile(PakPlatformFile, *Filename, false); +#else + FPakFile PakFile(PakPlatformFile, *Filename, false); +#endif + if (!PakFile.IsValid()) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to open PakFile")); + if (bCustomPakPlatformFile) + { + FPlatformFileManager::Get().SetPlatformFile(TopPlatformFile); + delete(PakPlatformFile); + } + return false; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 26 + FString PakFileMountPoint = PakFile->GetMountPoint(); +#else + FString PakFileMountPoint = PakFile.GetMountPoint(); +#endif + + FPaths::MakeStandardFilename(Mountpoint); + + FPaths::MakeStandardFilename(PakFileMountPoint); + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 26 + PakFile->SetMountPoint(*PakFileMountPoint); +#else + PakFile.SetMountPoint(*PakFileMountPoint); +#endif + + if (!PakPlatformFile->Mount(*Filename, 0, *PakFileMountPoint)) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to mount PakFile")); + if (bCustomPakPlatformFile) + { + FPlatformFileManager::Get().SetPlatformFile(TopPlatformFile); + delete(PakPlatformFile); + } + return false; + } + + if (ContentPath.IsEmpty()) + { + ContentPath = "/Plugins" + Mountpoint + "Content/"; + } + + FString MountDestination = PakFileMountPoint + ContentPath; + FPaths::MakeStandardFilename(MountDestination); + + FPackageName::RegisterMountPoint(Mountpoint, MountDestination); + + IAssetRegistry& AssetRegistry = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")).Get(); + +#if WITH_EDITOR +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 23 + int32 bPreviousGAllowUnversionedContentInEditor = GAllowUnversionedContentInEditor; +#else + bool bPreviousGAllowUnversionedContentInEditor = GAllowUnversionedContentInEditor; +#endif + GAllowUnversionedContentInEditor = true; +#endif + + if (AssetRegistryPath.IsEmpty()) + { + AssetRegistryPath = "/Plugins" + Mountpoint + "AssetRegistry.bin"; + } + + FArrayReader SerializedAssetData; + if (!FFileHelper::LoadFileToArray(SerializedAssetData, *(PakFileMountPoint + AssetRegistryPath))) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to parse AssetRegistry file")); + if (bCustomPakPlatformFile) + { + FPlatformFileManager::Get().SetPlatformFile(TopPlatformFile); + delete(PakPlatformFile); + } +#if WITH_EDITOR + GAllowUnversionedContentInEditor = bPreviousGAllowUnversionedContentInEditor; +#endif + return false; + } + + AssetRegistry.Serialize(SerializedAssetData); + + AssetRegistry.ScanPathsSynchronous({ Mountpoint }, true); + + TArray AssetData; + AssetRegistry.GetAllAssets(AssetData, false); + + for (auto Asset : AssetData) + { +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 0 + if (Asset.GetObjectPathString().StartsWith(Mountpoint)) +#else + if (Asset.ObjectPath.ToString().StartsWith(Mountpoint)) +#endif + { + Assets.Add(FLuaValue(Asset.GetAsset())); + } + } + + if (bCustomPakPlatformFile) + { + FPlatformFileManager::Get().SetPlatformFile(TopPlatformFile); + delete(PakPlatformFile); + } + +#if WITH_EDITOR + GAllowUnversionedContentInEditor = bPreviousGAllowUnversionedContentInEditor; +#endif + + return true; +} + +void ULuaBlueprintFunctionLibrary::SwitchOnLuaValueType(const FLuaValue& LuaValue, ELuaValueType& LuaValueTypes) +{ + LuaValueTypes = LuaValue.Type; +} + +void ULuaBlueprintFunctionLibrary::GetLuaReflectionType(UObject* InObject, const FString& Name, ELuaReflectionType& LuaReflectionTypes) +{ + LuaReflectionTypes = ELuaReflectionType::Unknown; + UClass* Class = InObject->GetClass(); + if (!Class) + { + return; + } + + if (Class->FindPropertyByName(FName(*Name)) != nullptr) + { + LuaReflectionTypes = ELuaReflectionType::Property; + return; + } + + if (Class->FindFunctionByName(FName(*Name))) + { + LuaReflectionTypes = ELuaReflectionType::Function; + return; + } +} + +void ULuaBlueprintFunctionLibrary::RegisterLuaConsoleCommand(const FString& CommandName, const FLuaValue& LuaConsoleCommand) +{ + FLuaMachineModule::Get().RegisterLuaConsoleCommand(CommandName, LuaConsoleCommand); +} + +void ULuaBlueprintFunctionLibrary::UnregisterLuaConsoleCommand(const FString& CommandName) +{ + FLuaMachineModule::Get().UnregisterLuaConsoleCommand(CommandName); +} + +ULuaState* ULuaBlueprintFunctionLibrary::CreateDynamicLuaState(UObject* WorldContextObject, TSubclassOf LuaStateClass) +{ + if (!LuaStateClass) + { + return nullptr; + } + + if (LuaStateClass == ULuaState::StaticClass()) + { + UE_LOG(LogLuaMachine, Error, TEXT("attempt to use LuaState Abstract class, please create a child of LuaState")); + return nullptr; + } + + + ULuaState* NewLuaState = NewObject((UObject*)GetTransientPackage(), LuaStateClass); + if (!NewLuaState) + { + return nullptr; + } + + return NewLuaState->GetLuaState(WorldContextObject->GetWorld()); +} diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaBlueprintPackage.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaBlueprintPackage.cpp new file mode 100644 index 00000000..f425b4b2 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaBlueprintPackage.cpp @@ -0,0 +1,35 @@ +// Copyright 2018-2023 - Roberto De Ioris + + +#include "LuaBlueprintPackage.h" +#include "LuaState.h" + +TSubclassOf ULuaBlueprintPackage::GetLuaState() const +{ + ULuaState* LuaState = Cast(GetOuter()); + if (LuaState) + { + return LuaState->GetClass(); + } + return nullptr; +} + +ULuaState* ULuaBlueprintPackage::GetLuaStateInstance() const +{ + return Cast(GetOuter()); +} + +UWorld* ULuaBlueprintPackage::GetWorld() const +{ + ULuaState* LuaState = Cast(GetOuter()); + if (LuaState) + { + return LuaState->GetWorld(); + } + return nullptr; +} + +void ULuaBlueprintPackage::Init() +{ + +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaCode.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaCode.cpp new file mode 100644 index 00000000..cbd0b6cd --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaCode.cpp @@ -0,0 +1,105 @@ +// Copyright 2018-2023 - Roberto De Ioris +// Reimport system by yama2akira (Akira Yamamoto) + +#include "LuaCode.h" +#include "LuaMachine.h" +#include "Serialization/CustomVersion.h" +#include "EditorFramework/AssetImportData.h" + +const FGuid FLuaCodeObjectVersion::GUID(0x01C2E96A1, 0xE24436EA, 0x6C69B025, 0x14E7FC3); +FCustomVersionRegistration GRegisterLuaCodeCustomVersion(FLuaCodeObjectVersion::GUID, FLuaCodeObjectVersion::LatestVersion, TEXT("LuaCodeVer")); + +ULuaCode::ULuaCode() +{ + bCookAsBytecode = true; + bCooked = false; +} + +void ULuaCode::Serialize(FArchive& Ar) +{ + bool bSkipOriginalCode = false; + if (Ar.IsCooking() && !Ar.IsLoading()) + { + if (bCookAsBytecode && !Code.IsEmpty()) + { + bCooked = true; + FString ErrorString; + ByteCode = ULuaState::ToByteCode(Code.ToString(), GetPathName(), ErrorString); + if (!ErrorString.IsEmpty()) + { + UE_LOG(LogLuaMachine, Error, TEXT("Unable to generate bytecode: %s"), *ErrorString); + } + bSkipOriginalCode = true; + } + } + else if (Ar.IsSaving()) + { + bCooked = false; + TArray EmptyData; + ByteCode = EmptyData; + } + + FText OriginalCode; + + if (bSkipOriginalCode) + { + OriginalCode = Code; + Code = FText::GetEmpty(); + } + + + Super::Serialize(Ar); + Ar.UsingCustomVersion(FLuaCodeObjectVersion::GUID); + + if (Ar.CustomVer(FLuaCodeObjectVersion::GUID) < FLuaCodeObjectVersion::FixDuplicationOfProperties) + { + Ar << bCooked; + Ar << Code; + Ar << bCookAsBytecode; + Ar << ByteCode; + } + + if (bSkipOriginalCode) + { + Code = OriginalCode; + } +} + +#if ENGINE_MAJOR_VERSION > 4 +void ULuaCode::PreSave(FObjectPreSaveContext ObjectSaveContext) +{ + Super::PreSave(ObjectSaveContext); +#else +void ULuaCode::PreSave(const ITargetPlatform * TargetPlatform) +{ + Super::PreSave(TargetPlatform); +#endif + + for (ULuaState* LuaState : FLuaMachineModule::Get().GetRegisteredLuaStates()) + { + if (LuaState->LuaCodeAsset == this) + { + FLuaMachineModule::Get().UnregisterLuaState(LuaState); + } + } +} + +#if WITH_EDITORONLY_DATA +void ULuaCode::PostInitProperties() +{ + if (!HasAnyFlags(RF_ClassDefaultObject)) + { + AssetImportData = NewObject(this, TEXT("AssetImportData")); + } + Super::PostInitProperties(); +} + +void ULuaCode::GetAssetRegistryTags(TArray& OutTags) const +{ + if (AssetImportData) + { + OutTags.Add(FAssetRegistryTag(SourceFileTagName(), AssetImportData->GetSourceData().ToJson(), FAssetRegistryTag::TT_Hidden)); + } + Super::GetAssetRegistryTags(OutTags); +} +#endif diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaCommandExecutor.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaCommandExecutor.cpp new file mode 100644 index 00000000..801d7119 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaCommandExecutor.cpp @@ -0,0 +1,69 @@ +// Copyright 2018-2023 - Roberto De Ioris + + +#include "LuaCommandExecutor.h" +#include "LuaBlueprintFunctionLibrary.h" + +FLuaCommandExecutor::FLuaCommandExecutor() +{ + LuaState = nullptr; +} + +FLuaCommandExecutor::~FLuaCommandExecutor() +{ +} + +FName FLuaCommandExecutor::GetName() const +{ + return FName(*FString::Printf(TEXT("LuaMachine:%s"), *LuaState->GetName())); +} + +FText FLuaCommandExecutor::GetDisplayName() const +{ + return FText::FromName(GetName()); +} + +FText FLuaCommandExecutor::GetDescription() const +{ + return GetDisplayName(); +} + +FText FLuaCommandExecutor::GetHintText() const +{ + return FText::GetEmpty(); +} + +void FLuaCommandExecutor::GetAutoCompleteSuggestions(const TCHAR* Input, TArray& Out) +{ +} + +void FLuaCommandExecutor::GetExecHistory(TArray& Out) +{ + IConsoleManager::Get().GetConsoleHistory(*(GetName().ToString()), Out); +} + +bool FLuaCommandExecutor::Exec(const TCHAR* Input) +{ + IConsoleManager::Get().AddConsoleHistoryEntry(*(GetName().ToString()), Input); + + LuaState->RunString(Input, ""); + + return true; +} + +bool FLuaCommandExecutor::AllowHotKeyClose() const +{ + return false; +} + +bool FLuaCommandExecutor::AllowMultiLine() const +{ + return true; +} + +FInputChord FLuaCommandExecutor::GetHotKey() const +{ + return FInputChord(); +} + + diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaComponent.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaComponent.cpp new file mode 100644 index 00000000..c5381a8d --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaComponent.cpp @@ -0,0 +1,375 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaComponent.h" +#include "LuaMachine.h" +#include "LuaBlueprintFunctionLibrary.h" +#include "GameFramework/Actor.h" + + +// Sets default values for this component's properties +ULuaComponent::ULuaComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = false; + + // ... + + bLazy = false; + bLogError = false; + bImplicitSelf = false; +} + +void ULuaComponent::OnRegister() +{ + Super::OnRegister(); + + if (GetWorld()->IsGameWorld()) + { + for (const FString& GlobalName : GlobalNames) + { + ULuaBlueprintFunctionLibrary::LuaSetGlobal(GetWorld(), LuaState, GlobalName, FLuaValue(this)); + } + } +} + +// Called when the game starts +void ULuaComponent::BeginPlay() +{ + Super::BeginPlay(); + + if (!bLazy) + FLuaMachineModule::Get().GetLuaState(LuaState, GetWorld()); + + // ... + +} + +// Called every frame +void ULuaComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + +ULuaState* ULuaComponent::LuaComponentGetState() +{ + return FLuaMachineModule::Get().GetLuaState(LuaState, GetWorld()); +} + +FLuaValue ULuaComponent::LuaGetField(const FString& Name) +{ + FLuaValue ReturnValue; + ULuaState* L = LuaComponentGetState(); + if (!L) + return ReturnValue; + + // push component pointer as userdata + L->NewUObject(this, nullptr); + L->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + int32 ItemsToPop = L->GetFieldFromTree(Name, false); + ReturnValue = L->ToLuaValue(-1); + + // we need to remove the return value and the object + L->Pop(ItemsToPop + 1); + + return ReturnValue; +} + +void ULuaComponent::LuaSetField(const FString& Name, FLuaValue Value) +{ + ULuaState* L = LuaComponentGetState(); + if (!L) + return; + + // push component pointer as userdata + L->NewUObject(this, nullptr); + L->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + L->SetFieldFromTree(Name, Value, false); + + // remove UObject + L->Pop(); + +} + +FLuaValue ULuaComponent::LuaCallFunction(const FString& Name, TArray Args, bool bGlobal) +{ + FLuaValue ReturnValue; + + ULuaState* L = LuaComponentGetState(); + if (!L) + return ReturnValue; + + // push component pointer as userdata + L->NewUObject(this, nullptr); + L->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + int32 ItemsToPop = L->GetFieldFromTree(Name, bGlobal); + + // first argument (self/actor) + L->PushValue(-(ItemsToPop + 1)); + int NArgs = 1; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + if (!L->PCall(NArgs, ReturnValue)) + { + if (L->InceptionLevel == 0) + { + if (bLogError) + L->LogError(L->LastError); + OnLuaError.Broadcast(L->LastError); + } + } + + // the return value and the function has been removed, so we do not need to change ItemsToPop + L->Pop(ItemsToPop + 1); + + return ReturnValue; +} + +TArray ULuaComponent::LuaCallFunctionMulti(FString Name, TArray Args, bool bGlobal) +{ + TArray ReturnValue; + + ULuaState* L = LuaComponentGetState(); + if (!L) + return ReturnValue; + + // push component pointer as userdata + L->NewUObject(this, nullptr); + L->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + int32 ItemsToPop = L->GetFieldFromTree(Name, bGlobal); + int32 StackTop = L->GetTop(); + + // first argument (self/actor) + L->PushValue(-(ItemsToPop + 1)); + int NArgs = 1; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + FLuaValue LastReturnValue; + if (!L->PCall(NArgs, LastReturnValue, LUA_MULTRET)) + { + if (L->InceptionLevel == 0) + { + if (bLogError) + L->LogError(L->LastError); + OnLuaError.Broadcast(L->LastError); + } + } + else + { + int32 NumOfReturnValues = (L->GetTop() - StackTop) + 1; + if (NumOfReturnValues > 0) + { + for (int32 i = -1; i >= -(NumOfReturnValues); i--) + { + ReturnValue.Insert(L->ToLuaValue(i), 0); + } + L->Pop(NumOfReturnValues - 1); + } + } + + // the return value and the function has been removed, so we do not need to change ItemsToPop + L->Pop(ItemsToPop + 1); + + return ReturnValue; +} + +FLuaValue ULuaComponent::LuaCallValue(FLuaValue Value, TArray Args) +{ + FLuaValue ReturnValue; + + ULuaState* L = Value.LuaState.Get(); + if (!L) + return ReturnValue; + + // push function + L->FromLuaValue(Value); + // push component pointer as userdata + L->NewUObject(this, nullptr); + L->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + int NArgs = 1; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + if (!L->PCall(NArgs, ReturnValue)) + { + if (L->InceptionLevel == 0) + { + if (bLogError) + L->LogError(L->LastError); + OnLuaError.Broadcast(L->LastError); + } + } + + L->Pop(); + + return ReturnValue; +} + +FLuaValue ULuaComponent::LuaCallValueIfNotNil(FLuaValue Value, TArray Args) +{ + FLuaValue ReturnValue; + if (Value.Type != ELuaValueType::Nil) + ReturnValue = LuaCallValue(Value, Args); + + return ReturnValue; +} + +FLuaValue ULuaComponent::LuaCallTableKey(FLuaValue InTable, FString Key, TArray Args) +{ + FLuaValue ReturnValue; + + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + FLuaValue Value = InTable.GetField(Key); + if (Value.Type == ELuaValueType::Nil) + return ReturnValue; + + return LuaCallValue(Value, Args); +} + +FLuaValue ULuaComponent::LuaCallTableIndex(FLuaValue InTable, int32 Index, TArray Args) +{ + FLuaValue ReturnValue; + + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + FLuaValue Value = InTable.GetFieldByIndex(Index); + if (Value.Type == ELuaValueType::Nil) + return ReturnValue; + + return LuaCallValue(Value, Args); +} + +TArray ULuaComponent::LuaCallValueMulti(FLuaValue Value, TArray Args) +{ + TArray ReturnValue; + + ULuaState* L = Value.LuaState.Get(); + if (!L) + return ReturnValue; + + // push function + L->FromLuaValue(Value); + int32 StackTop = L->GetTop(); + + // push component pointer as userdata + L->NewUObject(this, nullptr); + L->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + int NArgs = 1; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + FLuaValue LastReturnValue; + if (!L->PCall(NArgs, LastReturnValue, LUA_MULTRET)) + { + if (L->InceptionLevel == 0) + { + if (bLogError) + L->LogError(L->LastError); + OnLuaError.Broadcast(L->LastError); + } + } + else + { + int32 NumOfReturnValues = (L->GetTop() - StackTop) + 1; + if (NumOfReturnValues > 0) + { + for (int32 i = -1; i >= -(NumOfReturnValues); i--) + { + ReturnValue.Insert(L->ToLuaValue(i), 0); + } + L->Pop(NumOfReturnValues - 1); + } + } + + L->Pop(); + + return ReturnValue; +} + +TArray ULuaComponent::LuaCallValueMultiIfNotNil(FLuaValue Value, TArray Args) +{ + TArray ReturnValue; + if (Value.Type != ELuaValueType::Nil) + ReturnValue = LuaCallValueMulti(Value, Args); + + return ReturnValue; +} + +TArray ULuaComponent::LuaCallTableKeyMulti(FLuaValue InTable, FString Key, TArray Args) +{ + TArray ReturnValue; + + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + FLuaValue Value = InTable.GetField(Key); + if (Value.Type == ELuaValueType::Nil) + return ReturnValue; + + return LuaCallValueMulti(Value, Args); +} + +TArray ULuaComponent::LuaCallTableIndexMulti(FLuaValue InTable, int32 Index, TArray Args) +{ + TArray ReturnValue; + + if (InTable.Type != ELuaValueType::Table) + return ReturnValue; + + ULuaState* L = InTable.LuaState.Get(); + if (!L) + return ReturnValue; + + FLuaValue Value = InTable.GetFieldByIndex(Index); + if (Value.Type == ELuaValueType::Nil) + return ReturnValue; + + return LuaCallValueMulti(Value, Args); +} + +FLuaValue ULuaComponent::ReceiveLuaMetaIndex_Implementation(FLuaValue Key) +{ + return FLuaValue(); +} + +bool ULuaComponent::ReceiveLuaMetaNewIndex_Implementation(FLuaValue Key, FLuaValue Value) +{ + return false; +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaDelegate.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaDelegate.cpp new file mode 100644 index 00000000..eaad63c0 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaDelegate.cpp @@ -0,0 +1,40 @@ +// Copyright 2018-2023 - Roberto De Ioris + + +#include "LuaDelegate.h" +#include "LuaBlueprintFunctionLibrary.h" + +void ULuaDelegate::LuaDelegateFunction() +{ +} + +void ULuaDelegate::SetupLuaDelegate(UFunction* InSignature, ULuaState* InLuaState, FLuaValue InLuaValue) +{ + LuaDelegateSignature = InSignature; + LuaState = InLuaState; + LuaValue = InLuaValue; +} + +void ULuaDelegate::ProcessEvent(UFunction* Function, void* Parms) +{ + if (!LuaState.IsValid()) + { + return; + } + + TArray LuaArgs; +#if ENGINE_MAJOR_VERSION > 4 ||ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator It(LuaDelegateSignature); (It && (It->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++It) + { + FProperty* Prop = *It; +#else + for (TFieldIterator It(LuaDelegateSignature); (It && (It->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++It) + { + UProperty* Prop = *It; +#endif + bool bPropSuccess = false; + LuaArgs.Add(LuaState->FromProperty(Parms, Prop, bPropSuccess, 0)); + } + + ULuaBlueprintFunctionLibrary::LuaGlobalCallValue(LuaState->GetWorld(), LuaState->GetClass(), LuaValue, LuaArgs); +} diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaGlobalNameComponent.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaGlobalNameComponent.cpp new file mode 100644 index 00000000..3d8f2311 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaGlobalNameComponent.cpp @@ -0,0 +1,42 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaGlobalNameComponent.h" +#include "LuaBlueprintFunctionLibrary.h" + +// Sets default values for this component's properties +ULuaGlobalNameComponent::ULuaGlobalNameComponent() +{ + // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features + // off to improve performance if you don't need them. + PrimaryComponentTick.bCanEverTick = false; + + // ... +} + +void ULuaGlobalNameComponent::OnRegister() +{ + Super::OnRegister(); + + if (GetWorld()->IsGameWorld() && !LuaGlobalName.IsEmpty()) + { + ULuaBlueprintFunctionLibrary::LuaSetGlobal(GetWorld(), LuaState, LuaGlobalName, FLuaValue(GetOwner())); + } +} + +// Called when the game starts +void ULuaGlobalNameComponent::BeginPlay() +{ + Super::BeginPlay(); + + // ... +} + + +// Called every frame +void ULuaGlobalNameComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) +{ + Super::TickComponent(DeltaTime, TickType, ThisTickFunction); + + // ... +} + diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaInterface.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaInterface.cpp new file mode 100644 index 00000000..ce6862df --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaInterface.cpp @@ -0,0 +1,7 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LuaInterface.h" + + +// Add default functionality here for any ILuaInterface functions that are not pure virtual. diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaMachine.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaMachine.cpp new file mode 100644 index 00000000..eab2da3e --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaMachine.cpp @@ -0,0 +1,256 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaMachine.h" +#include "LuaBlueprintFunctionLibrary.h" +#if WITH_EDITOR +#include "Editor/UnrealEd/Public/Editor.h" +#include "Editor/PropertyEditor/Public/PropertyEditorModule.h" +#include "Runtime/Projects/Public/Interfaces/IPluginManager.h" +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 +#include "Styling/SlateStyleRegistry.h" +#else +#include "SlateCore/Public/Styling/SlateStyleRegistry.h" +#endif +#endif + +#define LOCTEXT_NAMESPACE "FLuaMachineModule" + +void FLuaMachineModule::StartupModule() +{ + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module +#if WITH_EDITOR + FEditorDelegates::BeginPIE.AddRaw(this, &FLuaMachineModule::CleanupLuaStates); + FEditorDelegates::EndPIE.AddRaw(this, &FLuaMachineModule::CleanupLuaStates); +#endif + + // streaming level hooks + FWorldDelegates::LevelAddedToWorld.AddRaw(this, &FLuaMachineModule::LuaLevelAddedToWorld); + FWorldDelegates::LevelRemovedFromWorld.AddRaw(this, &FLuaMachineModule::LuaLevelRemovedFromWorld); + +} + +void FLuaMachineModule::LuaLevelAddedToWorld(ULevel* Level, UWorld* World) +{ + for (ULuaState* LuaState : GetRegisteredLuaStates()) + { +#if ENGINE_MAJOR_VERSION > 4 + if (LuaState->IsValidLowLevel() && !IsValid(LuaState)) +#else + if (LuaState->IsValidLowLevel() && !LuaState->IsPendingKill()) +#endif + { + LuaState->ReceiveLuaLevelAddedToWorld(Level, World); + } + } +} + +void FLuaMachineModule::LuaLevelRemovedFromWorld(ULevel* Level, UWorld* World) +{ + for (ULuaState* LuaState : GetRegisteredLuaStates()) + { +#if ENGINE_MAJOR_VERSION > 4 + if (LuaState->IsValidLowLevel() && !IsValid(LuaState)) +#else + if (LuaState->IsValidLowLevel() && !LuaState->IsPendingKill()) +#endif + { + LuaState->ReceiveLuaLevelRemovedFromWorld(Level, World); + } + } +} + +void FLuaMachineModule::ShutdownModule() +{ + // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading, + // we call this function before unloading the module. +} + +void FLuaMachineModule::AddReferencedObjects(FReferenceCollector& Collector) +{ + Collector.AddReferencedObjects(LuaStates); +} + +void FLuaMachineModule::CleanupLuaStates(bool bIsSimulating) +{ + TArray> LuaStatesKeys; + LuaStates.GetKeys(LuaStatesKeys); + + TMap, ULuaState*> PersistentLuaStates; + + for (TSubclassOf LuaStateClass : LuaStatesKeys) + { + if (LuaStates[LuaStateClass]->bPersistent) + { + PersistentLuaStates.Add(LuaStateClass, LuaStates[LuaStateClass]); + } + else + { + if (FLuaCommandExecutor* LuaConsole = LuaStates[LuaStateClass]->GetLuaConsole()) + { + IModularFeatures::Get().UnregisterModularFeature(IConsoleCommandExecutor::ModularFeatureName(), LuaConsole); + } + } + } + + LuaStates = PersistentLuaStates; + OnRegisteredLuaStatesChanged.Broadcast(); +} + +ULuaState* FLuaMachineModule::GetLuaState(TSubclassOf LuaStateClass, UWorld* InWorld, bool bCheckOnly) +{ + if (!LuaStateClass) + { + return nullptr; + } + + if (LuaStateClass == ULuaState::StaticClass()) + { + UE_LOG(LogLuaMachine, Error, TEXT("attempt to use LuaState Abstract class, please create a child of LuaState")); + return nullptr; + } + + if (!LuaStates.Contains(LuaStateClass)) + { + if (bCheckOnly) + { + return nullptr; + } + ULuaState* NewLuaState = NewObject((UObject*)GetTransientPackage(), LuaStateClass); + LuaStates.Add(LuaStateClass, NewLuaState); + OnNewLuaState.Broadcast(NewLuaState); + OnRegisteredLuaStatesChanged.Broadcast(); + } + + return LuaStates[LuaStateClass]->GetLuaState(InWorld); +} + +TArray FLuaMachineModule::GetRegisteredLuaStates() +{ + TArray RegisteredStates; + for (TPair< TSubclassOf, ULuaState*>& Pair : LuaStates) + { + RegisteredStates.Add(Pair.Value); + } + + return RegisteredStates; +} + +void FLuaMachineModule::UnregisterLuaState(ULuaState* LuaState) +{ + TSubclassOf FoundLuaStateClass = nullptr; + for (TPair< TSubclassOf, ULuaState*>& Pair : LuaStates) + { + if (Pair.Value == LuaState) + { + FoundLuaStateClass = Pair.Key; + break; + } + } + + if (FoundLuaStateClass) + { + LuaStates.Remove(FoundLuaStateClass); + } + + // trick for waking up on low-level destructor + OnRegisteredLuaStatesChanged.Broadcast(); +} + +void FLuaMachineModule::RegisterLuaConsoleCommand(const FString& CommandName, const FLuaValue& LuaConsoleCommand) +{ + // first check in lua console commands + UnregisterLuaConsoleCommand(CommandName); + if (IConsoleManager::Get().FindConsoleObject(*CommandName)) + { + UE_LOG(LogLuaMachine, Error, TEXT("Lua Console Command Name \"%s\" is already in use."), *CommandName); + return; + } + + if (IConsoleManager::Get().RegisterConsoleCommand(*CommandName, *CommandName, FConsoleCommandWithArgsDelegate::CreateRaw(this, &FLuaMachineModule::RunLuaConsoleCommand, LuaConsoleCommand))) + { + LuaConsoleCommands.Add(CommandName); + } +} + +void FLuaMachineModule::UnregisterLuaConsoleCommand(const FString& CommandName) +{ + if (LuaConsoleCommands.Contains(CommandName)) + { + IConsoleManager::Get().UnregisterConsoleObject(*CommandName); + LuaConsoleCommands.Remove(CommandName); + } +} + +void FLuaMachineModule::RunLuaConsoleCommand(const TArray& Args, FLuaValue LuaConsoleCommand) +{ + TArray LuaArgs; + for (FString Arg : Args) + { + LuaArgs.Add(FLuaValue(Arg)); + } + ULuaBlueprintFunctionLibrary::LuaValueCallIfNotNil(LuaConsoleCommand, LuaArgs); +} + +FLuaMachineModule& FLuaMachineModule::Get() +{ + static FLuaMachineModule* Singleton = nullptr; + if (Singleton == nullptr) + { + Singleton = &FModuleManager::LoadModuleChecked("LuaMachine"); + } + return *Singleton; +} + +bool FLuaMachineModule::Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) +{ + if (FParse::Command(&Cmd, TEXT("luaspawn"))) + { + if (!*Cmd) + { + UE_LOG(LogLuaMachine, Error, TEXT("please specify a valid LuaState path.")); + return false; + } + + UObject* RequestedObject = LoadObject(nullptr, Cmd); + if (RequestedObject) + { + bool bLoaded = false; + UClass* ObjectAsClass = Cast(RequestedObject); + if (ObjectAsClass && ObjectAsClass->IsChildOf()) + { + bLoaded = true; + } + + if (!bLoaded) + { + UBlueprint* ObjectAsBlueprint = Cast(RequestedObject); + if (ObjectAsBlueprint) + { + ObjectAsClass = ObjectAsBlueprint->GeneratedClass; + if (ObjectAsClass && ObjectAsClass->IsChildOf()) + { + bLoaded = true; + } + } + } + + if (bLoaded) + { + ULuaState* SpawnedState = FLuaMachineModule::Get().GetLuaState(ObjectAsClass, InWorld, false); + if (SpawnedState) + { + UE_LOG(LogLuaMachine, Log, TEXT("%s spawned."), *SpawnedState->GetName()); + } + return true; + } + + UE_LOG(LogLuaMachine, Error, TEXT("specified argument is not a valid LuaState path.")); + } + } + + return false; +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FLuaMachineModule, LuaMachine) \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaMultiLineEditableTextBox.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaMultiLineEditableTextBox.cpp new file mode 100644 index 00000000..681cd25f --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaMultiLineEditableTextBox.cpp @@ -0,0 +1,234 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaMultiLineEditableTextBox.h" +#include "Runtime/Slate/Public/Widgets/Input/SMultiLineEditableTextBox.h" +#include "Runtime/Slate/Public/Widgets/Input/SEditableTextBox.h" +#include "LuaSyntaxHighlighter.h" + +#define LOCTEXT_NAMESPACE "UMG" + +FLuaCustomHighlighter::FLuaCustomHighlighter() +{ + Color = FLinearColor::White; +} + +ULuaMultiLineEditableTextBox::ULuaMultiLineEditableTextBox() +{ +#if ENGINE_MAJOR_VERSION >=5 && ENGINE_MINOR_VERSION >= 2 + EditableTextBoxStyle.SetTextStyle(CodeStyle); +#endif + + SEditableTextBox::FArguments Defaults; + WidgetStyle = *Defaults._Style; + WidgetStyle.BackgroundColor = FSlateColor(FLinearColor::Black); + WidgetStyle.ForegroundColor = FSlateColor(FLinearColor::White); + + TabSize = 2; + + bIsReadonly = false; + bHandleTab = true; + bHandleArrows = true; + + CodeStyle = FTextBlockStyle() +#if ENGINE_MAJOR_VERSION > 4 && ENGINE_MINOR_VERSION > 0 + .SetFont(WidgetStyle.TextStyle.Font) +#else + .SetFont(WidgetStyle.Font) +#endif + .SetColorAndOpacity(FLinearColor::White) + .SetShadowOffset(FVector2D::ZeroVector) + .SetSelectedBackgroundColor(FSlateColor(FLinearColor::Blue)) + .SetShadowColorAndOpacity(FLinearColor::Black); + + CommentColor = FLinearColor::Green; + StringColor = FLinearColor(FColor::Orange); + KeywordColor = FLinearColor(FColor::Cyan); + NilColor = FLinearColor::Red; + StdLibColor = FLinearColor::Yellow; + BasicColor = FLinearColor(FColor::Magenta); + +} + +FText ULuaMultiLineEditableTextBox::GetText() const +{ + if (EditableTextBoxPtr.IsValid()) + { + return EditableTextBoxPtr->GetText(); + } + return FText::GetEmpty(); +} + +FText ULuaMultiLineEditableTextBox::GetSelectedText() const +{ + if (EditableTextBoxPtr.IsValid()) + { + return EditableTextBoxPtr->GetSelectedText(); + } + return FText::GetEmpty(); +} + +void ULuaMultiLineEditableTextBox::SetText(FText InText) +{ + if (EditableTextBoxPtr.IsValid()) + { + EditableTextBoxPtr->SetText(InText); + } +} + +FReply ULuaMultiLineEditableTextBox::OnKeyChar(const FGeometry& InGeometry, const FCharacterEvent& InCharacterEvent) +{ + const TCHAR Character = InCharacterEvent.GetCharacter(); + if (Character == TEXT('\t')) + { + FString Spaces; + // using Max here for avoiding negative values + for (int32 i = 0; i < FMath::Max(TabSize, 0); i++) + Spaces = Spaces.AppendChar(TEXT(" ")[0]); + EditableTextBoxPtr->ClearSelection(); + EditableTextBoxPtr->InsertTextAtCursor(Spaces); + return FReply::Handled(); + } + return EditableTextBoxPtr->SMultiLineEditableTextBox::OnKeyChar(InGeometry, InCharacterEvent); +} + +FReply ULuaMultiLineEditableTextBox::OnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) +{ + FKey Key = InKeyEvent.GetKey(); + if (bHandleTab && Key == EKeys::Tab) + { + return FReply::Handled(); + } + + if (bHandleArrows) + { + if (Key == EKeys::Up) + { + MoveCursorUp(); + return FReply::Handled(); + } + + if (Key == EKeys::Down) + { + MoveCursorDown(); + return FReply::Handled(); + } + + if (Key == EKeys::Right) + { + MoveCursorRight(); + return FReply::Handled(); + } + + if (Key == EKeys::Left) + { + MoveCursorLeft(); + return FReply::Handled(); + } + } + + return EditableTextBoxPtr->SMultiLineEditableTextBox::OnKeyDown(InGeometry, InKeyEvent); +} + +void ULuaMultiLineEditableTextBox::OnCursorMoved(const FTextLocation& Location) +{ + CursorLocation = Location; +} + +int32 ULuaMultiLineEditableTextBox::GetCursorLine() const +{ + return CursorLocation.GetLineIndex(); +} + +int32 ULuaMultiLineEditableTextBox::GetCursorColumn() const +{ + return CursorLocation.GetOffset(); +} + +void ULuaMultiLineEditableTextBox::CursorGoTo(int32 Line, int32 Column) +{ + if (Line < 0) + Line = 0; + if (Column < 0) + Column = 0; + return EditableTextBoxPtr->GoTo(FTextLocation(Line, Column)); +} + +void ULuaMultiLineEditableTextBox::MoveCursorUp() +{ + return CursorGoTo(CursorLocation.GetLineIndex() - 1, 0); +} + +void ULuaMultiLineEditableTextBox::MoveCursorDown() +{ + return CursorGoTo(CursorLocation.GetLineIndex() + 1, 0); +} + +void ULuaMultiLineEditableTextBox::MoveCursorRight() +{ + return CursorGoTo(CursorLocation.GetLineIndex(), CursorLocation.GetOffset() + 1); +} + +void ULuaMultiLineEditableTextBox::MoveCursorLeft() +{ + return CursorGoTo(CursorLocation.GetLineIndex(), CursorLocation.GetOffset() - 1); +} + +void ULuaMultiLineEditableTextBox::SynchronizeProperties() +{ + Super::SynchronizeProperties(); + + EditableTextBoxPtr->SetStyle(&WidgetStyle); + + Super::SynchronizeTextLayoutProperties(*EditableTextBoxPtr); +} + +#if WITH_EDITOR +const FText ULuaMultiLineEditableTextBox::GetPaletteCategory() +{ + return LOCTEXT("Lua", "Lua"); +} +#endif + +void ULuaMultiLineEditableTextBox::ReleaseSlateResources(bool bReleaseChildren) +{ + Super::ReleaseSlateResources(bReleaseChildren); + + EditableTextBoxPtr.Reset(); +} + +TSharedRef ULuaMultiLineEditableTextBox::RebuildWidget() +{ + FLuaSyntaxTextStyle Style; + Style.NormalTextStyle = CodeStyle; + Style.CommentTextStyle = FTextBlockStyle(CodeStyle).SetColorAndOpacity(CommentColor); + Style.KeywordTextStyle = FTextBlockStyle(CodeStyle).SetColorAndOpacity(KeywordColor); + Style.NilTextStyle = FTextBlockStyle(CodeStyle).SetColorAndOpacity(NilColor); + Style.BasicTextStyle = FTextBlockStyle(CodeStyle).SetColorAndOpacity(BasicColor); + Style.StdLibTextStyle = FTextBlockStyle(CodeStyle).SetColorAndOpacity(StdLibColor); + Style.StringTextStyle = FTextBlockStyle(CodeStyle).SetColorAndOpacity(StringColor); + for (FLuaCustomHighlighter& Highlighter : CustomTokensMapping) + { + for (FString& Token : Highlighter.Tokens) + { + Style.CustomTextColorMapping.Add(Token, Highlighter.Color); + } + } + + EditableTextBoxPtr = SNew(SMultiLineEditableTextBox) + .Marshaller(FLuaMachineSyntaxHighlighterTextLayoutMarshaller::Create(Style)) +#if ENGINE_MAJOR_VERSION >=5 && ENGINE_MINOR_VERSION >= 1 + .Style(&EditableTextBoxStyle) +#else + .TextStyle(&CodeStyle) +#endif + .OnKeyCharHandler_UObject(this, &ULuaMultiLineEditableTextBox::OnKeyChar) + .OnKeyDownHandler_UObject(this, &ULuaMultiLineEditableTextBox::OnKeyDown) + .IsReadOnly(bIsReadonly) + .AllowContextMenu(false) + .OnCursorMoved_UObject(this, &ULuaMultiLineEditableTextBox::OnCursorMoved) + .Style(&WidgetStyle); + + return EditableTextBoxPtr.ToSharedRef(); +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaObject.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaObject.cpp new file mode 100644 index 00000000..b552a9e0 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaObject.cpp @@ -0,0 +1,103 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LuaObject.h" + +#include "LuaBlueprintFunctionLibrary.h" + +void ULuaObject::SetKey_Implementation(FLuaValue Key) +{ + lua_key=Key; +} + +void ULuaObject::SetValue_Implementation(FLuaValue Value, const FString& Field) +{ + lua_value=Value; +} + +FLuaValue ULuaObject::GetKey_Implementation() +{ + return lua_key; +} + +FLuaValue ULuaObject::GetValue_Implementation(const FString& Field) +{ + return lua_value; +} + +ULuaObject* ULuaObjectFunctions::CreateLuaObject(UObject* WorldContextObject, FLuaValue key, FLuaValue value) +{ + TSubclassOf target_class = ULuaObject::StaticClass(); + if (const TSubclassOf temp_class = GetMutableDefault()->DefaultObject.LoadSynchronous()) + { + target_class=temp_class; + } + ULuaObject* new_object = NewObject(WorldContextObject,target_class); + new_object->lua_key=key; + new_object->lua_value=value; + return new_object; +} + +TArray ULuaObjectFunctions::CreateLuaObjectsFromTable(UObject* WorldContextObject, FLuaValue table) +{ + TArray out; + for(FLuaValue i : ULuaBlueprintFunctionLibrary::LuaTableGetKeys(table)) + { + FString local_key = ULuaBlueprintFunctionLibrary::Conv_LuaValueToString(i); + ULuaObject* newobj= CreateLuaObject(WorldContextObject,i,ULuaBlueprintFunctionLibrary::LuaTableGetField(table,local_key)); + out.Add(newobj); + } + return out; +} + +TArray ULuaObjectFunctions::CreateLuaObjectsFromKeysInTable(UObject* WorldContextObject, FLuaValue keys, FLuaValue table) +{ + TArray out; + for(FLuaValue i : ULuaBlueprintFunctionLibrary::LuaTableGetValues(keys)) + { + FString local_key = ULuaBlueprintFunctionLibrary::Conv_LuaValueToString(i); + ULuaObject* newobj= CreateLuaObject(WorldContextObject,i,ULuaBlueprintFunctionLibrary::LuaTableGetField(table,local_key)); + out.Add(newobj); + } + return out; +} + +FLuaValue ULuaObjectFunctions::ConvertTableKeysToValues(UObject* WorldContextObject, FLuaValue table) +{ + FLuaValue new_table = ULuaBlueprintFunctionLibrary::LuaCreateTable(WorldContextObject,ULuaBlueprintFunctionLibrary::GetDefaultLuaState()); + int32 Tempindex=0; + for(FLuaValue i: ULuaBlueprintFunctionLibrary::LuaTableGetKeys(table)) + { + Tempindex+=1; + new_table=ULuaBlueprintFunctionLibrary::LuaTableSetByIndex(new_table,Tempindex,i); + } + return new_table; +} + +FLuaValue ULuaObjectFunctions::RunLuaScriptContainer(UObject* WorldContextObject, FLuaScriptContainer Script, + TSubclassOf State) +{ + if(Script.code_asset) + { + return ULuaBlueprintFunctionLibrary::LuaRunCodeAsset(WorldContextObject, State,Script.code_asset); + } + return ULuaBlueprintFunctionLibrary::LuaRunString(WorldContextObject, State,Script.code_string); +} + +void ULuaObjectFunctions::GetObjectKeyAndValue(UObject* Object, FLuaValue& Key, FLuaValue& Value) +{ + if(Object && Object->GetClass()->ImplementsInterface(ULuaInterface::StaticClass())) + { + Key=ILuaInterface::Execute_GetKey(Object); + Value=ILuaInterface::Execute_GetValue(Object,""); + } +} + +void ULuaObjectFunctions::SetObjectKeyAndValue(UObject* Object, FLuaValue Key, FLuaValue Value) +{ + if(Object && Object->GetClass()->ImplementsInterface(ULuaInterface::StaticClass())) + { + ILuaInterface::Execute_SetKey(Object,Key); + ILuaInterface::Execute_SetValue(Object,Value,""); + } +} diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaState.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaState.cpp new file mode 100644 index 00000000..5365c174 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaState.cpp @@ -0,0 +1,2785 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaState.h" +#include "LuaComponent.h" +#include "LuaUserDataObject.h" +#include "LuaMachine.h" +#include "LuaBlueprintPackage.h" +#include "LuaBlueprintFunctionLibrary.h" +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 0 +#include "AssetRegistry/AssetRegistryModule.h" +#else +#include "AssetRegistryModule.h" +#endif +#include "GameFramework/Actor.h" +#include "Runtime/Core/Public/Misc/FileHelper.h" +#include "Runtime/Core/Public/Misc/Paths.h" +#include "Runtime/Core/Public/Serialization/BufferArchive.h" +#include "Runtime/CoreUObject/Public/UObject/TextProperty.h" + +LUAMACHINE_API DEFINE_LOG_CATEGORY(LogLuaMachine); + +ULuaState::ULuaState() +{ + L = nullptr; + bLuaOpenLibs = true; + bDisabled = false; + bLogError = true; + bAddProjectContentDirToPackagePath = true; + bPersistent = false; + bEnableLineHook = false; + bEnableCallHook = false; + bEnableReturnHook = false; + bEnableCountHook = false; + bRawLuaFunctionCall = false; + + FCoreUObjectDelegates::GetPostGarbageCollect().AddUObject(this, &ULuaState::GCLuaDelegatesCheck); +} + +ULuaState* ULuaState::GetLuaState(UWorld* InWorld) +{ + CurrentWorld = InWorld; + + if (L != nullptr) + { + return this; + } + + if (bDisabled) + { + return nullptr; + } + + L = luaL_newstate(); + + if (bLuaOpenLibs) + { + luaL_openlibs(L); + } + + // load "package" for allowing minimal setup + luaL_requiref(L, "package", luaopen_package, 1); + lua_pop(L, 1); + + if (!bLuaOpenLibs) + { + if (LuaLibsLoader.bLoadBase) + { + luaL_requiref(L, "_G", luaopen_base, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadCoroutine) + { + luaL_requiref(L, "coroutine", luaopen_coroutine, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadTable) + { + luaL_requiref(L, "table", luaopen_table, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadIO) + { + luaL_requiref(L, "io", luaopen_io, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadOS) + { + luaL_requiref(L, "os", luaopen_os, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadString) + { + luaL_requiref(L, "string", luaopen_string, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadMath) + { + luaL_requiref(L, "math", luaopen_math, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadUTF8) + { + luaL_requiref(L, "utf8", luaopen_utf8, 1); + lua_pop(L, 1); + } + + if (LuaLibsLoader.bLoadDebug) + { + luaL_requiref(L, "debug", luaopen_debug, 1); + lua_pop(L, 1); + } + } + + ULuaState** LuaExtraSpacePtr = (ULuaState**)lua_getextraspace(L); + *LuaExtraSpacePtr = this; + // get the global table + lua_pushglobaltable(L); + // override print + PushCFunction(ULuaState::TableFunction_print); + SetField(-2, "print"); + + GetField(-1, "package"); + if (!OverridePackagePath.IsEmpty()) + { + OverridePackagePath.ReplaceInline(*FString("$(CONTENT_DIR)"), *FPaths::ProjectContentDir()); + lua_pushstring(L, TCHAR_TO_ANSI(*OverridePackagePath)); + SetField(-2, "path"); + } + + if (bAddProjectContentDirToPackagePath) + { + GetField(-1, "path"); + const char* CurrentLuaPath = lua_tostring(L, -1); + FString NewPackagePath = FString(CurrentLuaPath) + ";" + FPaths::ProjectContentDir() + "/?.lua"; + Pop(); + lua_pushstring(L, TCHAR_TO_ANSI(*NewPackagePath)); + SetField(-2, "path"); + } + + for (FString SubDir : AppendProjectContentDirSubDir) + { + GetField(-1, "path"); + const char* CurrentLuaPath = lua_tostring(L, -1); + FString NewPackagePath = FString(CurrentLuaPath) + ";" + FPaths::ProjectContentDir() / SubDir + "/?.lua"; + Pop(); + lua_pushstring(L, TCHAR_TO_ANSI(*NewPackagePath)); + SetField(-2, "path"); + } + + if (!OverridePackageCPath.IsEmpty()) + { + OverridePackageCPath.ReplaceInline(*FString("$(CONTENT_DIR)"), *FPaths::ProjectContentDir()); + + static const FString libExtension = +#if PLATFORM_MAC || PLATFORM_IOS + FString("dylib"); +#elif PLATFORM_LINUX || PLATFORM_ANDROID + FString("so"); +#elif PLATFORM_WINDOWS + FString("dll"); +#else + FString(""); +#endif + + OverridePackageCPath.ReplaceInline(*FString("$(LIB_EXT)"), *libExtension); + + lua_pushstring(L, TCHAR_TO_ANSI(*OverridePackageCPath)); + SetField(-2, "cpath"); + } + // manage RequireTable + GetField(-1, "preload"); + for (TPair& Pair : RequireTable) + { + PushCFunction(ULuaState::TableFunction_package_preload); + SetField(-2, TCHAR_TO_ANSI(*Pair.Key)); + } + + // pop package.prelod + Pop(1); + + // manage searchers + GetField(-1, "searchers"); + PushCFunction(ULuaState::TableFunction_package_loader); + constexpr int PackageLoadersFirstAvailableIndex = 5; + lua_seti(L, -2, PackageLoadersFirstAvailableIndex); + + // pop package.searchers (and package) + Pop(2); + + + for (TPair& Pair : Table) + { + FromLuaValue(Pair.Value, this, L); + SetField(-2, TCHAR_TO_ANSI(*Pair.Key)); + } + + for (TPair>& Pair : LuaBlueprintPackagesTable) + { + if (Pair.Value) + { + NewTable(); + ULuaBlueprintPackage* LuaBlueprintPackage = NewObject(this, Pair.Value); + if (LuaBlueprintPackage) + { + for (auto LuaPair : LuaBlueprintPackage->Table) + { + FromLuaValue(LuaPair.Value, LuaBlueprintPackage); + SetField(-2, TCHAR_TO_ANSI(*LuaPair.Key)); + } + // this avoid the package to be GC'd + LuaBlueprintPackages.Add(Pair.Key, LuaBlueprintPackage); + LuaBlueprintPackage->SelfTable = ToLuaValue(-1); + LuaBlueprintPackage->Init(); + LuaBlueprintPackage->ReceiveInit(); + } + } + else + { + PushNil(); + } + SetField(-2, TCHAR_TO_ANSI(*Pair.Key)); + } + + // pop global table + Pop(); + + // This allows subclasses to do any last minute initialization on lua state before + // we load code + ReceiveLuaStatePreInitialized(); + + int DebugMask = 0; + // install hooks + if (bEnableLineHook) + { + DebugMask |= LUA_MASKLINE; + } + if (bEnableCallHook) + { + DebugMask |= LUA_MASKCALL; + } + if (bEnableReturnHook) + { + DebugMask |= LUA_MASKRET; + } + if (bEnableCountHook) + { + DebugMask |= LUA_MASKCOUNT; + } + + if (DebugMask != 0) + { + lua_sethook(L, Debug_Hook, DebugMask, HookInstructionCount); + } + + if (LuaCodeAsset) + { + if (!RunCodeAsset(LuaCodeAsset)) + { + if (bLogError) + LogError(LastError); + ReceiveLuaError(LastError); + bDisabled = true; + return nullptr; + } + } + + if (!LuaFilename.IsEmpty()) + { + if (!RunFile(LuaFilename, true)) + { + if (bLogError) + LogError(LastError); + ReceiveLuaError(LastError); + bDisabled = true; + return nullptr; + } + } + + if (UserDataMetaTableFromCodeAsset) + { + if (!RunCodeAsset(UserDataMetaTableFromCodeAsset, 1)) + { + if (bLogError) + LogError(LastError); + ReceiveLuaError(LastError); + bDisabled = true; + return nullptr; + } + UserDataMetaTable = ToLuaValue(-1); + Pop(); + } + + LuaStateInit(); + ReceiveLuaStateInitialized(); + +#if WITH_EDITOR + if (!(GetFlags() & RF_ClassDefaultObject)) + { + LuaConsole.LuaState = this; + IModularFeatures::Get().RegisterModularFeature(IConsoleCommandExecutor::ModularFeatureName(), &LuaConsole); + } +#endif + + + return this; +} + +FLuaValue ULuaState::GetLuaBlueprintPackageTable(const FString& PackageName) +{ + if (!LuaBlueprintPackages.Contains(PackageName)) + { + return FLuaValue(); + } + + return LuaBlueprintPackages[PackageName]->SelfTable; +} + +bool ULuaState::RunCodeAsset(ULuaCode* CodeAsset, int NRet) +{ + + if (CodeAsset->bCooked && CodeAsset->bCookAsBytecode) + { +#if PLATFORM_ANDROID + // fix size_t of the bytecode + if (CodeAsset->ByteCode.Num() >= 14) + CodeAsset->ByteCode[13] = sizeof(size_t); +#endif + return RunCode(CodeAsset->ByteCode, CodeAsset->GetPathName(), NRet); + } + + return RunCode(CodeAsset->Code.ToString(), CodeAsset->GetPathName(), NRet); + +} + +bool ULuaState::RunFile(const FString& Filename, bool bIgnoreNonExistent, int NRet, bool bNonContentDirectory) +{ + TArray Code; + FString AbsoluteFilename = FPaths::Combine(FPaths::ProjectContentDir(), Filename); + + if (bNonContentDirectory) + { + AbsoluteFilename = Filename; + } + + if (!FPaths::FileExists(AbsoluteFilename)) + { + if (bIgnoreNonExistent) + return true; + LastError = FString::Printf(TEXT("Unable to open file %s"), *Filename); + FLuaValue LuaLastError = FLuaValue(LastError); + FromLuaValue(LuaLastError); + return false; + } + + if (FFileHelper::LoadFileToArray(Code, *AbsoluteFilename)) + { + if (RunCode(Code, AbsoluteFilename, NRet)) + { + return true; + } + return false; + } + + LastError = FString::Printf(TEXT("Unable to open file %s"), *Filename); + FLuaValue LuaLastError = FLuaValue(LastError); + FromLuaValue(LuaLastError); + return false; +} + +bool ULuaState::RunCode(const FString& Code, const FString& CodePath, int NRet) +{ + TArray Bytes; + Bytes.Append((uint8*)TCHAR_TO_UTF8(*Code), FCStringAnsi::Strlen(TCHAR_TO_UTF8(*Code))); + return RunCode(Bytes, CodePath, NRet); +} + +bool ULuaState::RunCode(const TArray& Code, const FString& CodePath, int NRet) +{ + FString FullCodePath = FString("@") + CodePath; + + if (luaL_loadbuffer(L, (const char*)Code.GetData(), Code.Num(), TCHAR_TO_ANSI(*FullCodePath))) + { + LastError = FString::Printf(TEXT("Lua loading error: %s"), ANSI_TO_TCHAR(lua_tostring(L, -1))); + return false; + } + else + { + + if (lua_pcall(L, 0, NRet, 0)) + { + LastError = FString::Printf(TEXT("Lua execution error: %s"), ANSI_TO_TCHAR(lua_tostring(L, -1))); + return false; + } + } + + return true; +} + +int ULuaState::ToByteCode_Writer(lua_State* L, const void* Ptr, size_t Size, void* UserData) +{ + TArray* Output = (TArray*)UserData; + Output->Append((uint8*)Ptr, Size); + return 0; +} + +TArray ULuaState::ToByteCode(const FString& Code, const FString& CodePath, FString& ErrorString) +{ + const TCHAR* CodeRaw = *Code; + FString FullCodePath = FString("@") + CodePath; + TArray Output; + + lua_State* L = luaL_newstate(); + if (luaL_loadbuffer(L, TCHAR_TO_UTF8(CodeRaw), FCStringAnsi::Strlen(TCHAR_TO_UTF8(CodeRaw)), TCHAR_TO_ANSI(*FullCodePath))) + { + ErrorString = ANSI_TO_TCHAR(lua_tostring(L, -1)); + Output.Empty(); + lua_close(L); + return Output; + } + + if (lua_dump(L, ULuaState::ToByteCode_Writer, &Output, 1)) + { + ErrorString = ANSI_TO_TCHAR(lua_tostring(L, -1)); + Output.Empty(); + lua_close(L); + return Output; + } + + lua_close(L); + return Output; +} + +void ULuaState::FromLuaValue(FLuaValue& LuaValue, UObject* CallContext, lua_State* State) +{ + if (!State) + { + State = this->L; + } + + switch (LuaValue.Type) + { + case ELuaValueType::Bool: + lua_pushboolean(State, LuaValue.Bool ? 1 : 0); + break; + case ELuaValueType::Integer: + lua_pushinteger(State, LuaValue.Integer); + break; + case ELuaValueType::Number: + lua_pushnumber(State, LuaValue.Number); + break; + case ELuaValueType::String: + { + TArray Bytes = LuaValue.ToBytes(); + lua_pushlstring(State, (const char*)Bytes.GetData(), Bytes.Num()); + } + break; + case ELuaValueType::Table: + if (LuaValue.LuaRef == LUA_NOREF) + { + lua_newtable(State); + lua_pushvalue(State, -1); + // hold references in the main state + LuaValue.LuaRef = luaL_ref(this->L, LUA_REGISTRYINDEX); + LuaValue.LuaState = this; + break; + } + if (this != LuaValue.LuaState) + { + lua_pushnil(State); + break; + } + lua_rawgeti(this->L, LUA_REGISTRYINDEX, LuaValue.LuaRef); + if (this->L != State) + lua_xmove(this->L, State, 1); + break; + case ELuaValueType::Thread: + if (LuaValue.LuaRef == LUA_NOREF) + { + lua_newthread(State); + lua_pushvalue(State, -1); + LuaValue.LuaRef = luaL_ref(this->L, LUA_REGISTRYINDEX); + LuaValue.LuaState = this; + break; + } + if (this != LuaValue.LuaState) + { + lua_pushnil(State); + break; + } + lua_rawgeti(this->L, LUA_REGISTRYINDEX, LuaValue.LuaRef); + if (this->L != State) + lua_xmove(this->L, State, 1); + break; + case ELuaValueType::Function: + if (this != LuaValue.LuaState || LuaValue.LuaRef == LUA_NOREF) + { + lua_pushnil(State); + break; + } + lua_rawgeti(this->L, LUA_REGISTRYINDEX, LuaValue.LuaRef); + if (this->L != State) + lua_xmove(this->L, State, 1); + break; + case ELuaValueType::UObject: + { + if (!LuaValue.Object) + { + lua_pushnil(State); + break; + } + + NewUObject(LuaValue.Object, State); + if (ULuaComponent* LuaComponent = Cast(LuaValue.Object)) + { + if (!LuaComponent->LuaState) + { + UE_LOG(LogLuaMachine, Warning, TEXT("%s has no associated LuaState"), *LuaComponent->GetFullName()); + } + // ensure we are in the same LuaState + else if (LuaComponent->LuaState == GetClass()) + { + SetupAndAssignUserDataMetatable(LuaComponent, LuaComponent->Metatable, State); + } + } + else if (ULuaUserDataObject* LuaUserDataObject = Cast(LuaValue.Object)) + { + if (!LuaUserDataObject->GetLuaState()) + { + UE_LOG(LogLuaMachine, Warning, TEXT("%s has no associated LuaState"), *LuaUserDataObject->GetFullName()); + } + // ensure we are in the same LuaState + else if (LuaUserDataObject->GetLuaState() == GetClass()) + { + SetupAndAssignUserDataMetatable(LuaUserDataObject, LuaUserDataObject->Metatable, State); + } + } + else + { + if (UserDataMetaTable.Type == ELuaValueType::Table) + { + FromLuaValue(UserDataMetaTable, nullptr, State); + } + else + { + lua_newtable(State); + // allow comparison between userdata/UObject/UFunction + lua_pushcfunction(State, ULuaState::MetaTableFunctionUserData__eq); + lua_setfield(State, -2, "__eq"); + } + lua_setmetatable(State, -2); + } + } + break; + case ELuaValueType::UFunction: + // if no context is assigned to the function, own it ! + if (!LuaValue.LuaState.IsValid()) + { + LuaValue.LuaState = this; + } + if (this != LuaValue.LuaState) + { + lua_pushnil(State); + break; + } + // first time we should have a CallContext, then we cache it in the Object field + if (!CallContext) + { + CallContext = LuaValue.Object; + } + if (CallContext) + { + UObject* FunctionOwner = CallContext; + if (ULuaComponent* LuaComponent = Cast(CallContext)) + { + FunctionOwner = LuaComponent->GetOwner(); + } + + if (FunctionOwner) + { + UFunction* Function = FunctionOwner->FindFunction(LuaValue.FunctionName); + if (Function) + { + // cache it for context-less calls + LuaValue.Object = CallContext; + FLuaUserData* LuaCallContext = (FLuaUserData*)lua_newuserdata(State, sizeof(FLuaUserData)); + LuaCallContext->Type = ELuaValueType::UFunction; + LuaCallContext->Context = CallContext; + LuaCallContext->Function = Function; + lua_newtable(State); + lua_pushcfunction(State, bRawLuaFunctionCall ? ULuaState::MetaTableFunction__rawcall : ULuaState::MetaTableFunction__call); + lua_setfield(State, -2, "__call"); + lua_setmetatable(State, -2); + return; + } + } + } + // no function found + lua_pushnil(State); + break; + case ELuaValueType::MulticastDelegate: + // if no context is assigned to the function, own it ! + if (!LuaValue.LuaState.IsValid()) + { + LuaValue.LuaState = this; + } + + if (this != LuaValue.LuaState) + { + lua_pushnil(State); + break; + } + { + FLuaUserData* LuaCallContext = (FLuaUserData*)lua_newuserdata(State, sizeof(FLuaUserData)); + LuaCallContext->Type = ELuaValueType::MulticastDelegate; + LuaCallContext->Function = reinterpret_cast(LuaValue.Object); + LuaCallContext->MulticastScriptDelegate = LuaValue.MulticastScriptDelegate; + lua_newtable(State); + lua_pushcfunction(State, bRawLuaFunctionCall ? ULuaState::MetaTableFunction__rawbroadcast : ULuaState::MetaTableFunction__rawbroadcast); + lua_setfield(State, -2, "__call"); + lua_setmetatable(State, -2); + return; + } + break; + default: + lua_pushnil(State); + } +} + +FLuaValue ULuaState::ToLuaValue(int Index, lua_State* State) +{ + if (!State) + { + State = this->L; + } + + FLuaValue LuaValue; + + if (lua_isboolean(State, Index)) + { + LuaValue = FLuaValue(lua_toboolean(State, Index) != 0); + } + else if (lua_type(State, Index) == LUA_TSTRING) + { + size_t StringLength = 0; + const char* String = lua_tolstring(State, Index, &StringLength); + LuaValue = FLuaValue(String, StringLength); + } + else if (lua_isinteger(State, Index)) + { + LuaValue = FLuaValue(static_cast(lua_tointeger(State, Index))); + } + else if (lua_type(State, Index) == LUA_TNUMBER) + { + LuaValue = FLuaValue(static_cast(lua_tonumber(State, Index))); + } + else if (lua_istable(State, Index)) + { + lua_pushvalue(State, Index); + if (State != this->L) + lua_xmove(State, this->L, 1); + LuaValue.Type = ELuaValueType::Table; + LuaValue.LuaState = this; + LuaValue.LuaRef = luaL_ref(this->L, LUA_REGISTRYINDEX); + } + else if (lua_isthread(State, Index)) + { + lua_pushvalue(State, Index); + if (State != this->L) + lua_xmove(State, this->L, 1); + LuaValue.Type = ELuaValueType::Thread; + LuaValue.LuaState = this; + LuaValue.LuaRef = luaL_ref(this->L, LUA_REGISTRYINDEX); + } + else if (lua_isfunction(State, Index)) + { + lua_pushvalue(State, Index); + if (State != this->L) + lua_xmove(State, this->L, 1); + LuaValue.Type = ELuaValueType::Function; + LuaValue.LuaState = this; + LuaValue.LuaRef = luaL_ref(this->L, LUA_REGISTRYINDEX); + } + else if (lua_isuserdata(State, Index)) + { + FLuaUserData* UserData = (FLuaUserData*)lua_touserdata(State, Index); + switch (UserData->Type) + { + case(ELuaValueType::UObject): + if (UserData->Context.IsValid()) + { + LuaValue.Type = UserData->Type; + LuaValue.Object = UserData->Context.Get(); + LuaValue.LuaState = this; + } + break; + case(ELuaValueType::UFunction): + if (UserData->Context.IsValid() && UserData->Function.IsValid()) + { + LuaValue.Type = UserData->Type; + LuaValue.FunctionName = UserData->Function->GetFName(); + LuaValue.Object = UserData->Context.Get(); + LuaValue.LuaState = this; + } + break; + } + } + + return LuaValue; +} + +int32 ULuaState::GetTop() +{ + return lua_gettop(L); +} + +int ULuaState::MetaTableFunctionUserData__index(lua_State* L) +{ + + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + FLuaUserData* UserData = (FLuaUserData*)lua_touserdata(L, 1); + + if (!UserData->Context.IsValid()) + { + return luaL_error(L, "invalid UObject for UserData %p", UserData); + } + + TMap* TablePtr = nullptr; + UObject* Context = UserData->Context.Get(); + + ULuaUserDataObject* LuaUserDataObject = nullptr; + ULuaComponent* LuaComponent = nullptr; + + FString Key = ANSI_TO_TCHAR(lua_tostring(L, 2)); + + LuaComponent = Cast(Context); + + if (LuaComponent) + { + TablePtr = &LuaComponent->Table; + } + else + { + LuaUserDataObject = Cast(Context); + if (LuaUserDataObject) + { + TablePtr = &LuaUserDataObject->Table; + } + } + + if (TablePtr) + { + FLuaValue* LuaValue = TablePtr->Find(Key); + if (LuaValue) + { + LuaState->FromLuaValue(*LuaValue, Context, L); + return 1; + + } + } + + if (LuaComponent) + { + FLuaValue MetaIndexReturnValue = LuaComponent->ReceiveLuaMetaIndex(Key); + LuaState->FromLuaValue(MetaIndexReturnValue, Context, L); + return 1; + } + + if (LuaUserDataObject) + { + FLuaValue MetaIndexReturnValue = LuaUserDataObject->ReceiveLuaMetaIndex(Key); + LuaState->FromLuaValue(MetaIndexReturnValue, MetaIndexReturnValue.Object ? MetaIndexReturnValue.Object : Context, L); + return 1; + } + + lua_pushnil(L); + return 1; +} + +int ULuaState::MetaTableFunctionUserData__newindex(lua_State* L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + FLuaUserData* UserData = (FLuaUserData*)lua_touserdata(L, 1); + if (!UserData->Context.IsValid()) + { + return luaL_error(L, "invalid UObject for UserData %p", UserData); + } + + TMap* TablePtr = nullptr; + UObject* Context = UserData->Context.Get(); + + ULuaComponent* LuaComponent = Cast(Context); + + if (LuaComponent) + { + TablePtr = &LuaComponent->Table; + } + else if (ULuaUserDataObject* LuaUserDataObject = Cast(Context)) + { + TablePtr = &LuaUserDataObject->Table; + } + + if (TablePtr) + { + FString Key = ANSI_TO_TCHAR(lua_tostring(L, 2)); + + FLuaValue* LuaValue = TablePtr->Find(Key); + if (LuaValue) + { + *LuaValue = LuaState->ToLuaValue(3, L); + } + else + { + if (LuaComponent) + { + if (LuaComponent->ReceiveLuaMetaNewIndex(LuaState->ToLuaValue(2, L), LuaState->ToLuaValue(3, L))) + { + return 0; + } + } + TablePtr->Add(Key, LuaState->ToLuaValue(3, L)); + } + } + + return 0; +} + +FLuaDebug ULuaState::LuaGetInfo(int32 Level) +{ + lua_Debug ar; + if (lua_getstack(L, Level, &ar) != 1) + return FLuaDebug(); + lua_getinfo(L, "lSn", &ar); + FLuaDebug LuaDebug; + LuaDebug.CurrentLine = ar.currentline; + LuaDebug.Source = ANSI_TO_TCHAR(ar.source); + LuaDebug.Name = ANSI_TO_TCHAR(ar.name); + LuaDebug.NameWhat = ANSI_TO_TCHAR(ar.namewhat); + LuaDebug.What = ANSI_TO_TCHAR(ar.what); + + return LuaDebug; +} + +TMap ULuaState::LuaGetLocals(int32 Level) +{ + TMap ReturnValue; + + lua_Debug ar; + if (lua_getstack(L, Level, &ar) != 1) + return ReturnValue; + + int Index = 1; + const char* name = lua_getlocal(L, &ar, Index); + while (name) + { + FLuaValue LuaValue = ToLuaValue(-1); + ReturnValue.Add(ANSI_TO_TCHAR(name), LuaValue); + Pop(); + name = lua_getlocal(L, &ar, ++Index); + } + return ReturnValue; +} + +void ULuaState::Debug_Hook(lua_State* L, lua_Debug* ar) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + FLuaDebug LuaDebug; + lua_getinfo(L, "lSn", ar); + LuaDebug.CurrentLine = ar->currentline; + LuaDebug.Source = ANSI_TO_TCHAR(ar->source); + LuaDebug.Name = ANSI_TO_TCHAR(ar->name); + LuaDebug.NameWhat = ANSI_TO_TCHAR(ar->namewhat); + LuaDebug.What = ANSI_TO_TCHAR(ar->what); + + switch (ar->event) + { + case LUA_HOOKLINE: + LuaState->ReceiveLuaLineHook(LuaDebug); + break; + case LUA_HOOKCALL: + LuaState->ReceiveLuaCallHook(LuaDebug); + break; + case LUA_HOOKRET: + LuaState->ReceiveLuaReturnHook(LuaDebug); + break; + case LUA_HOOKCOUNT: + LuaState->ReceiveLuaCountHook(LuaDebug); + break; + default: + break; + } +} + +int ULuaState::MetaTableFunctionUserData__eq(lua_State* L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + + FLuaUserData* UserData = (FLuaUserData*)lua_touserdata(L, 1); + if (!UserData->Context.IsValid()) + { + return luaL_error(L, "invalid UObject for UserData %p", UserData); + } + + FLuaUserData* UserData2 = (FLuaUserData*)lua_touserdata(L, 2); + if (!UserData2->Context.IsValid()) + { + return luaL_error(L, "invalid UObject for UserData %p", UserData2); + } + + if (UserData->Type == UserData2->Type && UserData->Context.Get() == UserData2->Context.Get()) + { + if (UserData->Type == ELuaValueType::UFunction) + { + if (!UserData->Function.IsValid()) + { + return luaL_error(L, "invalid UFunction for UserData %p", UserData); + } + if (!UserData2->Function.IsValid()) + { + return luaL_error(L, "invalid UFunction for UserData %p", UserData2); + } + if (UserData->Function.Get() == UserData2->Function.Get()) + { + lua_pushboolean(L, 1); + return 1; + } + } + else if (UserData->Type == ELuaValueType::UObject) + { + lua_pushboolean(L, 1); + return 1; + } + } + + lua_pushboolean(L, 0); + return 1; +} + +int ULuaState::MetaTableFunctionUserData__gc(lua_State* L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + + FLuaUserData* UserData = (FLuaUserData*)lua_touserdata(L, 1); + if (!UserData->Context.IsValid()) + { + return luaL_error(L, "invalid UObject for UserData %p", UserData); + } + + ULuaUserDataObject* LuaUserDataObject = Cast(UserData->Context.Get()); + if (LuaUserDataObject) + { + LuaState->TrackedLuaUserDataObjects.Remove(LuaUserDataObject); + LuaUserDataObject->ReceiveLuaGC(); + } + + lua_pushnil(L); + return 1; +} + +int ULuaState::MetaTableFunction__call(lua_State* L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + FLuaUserData* LuaCallContext = (FLuaUserData*)lua_touserdata(L, 1); + + if (!LuaCallContext->Context.IsValid() || !LuaCallContext->Function.IsValid()) + { + return luaL_error(L, "invalid lua UFunction for UserData %p", LuaCallContext); + } + + int NArgs = lua_gettop(L); + + UObject* CallScope = LuaCallContext->Context.Get(); + bool bImplicitSelf = false; + int StackPointer = 2; + + if (ULuaComponent* LuaComponent = Cast(CallScope)) + { + CallScope = LuaComponent->GetOwner(); + if (NArgs > 0) + { + FLuaValue LuaFirstArgument = LuaState->ToLuaValue(StackPointer, L); + if (LuaFirstArgument.Type == ELuaValueType::UObject && LuaFirstArgument.Object == LuaComponent) + { + bImplicitSelf = LuaComponent->bImplicitSelf; + } + } + } + else if (ULuaUserDataObject* LuaUserDataObject = Cast(CallScope)) + { + if (NArgs > 0) + { + FLuaValue LuaFirstArgument = LuaState->ToLuaValue(StackPointer, L); + if (LuaFirstArgument.Type == ELuaValueType::UObject && LuaFirstArgument.Object == LuaUserDataObject) + { + bImplicitSelf = LuaUserDataObject->bImplicitSelf; + } + } + } + + FScopeCycleCounterUObject ObjectScope(CallScope); + FScopeCycleCounterUObject FunctionScope(LuaCallContext->Function.Get()); + + void* Parameters = FMemory_Alloca(LuaCallContext->Function->ParmsSize); + FMemory::Memzero(Parameters, LuaCallContext->Function->ParmsSize); + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) + { + FProperty* Prop = *It; +#else + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) + { + UProperty* Prop = *It; +#endif + if (!Prop->HasAnyPropertyFlags(CPF_ZeroConstructor)) + { + Prop->InitializeValue_InContainer(Parameters); + } + } + + if (bImplicitSelf) + { + NArgs--; + StackPointer++; + } + + // arguments +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs && ((FArgs->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++FArgs) + { + FProperty* Prop = *FArgs; + FStructProperty* LuaProp = CastField(Prop); +#else + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs && ((FArgs->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++FArgs) + { + UProperty* Prop = *FArgs; + UStructProperty* LuaProp = Cast(Prop); +#endif + if (!LuaProp) + { +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FArrayProperty* ArrayProp = CastField(Prop); + if (ArrayProp) + { + LuaProp = CastField(ArrayProp->Inner); +#else + UArrayProperty* ArrayProp = Cast(Prop); + if (ArrayProp) + { + LuaProp = Cast(ArrayProp->Inner); +#endif + if (!LuaProp) + { + break; + } + if (LuaProp->Struct != FLuaValue::StaticStruct()) + { + break; + } + // start filling the array with the rest of arguments + int ArgsToProcess = NArgs - StackPointer + 1; + if (ArgsToProcess < 1) + { + break; + } + FScriptArrayHelper_InContainer ArrayHelper(ArrayProp, LuaProp->ContainerPtrToValuePtr(Parameters)); + ArrayHelper.AddValues(ArgsToProcess); + for (int i = StackPointer; i < StackPointer + ArgsToProcess; i++) + { + FLuaValue LuaValue = LuaState->ToLuaValue(i, L); + *LuaProp->ContainerPtrToValuePtr(ArrayHelper.GetRawPtr(i - StackPointer)) = LuaValue; + } + } + break; + } + if (LuaProp->Struct != FLuaValue::StaticStruct()) + { + break; + } + + FLuaValue LuaValue = LuaState->ToLuaValue(StackPointer++, L); + *LuaProp->ContainerPtrToValuePtr(Parameters) = LuaValue; + } + + LuaState->InceptionLevel++; + CallScope->ProcessEvent(LuaCallContext->Function.Get(), Parameters); + check(LuaState->InceptionLevel > 0); + LuaState->InceptionLevel--; + + if (LuaState->InceptionLevel == 0) + { + FString Error; + while (LuaState->InceptionErrors.Dequeue(Error)) + { + ULuaComponent* LuaComponent = Cast(LuaCallContext->Context); + if (LuaComponent) + { + if (LuaComponent->bLogError) + { + LuaState->LogError(Error); + } + LuaComponent->OnLuaError.Broadcast(Error); + } + else + { + if (LuaState->bLogError) + { + LuaState->LogError(Error); + } + LuaState->ReceiveLuaError(Error); + } + } + } + + int ReturnedValues = 0; + + // get return value +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs; ++FArgs) + { + FProperty* Prop = *FArgs; +#else + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs; ++FArgs) + { + UProperty* Prop = *FArgs; +#endif + if (!Prop->HasAnyPropertyFlags(CPF_ReturnParm | CPF_OutParm)) + { + continue; + } + + // avoid input args (at all costs !) + if (Prop->HasAnyPropertyFlags(CPF_ConstParm | CPF_ReferenceParm)) + { + continue; + } +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FStructProperty* LuaProp = CastField(Prop); + if (!LuaProp) + { + FArrayProperty* ArrayProp = CastField(Prop); + if (ArrayProp) + { + LuaProp = CastField(ArrayProp->Inner); +#else + UStructProperty* LuaProp = Cast(Prop); + if (!LuaProp) + { + UArrayProperty* ArrayProp = Cast(Prop); + if (ArrayProp) + { + LuaProp = Cast(ArrayProp->Inner); +#endif + if (!LuaProp) + break; + if (LuaProp->Struct != FLuaValue::StaticStruct()) + break; + + FScriptArrayHelper_InContainer ArrayHelper(ArrayProp, LuaProp->ContainerPtrToValuePtr(Parameters)); + for (int i = 0; i < ArrayHelper.Num(); i++) + { + FLuaValue* LuaValue = LuaProp->ContainerPtrToValuePtr(ArrayHelper.GetRawPtr(i)); + ReturnedValues++; + LuaState->FromLuaValue(*LuaValue, nullptr, L); + } + + + } + break; + } + + if (LuaProp->Struct != FLuaValue::StaticStruct()) + break; + + FLuaValue* LuaValue = LuaProp->ContainerPtrToValuePtr(Parameters); + if (LuaValue) + { + ReturnedValues++; + LuaState->FromLuaValue(*LuaValue, nullptr, L); + } + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) +#else + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) +#endif + { + It->DestroyValue_InContainer(Parameters); + } + + + if (ReturnedValues > 0) + return ReturnedValues; + + lua_pushnil(L); + return 1; +} + +int ULuaState::MetaTableFunction__rawcall(lua_State * L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + FLuaUserData* LuaCallContext = (FLuaUserData*)lua_touserdata(L, 1); + + if (!LuaCallContext->Context.IsValid() || !LuaCallContext->Function.IsValid()) + { + return luaL_error(L, "invalid lua UFunction for UserData %p", LuaCallContext); + } + + int NArgs = lua_gettop(L); + + UObject* CallScope = LuaCallContext->Context.Get(); + bool bImplicitSelf = false; + int StackPointer = 2; + + if (ULuaComponent* LuaComponent = Cast(CallScope)) + { + CallScope = LuaComponent->GetOwner(); + if (NArgs > 0) + { + FLuaValue LuaFirstArgument = LuaState->ToLuaValue(StackPointer, L); + if (LuaFirstArgument.Type == ELuaValueType::UObject && LuaFirstArgument.Object == LuaComponent) + { + bImplicitSelf = LuaComponent->bImplicitSelf; + } + } + } + else if (ULuaUserDataObject* LuaUserDataObject = Cast(CallScope)) + { + if (NArgs > 0) + { + FLuaValue LuaFirstArgument = LuaState->ToLuaValue(StackPointer, L); + if (LuaFirstArgument.Type == ELuaValueType::UObject && LuaFirstArgument.Object == LuaUserDataObject) + { + bImplicitSelf = LuaUserDataObject->bImplicitSelf; + } + } + } + + FScopeCycleCounterUObject ObjectScope(CallScope); + FScopeCycleCounterUObject FunctionScope(LuaCallContext->Function.Get()); + + void* Parameters = FMemory_Alloca(LuaCallContext->Function->ParmsSize); + FMemory::Memzero(Parameters, LuaCallContext->Function->ParmsSize); + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) + { + FProperty* Prop = *It; +#else + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) + { + UProperty* Prop = *It; +#endif + if (!Prop->HasAnyPropertyFlags(CPF_ZeroConstructor)) + { + Prop->InitializeValue_InContainer(Parameters); + } + } + + if (bImplicitSelf) + { + NArgs--; + StackPointer++; + } + + // arguments +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs && ((FArgs->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++FArgs) + { + FProperty* Prop = *FArgs; +#else + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs && ((FArgs->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++FArgs) + { + UProperty* Prop = *FArgs; +#endif + bool bPropertySet = false; + LuaState->ToProperty(Parameters, Prop, LuaState->ToLuaValue(StackPointer++, L), bPropertySet, 0); + } + + LuaState->InceptionLevel++; + CallScope->ProcessEvent(LuaCallContext->Function.Get(), Parameters); + check(LuaState->InceptionLevel > 0); + LuaState->InceptionLevel--; + + if (LuaState->InceptionLevel == 0) + { + FString Error; + while (LuaState->InceptionErrors.Dequeue(Error)) + { + ULuaComponent* LuaComponent = Cast(LuaCallContext->Context); + if (LuaComponent) + { + if (LuaComponent->bLogError) + { + LuaState->LogError(Error); + } + LuaComponent->OnLuaError.Broadcast(Error); + } + else + { + if (LuaState->bLogError) + { + LuaState->LogError(Error); + } + LuaState->ReceiveLuaError(Error); + } + } + } + + int ReturnedValues = 0; + + // get return value +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs; ++FArgs) + { + FProperty* Prop = *FArgs; +#else + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs; ++FArgs) + { + UProperty* Prop = *FArgs; +#endif + if (!Prop->HasAnyPropertyFlags(CPF_ReturnParm | CPF_OutParm)) + { + continue; + } + + // avoid input args (at all costs !) + if (Prop->HasAnyPropertyFlags(CPF_ConstParm | CPF_ReferenceParm)) + { + continue; + } + + bool bPropertyGet = false; + FLuaValue LuaValue = LuaState->FromProperty(Parameters, Prop, bPropertyGet, 0); + ReturnedValues++; + LuaState->FromLuaValue(LuaValue, nullptr, L); + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) +#else + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) +#endif + { + It->DestroyValue_InContainer(Parameters); + } + + if (ReturnedValues > 0) + { + return ReturnedValues; + } + + lua_pushnil(L); + return 1; +} + +int ULuaState::MetaTableFunction__rawbroadcast(lua_State * L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + FLuaUserData* LuaCallContext = (FLuaUserData*)lua_touserdata(L, 1); + + if (!LuaCallContext->MulticastScriptDelegate || !LuaCallContext->Function.IsValid()) + { + return luaL_error(L, "invalid lua Multicast Delegate for UserData %p", LuaCallContext); + } + + int NArgs = lua_gettop(L); + int StackPointer = 2; + + FScopeCycleCounterUObject FunctionScope(LuaCallContext->Function.Get()); + + void* Parameters = FMemory_Alloca(LuaCallContext->Function->ParmsSize); + FMemory::Memzero(Parameters, LuaCallContext->Function->ParmsSize); + + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) + { + FProperty* Prop = *It; + if (!Prop->HasAnyPropertyFlags(CPF_ZeroConstructor)) + { + Prop->InitializeValue_InContainer(Parameters); + } + } + + // arguments + for (TFieldIterator FArgs(LuaCallContext->Function.Get()); FArgs && ((FArgs->PropertyFlags & (CPF_Parm | CPF_ReturnParm)) == CPF_Parm); ++FArgs) + { + FProperty* Prop = *FArgs; + bool bPropertySet = false; + LuaState->ToProperty(Parameters, Prop, LuaState->ToLuaValue(StackPointer++, L), bPropertySet, 0); + } + + LuaState->InceptionLevel++; + LuaCallContext->MulticastScriptDelegate->ProcessMulticastDelegate(Parameters); + check(LuaState->InceptionLevel > 0); + LuaState->InceptionLevel--; + + if (LuaState->InceptionLevel == 0) + { + FString Error; + while (LuaState->InceptionErrors.Dequeue(Error)) + { + if (LuaState->bLogError) + { + LuaState->LogError(Error); + } + LuaState->ReceiveLuaError(Error); + } + } + + // no return values in multicast delegates + for (TFieldIterator It(LuaCallContext->Function.Get()); (It && It->HasAnyPropertyFlags(CPF_Parm)); ++It) + { + It->DestroyValue_InContainer(Parameters); + } + + lua_pushnil(L); + return 1; +} + +int ULuaState::TableFunction_print(lua_State * L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + TArray Messages; + + int n = lua_gettop(L); + lua_getglobal(L, "tostring"); + for (int i = 1; i <= n; i++) + { + lua_pushvalue(L, -1); + lua_pushvalue(L, i); + lua_call(L, 1, 1); + const char* s = lua_tostring(L, -1); + if (!s) + return luaL_error(L, "'tostring must return a string to 'print'"); + FString Value = ANSI_TO_TCHAR(s); + lua_pop(L, 1); + Messages.Add(Value); + } + LuaState->Log(FString::Join(Messages, TEXT("\t"))); + return 0; +} + +int ULuaState::TableFunction_package_loader_codeasset(lua_State * L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + + // use the second (sanitized by the loader) argument + FString Key = ANSI_TO_TCHAR(lua_tostring(L, 2)); + + FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry")); +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 0 + FAssetData AssetData = AssetRegistryModule.Get().GetAssetByObjectPath(Key); + if (AssetData.IsValid() && AssetData.AssetClassPath.ToString() == "LuaCode") +#else + FAssetData AssetData = AssetRegistryModule.Get().GetAssetByObjectPath(*Key); + if (AssetData.IsValid() && AssetData.AssetClass == "LuaCode") +#endif + { + ULuaCode* LuaCode = Cast(AssetData.GetAsset()); + if (LuaCode) + { + if (!LuaState->RunCodeAsset(LuaCode, 1)) + { + return luaL_error(L, "%s", lua_tostring(L, -1)); + } + return 1; + } + } + + return luaL_error(L, "unable to load asset '%s'", TCHAR_TO_UTF8(*Key)); +} + +int ULuaState::TableFunction_package_loader_asset(lua_State * L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + + // use the second (sanitized by the loader) argument + const FString Key = ANSI_TO_TCHAR(lua_tostring(L, 2)); + + if (LuaState->RunFile(Key, true, 1)) + { + return 1; + } + return luaL_error(L, "%s", lua_tostring(L, -1)); +} + +int ULuaState::TableFunction_package_loader(lua_State * L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + + FString Key = ANSI_TO_TCHAR(lua_tostring(L, 1)); + + // check for code assets + if (FPackageName::IsValidObjectPath(Key)) + { + // fix asset name (if required) + int32 LastSlashIndex = -1; + Key.FindLastChar('/', LastSlashIndex); + const FString LastPart = Key.RightChop(LastSlashIndex + 1); + if (!LastPart.Contains(".")) + { + Key = FString::Printf(TEXT("%s.%s"), *Key, *LastPart); + } + + lua_pushcfunction(L, ULuaState::TableFunction_package_loader_codeasset); + lua_pushstring(L, TCHAR_TO_UTF8(*Key)); + return 2; + } + else + { + // TODO: make it smarter by checking for file extension... + if (!Key.EndsWith(".lua")) + { + Key += ".lua"; + } + // search in root content... + FString AbsoluteFilename = FPaths::Combine(FPaths::ProjectContentDir(), Key); + if (FPaths::FileExists(AbsoluteFilename)) + { + lua_pushcfunction(L, ULuaState::TableFunction_package_loader_asset); + lua_pushstring(L, TCHAR_TO_UTF8(*Key)); + return 2; + } + else + { + // or search in additional paths + for (FString AdditionalPath : LuaState->AppendProjectContentDirSubDir) + { + AbsoluteFilename = FPaths::Combine(FPaths::ProjectContentDir(), AdditionalPath, Key); + if (FPaths::FileExists(AbsoluteFilename)) + { + lua_pushcfunction(L, ULuaState::TableFunction_package_loader_asset); + lua_pushstring(L, TCHAR_TO_UTF8(*(AdditionalPath / Key))); + return 2; + } + } + } + } + + // use UTF8 as the package name can contains non-ASCII chars + lua_pushstring(L, TCHAR_TO_UTF8(*FString::Printf(TEXT("\n\tno asset '%s'"), *Key))); + return 1; +} + +int ULuaState::TableFunction_package_preload(lua_State * L) +{ + ULuaState* LuaState = ULuaState::GetFromExtraSpace(L); + + if (LuaState->L != L) + return luaL_error(L, "you cannot call package.preload from a thread/coroutine (error while loading %s)", lua_tostring(L, 1)); + + FString Key = ANSI_TO_TCHAR(lua_tostring(L, 1)); + + // check for code assets + ULuaCode** LuaCodePtr = LuaState->RequireTable.Find(Key); + if (!LuaCodePtr) + { + if (LuaState->bAddProjectContentDirToPackagePath && LuaState->RunFile(Key + ".lua", true, 1)) + { + return 1; + } + return luaL_error(L, "%s", lua_tostring(L, -1)); + + // now search in additional paths + for (FString AdditionalPath : LuaState->AppendProjectContentDirSubDir) + { + if (LuaState->RunFile(AdditionalPath / Key + ".lua", true, 1)) + { + return 1; + } + return luaL_error(L, "%s", lua_tostring(L, -1)); + + } + return luaL_error(L, "unable to find package %s", TCHAR_TO_ANSI(*Key)); + } + + ULuaCode* LuaCode = *LuaCodePtr; + if (!LuaCode) + { + return luaL_error(L, "LuaCodeAsset not set for package %s", TCHAR_TO_ANSI(*Key)); + } + + if (!LuaState->RunCodeAsset(LuaCode, 1)) + { + return luaL_error(L, "%s", lua_tostring(L, -1)); + } + + return 1; +} + +void ULuaState::ReceiveLuaError_Implementation(const FString & Message) +{ + +} + +void ULuaState::ReceiveLuaCallHook_Implementation(const FLuaDebug & LuaDebug) +{ + +} + +void ULuaState::ReceiveLuaReturnHook_Implementation(const FLuaDebug & LuaDebug) +{ + +} + +void ULuaState::ReceiveLuaLineHook_Implementation(const FLuaDebug & LuaDebug) +{ + +} + +void ULuaState::ReceiveLuaCountHook(const FLuaDebug & LuaDebug) +{ + +} + +void ULuaState::ReceiveLuaLevelRemovedFromWorld_Implementation(ULevel * Level, UWorld * World) +{ + +} + +void ULuaState::ReceiveLuaLevelAddedToWorld_Implementation(ULevel * Level, UWorld * World) +{ + +} + +void ULuaState::ReceiveLuaStatePreInitialized_Implementation() +{ + +} + +void ULuaState::ReceiveLuaStateInitialized_Implementation() +{ + +} + +void ULuaState::NewTable() +{ + lua_newtable(L); +} + +void ULuaState::SetMetaTable(int Index) +{ + lua_setmetatable(L, Index); +} + +void ULuaState::GetMetaTable(int Index) +{ + lua_getmetatable(L, Index); +} + +void ULuaState::SetField(int Index, const char* FieldName) +{ + lua_setfield(L, Index, FieldName); +} + +void ULuaState::GetField(int Index, const char* FieldName) +{ + lua_getfield(L, Index, FieldName); +} + +void ULuaState::RawGetI(int Index, int N) +{ + lua_rawgeti(L, Index, N); +} + +void ULuaState::RawSetI(int Index, int N) +{ + lua_rawseti(L, Index, N); +} + +void ULuaState::PushGlobalTable() +{ + lua_pushglobaltable(L); +} + +void ULuaState::PushRegistryTable() +{ + lua_pushvalue(L, LUA_REGISTRYINDEX); +} + +int32 ULuaState::GetFieldFromTree(const FString & Tree, bool bGlobal) +{ + TArray Parts; + Tree.ParseIntoArray(Parts, TEXT(".")); + if (Parts.Num() == 0) + { + LastError = FString::Printf(TEXT("invalid Lua key: \"%s\""), *Tree); + if (bLogError) + LogError(LastError); + ReceiveLuaError(LastError); + PushNil(); + return 1; + } + + int32 AdditionalPop = bGlobal ? 1 : 0; + + if (bGlobal) + { + PushGlobalTable(); + } + int32 i; + + for (i = 0; i < Parts.Num(); i++) + { + GetField(-1, TCHAR_TO_ANSI(*Parts[i])); + + if (lua_isnil(L, -1)) + { + if (i == Parts.Num() - 1) + { + return i + 1 + AdditionalPop; + } + LastError = FString::Printf(TEXT("Lua key \"%s\" is nil"), *Parts[i]); + if (bLogError) + LogError(LastError); + ReceiveLuaError(LastError); + return i + 1 + AdditionalPop; + } + } + return i + AdditionalPop; +} + +void ULuaState::SetFieldFromTree(const FString & Tree, FLuaValue & Value, bool bGlobal, UObject * CallContext) +{ + TArray Parts; + Tree.ParseIntoArray(Parts, TEXT(".")); + + int32 ItemsToPop = GetFieldFromTree(Tree, bGlobal); + // invalid key + if (ItemsToPop != (Parts.Num() + (bGlobal ? 1 : 0))) + { + Pop(ItemsToPop); + return; + } + + Pop(); + FromLuaValue(Value, CallContext); + SetField(-2, TCHAR_TO_ANSI(*Parts.Last())); + Pop(ItemsToPop - 1); +} + + +void ULuaState::NewUObject(UObject * Object, lua_State * State) +{ + if (!State) + { + State = this->L; + } + FLuaUserData* UserData = (FLuaUserData*)lua_newuserdata(State, sizeof(FLuaUserData)); + UserData->Type = ELuaValueType::UObject; + UserData->Context = Object; + UserData->Function = nullptr; +} + +void ULuaState::GetGlobal(const char* Name) +{ + lua_getglobal(L, Name); +} + +void ULuaState::SetGlobal(const char* Name) +{ + lua_setglobal(L, Name); +} + +void ULuaState::PushValue(int Index) +{ + lua_pushvalue(L, Index); +} + +bool ULuaState::PCall(int NArgs, FLuaValue & Value, int NRet) +{ + bool bSuccess = Call(NArgs, Value, NRet); + if (!bSuccess) + { + if (InceptionLevel > 0) + { + InceptionErrors.Enqueue(LastError); + } + else + { + if (bLogError) + LogError(LastError); + ReceiveLuaError(LastError); + } + } + return bSuccess; +} + +bool ULuaState::Call(int NArgs, FLuaValue & Value, int NRet) +{ + if (lua_pcall(L, NArgs, NRet, 0)) + { + LastError = FString::Printf(TEXT("Lua error: %s"), ANSI_TO_TCHAR(lua_tostring(L, -1))); + return false; + } + + if (NRet > 0) + { + Value = ToLuaValue(-1); + } + return true; +} + +void ULuaState::Pop(int32 Amount) +{ + lua_pop(L, Amount); +} + +void ULuaState::PushNil() +{ + lua_pushnil(L); +} + +void ULuaState::PushCFunction(lua_CFunction Function) +{ + lua_pushcfunction(L, Function); +} + +void* ULuaState::NewUserData(size_t DataSize) +{ + return lua_newuserdata(L, DataSize); +} + +void ULuaState::Unref(int Ref) +{ + luaL_unref(L, LUA_REGISTRYINDEX, Ref); +} + +void ULuaState::UnrefChecked(int Ref) +{ + // in case of moved value (like when compiling a blueprint), L should be nullptr + if (!L) + return; + + Unref(Ref); +} + +int ULuaState::NewRef() +{ + return luaL_ref(L, LUA_REGISTRYINDEX); +} + +void ULuaState::GetRef(int Ref) +{ + lua_rawgeti(L, LUA_REGISTRYINDEX, Ref); +} + +int ULuaState::Next(int Index) +{ + return lua_next(L, Index); +} + +bool ULuaState::Yield(int Index, int NArgs) +{ + lua_State* Coroutine = lua_tothread(L, Index); + if (!Coroutine) + return false; + + if (lua_status(Coroutine) == LUA_OK && lua_gettop(Coroutine) == 0) + { + lua_pushboolean(L, 0); + lua_pushstring(L, "Lua error: cannot yield a dead coroutine"); + return false; + } + + lua_xmove(L, Coroutine, NArgs); + + int Ret = lua_yield(Coroutine, NArgs); + + if (Ret != LUA_OK) + { + lua_pushboolean(L, 0); + lua_xmove(Coroutine, L, 1); + return false; + } + + int NRet = lua_gettop(Coroutine); + lua_pushboolean(L, 1); + lua_xmove(Coroutine, L, NRet); + return true; +} + +bool ULuaState::Resume(int Index, int NArgs) +{ + lua_State* Coroutine = lua_tothread(L, Index); + if (!Coroutine) + return false; + + if (lua_status(Coroutine) == LUA_OK && lua_gettop(Coroutine) == 0) + { + lua_pushboolean(L, 0); + lua_pushstring(L, "Lua error: cannot resume dead coroutine"); + return false; + } + + lua_xmove(L, Coroutine, NArgs); + int Ret = lua_resume(Coroutine, L, NArgs); + if (Ret != LUA_OK && Ret != LUA_YIELD) + { + lua_pushboolean(L, 0); + lua_xmove(Coroutine, L, 1); + return false; + } + + int NRet = lua_gettop(Coroutine); + lua_pushboolean(L, 1); + lua_xmove(Coroutine, L, NRet); + return true; +} + +int ULuaState::GC(int What, int Data) +{ + return lua_gc(L, What, Data); +} + +void ULuaState::Len(int Index) +{ + lua_len(L, Index); +} + +int32 ULuaState::ILen(int Index) +{ + return luaL_len(L, Index); +} + +int32 ULuaState::ToInteger(int Index) +{ + return lua_tointeger(L, Index); +} + +FLuaValue ULuaState::CreateLuaTable() +{ + FLuaValue NewTable; + NewTable.Type = ELuaValueType::Table; + NewTable.LuaState = this; + FromLuaValue(NewTable); + Pop(); + return NewTable; +} + +FLuaValue ULuaState::CreateLuaLazyTable() +{ + FLuaValue NewTable; + NewTable.Type = ELuaValueType::Table; + NewTable.LuaState = this; + return NewTable; +} + +FLuaValue ULuaState::CreateLuaThread(FLuaValue Value) +{ + FLuaValue NewThread; + NewThread.Type = ELuaValueType::Thread; + NewThread.LuaState = this; + FromLuaValue(NewThread); + lua_State* NewLuaThread = lua_tothread(L, -1); + FromLuaValue(Value, nullptr, NewLuaThread); + Pop(); + return NewThread; +} + +ELuaThreadStatus ULuaState::GetLuaThreadStatus(FLuaValue Value) +{ + if (Value.Type != ELuaValueType::Thread || Value.LuaState != this) + return ELuaThreadStatus::Invalid; + + FromLuaValue(Value); + lua_State* LuaThread = lua_tothread(L, -1); + int ReturnValue = lua_status(LuaThread); + Pop(); + + if (ReturnValue == 0) + return ELuaThreadStatus::Ok; + + if (ReturnValue == LUA_YIELD) + return ELuaThreadStatus::Suspended; + + return ELuaThreadStatus::Error; +} + +int32 ULuaState::GetLuaThreadStackTop(FLuaValue Value) +{ + if (Value.Type != ELuaValueType::Thread || Value.LuaState != this) + return MIN_int32; + + FromLuaValue(Value); + lua_State* LuaThread = lua_tothread(L, -1); + int ReturnValue = lua_gettop(LuaThread); + Pop(); + + return ReturnValue; +} + +TSharedRef ULuaState::AddLuaSmartReference(FLuaValue Value) +{ + TSharedRef Ref = MakeShared(); + Ref->LuaState = this; + Ref->Value = Value; + + LuaSmartReferences.Add(Ref); + + return Ref; +} + +void ULuaState::RemoveLuaSmartReference(TSharedRef Ref) +{ + LuaSmartReferences.Remove(Ref); +} + +ULuaState::~ULuaState() +{ + FCoreUObjectDelegates::GetPostGarbageCollect().Remove(GCLuaDelegatesHandle); + +#if WITH_EDITOR + if (LuaConsole.LuaState) + { + IModularFeatures::Get().UnregisterModularFeature(IConsoleCommandExecutor::ModularFeatureName(), &LuaConsole); + } +#endif + + FLuaMachineModule::Get().UnregisterLuaState(this); + + if (L) + { + lua_close(L); + L = nullptr; + } +} + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 +#define LUAVALUE_PROP_CAST(Type, Type2) F##Type* __##Type##__ = CastField(Property);\ + if (__##Type##__)\ + {\ + return FLuaValue((Type2)__##Type##__->GetPropertyValue_InContainer(Buffer, Index));\ + } + +#define LUAVALUE_PROP_CAST_TOSTRING(Type) F##Type* __##Type##__ = CastField(Property);\ + if (__##Type##__)\ + {\ + return FLuaValue(__##Type##__->GetPropertyValue_InContainer(Buffer, Index).ToString());\ + } + +#define LUAVALUE_PROP_SET(Type, Value) F##Type* __##Type##__ = CastField(Property);\ + if (__##Type##__)\ + {\ + __##Type##__->SetPropertyValue_InContainer(Buffer, Value, Index);\ + return;\ + } +#else +#define LUAVALUE_PROP_CAST(Type, Type2) U##Type* __##Type##__ = Cast(Property);\ + if (__##Type##__)\ + {\ + return FLuaValue((Type2)__##Type##__->GetPropertyValue_InContainer(Buffer, Index));\ + } + +#define LUAVALUE_PROP_CAST_TOSTRING(Type) U##Type* __##Type##__ = Cast(Property);\ + if (__##Type##__)\ + {\ + return FLuaValue(__##Type##__->GetPropertyValue_InContainer(Buffer, Index).ToString());\ + } + +#define LUAVALUE_PROP_SET(Type, Value) U##Type* __##Type##__ = Cast(Property);\ + if (__##Type##__)\ + {\ + __##Type##__->SetPropertyValue_InContainer(Buffer, Value, Index);\ + return;\ + } +#endif + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 +FLuaValue ULuaState::FromUProperty(void* Buffer, FProperty * Property, bool& bSuccess, int32 Index) +{ + return FromFProperty(Buffer, Property, bSuccess, Index); +} +void ULuaState::ToUProperty(void* Buffer, FProperty * Property, FLuaValue Value, bool& bSuccess, int32 Index) +{ + ToFProperty(Buffer, Property, Value, bSuccess, Index); +} +#endif + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 +FLuaValue ULuaState::FromFProperty(void* Buffer, FProperty * Property, bool& bSuccess, int32 Index) +#else +FLuaValue ULuaState::FromUProperty(void* Buffer, UProperty * Property, bool& bSuccess, int32 Index) +#endif +{ + bSuccess = true; + + LUAVALUE_PROP_CAST(BoolProperty, bool); + LUAVALUE_PROP_CAST(DoubleProperty, double); + LUAVALUE_PROP_CAST(FloatProperty, float); + LUAVALUE_PROP_CAST(IntProperty, int32); + LUAVALUE_PROP_CAST(UInt32Property, int32); + LUAVALUE_PROP_CAST(Int16Property, int32); + LUAVALUE_PROP_CAST(Int8Property, int32); + LUAVALUE_PROP_CAST(ByteProperty, int32); + LUAVALUE_PROP_CAST(UInt16Property, int32); + + LUAVALUE_PROP_CAST(StrProperty, FString); + LUAVALUE_PROP_CAST_TOSTRING(NameProperty); + LUAVALUE_PROP_CAST_TOSTRING(TextProperty); + + LUAVALUE_PROP_CAST(ClassProperty, UObject*); + LUAVALUE_PROP_CAST(ObjectProperty, UObject*); + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FEnumProperty* EnumProperty = CastField(Property); + + if (EnumProperty) + { + const uint8* EnumValue = EnumProperty->ContainerPtrToValuePtr(Buffer, Index); + return FLuaValue((int32)*EnumValue); + } +#endif + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FObjectPropertyBase* ObjectPropertyBase = CastField(Property); +#else + UObjectPropertyBase* ObjectPropertyBase = Cast(Property); +#endif + if (ObjectPropertyBase) + { + return FLuaValue(ObjectPropertyBase->GetObjectPropertyValue_InContainer(Buffer, Index)); + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FWeakObjectProperty* WeakObjectProperty = CastField(Property); +#else + UWeakObjectProperty* WeakObjectProperty = Cast(Property); +#endif + if (WeakObjectProperty) + { + const FWeakObjectPtr& WeakPtr = WeakObjectProperty->GetPropertyValue_InContainer(Buffer, Index); + return FLuaValue(WeakPtr.Get()); + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FMulticastDelegateProperty* MulticastProperty = CastField(Property)) +#else + if (UMulticastDelegateProperty* MulticastProperty = Cast(Property)) +#endif + { + FLuaValue MulticastValue; + MulticastValue.Type = ELuaValueType::MulticastDelegate; + MulticastValue.Object = MulticastProperty->SignatureFunction; + MulticastValue.MulticastScriptDelegate = reinterpret_cast(MulticastProperty->ContainerPtrToValuePtr(Buffer)); + return MulticastValue; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FDelegateProperty* DelegateProperty = CastField(Property)) +#else + if (UDelegateProperty* DelegateProperty = Cast(Property)) +#endif + { + const FScriptDelegate& ScriptDelegate = DelegateProperty->GetPropertyValue_InContainer(Buffer, Index); + return FLuaValue::FunctionOfObject((UObject*)ScriptDelegate.GetUObject(), ScriptDelegate.GetFunctionName()); + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FArrayProperty* ArrayProperty = CastField(Property)) +#else + if (UArrayProperty* ArrayProperty = Cast(Property)) +#endif + { + FLuaValue NewLuaArray = CreateLuaTable(); + FScriptArrayHelper_InContainer Helper(ArrayProperty, Buffer, Index); + for (int32 ArrayIndex = 0; ArrayIndex < Helper.Num(); ArrayIndex++) + { + uint8* ArrayItemPtr = Helper.GetRawPtr(ArrayIndex); + bool bArrayItemSuccess = false; + NewLuaArray.SetFieldByIndex(ArrayIndex + 1, FromProperty(ArrayItemPtr, ArrayProperty->Inner, bArrayItemSuccess, 0)); + } + return NewLuaArray; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FMapProperty* MapProperty = CastField(Property)) +#else + if (UMapProperty* MapProperty = Cast(Property)) +#endif + { + FLuaValue NewLuaTable = CreateLuaTable(); + FScriptMapHelper_InContainer Helper(MapProperty, Buffer, Index); + for (int32 MapIndex = 0; MapIndex < Helper.Num(); MapIndex++) + { + uint8* ArrayKeyPtr = Helper.GetKeyPtr(MapIndex); + uint8* ArrayValuePtr = Helper.GetValuePtr(MapIndex); + bool bArrayItemSuccess = false; + NewLuaTable.SetField( + FromProperty(ArrayKeyPtr, MapProperty->KeyProp, bArrayItemSuccess, 0).ToString(), + FromProperty(ArrayValuePtr, MapProperty->ValueProp, bArrayItemSuccess, 0)); + } + return NewLuaTable; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FSetProperty* SetProperty = CastField(Property)) +#else + if (USetProperty* SetProperty = Cast(Property)) +#endif + { + FLuaValue NewLuaArray = CreateLuaTable(); + FScriptSetHelper_InContainer Helper(SetProperty, Buffer, Index); + for (int32 SetIndex = 0; SetIndex < Helper.Num(); SetIndex++) + { + uint8* ArrayItemPtr = Helper.GetElementPtr(SetIndex); + bool bArrayItemSuccess = false; + NewLuaArray.SetFieldByIndex(SetIndex + 1, FromProperty(ArrayItemPtr, SetProperty->ElementProp, bArrayItemSuccess, 0)); + } + return NewLuaArray; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FStructProperty* StructProperty = CastField(Property)) +#else + if (UStructProperty* StructProperty = Cast(Property)) +#endif + { + // fast path + if (StructProperty->Struct == FLuaValue::StaticStruct()) + { + FLuaValue* LuaValuePtr = StructProperty->ContainerPtrToValuePtr(Buffer); + // trick for allowing lazy tables creation + FromLuaValue(*LuaValuePtr); + Pop(); + return *LuaValuePtr; + } + + const uint8* StructContainer = StructProperty->ContainerPtrToValuePtr(Buffer, Index); + + return StructToLuaTable(StructProperty->Struct, StructContainer); + } + + bSuccess = false; + return FLuaValue(); +} + +FLuaValue ULuaState::StructToLuaTable(UScriptStruct * InScriptStruct, const uint8 * StructData) +{ + FLuaValue NewLuaTable = CreateLuaTable(); +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator It(InScriptStruct); It; ++It) +#else + for (TFieldIterator It(InScriptStruct); It; ++It) +#endif + { +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FProperty* FieldProp = *It; +#else + UProperty* FieldProp = *It; +#endif + FString PropName = FieldProp->GetName(); + bool bTableItemSuccess = false; + NewLuaTable.SetField(PropName, FromProperty((void*)StructData, FieldProp, bTableItemSuccess, 0)); + } + return NewLuaTable; +} + +FLuaValue ULuaState::StructToLuaTable(UScriptStruct * InScriptStruct, const TArray&StructData) +{ + return StructToLuaTable(InScriptStruct, StructData.GetData()); +} + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 +void ULuaState::ToFProperty(void* Buffer, FProperty * Property, FLuaValue Value, bool& bSuccess, int32 Index) +#else +void ULuaState::ToUProperty(void* Buffer, UProperty * Property, FLuaValue Value, bool& bSuccess, int32 Index) +#endif +{ + bSuccess = true; + + LUAVALUE_PROP_SET(BoolProperty, Value.ToBool()); + LUAVALUE_PROP_SET(DoubleProperty, Value.ToFloat()); + LUAVALUE_PROP_SET(FloatProperty, Value.ToFloat()); + LUAVALUE_PROP_SET(IntProperty, Value.ToInteger()); + LUAVALUE_PROP_SET(UInt32Property, Value.ToInteger()); + LUAVALUE_PROP_SET(Int16Property, Value.ToInteger()); + LUAVALUE_PROP_SET(Int8Property, Value.ToInteger()); + LUAVALUE_PROP_SET(ByteProperty, Value.ToInteger()); + LUAVALUE_PROP_SET(UInt16Property, Value.ToInteger()); + + LUAVALUE_PROP_SET(StrProperty, Value.ToString()); + LUAVALUE_PROP_SET(NameProperty, Value.ToName()); + LUAVALUE_PROP_SET(TextProperty, FText::FromString(Value.ToString())); + + LUAVALUE_PROP_SET(ClassProperty, Value.Object); + LUAVALUE_PROP_SET(ObjectProperty, Value.Object); + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FEnumProperty* EnumProperty = CastField(Property); + + if (EnumProperty) + { + uint8* EnumValue = EnumProperty->ContainerPtrToValuePtr(Buffer, Index); + *EnumValue = Value.ToInteger(); + return; + } +#endif + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FObjectPropertyBase* ObjectPropertyBase = CastField(Property); +#else + UObjectPropertyBase* ObjectPropertyBase = Cast(Property); +#endif + if (ObjectPropertyBase) + { + ObjectPropertyBase->SetObjectPropertyValue_InContainer(Buffer, Value.Object, Index); + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FWeakObjectProperty* WeakObjectProperty = CastField(Property); +#else + UWeakObjectProperty* WeakObjectProperty = Cast(Property); +#endif + if (WeakObjectProperty) + { + FWeakObjectPtr WeakPtr(Value.Object); + WeakObjectProperty->SetPropertyValue_InContainer(Buffer, WeakPtr, Index); + return; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FMulticastDelegateProperty* MulticastProperty = CastField(Property)) +#else + if (UMulticastDelegateProperty* MulticastProperty = Cast(Property)) +#endif + { + if (Value.IsNil()) + { + UObject* Object = static_cast(Buffer); + UnregisterLuaDelegatesOfObject(Object); + MulticastProperty->ClearDelegate(Object); + return; + } + + ULuaDelegate* LuaDelegate = NewObject(); + LuaDelegate->SetupLuaDelegate(MulticastProperty->SignatureFunction, this, Value); + RegisterLuaDelegate((UObject*)Buffer, LuaDelegate); + + FScriptDelegate Delegate; + Delegate.BindUFunction(LuaDelegate, FName("LuaDelegateFunction")); + + MulticastProperty->AddDelegate(Delegate, (UObject*)Buffer); + return; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FDelegateProperty* DelegateProperty = CastField(Property)) +#else + if (UDelegateProperty* DelegateProperty = Cast(Property)) +#endif + { + if (Value.IsNil()) + { + UObject* Object = static_cast(Buffer); + UnregisterLuaDelegatesOfObject(Object); + DelegateProperty->SetPropertyValue_InContainer(Buffer, FScriptDelegate(), Index); + return; + } + + ULuaDelegate* LuaDelegate = NewObject(); + LuaDelegate->SetupLuaDelegate(DelegateProperty->SignatureFunction, this, Value); + RegisterLuaDelegate((UObject*)Buffer, LuaDelegate); + + FScriptDelegate Delegate; + Delegate.BindUFunction(LuaDelegate, FName("LuaDelegateFunction")); + + DelegateProperty->SetPropertyValue_InContainer(Buffer, Delegate, Index); + return; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FStructProperty* StructProperty = CastField(Property)) +#else + if (UStructProperty* StructProperty = Cast(Property)) +#endif + { + // fast path + if (StructProperty->Struct == FLuaValue::StaticStruct()) + { + FLuaValue* LuaValuePtr = StructProperty->ContainerPtrToValuePtr(Buffer); + *LuaValuePtr = Value; + return; + } + + const uint8* StructContainer = StructProperty->ContainerPtrToValuePtr(Buffer, Index); + LuaTableToStruct(Value, StructProperty->Struct, (uint8*)StructContainer); + return; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FArrayProperty* ArrayProperty = CastField(Property)) +#else + if (UArrayProperty* ArrayProperty = Cast(Property)) +#endif + { + FScriptArrayHelper_InContainer Helper(ArrayProperty, Buffer, Index); + TArray ArrayValues = ULuaBlueprintFunctionLibrary::LuaTableGetValues(Value); + Helper.Resize(ArrayValues.Num()); + for (int32 ArrayIndex = 0; ArrayIndex < Helper.Num(); ArrayIndex++) + { + uint8* ArrayItemPtr = Helper.GetRawPtr(ArrayIndex); + bool bArrayItemSuccess = false; + ToProperty(ArrayItemPtr, ArrayProperty->Inner, ArrayValues[ArrayIndex], bArrayItemSuccess, 0); + } + return; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FMapProperty* MapProperty = CastField(Property)) +#else + if (UMapProperty* MapProperty = Cast(Property)) +#endif + { + FScriptMapHelper_InContainer Helper(MapProperty, Buffer, Index); + Helper.EmptyValues(); + TArray TableKeys = ULuaBlueprintFunctionLibrary::LuaTableGetKeys(Value); + for (FLuaValue TableKey : TableKeys) + { + int32 NewIndex = Helper.AddUninitializedValue(); + uint8* KeyBuffer = Helper.GetKeyPtr(NewIndex); + uint8* ValueBuffer = Helper.GetValuePtr(NewIndex); + bool bTableItemSuccess = false; + ToProperty(KeyBuffer, Helper.GetKeyProperty(), TableKey, bTableItemSuccess, 0); + ToProperty(ValueBuffer, Helper.GetValueProperty(), TableKey, bTableItemSuccess, 0); + } + return; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + if (FSetProperty* SetProperty = CastField(Property)) +#else + if (USetProperty* SetProperty = Cast(Property)) +#endif + { + FScriptSetHelper_InContainer Helper(SetProperty, Buffer, Index); + TArray ArrayValues = ULuaBlueprintFunctionLibrary::LuaTableGetValues(Value); + Helper.EmptyElements(ArrayValues.Num()); + for (int32 ArrayIndex = 0; ArrayIndex < Helper.Num(); ArrayIndex++) + { + uint8* SetItemPtr = Helper.GetElementPtr(ArrayIndex); + bool bArrayItemSuccess = false; + ToProperty(SetItemPtr, SetProperty->ElementProp, ArrayValues[ArrayIndex], bArrayItemSuccess, 0); + } + return; + } + + bSuccess = false; +} + +void ULuaState::LuaTableToStruct(FLuaValue & LuaValue, UScriptStruct * InScriptStruct, uint8 * StructData) +{ + TArray TableKeys = ULuaBlueprintFunctionLibrary::LuaTableGetKeys(LuaValue); + for (FLuaValue TableKey : TableKeys) + { +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FProperty* StructProp = InScriptStruct->FindPropertyByName(TableKey.ToName()); +#else + UProperty* StructProp = InScriptStruct->FindPropertyByName(TableKey.ToName()); +#endif + if (StructProp) + { + bool bStructValueSuccess = false; + ToProperty((void*)StructData, StructProp, LuaValue.GetField(TableKey.ToString()), bStructValueSuccess, 0); + } + } +} + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 +void ULuaState::ToProperty(void* Buffer, FProperty * Property, FLuaValue Value, bool& bSuccess, int32 Index) +{ + ToFProperty(Buffer, Property, Value, bSuccess, Index); +} + +FLuaValue ULuaState::FromProperty(void* Buffer, FProperty * Property, bool& bSuccess, int32 Index) +{ + return FromFProperty(Buffer, Property, bSuccess, Index); +} +#else +void ULuaState::ToProperty(void* Buffer, UProperty * Property, FLuaValue Value, bool& bSuccess, int32 Index) +{ + ToUProperty(Buffer, Property, Value, bSuccess, Index); +} +FLuaValue ULuaState::FromProperty(void* Buffer, UProperty * Property, bool& bSuccess, int32 Index) +{ + return FromUProperty(Buffer, Property, bSuccess, Index); +} +#endif + + +FLuaValue ULuaState::GetLuaValueFromProperty(UObject * InObject, const FString & PropertyName) +{ + if (!InObject) + { + return FLuaValue(); + } + + UClass* Class = InObject->GetClass(); +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FProperty* Property = nullptr; +#else + UProperty* Property = nullptr; +#endif + Property = Class->FindPropertyByName(*PropertyName); + if (Property) + { + bool bSuccess = false; + return FromProperty(InObject, Property, bSuccess); + } + + return FLuaValue(); +} + +bool ULuaState::SetPropertyFromLuaValue(UObject * InObject, const FString & PropertyName, FLuaValue Value) +{ + if (!InObject) + { + return false; + } + + UClass* Class = InObject->GetClass(); +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FProperty* Property = nullptr; +#else + UProperty* Property = nullptr; +#endif + Property = Class->FindPropertyByName(*PropertyName); + if (Property) + { + bool bSuccess = false; + ToProperty(InObject, Property, Value, bSuccess); + return bSuccess; + } + + return false; +} + +void ULuaState::SetUserDataMetaTable(FLuaValue MetaTable) +{ + UserDataMetaTable = MetaTable; +} + +void ULuaState::SetupAndAssignUserDataMetatable(UObject * Context, TMap&Metatable, lua_State * State) +{ + if (!State) + { + State = this->L; + } + + lua_newtable(State); + lua_pushcfunction(State, ULuaState::MetaTableFunctionUserData__index); + lua_setfield(State, -2, "__index"); + lua_pushcfunction(State, ULuaState::MetaTableFunctionUserData__newindex); + lua_setfield(State, -2, "__newindex"); + lua_pushcfunction(State, ULuaState::MetaTableFunctionUserData__eq); + lua_setfield(State, -2, "__eq"); + if (Context->IsA()) + { + lua_pushcfunction(State, ULuaState::MetaTableFunctionUserData__gc); + lua_setfield(State, -2, "__gc"); + } + + for (TPair& Pair : Metatable) + { + // first check for UFunction + if (Pair.Value.Type == ELuaValueType::UFunction) + { + UObject* FunctionOwner = Context; + if (ULuaComponent* LuaComponent = Cast(Context)) + { + FunctionOwner = LuaComponent->GetOwner(); + } + + if (FunctionOwner) + { + UFunction* Function = FunctionOwner->FindFunction(Pair.Value.FunctionName); + if (Function) + { + FLuaUserData* LuaCallContext = (FLuaUserData*)lua_newuserdata(State, sizeof(FLuaUserData)); + LuaCallContext->Type = ELuaValueType::UFunction; + LuaCallContext->Context = Context; + LuaCallContext->Function = Function; + + lua_newtable(State); + lua_pushcfunction(State, bRawLuaFunctionCall ? ULuaState::MetaTableFunction__rawcall : ULuaState::MetaTableFunction__call); + lua_setfield(State, -2, "__call"); + lua_setmetatable(State, -2); + } + else + { + lua_pushnil(State); + } + } + } + else { + FromLuaValue(Pair.Value, nullptr, State); + } + lua_setfield(State, -2, TCHAR_TO_ANSI(*Pair.Key)); + } + + lua_setmetatable(State, -2); +} + +FLuaValue ULuaState::NewLuaUserDataObject(TSubclassOf LuaUserDataObjectClass, bool bTrackObject) +{ + ULuaUserDataObject* LuaUserDataObject = NewObject(this, LuaUserDataObjectClass); + if (LuaUserDataObject) + { + if (bTrackObject) + { + TrackedLuaUserDataObjects.Add(LuaUserDataObject); + } + LuaUserDataObject->ReceiveLuaUserDataTableInit(); + return FLuaValue(LuaUserDataObject); + } + + return FLuaValue(); +} + +void ULuaState::SetLuaUserDataField(FLuaValue UserData, const FString & Key, FLuaValue Value) +{ + if (UserData.Type != ELuaValueType::UObject || !UserData.Object) + return; + + if (ULuaComponent* LuaComponent = Cast(UserData.Object)) + { + LuaComponent->LuaSetField(Key, Value); + return; + } + + if (ULuaUserDataObject* LuaUserDataObject = Cast(UserData.Object)) + { + LuaUserDataObject->LuaSetField(Key, Value); + return; + } +} + +FLuaValue ULuaState::GetLuaUserDataField(FLuaValue UserData, const FString & Key) +{ + if (UserData.Type != ELuaValueType::UObject || !UserData.Object) + return FLuaValue(); + + if (ULuaComponent* LuaComponent = Cast(UserData.Object)) + { + return LuaComponent->LuaGetField(Key); + } + + if (ULuaUserDataObject* LuaUserDataObject = Cast(UserData.Object)) + { + return LuaUserDataObject->LuaGetField(Key); + } + + return FLuaValue(); +} + +const void* ULuaState::ToPointer(int Index) +{ + return lua_topointer(L, Index); +} + +void ULuaState::LuaStateInit() +{ +} + +void ULuaState::GCLuaDelegatesCheck() +{ + TSet> DeadObjects; + for (TPair, FLuaDelegateGroup>& Pair : LuaDelegatesMap) + { + if (!Pair.Key.IsValid()) + { + DeadObjects.Add(Pair.Key); + } + } + + for (TWeakObjectPtr& WeakObjectPtr : DeadObjects) + { + LuaDelegatesMap.Remove(WeakObjectPtr); + } +} + +void ULuaState::RegisterLuaDelegate(UObject * InObject, ULuaDelegate * InLuaDelegate) +{ + FLuaDelegateGroup* LuaDelegateGroup = LuaDelegatesMap.Find(InObject); + if (LuaDelegateGroup) + { + LuaDelegateGroup->LuaDelegates.Add(InLuaDelegate); + } + else + { + FLuaDelegateGroup NewLuaDelegateGroup; + NewLuaDelegateGroup.LuaDelegates.Add(InLuaDelegate); + LuaDelegatesMap.Add(InObject, NewLuaDelegateGroup); + } +} + +void ULuaState::UnregisterLuaDelegatesOfObject(UObject* InObject) +{ + LuaDelegatesMap.Remove(InObject); +} + +TArray ULuaState::GetPropertiesNames(UObject * InObject) +{ + TArray Names; + + if (!InObject) + { + return Names; + } + + UClass* Class = InObject->GetClass(); + if (!Class) + { + return Names; + } + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator It(Class); It; ++It) +#else + for (TFieldIterator It(Class); It; ++It) +#endif + { + Names.Add((*It)->GetName()); + } + + return Names; +} + +TArray ULuaState::GetFunctionsNames(UObject * InObject) +{ + TArray Names; + + if (!InObject) + { + return Names; + } + + UClass* Class = InObject->GetClass(); + if (!Class) + { + return Names; + } + + for (TFieldIterator It(Class); It; ++It) + { + Names.Add((*It)->GetName()); + } + + return Names; +} + +void ULuaState::AddLuaValueToLuaState(const FString & Name, FLuaValue LuaValue) +{ + SetFieldFromTree(Name, LuaValue, true); +} + +FLuaValue ULuaState::RunString(const FString & CodeString, FString CodePath) +{ + FLuaValue ReturnValue; + if (CodePath.IsEmpty()) + { + CodePath = CodeString; + } + + if (!RunCode(CodeString, CodePath, 1)) + { + if (bLogError) + LogError(LastError); + ReceiveLuaError(LastError); + } + else + { + ReturnValue = ToLuaValue(-1); + } + + Pop(); + return ReturnValue; +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaSubsystem.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaSubsystem.cpp new file mode 100644 index 00000000..24d1945d --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaSubsystem.cpp @@ -0,0 +1,62 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "LuaSubsystem.h" + +#include "LuaBlueprintFunctionLibrary.h" +#include "LuaSettings.h" +#include "HAL/FileManager.h" +#include "Kismet/KismetSystemLibrary.h" +#include "Algo/Sort.h" + +void ULuaSubsystem::Initialize(FSubsystemCollectionBase& Collection) +{ + settings_ref = GetMutableDefault(); + if(settings_ref->bAutorunFiles) + { + RunLocalFile(settings_ref->Autorun_InitFile); + } + + for(TSoftObjectPtr temp_asset: settings_ref->AutorunCodeAssets) + { + ULuaBlueprintFunctionLibrary::LuaRunCodeAsset(GetWorld(),ULuaBlueprintFunctionLibrary::GetDefaultLuaState(),temp_asset.LoadSynchronous()); + } + Super::Initialize(Collection); +} + +FString ULuaSubsystem::GetLocalFilesPath() +{ + return UKismetSystemLibrary::GetProjectContentDirectory()+settings_ref->Autorun_ContentPath+"/"; +} + +FLuaValue ULuaSubsystem::RunLocalFile(const FString& file) +{ + + const FString target_path = GetLocalFilesPath()+file+".lua"; + UE_LOG(LogTemp, Log, TEXT("Tried to autorun Luafile: %s"), *target_path); + return ULuaBlueprintFunctionLibrary::LuaRunNonContentFile(GetWorld(),ULuaBlueprintFunctionLibrary::GetDefaultLuaState(),target_path,true); +} + +void ULuaSubsystem::RunLocalFilesInPath(const FString& path, bool bRecursive) +{ + TArray FileNames; + IFileManager & FileManager = IFileManager::Get(); + const FString target_path = GetLocalFilesPath()+path+"/"; + UE_LOG(LogTemp, Log, TEXT("Getting lua files from path: %s"), *target_path); + if(bRecursive) + { + FileManager.FindFilesRecursive(FileNames,*target_path,TEXT("*"),true,false); + //*TEXT("*")+TEXT(".lua") + } + else + { + FileManager.FindFiles(FileNames,*target_path,TEXT(".lua")); + } + Algo::Sort(FileNames); + + for(FString i : FileNames) + { + UE_LOG(LogTemp, Log, TEXT("Tried to autorun Luafile from path: %s"), *i); + ULuaBlueprintFunctionLibrary::LuaRunNonContentFile(GetWorld(),ULuaBlueprintFunctionLibrary::GetDefaultLuaState(),i,true); + } +} diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaSyntaxHighlighter.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaSyntaxHighlighter.cpp new file mode 100644 index 00000000..77359436 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaSyntaxHighlighter.cpp @@ -0,0 +1,305 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaSyntaxHighlighter.h" +#include "Runtime/Slate/Public/Framework/Text/IRun.h" +#include "Runtime/Slate/Public/Framework/Text/TextLayout.h" +#include "Runtime/Slate/Public/Framework/Text/SlateTextRun.h" + +#define ADD_RULE(rule) TokenizerRules.Add(FSyntaxTokenizer::FRule(TEXT(rule))) + +#define ADD_RULE_BASIC(rule) ADD_RULE(rule); BasicTokens.Add(TEXT(rule)) + +#define ADD_RULE_STDLIB(rule) ADD_RULE(rule); StdLibTokens.Add(TEXT(rule)) + +FLuaMachineSyntaxHighlighterTextLayoutMarshaller::FLuaMachineSyntaxHighlighterTextLayoutMarshaller(TSharedPtr InTokenizer, TArray InBasicTokens, TArray InStdLibTokens, FLuaSyntaxTextStyle InLuaSyntaxTextStyle) : + FSyntaxHighlighterTextLayoutMarshaller(InTokenizer), + BasicTokens(InBasicTokens), + StdLibTokens(InStdLibTokens), + SyntaxTextStyle(InLuaSyntaxTextStyle) +{ + +} + +TSharedRef FLuaMachineSyntaxHighlighterTextLayoutMarshaller::Create(FLuaSyntaxTextStyle LuaSyntaxTextStyle) +{ + TArray TokenizerRules; + + TArray BasicTokens; + TArray StdLibTokens; + + ADD_RULE("--[["); + ADD_RULE("--]]"); + ADD_RULE("--"); + ADD_RULE("[["); + ADD_RULE("]]"); + ADD_RULE("\\'"); + ADD_RULE("\\\""); + ADD_RULE("'"); + ADD_RULE("\""); + + ADD_RULE("nil"); + ADD_RULE("self"); + ADD_RULE("..."); + ADD_RULE("_G"); + ADD_RULE("_VERSION"); + + ADD_RULE("and"); + ADD_RULE("end"); + ADD_RULE("in"); + ADD_RULE("repeat"); + ADD_RULE("break"); + ADD_RULE("false"); + ADD_RULE("local"); + ADD_RULE("return"); + ADD_RULE("do"); + ADD_RULE("for"); + ADD_RULE("then"); + ADD_RULE("else"); + ADD_RULE("elseif"); + ADD_RULE("function"); + ADD_RULE("not"); + ADD_RULE("true"); + ADD_RULE("if"); + ADD_RULE("or"); + ADD_RULE("until"); + ADD_RULE("while"); + + ADD_RULE_BASIC("assert"); + ADD_RULE_BASIC("collectgarbage"); + ADD_RULE_BASIC("require"); + ADD_RULE_BASIC("dofile"); + ADD_RULE_BASIC("error"); + ADD_RULE_BASIC("getmetatable"); + ADD_RULE_BASIC("ipairs"); + ADD_RULE_BASIC("load"); + ADD_RULE_BASIC("loadfile"); + ADD_RULE_BASIC("next"); + ADD_RULE_BASIC("pairs"); + ADD_RULE_BASIC("pcall"); + ADD_RULE_BASIC("print"); + ADD_RULE_BASIC("rawequal"); + ADD_RULE_BASIC("rawget"); + ADD_RULE_BASIC("rawlen"); + ADD_RULE_BASIC("rawset"); + ADD_RULE_BASIC("select"); + ADD_RULE_BASIC("setmetatable"); + ADD_RULE_BASIC("tonumber"); + ADD_RULE_BASIC("tostring"); + ADD_RULE_BASIC("type"); + ADD_RULE_BASIC("xpcall"); + + ADD_RULE_STDLIB("coroutine"); + ADD_RULE_STDLIB("package"); + ADD_RULE_STDLIB("string"); + ADD_RULE_STDLIB("utf8"); + ADD_RULE_STDLIB("table"); + ADD_RULE_STDLIB("math"); + ADD_RULE_STDLIB("io"); + ADD_RULE_STDLIB("file"); + ADD_RULE_STDLIB("os"); + ADD_RULE_STDLIB("debug"); + + for (TPair& Pair : LuaSyntaxTextStyle.CustomTextColorMapping) + { + LuaSyntaxTextStyle.CustomTextStyleMapping.Add(Pair.Key, FTextBlockStyle(LuaSyntaxTextStyle.NormalTextStyle).SetColorAndOpacity(Pair.Value)); + } + + for (TPair& Pair : LuaSyntaxTextStyle.CustomTextStyleMapping) + { + TokenizerRules.Add(FSyntaxTokenizer::FRule(*Pair.Key)); + } + + TokenizerRules.Sort([](const FSyntaxTokenizer::FRule& A, const FSyntaxTokenizer::FRule& B) { + return A.MatchText.Len() > B.MatchText.Len(); + }); + + + return MakeShareable(new FLuaMachineSyntaxHighlighterTextLayoutMarshaller(FSyntaxTokenizer::Create(TokenizerRules), BasicTokens, StdLibTokens, LuaSyntaxTextStyle)); +} + +void FLuaMachineSyntaxHighlighterTextLayoutMarshaller::ParseTokens(const FString& SourceString, FTextLayout& TargetTextLayout, TArray TokenizedLines) +{ + + enum class EParseState : uint8 + { + None, + LookingForSingleLineComment, + LookingForMultiLineComment, + LookingForSingleQuoteString, + LookingForDoubleQuoteString, + LookingForMultiLineString, + }; + + TArray LinesToAdd; + LinesToAdd.Reserve(TokenizedLines.Num()); + + + EParseState ParseState = EParseState::None; + + for (const FSyntaxTokenizer::FTokenizedLine& TokenizedLine : TokenizedLines) + { + TSharedRef ModelString = MakeShareable(new FString()); + TArray> Runs; + + if (ParseState == EParseState::LookingForSingleLineComment) + { + ParseState = EParseState::None; + } + + + + for (const FSyntaxTokenizer::FToken& Token : TokenizedLine.Tokens) + { + const FString TokenString = SourceString.Mid(Token.Range.BeginIndex, Token.Range.Len()); + const FTextRange ModelRange(ModelString->Len(), ModelString->Len() + TokenString.Len()); + + ModelString->Append(TokenString); + + FRunInfo RunInfo(TEXT("SyntaxHighlight.LuaMachine.Normal")); + + FTextBlockStyle CurrentBlockStyle = SyntaxTextStyle.NormalTextStyle; + + bool bIsWhitespace = FString(TokenString).TrimEnd().IsEmpty(); + if (!bIsWhitespace) + { + bool bHasMatchedSyntax = false; + if (Token.Type == FSyntaxTokenizer::ETokenType::Syntax) + { + if (ParseState == EParseState::None) + { + TCHAR NextChar = TEXT(" ")[0]; + TCHAR PrevChar = TEXT(" ")[0]; + if (Token.Range.EndIndex < SourceString.Len()) + { + NextChar = SourceString[Token.Range.EndIndex]; + } + if (Token.Range.BeginIndex > 0) + { + PrevChar = SourceString[Token.Range.BeginIndex - 1]; + } + if (TokenString == TEXT("--")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Comment"); + CurrentBlockStyle = SyntaxTextStyle.CommentTextStyle; + ParseState = EParseState::LookingForSingleLineComment; + } + else if (TokenString == TEXT("--[[")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Comment"); + CurrentBlockStyle = SyntaxTextStyle.CommentTextStyle; + ParseState = EParseState::LookingForMultiLineComment; + } + else if (TokenString == TEXT("[[")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.String"); + CurrentBlockStyle = SyntaxTextStyle.StringTextStyle; + ParseState = EParseState::LookingForMultiLineString; + bHasMatchedSyntax = true; + } + else if (TokenString == TEXT("'")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.String"); + CurrentBlockStyle = SyntaxTextStyle.StringTextStyle; + ParseState = EParseState::LookingForSingleQuoteString; + bHasMatchedSyntax = true; + } + else if (TokenString == TEXT("\"")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.String"); + CurrentBlockStyle = SyntaxTextStyle.StringTextStyle; + ParseState = EParseState::LookingForDoubleQuoteString; + bHasMatchedSyntax = true; + } + else if (!TChar::IsAlpha(NextChar) && !TChar::IsDigit(NextChar) && !TChar::IsAlpha(PrevChar) && !TChar::IsDigit(PrevChar) && NextChar != TCHAR('_') && PrevChar != TCHAR('_')) + { + if (TokenString == TEXT("nil") || TokenString == TEXT("self") || TokenString == TEXT("_G") || TokenString == TEXT("_VERSION") || TokenString == TEXT("...")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Nil"); + CurrentBlockStyle = SyntaxTextStyle.NilTextStyle; + } + else if (BasicTokens.Contains(TokenString)) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Basic"); + CurrentBlockStyle = SyntaxTextStyle.BasicTextStyle; + } + else if (StdLibTokens.Contains(TokenString)) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.StdLib"); + CurrentBlockStyle = SyntaxTextStyle.StdLibTextStyle; + } + else { + if (SyntaxTextStyle.CustomTextStyleMapping.Contains(TokenString)) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Custom"); + CurrentBlockStyle = SyntaxTextStyle.CustomTextStyleMapping[TokenString]; + } + else + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Keyword"); + CurrentBlockStyle = SyntaxTextStyle.KeywordTextStyle; + } + } + ParseState = EParseState::None; + } + } + else if (ParseState == EParseState::LookingForMultiLineComment && TokenString == TEXT("--]]")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Comment"); + CurrentBlockStyle = SyntaxTextStyle.CommentTextStyle; + ParseState = EParseState::None; + } + else if (ParseState == EParseState::LookingForMultiLineString && TokenString == TEXT("]]")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.String"); + CurrentBlockStyle = SyntaxTextStyle.StringTextStyle; + ParseState = EParseState::None; + } + else if (ParseState == EParseState::LookingForSingleQuoteString && TokenString == TEXT("'")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.String"); + CurrentBlockStyle = SyntaxTextStyle.StringTextStyle; + ParseState = EParseState::None; + } + else if (ParseState == EParseState::LookingForDoubleQuoteString && TokenString == TEXT("\"")) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.String"); + CurrentBlockStyle = SyntaxTextStyle.StringTextStyle; + ParseState = EParseState::None; + } + + } + + if (Token.Type == FSyntaxTokenizer::ETokenType::Literal || !bHasMatchedSyntax) + { + if (ParseState == EParseState::LookingForSingleLineComment) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Comment"); + CurrentBlockStyle = SyntaxTextStyle.CommentTextStyle; + } + else if (ParseState == EParseState::LookingForMultiLineComment) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.Comment"); + CurrentBlockStyle = SyntaxTextStyle.CommentTextStyle; + } + else if (ParseState == EParseState::LookingForMultiLineString || ParseState == EParseState::LookingForSingleQuoteString || ParseState == EParseState::LookingForDoubleQuoteString) + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.String"); + CurrentBlockStyle = SyntaxTextStyle.StringTextStyle; + } + } + TSharedRef Run = FSlateTextRun::Create(RunInfo, ModelString, CurrentBlockStyle, ModelRange); + Runs.Add(Run); + } + else + { + RunInfo.Name = TEXT("SyntaxHighlight.LuaMachine.WhiteSpace"); + TSharedRef Run = FSlateTextRun::Create(RunInfo, ModelString, SyntaxTextStyle.NormalTextStyle, ModelRange); + Runs.Add(Run); + } + } + + LinesToAdd.Emplace(MoveTemp(ModelString), MoveTemp(Runs)); + } + + TargetTextLayout.AddLines(LinesToAdd); +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaTableAsset.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaTableAsset.cpp new file mode 100644 index 00000000..0d24ca0d --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaTableAsset.cpp @@ -0,0 +1,14 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaTableAsset.h" + +FLuaValue ULuaTableAsset::ToLuaTable(ULuaState* LuaState) +{ + FLuaValue NewTable = LuaState->CreateLuaTable(); + for (TPair& Pair : Table) + { + NewTable.SetField(Pair.Key, Pair.Value); + } + + return NewTable; +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaUserDataObject.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaUserDataObject.cpp new file mode 100644 index 00000000..c97b0b2c --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaUserDataObject.cpp @@ -0,0 +1,181 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaUserDataObject.h" + +TSubclassOf ULuaUserDataObject::GetLuaState() const +{ + ULuaState* LuaState = Cast(GetOuter()); + if (LuaState) + { + return LuaState->GetClass(); + } + return nullptr; +} + +ULuaState* ULuaUserDataObject::GetLuaStateInstance() const +{ + return Cast(GetOuter()); +} + +UWorld* ULuaUserDataObject::GetWorld() const +{ + ULuaState* LuaState = Cast(GetOuter()); + if (LuaState) + { + return LuaState->GetWorld(); + } + return nullptr; +} + +TSharedPtr ULuaUserDataObject::AddLuaSmartReference(FLuaValue Value) +{ + ULuaState* LuaState = Cast(GetOuter()); + if (LuaState) + { + return LuaState->AddLuaSmartReference(Value); + } + return nullptr; +} + +void ULuaUserDataObject::RemoveLuaSmartReference(TSharedPtr Ref) +{ + if (!Ref.IsValid()) + return; + + ULuaState* LuaState = Cast(GetOuter()); + if (LuaState) + { + return LuaState->RemoveLuaSmartReference(Ref.ToSharedRef()); + } +} + +FLuaValue ULuaUserDataObject::LuaGetField(const FString& Name) +{ + ULuaState* LuaState = Cast(GetOuter()); + if (!LuaState) + return FLuaValue(); + + // push component pointer as userdata + LuaState->NewUObject(this, nullptr); + LuaState->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + int32 ItemsToPop = LuaState->GetFieldFromTree(Name, false); + FLuaValue ReturnValue = LuaState->ToLuaValue(-1); + + // we need to remove the return value and the object + LuaState->Pop(ItemsToPop + 1); + + return ReturnValue; +} + +void ULuaUserDataObject::LuaSetField(const FString& Name, FLuaValue Value) +{ + ULuaState* LuaState = Cast(GetOuter()); + if (!LuaState) + return; + + // push component pointer as userdata + LuaState->NewUObject(this, nullptr); + LuaState->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + LuaState->SetFieldFromTree(Name, Value, false, this); + + // remove UObject + LuaState->Pop(); +} + +TArray ULuaUserDataObject::GetObjectUFunctions(bool bOnlyPublic) +{ + TArray FunctionNames; + + UClass* RelevantClass = GetClass(); + UClass* ParentClass = RelevantClass->GetSuperClass(); + while (ParentClass != ULuaUserDataObject::StaticClass()) + { + RelevantClass = ParentClass; + ParentClass = ParentClass->GetSuperClass(); + } + + for (TFieldIterator It(GetClass()); It; ++It) + { + UFunction* Function = *It; + bool bSuccess = true; + if (bOnlyPublic && !Function->HasAnyFunctionFlags(EFunctionFlags::FUNC_Public)) + { + bSuccess = false; + } + + if (bSuccess) + { + if (Function->GetOuterUClass()->IsChildOf(RelevantClass)) + { + UFunction* SuperFunction = Function->GetSuperFunction(); + if (SuperFunction && !SuperFunction->GetOuterUClass()->IsChildOf(RelevantClass)) + { + continue; + } + FunctionNames.Add(Function->GetName()); + } + } + } + + return FunctionNames; +} + +void ULuaUserDataObject::ReceiveLuaUserDataTableInit_Implementation() +{ + +} + +void ULuaUserDataObject::ReceiveLuaGC_Implementation() +{ + +} + +FLuaValue ULuaUserDataObject::ReceiveLuaMetaIndex_Implementation(FLuaValue Key) +{ + return FLuaValue(); +} + +FLuaValue ULuaUserDataObject::UFunctionToLuaValue(const FString& FunctionName) +{ + FName FunctionFName = FName(*FunctionName); + UFunction* Function = FindFunction(FunctionFName); + if (!Function) + { + return FLuaValue(); + } + + return FLuaValue::Function(FunctionFName); +} + +FLuaValue ULuaUserDataObject::LuaCallFunction(const FString& Name, TArray Args, bool bGlobal) +{ + FLuaValue ReturnValue; + + ULuaState* L = GetLuaStateInstance(); + if (!L) + return ReturnValue; + + // push userdata pointer as userdata + L->NewUObject(this, nullptr); + L->SetupAndAssignUserDataMetatable(this, Metatable, nullptr); + + int32 ItemsToPop = L->GetFieldFromTree(Name, bGlobal); + + // first argument (self/actor) + L->PushValue(-(ItemsToPop + 1)); + int NArgs = 1; + for (FLuaValue& Arg : Args) + { + L->FromLuaValue(Arg); + NArgs++; + } + + L->PCall(NArgs, ReturnValue); + + // the return value and the function has been removed, so we do not need to change ItemsToPop + L->Pop(ItemsToPop + 1); + + return ReturnValue; +} diff --git a/OmegaGameFramework/Source/LuaMachine/Private/LuaValue.cpp b/OmegaGameFramework/Source/LuaMachine/Private/LuaValue.cpp new file mode 100644 index 00000000..882005e7 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Private/LuaValue.cpp @@ -0,0 +1,423 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaValue.h" +#include "LuaState.h" +#include "Misc/Base64.h" + +FString FLuaValue::ToString() const +{ + switch (Type) + { + case ELuaValueType::Bool: + return Bool ? FString(TEXT("true")) : FString(TEXT("false")); + case ELuaValueType::Integer: + return FString::FromInt(Integer); + case ELuaValueType::Number: + return FString::SanitizeFloat(Number); + case ELuaValueType::String: + return String; + case ELuaValueType::Table: + return FString::Printf(TEXT("table: %d"), LuaRef); + case ELuaValueType::Function: + return FString::Printf(TEXT("function: %d"), LuaRef); + case ELuaValueType::UObject: + return Object->GetFullName(); + case ELuaValueType::UFunction: + return Object ? (FunctionName.ToString() + " @ " + Object->GetClass()->GetPathName()) : FunctionName.ToString(); + case ELuaValueType::Thread: + return FString::Printf(TEXT("thread: %d"), LuaRef); + } + return FString(TEXT("nil")); +} + +FName FLuaValue::ToName() const +{ + return FName(*ToString()); +} + +int32 FLuaValue::ToInteger() const +{ + switch (Type) + { + case ELuaValueType::Bool: + return Bool ? 1 : 0; + case ELuaValueType::Integer: + return Integer; + case ELuaValueType::Number: + return Number; + case ELuaValueType::String: + return FCString::Atoi(*String); + } + return 0; +} + +double FLuaValue::ToFloat() const +{ + switch (Type) + { + case ELuaValueType::Bool: + return Bool ? 1.0 : 0.0; + case ELuaValueType::Integer: + return Integer; + case ELuaValueType::Number: + return Number; + case ELuaValueType::String: + return FCString::Atod(*String); + } + return 0.0; +} + +bool FLuaValue::ToBool() const +{ + switch (Type) + { + case ELuaValueType::Nil: + return false; + case ELuaValueType::Bool: + return Bool; + case ELuaValueType::Integer: + return Integer != 0; + case ELuaValueType::Number: + return Number != 0; + } + return true; +} + +void FLuaValue::Unref() +{ + if (!LuaState.IsValid()) + { + LuaRef = LUA_NOREF; + return; + } + + if (Type == ELuaValueType::Table || Type == ELuaValueType::Function || Type == ELuaValueType::Thread) + { + if (LuaRef != LUA_NOREF) + { + // special case for when the engine is shutting down +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 24 + if (IsEngineExitRequested()) +#else + if (GIsRequestingExit) +#endif + { + if (!LuaState->IsValidLowLevel()) + { + LuaRef = LUA_NOREF; + return; + } + } + // use UnrefCheck here to support moving of LuaState + LuaState->UnrefChecked(LuaRef); + } + LuaRef = LUA_NOREF; + } +} + +FLuaValue::~FLuaValue() +{ + Unref(); +} + +FLuaValue::FLuaValue(const FLuaValue& SourceValue) +{ + Type = SourceValue.Type; + Object = SourceValue.Object; + LuaRef = SourceValue.LuaRef; + LuaState = SourceValue.LuaState; + Bool = SourceValue.Bool; + Integer = SourceValue.Integer; + Number = SourceValue.Number; + String = SourceValue.String; + FunctionName = SourceValue.FunctionName; + MulticastScriptDelegate = SourceValue.MulticastScriptDelegate; + + // make a new reference to the table, to avoid it being destroyed + if (LuaRef != LUA_NOREF) + { + LuaState->GetRef(LuaRef); + LuaRef = LuaState->NewRef(); + } +} + +FLuaValue& FLuaValue::operator = (const FLuaValue& SourceValue) +{ + Type = SourceValue.Type; + Object = SourceValue.Object; + LuaRef = SourceValue.LuaRef; + LuaState = SourceValue.LuaState; + Bool = SourceValue.Bool; + Integer = SourceValue.Integer; + Number = SourceValue.Number; + String = SourceValue.String; + FunctionName = SourceValue.FunctionName; + MulticastScriptDelegate = SourceValue.MulticastScriptDelegate; + + // make a new reference to the table, to avoid it being destroyed + if (LuaRef != LUA_NOREF) + { + LuaState->GetRef(LuaRef); + LuaRef = LuaState->NewRef(); + } + + return *this; +} + +FLuaValue FLuaValue::SetField(const FString& Key, FLuaValue Value) +{ + if (Type != ELuaValueType::Table) + return *this; + + if (!LuaState.IsValid()) + return *this; + + LuaState->FromLuaValue(*this); + LuaState->FromLuaValue(Value); + LuaState->SetField(-2, TCHAR_TO_ANSI(*Key)); + LuaState->Pop(); + return *this; +} + +FLuaValue FLuaValue::SetField(const FString& Key, lua_CFunction CFunction) +{ + if (Type != ELuaValueType::Table) + return *this; + + if (!LuaState.IsValid()) + return *this; + + LuaState->FromLuaValue(*this); + LuaState->PushCFunction(CFunction); + LuaState->SetField(-2, TCHAR_TO_ANSI(*Key)); + LuaState->Pop(); + return *this; +} + +FLuaValue FLuaValue::SetMetaTable(FLuaValue MetaTable) +{ + if (Type != ELuaValueType::Table || MetaTable.Type != ELuaValueType::Table) + return *this; + + if (!LuaState.IsValid()) + return *this; + + LuaState->FromLuaValue(*this); + LuaState->FromLuaValue(MetaTable); + LuaState->SetMetaTable(-2); + LuaState->Pop(); + + return *this; +} + + +FLuaValue FLuaValue::GetField(const FString& Key) +{ + if (Type != ELuaValueType::Table) + return FLuaValue(); + + if (!LuaState.IsValid()) + return FLuaValue(); + + LuaState->FromLuaValue(*this); + LuaState->GetField(-1, TCHAR_TO_ANSI(*Key)); + FLuaValue ReturnValue = LuaState->ToLuaValue(-1); + LuaState->Pop(2); + return ReturnValue; +} + +FLuaValue FLuaValue::GetFieldByIndex(int32 Index) +{ + if (Type != ELuaValueType::Table) + return FLuaValue(); + + if (!LuaState.IsValid()) + return FLuaValue(); + + LuaState->FromLuaValue(*this); + LuaState->RawGetI(-1, Index); + FLuaValue ReturnValue = LuaState->ToLuaValue(-1); + LuaState->Pop(2); + return ReturnValue; +} + +FLuaValue FLuaValue::SetFieldByIndex(int32 Index, FLuaValue Value) +{ + if (Type != ELuaValueType::Table) + return *this; + + if (!LuaState.IsValid()) + return *this; + + LuaState->FromLuaValue(*this); + LuaState->FromLuaValue(Value); + LuaState->RawSetI(-2, Index); + LuaState->Pop(); + return *this; +} + +bool FLuaValue::IsReferencedInLuaRegistry() const +{ + return LuaRef != LUA_NOREF; +} + +bool FLuaValue::IsNil() const +{ + return Type == ELuaValueType::Nil; +} + +FLuaValue FLuaValue::FromJsonValue(ULuaState* L, FJsonValue& JsonValue) +{ + if (JsonValue.Type == EJson::String) + { + return FLuaValue(JsonValue.AsString()); + } + else if (JsonValue.Type == EJson::Number) + { + return FLuaValue((float)JsonValue.AsNumber()); + } + else if (JsonValue.Type == EJson::Boolean) + { + return FLuaValue(JsonValue.AsBool()); + } + else if (JsonValue.Type == EJson::Array) + { + FLuaValue LuaArray = L->CreateLuaTable(); + int32 Index = 1; + auto JsonValues = JsonValue.AsArray(); + for (auto JsonItem : JsonValues) + { + FLuaValue LuaItem; + if (JsonItem.IsValid()) + { + LuaItem = FromJsonValue(L, *JsonItem); + } + LuaArray.SetFieldByIndex(Index++, LuaItem); + } + return LuaArray; + } + else if (JsonValue.Type == EJson::Object) + { + FLuaValue LuaTable = L->CreateLuaTable(); + auto JsonObject = JsonValue.AsObject(); + for (TPair> Pair : JsonObject->Values) + { + FLuaValue LuaItem; + if (Pair.Value.IsValid()) + { + LuaItem = FromJsonValue(L, *Pair.Value); + } + LuaTable.SetField(Pair.Key, LuaItem); + } + return LuaTable; + } + + // default to nil + return FLuaValue(); +} + +TSharedPtr FLuaValue::ToJsonValue() +{ + switch (Type) + { + case ELuaValueType::Integer: + return MakeShared(Integer); + case ELuaValueType::Number: + return MakeShared(Number); + case ELuaValueType::Bool: + return MakeShared(Bool); + case ELuaValueType::String: + return MakeShared(String); + case ELuaValueType::UFunction: + return MakeShared(FunctionName.ToString()); + case ELuaValueType::UObject: + return MakeShared(Object ? Object->GetFullName() : ""); + case ELuaValueType::Table: + { + + ULuaState* L = LuaState.Get(); + if (!L) + return MakeShared(); + + bool bIsArray = true; + + TArray> Items; + L->FromLuaValue(*this); // push the table + L->PushNil(); // first key + while (L->Next(-2)) + { + auto Key = L->ToLuaValue(-2); + auto Value = L->ToLuaValue(-1); + Items.Add(TPair(Key, Value)); + if (Key.Type != ELuaValueType::Integer) + { + bIsArray = false; + } + L->Pop(); // pop the value + } + L->Pop(); // pop the table + + // check if it is a valid lua "array" + if (bIsArray) + { + TArray> JsonValues; + int32 Index = 1; + for (;;) + { + FLuaValue Item = GetFieldByIndex(Index++); + if (Item.Type == ELuaValueType::Nil) + break; + JsonValues.Add(Item.ToJsonValue()); + } + return MakeShared(JsonValues); + } + + auto JsonObject = MakeShared(); + for (auto Pair : Items) + { + JsonObject->SetField(Pair.Key.ToString(), Pair.Value.ToJsonValue()); + } + auto JsonValueObject = MakeShared(JsonObject); + return JsonValueObject; + } + return MakeShared(); + } + + return MakeShared(); +} + +TArray FLuaValue::ToBytes() const +{ + TArray Bytes; + if (Type != ELuaValueType::String) + return Bytes; + + int32 StringLength = String.Len(); + Bytes.AddUninitialized(StringLength); + for (int32 i = 0; i < StringLength; i++) + { + uint16 CharValue = (uint16)String[i]; + if (CharValue == 0xffff) + { + Bytes[i] = 0; + } + else + { + Bytes[i] = (uint8)String[i]; + } + } + + return Bytes; +} + +FLuaValue FLuaValue::FromBase64(const FString& Base64) +{ + TArray Bytes; + FBase64::Decode(Base64, Bytes); + return FLuaValue(Bytes); +} + +FString FLuaValue::ToBase64() const +{ + return FBase64::Encode(ToBytes()); +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaBlueprintFunctionLibrary.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaBlueprintFunctionLibrary.h new file mode 100644 index 00000000..a069dd86 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaBlueprintFunctionLibrary.h @@ -0,0 +1,429 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "LuaState.h" +#include "LuaValue.h" +#include "LuaSettings.h" +#include "LuaTableAsset.h" +#include "UObject/TextProperty.h" +#include "Runtime/Engine/Classes/Engine/World.h" +#include "Runtime/Online/HTTP/Public/HttpModule.h" +#include "Sound/SoundWave.h" +#include "LuaBlueprintFunctionLibrary.generated.h" + +/** + * + */ + +DECLARE_DYNAMIC_DELEGATE_ThreeParams(FLuaHttpSuccess, FLuaValue, ReturnValue, bool, bWasSuccessful, int32, StatusCode); +DECLARE_DYNAMIC_DELEGATE_TwoParams(FLuaHttpResponseReceived, FLuaValue, Context, FLuaValue, Response); +DECLARE_DYNAMIC_DELEGATE_OneParam(FLuaHttpError, FLuaValue, Context); + +UENUM(BlueprintType) +enum class ELuaReflectionType : uint8 +{ + Unknown, + Property, + Function, +}; + + +UCLASS() +class LUAMACHINE_API ULuaBlueprintFunctionLibrary : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + + UFUNCTION() + static ULuaState* LOCAL_getLuaState(UObject* WorldContextObject, TSubclassOf StateClass); + +public: + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static TSubclassOf GetDefaultLuaState(); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaCreateNil(); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaCreateString(const FString& String); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaCreateNumber(const float Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaCreateInteger(const int32 Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaCreateBool(const bool bInBool); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static FLuaValue LuaCreateTable(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaCreateThread(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value /* Function */); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaCreateObject(UObject* InObject); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static FLuaValue LuaCreateObjectInState(UObject* WorldContextObject, TSubclassOf State, UObject* InObject); + + UFUNCTION(BlueprintCallable, meta=(AdvancedDisplay="State", WorldContext="WorldContextObject"), Category="Lua") + static FLuaValue LuaGetGlobal(UObject* WorldContextObject, TSubclassOf State, const FString& Name); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static void LuaSetGlobal(UObject* WorldContextObject, TSubclassOf State, const FString& Name, FLuaValue Value); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static void LuaSetUserDataMetaTable(UObject* WorldContextObject, TSubclassOf State, FLuaValue MetaTable); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static FLuaValue AssignLuaValueToLuaState(UObject* WorldContextObject, FLuaValue Value, TSubclassOf State); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaTableGetField(FLuaValue Table, const FString& Key); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue GetLuaComponentAsLuaValue(AActor* Actor); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue GetLuaComponentByStateAsLuaValue(AActor* Actor, TSubclassOf State); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue GetLuaComponentByNameAsLuaValue(AActor* Actor, const FString& Name); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue GetLuaComponentByStateAndNameAsLuaValue(AActor* Actor, TSubclassOf State, const FString& Name); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaComponentGetField(FLuaValue LuaComponent, const FString& Key); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static FLuaValue LuaTableGetByIndex(FLuaValue Table, const int32 Index); + + /* Assigns a value to a table index, returned value is the table itself */ + UFUNCTION(BlueprintCallable, Category="Lua") + static FLuaValue LuaTableSetByIndex(FLuaValue Table, const int32 Index, FLuaValue Value); + + /* Returns the array of keys in the table */ + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static TArray LuaTableGetKeys(FLuaValue Table); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static TArray LuaTableGetValues(FLuaValue Table); + + /* Assigns a value to a table key, returned value is the table itself */ + UFUNCTION(BlueprintCallable, Category="Lua") + static FLuaValue LuaTableSetField(FLuaValue Table, const FString& Key, FLuaValue Value); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject", AutoCreateRefTerm = "Args"), Category="Lua") + static FLuaValue LuaGlobalCall(UObject* WorldContextObject, TSubclassOf State, const FString& Name, TArray Args); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject", AutoCreateRefTerm = "Args"), Category="Lua") + static TArray LuaGlobalCallMulti(UObject* WorldContextObject, TSubclassOf State, const FString& Name, TArray Args); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject", AutoCreateRefTerm = "Args"), Category="Lua") + static FLuaValue LuaGlobalCallValue(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject", AutoCreateRefTerm = "Args"), Category="Lua") + static TArray LuaGlobalCallValueMulti(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintPure, meta = (WorldContext = "WorldContextObject", AutoCreateRefTerm = "Args"), Category = "Lua") + static ULuaState* LuaGetState(UObject* WorldContextObject, TSubclassOf State); + + /* Calls a lua value (must be callable) */ + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category="Lua") + static FLuaValue LuaValueCall(FLuaValue Value, TArray Args); + + /* Calls a lua value (must be callable and not nil) */ + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category="Lua") + static FLuaValue LuaValueCallIfNotNil(FLuaValue Value, TArray Args); + + /* Calls a lua value taken from a table by key (must be callable) */ + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category="Lua") + static FLuaValue LuaTableKeyCall(FLuaValue InTable, const FString& Key, TArray Args); + + /* Calls a lua value taken from a table by key (must be callable), passing the table itself as the first argument (useful for table:function syntax) */ + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category = "Lua") + static FLuaValue LuaTableKeyCallWithSelf(FLuaValue InTable, const FString& Key, TArray Args); + + /* Calls a lua value taken from a table by index (must be callable) */ + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category="Lua") + static FLuaValue LuaTableIndexCall(FLuaValue InTable, const int32 Index, TArray Args); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static TArray LuaTableUnpack(FLuaValue InTable); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaTablePack(UObject* WorldContextObject, TSubclassOf State, TArray Values); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaTableMergePack(UObject* WorldContextObject, TSubclassOf State, TArray Values1, TArray Values2); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static TArray LuaTableMergeUnpack(FLuaValue InTable1, FLuaValue InTable2); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static void LuaTableFillObject(FLuaValue InTable, UObject* InObject); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaTableFromMap(UObject* WorldContextObject, TSubclassOf State, TMap Map); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static TArray LuaTableRange(FLuaValue InTable, const int32 First, const int32 Last); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static TArray LuaValueArrayMerge(TArray Array1, TArray Array2); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static TArray LuaValueArrayAppend(TArray Array, FLuaValue Value); + + /* Calls a lua value with multiple return values (must be callable) */ + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category="Lua") + static TArray LuaValueCallMulti(FLuaValue Value, TArray Args); + + /* Resume a lua coroutine/thread with multiple return values (must be callable) */ + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category = "Lua") + static TArray LuaValueResumeMulti(FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static ELuaThreadStatus LuaThreadGetStatus(FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static int32 LuaThreadGetStackTop(FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static int32 LuaValueLength(FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static bool LuaValueIsReferencedInLuaRegistry(FLuaValue Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static UClass* LuaValueToBlueprintGeneratedClass(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static UObject* LuaValueLoadObject(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static UClass* LuaValueLoadClass(const FLuaValue& Value, const bool bDetectBlueprintGeneratedClass); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = "Lua") + static bool LuaValueFromJson(UObject* WorldContextObject, TSubclassOf State, const FString& Json, FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static FString LuaValueToJson(FLuaValue Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static FLuaValue LuaValueFromBase64(const FString& Base64); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static FString LuaValueToBase64(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static FLuaValue LuaValueFromUTF16(const FString& String); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static FString LuaValueToUTF16(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static FLuaValue LuaValueFromUTF8(const FString& String); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static FString LuaValueToUTF8(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static FLuaValue LuaValueFromUTF32(const FString& String); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static FString LuaValueToUTF32(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static int64 LuaValueToPointer(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FString LuaValueToHexPointer(UObject* WorldContextObject, TSubclassOf State, FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static int32 LuaGetTop(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static void LuaStateDestroy(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static void LuaStateReload(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static FLuaValue LuaRunFile(UObject* WorldContextObject, TSubclassOf State, const FString& Filename, const bool bIgnoreNonExistent); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaRunNonContentFile(UObject* WorldContextObject, TSubclassOf State, const FString& Filename, const bool bIgnoreNonExistent); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static FLuaValue LuaRunCodeAsset(UObject* WorldContextObject, TSubclassOf State, ULuaCode* CodeAsset); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static FLuaValue LuaRunByteCode(UObject* WorldContextObject, TSubclassOf State, const TArray& ByteCode, const FString& CodePath); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static FLuaValue LuaRunString(UObject* WorldContextObject, TSubclassOf State, const FString& CodeString, FString CodePath=""); + + /* Make an HTTP GET request to the specified URL to download the Lua script to run */ + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject", AutoCreateRefTerm = "Headers"), Category = "Lua") + static void LuaRunURL(UObject* WorldContextObject, TSubclassOf State, const FString& URL, TMap Headers, const FString& SecurityHeader, const FString& SignaturePublicExponent, const FString& SignatureModulus, FLuaHttpSuccess Completed); + + /* Make an HTTP GET request to the specified URL to download the Lua script to run */ + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject", AutoCreateRefTerm = "Headers,Error,ResponseReceived"), Category = "Lua") + static void LuaHttpRequest(UObject* WorldContextObject, TSubclassOf State, const FString& Method, const FString& URL, TMap Headers, FLuaValue Body, FLuaValue Context, const FLuaHttpResponseReceived& ResponseReceived, const FLuaHttpError& Error); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static UTexture2D* LuaValueToTransientTexture(const int32 Width, const int32 Height, const FLuaValue& Value, const EPixelFormat PixelFormat = EPixelFormat::PF_B8G8R8A8, bool bDetectFormat = false); + + + UFUNCTION(BlueprintCallable, meta = (AutoCreateRefTerm = "Args"), Category = "Lua") + static void LuaValueYield(FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static bool LuaLoadPakFile(const FString& Filename, FString Mountpoint, TArray& Assets, FString ContentPath, FString AssetRegistryPath); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaNewLuaUserDataObject(UObject* WorldContextObject, TSubclassOf State, TSubclassOf UserDataObjectClass, bool bTrackObject=true); + + UFUNCTION(BlueprintCallable, BlueprintPure, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static int32 LuaGetUsedMemory(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static void LuaGCCollect(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static void LuaGCStop(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category="Lua") + static void LuaGCRestart(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, meta = (AdvancedDisplay="State", WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaTableAssetToLuaTable(UObject* WorldContextObject, TSubclassOf State, ULuaTableAsset* TableAsset); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static bool LuaTableImplements(FLuaValue Table, ULuaTableAsset* TableAsset); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static bool LuaTableImplementsAll(FLuaValue Table, TArray TableAssets); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static bool LuaTableImplementsAny(FLuaValue Table, TArray TableAssets); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsNil(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsOwned(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static TSubclassOf LuaValueGetOwner(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsNotNil(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsTable(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsBoolean(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsNumber(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsInteger(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsString(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsFunction(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + static bool LuaValueIsThread(const FLuaValue& Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static FVector LuaTableToVector(FLuaValue Value); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static FLuaValue LuaTableSetMetaTable(FLuaValue InTable, FLuaValue InMetaTable); + + UFUNCTION(BlueprintPure, meta=(DisplayName = "To String (LuaValue)", BlueprintAutocast), Category="Lua") + static FString Conv_LuaValueToString(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Text (LuaValue)", BlueprintAutocast), Category="Lua") + static FText Conv_LuaValueToText(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Name (LuaValue)", BlueprintAutocast), Category="Lua") + static FName Conv_LuaValueToName(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Object (LuaValue)", BlueprintAutocast), Category="Lua") + static UObject* Conv_LuaValueToObject(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Class (LuaValue)", BlueprintAutocast), Category="Lua") + static UClass* Conv_LuaValueToClass(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To LuaValue (Object)", BlueprintAutocast), Category="Lua") + static FLuaValue Conv_ObjectToLuaValue(UObject* Object); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To LuaValue (Float)", BlueprintAutocast), Category="Lua") + static FLuaValue Conv_FloatToLuaValue(const float Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Int (LuaValue)", BlueprintAutocast), Category="Lua") + static int32 Conv_LuaValueToInt(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Float (LuaValue)", BlueprintAutocast), Category="Lua") + static float Conv_LuaValueToFloat(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Vector (LuaValue)", BlueprintAutocast), Category = "Lua") + static FVector Conv_LuaValueToFVector(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To Bool (LuaValue)", BlueprintAutocast), Category="Lua") + static bool Conv_LuaValueToBool(const FLuaValue& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To LuaValue (Int)", BlueprintAutocast), Category="Lua") + static FLuaValue Conv_IntToLuaValue(const int32 Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To LuaValue (String)", BlueprintAutocast), Category="Lua") + static FLuaValue Conv_StringToLuaValue(const FString& Value); + + UFUNCTION(BlueprintPure, meta = (BDisplayName = "To LuaValue (Text)", lueprintAutocast), Category="Lua") + static FLuaValue Conv_TextToLuaValue(const FText& Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To LuaValue (Name)", BlueprintAutocast), Category="Lua") + static FLuaValue Conv_NameToLuaValue(const FName Value); + + UFUNCTION(BlueprintPure, meta = (DisplayName = "To LuaValue (Bool)", BlueprintAutocast), Category="Lua") + static FLuaValue Conv_BoolToLuaValue(const bool Value); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = "Lua") + static FLuaValue LuaCreateLazyTable(UObject* WorldContextObject, TSubclassOf State); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static FLuaValue LuaCreateUFunction(UObject* InObject, const FString& FunctionName); + + UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "LuaValueTypes"), Category = "Lua") + static void SwitchOnLuaValueType(const FLuaValue& LuaValue, ELuaValueType& LuaValueTypes); + + UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "LuaReflectionTypes"), Category = "Lua") + static void GetLuaReflectionType(UObject* InObject, const FString& Name, ELuaReflectionType& LuaReflectionTypes); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static void RegisterLuaConsoleCommand(const FString& CommandName, const FLuaValue& LuaConsoleCommand); + + UFUNCTION(BlueprintCallable, Category = "Lua") + static void UnregisterLuaConsoleCommand(const FString& CommandName); + + UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = "Lua") + static ULuaState* CreateDynamicLuaState(UObject* WorldContextObject, TSubclassOf LuaStateClass); + +private: + static void HttpRequestDone(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, TSubclassOf LuaState, TWeakObjectPtr World, const FString SecurityHeader, const FString SignaturePublicExponent, const FString SignatureModulus, FLuaHttpSuccess Completed); + static void HttpGenericRequestDone(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful, TWeakPtr Context, FLuaHttpResponseReceived ResponseReceived, FLuaHttpError Error); + +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaBlueprintPackage.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaBlueprintPackage.h new file mode 100644 index 00000000..180bf534 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaBlueprintPackage.h @@ -0,0 +1,41 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "LuaState.h" +#include "LuaBlueprintPackage.generated.h" + +/** + * + */ +UCLASS(Abstract, Blueprintable, HideDropdown) +class LUAMACHINE_API ULuaBlueprintPackage : public UObject +{ + GENERATED_BODY() + + +public: + UPROPERTY(EditAnywhere, Category = "Lua") + TMap Table; + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + TSubclassOf GetLuaState() const; + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + ULuaState* GetLuaStateInstance() const; + + virtual UWorld* GetWorld() const override; + + UPROPERTY() + FLuaValue SelfTable; + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + FLuaValue GetSelfLuaTable() const { return SelfTable; } + + virtual void Init(); + + UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "Init"), Category = "Lua") + void ReceiveInit(); +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaCode.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaCode.h new file mode 100644 index 00000000..f4253035 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaCode.h @@ -0,0 +1,76 @@ +// Copyright 2018-2023 - Roberto De Ioris +// Reimport system by yama2akira (Akira Yamamoto) + +#pragma once + +#include "CoreMinimal.h" +#include "Runtime/Launch/Resources/Version.h" +#include "Engine/DataAsset.h" +#if ENGINE_MAJOR_VERSION > 4 +#include "UObject/ObjectSaveContext.h" +#endif +#include "LuaCode.generated.h" + +struct LUAMACHINE_API FLuaCodeObjectVersion +{ + enum Type + { + // Before any version changes were made + BeforeCustomVersionWasAdded = 0, + + // Fixed duplication of properties + FixDuplicationOfProperties, + + VersionPlusOne, + LatestVersion = VersionPlusOne - 1 + + }; + + // The GUID for this custom version number + const static FGuid GUID; + +private: + FLuaCodeObjectVersion() {} +}; + + +/** + * + */ +UCLASS(BlueprintType) +class LUAMACHINE_API ULuaCode : public UDataAsset +{ + GENERATED_BODY() + +public: + + ULuaCode(); + + UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Lua") + FText Code; + + UPROPERTY(EditAnywhere, Category="Lua") + bool bCookAsBytecode; + + UPROPERTY() + TArray ByteCode; + + UPROPERTY() + bool bCooked; + + virtual void Serialize(FArchive& Ar) override; + +#if ENGINE_MAJOR_VERSION > 4 + virtual void PreSave(FObjectPreSaveContext ObjectSaveContext) override; +#else + virtual void PreSave(const ITargetPlatform* TargetPlatform) override; +#endif + +#if WITH_EDITORONLY_DATA + virtual void PostInitProperties() override; + virtual void GetAssetRegistryTags(TArray& OutTags) const override; + + UPROPERTY(VisibleAnywhere, Instanced, Category = Reimport) + class UAssetImportData* AssetImportData; +#endif +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaCommandExecutor.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaCommandExecutor.h new file mode 100644 index 00000000..a50874f5 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaCommandExecutor.h @@ -0,0 +1,40 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "HAL/IConsoleManager.h" +#include "Framework/Commands/InputChord.h" +#include "Runtime/Launch/Resources/Version.h" + +class ULuaState; + +/** + * + */ +class LUAMACHINE_API FLuaCommandExecutor : public IConsoleCommandExecutor +{ +public: + FLuaCommandExecutor(); + ~FLuaCommandExecutor(); + + FName GetName() const override; + FText GetDisplayName() const override; + FText GetDescription() const override; + FText GetHintText() const override; + void GetAutoCompleteSuggestions(const TCHAR* Input, TArray& Out) override; + void GetExecHistory(TArray& Out) override; + bool Exec(const TCHAR* Input) override; + bool AllowHotKeyClose() const override; + bool AllowMultiLine() const override; + FInputChord GetHotKey() const override; + +#if ENGINE_MAJOR_VERSION > 4 && ENGINE_MINOR_VERSION > 0 + FInputChord GetIterateExecutorHotKey() const + { + return {}; + } +#endif + + ULuaState* LuaState; +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaComponent.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaComponent.h new file mode 100644 index 00000000..208715c6 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaComponent.h @@ -0,0 +1,102 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "LuaState.h" +#include "LuaValue.h" +#include "LuaComponent.generated.h" + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FLuaComponentError, FString, Message); + + +UCLASS(Blueprintable, ClassGroup=(Scripting), meta=(BlueprintSpawnableComponent) ) +class LUAMACHINE_API ULuaComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + // Sets default values for this component's properties + ULuaComponent(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + TSubclassOf LuaState; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + TMap Table; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + TMap Metatable; + + UPROPERTY(EditAnywhere, Category="Lua") + bool bLazy; + + UPROPERTY(EditAnywhere, Category="Lua") + bool bLogError; + + UPROPERTY(EditAnywhere, Category = "Lua") + bool bImplicitSelf; + + UPROPERTY(EditAnywhere, Category = "Lua") + TArray GlobalNames; + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + FLuaValue LuaCallFunction(const FString& Name, TArray Args, bool bGlobal); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + FLuaValue LuaCallValue(FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + FLuaValue LuaCallValueIfNotNil(FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + FLuaValue LuaCallTableKey(FLuaValue InTable, FString Key, TArray Args); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + FLuaValue LuaCallTableIndex(FLuaValue InTable, int32 Index, TArray Args); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + TArray LuaCallFunctionMulti(FString Name, TArray Args, bool bGlobal); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + TArray LuaCallValueMulti(FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + TArray LuaCallValueMultiIfNotNil(FLuaValue Value, TArray Args); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + TArray LuaCallTableKeyMulti(FLuaValue InTable, FString Key, TArray Args); + + UFUNCTION(BlueprintCallable, Category="Lua", meta = (AutoCreateRefTerm = "Args")) + TArray LuaCallTableIndexMulti(FLuaValue InTable, int32 Index, TArray Args); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category="Lua") + FLuaValue LuaGetField(const FString& Name); + + UFUNCTION(BlueprintCallable, Category="Lua") + void LuaSetField(const FString& Name, FLuaValue Value); + + UPROPERTY(BlueprintAssignable, Category = "Lua", meta = (DisplayName = "On Lua Error")) + FLuaComponentError OnLuaError; + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Component Metatable __index")) + FLuaValue ReceiveLuaMetaIndex(FLuaValue Key); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Component Metatable __newindex")) + bool ReceiveLuaMetaNewIndex(FLuaValue Key, FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + ULuaState* LuaComponentGetState(); + + virtual void OnRegister() override; + +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaDelegate.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaDelegate.h new file mode 100644 index 00000000..b0ba817c --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaDelegate.h @@ -0,0 +1,31 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "LuaValue.h" +#include "UObject/NoExportTypes.h" +#include "LuaDelegate.generated.h" + +/** + * + */ +UCLASS() +class LUAMACHINE_API ULuaDelegate : public UObject +{ + GENERATED_BODY() + +public: + + void SetupLuaDelegate(UFunction* InSignature, ULuaState* InLuaState, FLuaValue InLuaValue); + + virtual void ProcessEvent(UFunction* Function, void* Parms) override; + + UFUNCTION() + void LuaDelegateFunction(); + +private: + TWeakObjectPtr LuaState; + FLuaValue LuaValue; + UFunction* LuaDelegateSignature; +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaGlobalNameComponent.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaGlobalNameComponent.h new file mode 100644 index 00000000..c045895c --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaGlobalNameComponent.h @@ -0,0 +1,36 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Components/ActorComponent.h" +#include "LuaState.h" +#include "LuaGlobalNameComponent.generated.h" + + +UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) +class LUAMACHINE_API ULuaGlobalNameComponent : public UActorComponent +{ + GENERATED_BODY() + +public: + // Sets default values for this component's properties + ULuaGlobalNameComponent(); + +protected: + // Called when the game starts + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; + + virtual void OnRegister() override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lua") + TSubclassOf LuaState; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lua") + FString LuaGlobalName; + +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaInterface.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaInterface.h new file mode 100644 index 00000000..f3251f26 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaInterface.h @@ -0,0 +1,37 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LuaValue.h" + +#include "LuaInterface.generated.h" + +// This class does not need to be modified. +UINTERFACE(MinimalAPI) +class ULuaInterface : public UInterface +{ + GENERATED_BODY() +}; + +/** + * + */ +class LUAMACHINE_API ILuaInterface +{ + GENERATED_BODY() + + // Add interface functions to this class. This is the class that will be inherited to implement this interface. +public: + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Lua") + void SetValue(FLuaValue Value,const FString& Field=""); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Lua") + void SetKey(FLuaValue Key); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Lua") + FLuaValue GetValue(const FString& Field); + + UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="Lua") + FLuaValue GetKey(); +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaMachine.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaMachine.h new file mode 100644 index 00000000..6749cb20 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaMachine.h @@ -0,0 +1,56 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Modules/ModuleManager.h" +#include "UObject/GCObject.h" +#include "LuaState.h" +#include "HAL/IConsoleManager.h" + +DECLARE_MULTICAST_DELEGATE(FOnRegisteredLuaStatesChanged); +DECLARE_MULTICAST_DELEGATE_OneParam(FOnNewLuaState, ULuaState*); + +class LUAMACHINE_API FLuaMachineModule : public IModuleInterface, public FGCObject, public FSelfRegisteringExec +{ +public: + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + + static FLuaMachineModule& Get(); + + void CleanupLuaStates(bool bIsSimulating); + void UnregisterLuaState(ULuaState* LuaState); + + ULuaState* GetLuaState(TSubclassOf LuaStateClass, UWorld* InWorld, bool bCheckOnly=false); + + TArray GetRegisteredLuaStates(); + + FOnNewLuaState OnNewLuaState; + FOnRegisteredLuaStatesChanged OnRegisteredLuaStatesChanged; + + void LuaLevelAddedToWorld(ULevel* Level, UWorld* World); + void LuaLevelRemovedFromWorld(ULevel* Level, UWorld* World); + + void AddReferencedObjects(FReferenceCollector& Collector) override; + + void RegisterLuaConsoleCommand(const FString& CommandName, const FLuaValue& LuaConsoleCommand); + void UnregisterLuaConsoleCommand(const FString& CommandName); + + void RunLuaConsoleCommand(const TArray& Args, FLuaValue LuaConsoleCommand); + +#if ENGINE_MAJOR_VERSION > 4 + virtual FString GetReferencerName() const override + { + return TEXT("FLuaMachineModule"); + } +#endif + + virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar); + +private: + TMap, ULuaState*> LuaStates; + TSet LuaConsoleCommands; +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaMultiLineEditableTextBox.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaMultiLineEditableTextBox.h new file mode 100644 index 00000000..08266a6a --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaMultiLineEditableTextBox.h @@ -0,0 +1,129 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Components/TextWidgetTypes.h" +#include "Components/MultiLineEditableTextBox.h" +#include "Runtime/Launch/Resources/Version.h" +#include "LuaMultiLineEditableTextBox.generated.h" + +USTRUCT(BlueprintType) +struct LUAMACHINE_API FLuaCustomHighlighter +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = "Lua") + FLinearColor Color; + + UPROPERTY(EditAnywhere, Category = "Lua") + TArray Tokens; + + FLuaCustomHighlighter(); +}; + +/** + * + */ +UCLASS(meta=(DisplayName="Lua Code Box")) +class LUAMACHINE_API ULuaMultiLineEditableTextBox : public UTextLayoutWidget +{ + GENERATED_BODY() + +public: + ULuaMultiLineEditableTextBox(); + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "Style")) + FEditableTextBoxStyle WidgetStyle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "Code Style")) + FTextBlockStyle CodeStyle; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "Comment Color")) + FLinearColor CommentColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "String Color")) + FLinearColor StringColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "Keyword Color")) + FLinearColor KeywordColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "Nil Color")) + FLinearColor NilColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "Basic Color")) + FLinearColor BasicColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style", meta = (DisplayName = "StdLib Color")) + FLinearColor StdLibColor; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lua Code", meta = (DisplayName = "Tab Size")) + int32 TabSize; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Appearance") + bool bIsReadonly; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lua Code") + bool bHandleTab; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lua Code") + bool bHandleArrows; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Style") + TArray CustomTokensMapping; + + UFUNCTION(BlueprintPure, Category = "Widget", meta = (DisplayName = "GetText (Lua Code Box)")) + FText GetText() const; + + UFUNCTION(BlueprintCallable, Category = "Widget", meta = (DisplayName = "SetText (Lua Code Box)")) + void SetText(FText InText); + + UFUNCTION(BlueprintPure, Category = "Widget", meta = (DisplayName = "GetCursorLine (Lua Code Box)")) + int32 GetCursorLine() const; + + UFUNCTION(BlueprintPure, Category = "Widget", meta = (DisplayName = "GetCursorColumn (Lua Code Box)")) + int32 GetCursorColumn() const; + + UFUNCTION(BlueprintCallable, Category = "Widget", meta = (DisplayName = "MoveCursorUp (Lua Code Box)")) + void MoveCursorUp(); + + UFUNCTION(BlueprintCallable, Category = "Widget", meta = (DisplayName = "MoveCursorDown (Lua Code Box)")) + void MoveCursorDown(); + + UFUNCTION(BlueprintCallable, Category = "Widget", meta = (DisplayName = "MoveCursorRight (Lua Code Box)")) + void MoveCursorRight(); + + UFUNCTION(BlueprintCallable, Category = "Widget", meta = (DisplayName = "MoveCursorLeft (Lua Code Box)")) + void MoveCursorLeft(); + + UFUNCTION(BlueprintCallable, Category = "Widget", meta = (DisplayName = "CursorGoTo (Lua Code Box)")) + void CursorGoTo(int32 Line, int32 Column); + + UFUNCTION(BlueprintPure, Category = "Widget", meta = (DisplayName = "GetSelectedText (Lua Code Box)")) + FText GetSelectedText() const; + + virtual FReply OnKeyChar(const FGeometry& InGeometry, const FCharacterEvent& InCharacterEvent); + + virtual FReply OnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent); + + virtual void OnCursorMoved(const FTextLocation& Location); + + virtual void SynchronizeProperties() override; + +#if WITH_EDITOR + virtual const FText GetPaletteCategory() override; +#endif + + virtual void ReleaseSlateResources(bool bReleaseChildren) override; + +protected: + virtual TSharedRef RebuildWidget() override; + + TSharedPtr EditableTextBoxPtr; + + FTextLocation CursorLocation; + +#if ENGINE_MAJOR_VERSION >=5 && ENGINE_MINOR_VERSION >= 1 + FEditableTextBoxStyle EditableTextBoxStyle; +#endif +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaObject.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaObject.h new file mode 100644 index 00000000..119af470 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaObject.h @@ -0,0 +1,67 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "LuaCode.h" +#include "LuaInterface.h" +#include "Engine/DataAsset.h" +#include "LuaObject.generated.h" + +USTRUCT(BlueprintType) +struct FLuaScriptContainer +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua",meta=(MultiLine)) + FString code_string; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua",meta=(MultiLine)) + ULuaCode* code_asset; +}; + +UCLASS() +class LUAMACHINE_API ULuaObject : public UPrimaryDataAsset, public ILuaInterface +{ + GENERATED_BODY() +public: + UPROPERTY() + FLuaValue lua_key; + UPROPERTY() + FLuaValue lua_value; + virtual void SetKey_Implementation(FLuaValue Key) override; + virtual void SetValue_Implementation(FLuaValue Value, const FString& Field) override; + virtual FLuaValue GetKey_Implementation() override; + virtual FLuaValue GetValue_Implementation(const FString& Field) override; +}; + + +UCLASS() +class LUAMACHINE_API ULuaObjectFunctions : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, Category="Lua|Object", meta=(WorldContext="WorldContextObject")) + static ULuaObject* CreateLuaObject(UObject* WorldContextObject, FLuaValue key, FLuaValue value); + + UFUNCTION(BlueprintCallable, Category="Lua|Object", meta=(WorldContext="WorldContextObject")) + static TArray CreateLuaObjectsFromTable(UObject* WorldContextObject,FLuaValue table); + + //Will create a list of objects with the keys from the "key" table, and their values from their corresponding "table" value. + UFUNCTION(BlueprintCallable, Category="Lua|Object", meta=(WorldContext="WorldContextObject")) + static TArray CreateLuaObjectsFromKeysInTable(UObject* WorldContextObject,FLuaValue keys,FLuaValue table); + + UFUNCTION(BlueprintCallable, Category="Lua|Object", meta=(WorldContext="WorldContextObject")) + static FLuaValue ConvertTableKeysToValues(UObject* WorldContextObject, FLuaValue table); + + UFUNCTION(BlueprintCallable, Category="Lua|Object", meta=(WorldContext="WorldContextObject", AdvancedDisplay="State")) + static FLuaValue RunLuaScriptContainer(UObject* WorldContextObject,FLuaScriptContainer Script,TSubclassOf State); + + UFUNCTION(BlueprintCallable, Category="Lua|Object", meta=(WorldContext="WorldContextObject", AdvancedDisplay="State")) + static void GetObjectKeyAndValue(UObject* Object, FLuaValue& Key,FLuaValue& Value); + + UFUNCTION(BlueprintCallable, Category="Lua|Object", meta=(WorldContext="WorldContextObject", AdvancedDisplay="State")) + static void SetObjectKeyAndValue(UObject* Object, FLuaValue Key,FLuaValue Value); +}; \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaSettings.cpp b/OmegaGameFramework/Source/LuaMachine/Public/LuaSettings.cpp new file mode 100644 index 00000000..17294abe --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaSettings.cpp @@ -0,0 +1,8 @@ +#include "LuaSettings.h" + + +ULuaSettings::ULuaSettings(const FObjectInitializer& ObjectInitializer) + : Super(ObjectInitializer) +{ + +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaSettings.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaSettings.h new file mode 100644 index 00000000..edde4c42 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaSettings.h @@ -0,0 +1,32 @@ + +#pragma once + +#include "CoreMinimal.h" +#include "LuaState.h" +#include "Engine/DeveloperSettings.h" +#include "UObject/SoftObjectPath.h" +#include "LuaSettings.generated.h" + +class ULuaObject; + +UCLASS(config = Game, defaultconfig, meta = (DisplayName = "Omega: Lua")) +class LUAMACHINE_API ULuaSettings : public UDeveloperSettings +{ + GENERATED_UCLASS_BODY() + +public: + + UPROPERTY(EditAnywhere, config, Category = "Default", meta = (MetaClass = "LuaState")) + TSoftClassPtr DefaultState; + UPROPERTY(EditAnywhere, config, Category = "Default", meta = (MetaClass = "LuaState")) + TSoftClassPtr DefaultObject; + UPROPERTY(EditAnywhere, config, Category = "Default") + bool bAutorunFiles=false; + UPROPERTY(EditAnywhere, config, Category = "Default") + FString Autorun_ContentPath="Lua"; + UPROPERTY(EditAnywhere, config, Category = "Default") + FString Autorun_InitFile="main"; + UPROPERTY(EditAnywhere, config, Category = "Default") + TArray> AutorunCodeAssets; +}; + diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaState.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaState.h new file mode 100644 index 00000000..85de3d8e --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaState.h @@ -0,0 +1,543 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/Blueprint.h" +#include "ThirdParty/lua/lua.hpp" +#include "LuaValue.h" +#include "LuaCode.h" +#include "Runtime/Core/Public/Containers/Queue.h" +#include "Runtime/Launch/Resources/Version.h" +#include "LuaDelegate.h" +#include "LuaCommandExecutor.h" +#include "LuaState.generated.h" + +LUAMACHINE_API DECLARE_LOG_CATEGORY_EXTERN(LogLuaMachine, Log, All); + +/** + * + */ + +class ULuaBlueprintPackage; + +struct FLuaUserData +{ + ELuaValueType Type; + // we use weak pointers as both fields can eventually be garbage collected + // while the lua VM hold a reference to the userdata + TWeakObjectPtr Context; + TWeakObjectPtr Function; + + // meaningful only for multicast delegates broadcasting + FMulticastScriptDelegate* MulticastScriptDelegate; + + FLuaUserData(UObject* InObject) + { + Type = ELuaValueType::UObject; + Context = InObject; + MulticastScriptDelegate = nullptr; + } + + FLuaUserData(UObject* InObject, UFunction* InFunction) + { + Type = ELuaValueType::UFunction; + Context = InObject; + Function = InFunction; + MulticastScriptDelegate = nullptr; + } +}; + +UENUM(BlueprintType) +enum class ELuaThreadStatus : uint8 +{ + Invalid, + Ok, + Suspended, + Error, +}; + +USTRUCT() +struct FLuaLibsLoader +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load base")) + bool bLoadBase; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load coroutine")) + bool bLoadCoroutine; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load table")) + bool bLoadTable; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load io")) + bool bLoadIO; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load os")) + bool bLoadOS; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load string")) + bool bLoadString; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load math")) + bool bLoadMath; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load utf8")) + bool bLoadUTF8; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load debug")) + bool bLoadDebug; + + FLuaLibsLoader() + : bLoadBase(true) + , bLoadCoroutine(true) + , bLoadTable(true) + , bLoadIO(true) + , bLoadOS(true) + , bLoadString(true) + , bLoadMath(true) + , bLoadUTF8(true) + , bLoadDebug(false) + {} + +}; + +USTRUCT(BlueprintType) +struct FLuaDebug +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + int32 CurrentLine; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + FString Source; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + FString Name; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + FString NameWhat; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + FString What; + + FLuaDebug() + : CurrentLine(0) + { + + } +}; + +USTRUCT(BlueprintType) +struct FLuaDelegateGroup +{ + GENERATED_BODY() + + UPROPERTY() + TArray LuaDelegates; +}; + + +struct FLuaSmartReference : public TSharedFromThis +{ + ULuaState* LuaState; + FLuaValue Value; +}; + + +class ULuaUserDataObject; + +UCLASS(Abstract, Blueprintable, HideDropdown) +class LUAMACHINE_API ULuaState : public UObject +{ + GENERATED_BODY() + +public: + ULuaState(); + ~ULuaState(); + + virtual UWorld* GetWorld() const override { return CurrentWorld; } + + UPROPERTY(EditAnywhere, Category = "Lua") + ULuaCode* LuaCodeAsset; + + UPROPERTY(EditAnywhere, Category = "Lua") + FString LuaFilename; + + UPROPERTY(EditAnywhere, Category = "Lua") + TMap Table; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Lua Blueprint Packages Table")) + TMap> LuaBlueprintPackagesTable; + + UPROPERTY(EditAnywhere, Category = "Lua") + TMap RequireTable; + + UPROPERTY(EditAnywhere, Category = "Lua") + bool bLuaOpenLibs; + + UPROPERTY(EditAnywhere, Category = "Lua", meta = (DisplayName = "Load Specific Lua Libraries (only if \"Lua Open Libs\" is false)")) + FLuaLibsLoader LuaLibsLoader; + + UPROPERTY(EditAnywhere, Category = "Lua") + bool bAddProjectContentDirToPackagePath; + + UPROPERTY(EditAnywhere, Category = "Lua") + TArray AppendProjectContentDirSubDir; + + UPROPERTY(EditAnywhere, Category = "Lua") + FString OverridePackagePath; + + UPROPERTY(EditAnywhere, Category = "Lua") + FString OverridePackageCPath; + + UPROPERTY(EditAnywhere, meta = (DisplayName = "UserData MetaTable from CodeAsset"), Category = "Lua") + ULuaCode* UserDataMetaTableFromCodeAsset; + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Error")) + void ReceiveLuaError(const FString& Message); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Line Hook")) + void ReceiveLuaLineHook(const FLuaDebug& LuaDebug); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Call Hook")) + void ReceiveLuaCallHook(const FLuaDebug& LuaDebug); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Return Hook")) + void ReceiveLuaReturnHook(const FLuaDebug& LuaDebug); + + // Not BlueprintNativeEvent, as throwing a luaL_error from an RTTI call results in leaving the VM in an unexpected + // state and will result in exceptions + UFUNCTION(Category = "Lua", meta = (DisplayName = "Lua Count Hook")) + virtual void ReceiveLuaCountHook(const FLuaDebug& LuaDebug); + + UFUNCTION(BlueprintCallable, Category = "Lua") + FLuaValue NewLuaUserDataObject(TSubclassOf LuaUserDataObjectClass, bool bTrackObject=true); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + FLuaDebug LuaGetInfo(const int32 Level); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + TMap LuaGetLocals(const int32 Level); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + TSubclassOf GetSelfLuaState() const { return GetClass(); } + + template + FLuaValue NewLuaUserDataObject(bool bTrackObject = true) + { + return NewLuaUserDataObject(T::StaticClass(), bTrackObject); + } + + UFUNCTION(BlueprintCallable, Category = "Lua") + void SetLuaUserDataField(FLuaValue UserData, const FString& Key, FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + FLuaValue GetLuaUserDataField(FLuaValue UserData, const FString& Key); + + UFUNCTION(BlueprintCallable, Category = "Lua") + FLuaValue GetLuaValueFromProperty(UObject* InObject, const FString& PropertyName); + + UFUNCTION(BlueprintCallable, Category = "Lua") + bool SetPropertyFromLuaValue(UObject* InObject, const FString& PropertyName, FLuaValue Value); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + FLuaValue GetLuaBlueprintPackageTable(const FString& PackageName); + + void FromLuaValue(FLuaValue& LuaValue, UObject* CallContext = nullptr, lua_State* State = nullptr); + FLuaValue ToLuaValue(int Index, lua_State* State = nullptr); + + ELuaThreadStatus GetLuaThreadStatus(FLuaValue Value); + int32 GetLuaThreadStackTop(FLuaValue Value); + + UPROPERTY(EditAnywhere, Category = "Lua") + bool bLogError; + + /* Enable it if you want this Lua state to not be destroyed during PIE. Useful for editor scripting */ + UPROPERTY(EditAnywhere, Category = "Lua") + bool bPersistent; + + /* Enable debug of each Lua line. The LuaLineHook event will be triggered */ + UPROPERTY(EditAnywhere, Category = "Lua") + bool bEnableLineHook; + + /* Enable debug of each Lua call. The LuaCallHook event will be triggered */ + UPROPERTY(EditAnywhere, Category = "Lua") + bool bEnableCallHook; + + /* Enable debug of each Lua return. The LuaReturnHook event will be triggered */ + UPROPERTY(EditAnywhere, Category = "Lua") + bool bEnableReturnHook; + + /* Enable debug for reaching a number of Lua instruction. The LuaCountHook event will be triggered */ + UPROPERTY(EditAnywhere, Category = "Lua") + bool bEnableCountHook; + + /* Number of instructions to wait for when the Count Hook is enabled */ + UPROPERTY(EditAnywhere, Category = "Lua", Meta = (EditCondition = "bEnableCountHook")) + int32 HookInstructionCount = 25000; + + UPROPERTY() + TMap LuaBlueprintPackages; + + TArray> LuaSmartReferences; + + UPROPERTY() + TArray TrackedLuaUserDataObjects; + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Level Added To World")) + void ReceiveLuaLevelAddedToWorld(ULevel* Level, UWorld* World); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua Level Removed From World")) + void ReceiveLuaLevelRemovedFromWorld(ULevel* Level, UWorld* World); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua State Pre Initialization")) + void ReceiveLuaStatePreInitialized(); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua State Initialized")) + void ReceiveLuaStateInitialized(); + + int32 GetTop(); + + FString LastError; + + int32 InceptionLevel; + + TQueue InceptionErrors; + + void NewTable(); + + void SetMetaTable(int Index); + void GetMetaTable(int Index); + + void SetField(int Index, const char* FieldName); + + void GetField(int Index, const char* FieldName); + + void NewUObject(UObject* Object, lua_State* State); + + void* NewUserData(size_t DataSize); + + void GetGlobal(const char* Name); + + int32 GetFieldFromTree(const FString& Tree, bool bGlobal = true); + + void SetFieldFromTree(const FString& Tree, FLuaValue& Value, bool bGlobal, UObject* CallContext = nullptr); + + void SetGlobal(const char* Name); + + void PushValue(int Index); + + void PushGlobalTable(); + + bool PCall(int NArgs, FLuaValue& Value, int NRet = 1); + bool Call(int NArgs, FLuaValue& Value, int NRet = 1); + + void Pop(int32 Amount = 1); + + void PushNil(); + + void Unref(int Ref); + void UnrefChecked(int Ref); + int NewRef(); + void GetRef(int Ref); + int Next(int Index); + + bool Resume(int Index, int NArgs); + bool Yield(int Index, int NArgs); + + int GC(int What, int Data = 0); + + int32 ToInteger(int Index); + + void Len(int Index); + + int32 ILen(int Index); + + void RawGetI(int Index, int N); + void RawSetI(int Index, int N); + + void PushCFunction(lua_CFunction Function); + + ULuaState* GetLuaState(UWorld* InWorld); + + bool RunCode(const TArray& Code, const FString& CodePath, int NRet = 0); + bool RunCode(const FString& Code, const FString& CodePath, int NRet = 0); + + bool RunCodeAsset(ULuaCode* CodeAsset, int NRet = 0); + + FLuaValue CreateLuaTable(); + FLuaValue CreateLuaThread(FLuaValue Value); + + FLuaValue CreateLuaLazyTable(); + + bool RunFile(const FString& Filename, bool bIgnoreNonExistent, int NRet = 0, bool bNonContentDirectory=false); + + static int MetaTableFunctionUserData__index(lua_State* L); + static int MetaTableFunctionUserData__newindex(lua_State* L); + + static int TableFunction_print(lua_State* L); + static int TableFunction_package_preload(lua_State* L); + static int TableFunction_package_loader(lua_State* L); + static int TableFunction_package_loader_codeasset(lua_State* L); + static int TableFunction_package_loader_asset(lua_State* L); + + static int MetaTableFunction__call(lua_State* L); + static int MetaTableFunction__rawcall(lua_State* L); + static int MetaTableFunction__rawbroadcast(lua_State* L); + + static int MetaTableFunctionUserData__eq(lua_State* L); + static int MetaTableFunctionUserData__gc(lua_State* L); + + static int ToByteCode_Writer(lua_State* L, const void* Ptr, size_t Size, void* UserData); + + static void Debug_Hook(lua_State* L, lua_Debug* ar); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + static TArray ToByteCode(const FString& Code, const FString& CodePath, FString& ErrorString); + +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FLuaValue FromUProperty(void* Buffer, FProperty* Property, bool& bSuccess, int32 Index = 0); + void ToUProperty(void* Buffer, FProperty* Property, FLuaValue Value, bool& bSuccess, int32 Index = 0); + FLuaValue FromFProperty(void* Buffer, FProperty* Property, bool& bSuccess, int32 Index = 0); + void ToFProperty(void* Buffer, FProperty* Property, FLuaValue Value, bool& bSuccess, int32 Index = 0); + FLuaValue FromProperty(void* Buffer, FProperty* Property, bool& bSuccess, int32 Index = 0); + void ToProperty(void* Buffer, FProperty* Property, FLuaValue Value, bool& bSuccess, int32 Index = 0); +#else + FLuaValue FromUProperty(void* Buffer, UProperty* Property, bool& bSuccess, int32 Index = 0); + void ToUProperty(void* Buffer, UProperty* Property, FLuaValue Value, bool& bSuccess, int32 Index = 0); + FLuaValue FromProperty(void* Buffer, UProperty* Property, bool& bSuccess, int32 Index = 0); + void ToProperty(void* Buffer, UProperty* Property, FLuaValue Value, bool& bSuccess, int32 Index = 0); +#endif + + static ULuaState* GetFromExtraSpace(lua_State* L) + { + ULuaState** LuaExtraSpacePtr = (ULuaState**)lua_getextraspace(L); + return *LuaExtraSpacePtr; + } + + void Log(const FString& Message) + { + UE_LOG(LogLuaMachine, Log, TEXT("%s"), *Message); + } + + void LogWarning(const FString& Message) + { + UE_LOG(LogLuaMachine, Warning, TEXT("%s"), *Message); + } + + void LogError(const FString& Message) + { + UE_LOG(LogLuaMachine, Error, TEXT("%s"), *Message); + } + + void SetUserDataMetaTable(FLuaValue MetaTable); + + FORCEINLINE lua_State* GetInternalLuaState() const { return L; } + + void PushRegistryTable(); + + TSharedRef AddLuaSmartReference(FLuaValue Value); + void RemoveLuaSmartReference(TSharedRef Ref); + + void SetupAndAssignUserDataMetatable(UObject* Context, TMap& Metatable, lua_State* State); + + const void* ToPointer(int Index); + + UPROPERTY(EditAnywhere, Category = "Lua") + bool bRawLuaFunctionCall; + + void GCLuaDelegatesCheck(); + + void RegisterLuaDelegate(UObject* InObject, ULuaDelegate* InLuaDelegate); + void UnregisterLuaDelegatesOfObject(UObject* InObject); + + TArray GetPropertiesNames(UObject* InObject); + TArray GetFunctionsNames(UObject* InObject); + + FLuaValue StructToLuaTable(UScriptStruct* InScriptStruct, const uint8* StructData); + + UFUNCTION(BlueprintCallable, Category = "Lua") + FLuaValue StructToLuaTable(UScriptStruct* InScriptStruct, const TArray& StructData); + + void LuaTableToStruct(FLuaValue& LuaValue, UScriptStruct* InScriptStruct, uint8* StructData); + + template + FLuaValue StructToLuaValue(T& InStruct) + { + return StructToLuaTable(T::StaticStruct(), (const uint8*)&InStruct); + } + + template + T LuaValueToStruct(FLuaValue& LuaValue) + { + T InStruct; + LuaTableToStruct(LuaValue, T::StaticStruct(), (uint8*)&InStruct); + return InStruct; + } + + template + T LuaValueToBaseStruct(FLuaValue& LuaValue) + { + T InStruct; + LuaTableToStruct(LuaValue, TBaseStructure::Get(), (uint8*)&InStruct); + return InStruct; + } + + FORCEINLINE FLuaCommandExecutor* GetLuaConsole() { return &LuaConsole; } + + UFUNCTION(BlueprintCallable, Category = "Lua") + void AddLuaValueToLuaState(const FString& Name, FLuaValue LuaValue); + + UFUNCTION(BlueprintCallable, Category = "Lua") + FLuaValue RunString(const FString& CodeString, FString CodePath); + +protected: + lua_State* L; + bool bDisabled; + + UWorld* CurrentWorld; + + FLuaValue UserDataMetaTable; + + virtual void LuaStateInit(); + + FDelegateHandle GCLuaDelegatesHandle; + + UPROPERTY() + TMap, FLuaDelegateGroup> LuaDelegatesMap; + + FLuaCommandExecutor LuaConsole; +}; + +#define LUACFUNCTION(FuncClass, FuncName, NumRetValues, NumArgs) static int FuncName ## _C(lua_State* L)\ +{\ + FuncClass* LuaState = (FuncClass*)ULuaState::GetFromExtraSpace(L);\ + int TrueNumArgs = lua_gettop(L);\ + if (TrueNumArgs != NumArgs)\ + {\ + return luaL_error(L, "invalid number of arguments for %s (got %d, expected %d)", #FuncName, TrueNumArgs, NumArgs);\ + }\ + TArray LuaArgs;\ + for (int32 LuaArgIndex = 0; LuaArgIndex < NumArgs; LuaArgIndex++)\ + {\ + LuaArgs.Add(LuaState->ToLuaValue(LuaArgIndex + 1, L));\ + }\ + FLuaValue NilValue;\ + TArray RetValues = LuaState->FuncName(LuaArgs);\ + for (int32 RetIndex = 0; RetIndex < NumRetValues; RetIndex++)\ + {\ + if (RetIndex < RetValues.Num())\ + {\ + LuaState->FromLuaValue(RetValues[RetIndex]);\ + }\ + else\ + {\ + LuaState->FromLuaValue(NilValue);\ + }\ + }\ + return NumRetValues;\ +}\ +TArray FuncName(TArray LuaArgs) \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaSubsystem.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaSubsystem.h new file mode 100644 index 00000000..0ecf4167 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaSubsystem.h @@ -0,0 +1,33 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "LuaSubsystem.generated.h" + +class ULuaSettings; +/** + * + */ +UCLASS() +class LUAMACHINE_API ULuaSubsystem : public UGameInstanceSubsystem +{ + GENERATED_BODY() + + virtual void Initialize(FSubsystemCollectionBase& Collection) override; + + UPROPERTY() + ULuaSettings* settings_ref; + +public: + UFUNCTION(BlueprintPure,Category="Lua") + FString GetLocalFilesPath(); + + UFUNCTION(BlueprintCallable,Category="Lua") + FLuaValue RunLocalFile(const FString& file); + + UFUNCTION(BlueprintCallable,Category="Lua") + void RunLocalFilesInPath(const FString& path,bool bRecursive); +}; + diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaSyntaxHighlighter.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaSyntaxHighlighter.h new file mode 100644 index 00000000..e873d5d1 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaSyntaxHighlighter.h @@ -0,0 +1,36 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "Runtime/Slate/Public/Framework/Text/SyntaxHighlighterTextLayoutMarshaller.h" + +struct FLuaSyntaxTextStyle +{ + FTextBlockStyle NormalTextStyle; + FTextBlockStyle CommentTextStyle; + FTextBlockStyle StringTextStyle; + FTextBlockStyle KeywordTextStyle; + FTextBlockStyle NilTextStyle; + FTextBlockStyle BasicTextStyle; + FTextBlockStyle StdLibTextStyle; + TMap CustomTextColorMapping; + TMap CustomTextStyleMapping; +}; + + +class LUAMACHINE_API FLuaMachineSyntaxHighlighterTextLayoutMarshaller : public FSyntaxHighlighterTextLayoutMarshaller +{ +public: + + FLuaMachineSyntaxHighlighterTextLayoutMarshaller(TSharedPtr InTokenizer, TArray InBasicTokens, TArray InStdLibTokens, FLuaSyntaxTextStyle InLuaSyntaxTextStyle); + + static TSharedRef Create(FLuaSyntaxTextStyle LuaSyntaxTextStyle); + +protected: + virtual void ParseTokens(const FString& SourceString, FTextLayout& TargetTextLayout, TArray TokenizedLines) override; + + TArray BasicTokens; + TArray StdLibTokens; + + FLuaSyntaxTextStyle SyntaxTextStyle; +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaTableAsset.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaTableAsset.h new file mode 100644 index 00000000..a92f91eb --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaTableAsset.h @@ -0,0 +1,25 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Engine/DataAsset.h" +#include "LuaState.h" +#include "LuaValue.h" +#include "LuaTableAsset.generated.h" + +/** + * + */ +UCLASS(BlueprintType) +class LUAMACHINE_API ULuaTableAsset : public UDataAsset +{ + GENERATED_BODY() + +public: + + UPROPERTY(EditAnywhere, Category = "Lua") + TMap Table; + + FLuaValue ToLuaTable(ULuaState* LuaState); +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaUserDataObject.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaUserDataObject.h new file mode 100644 index 00000000..ff6e01fe --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaUserDataObject.h @@ -0,0 +1,64 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "LuaState.h" +#include "LuaUserDataObject.generated.h" + +/** + * + */ +UCLASS(Abstract, Blueprintable, HideDropdown) +class LUAMACHINE_API ULuaUserDataObject : public UObject +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + TSubclassOf GetLuaState() const; + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + ULuaState* GetLuaStateInstance() const; + + virtual UWorld* GetWorld() const override; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + TMap Table; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + TMap Metatable; + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Lua") + bool bImplicitSelf; + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + FLuaValue LuaGetField(const FString& Name); + + UFUNCTION(BlueprintCallable, Category = "Lua") + void LuaSetField(const FString& Name, FLuaValue Value); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua UserData Metatable __gc")) + void ReceiveLuaGC(); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua UserData Metatable __index")) + FLuaValue ReceiveLuaMetaIndex(FLuaValue Key); + + UFUNCTION(BlueprintNativeEvent, Category = "Lua", meta = (DisplayName = "Lua UserData Table Init")) + void ReceiveLuaUserDataTableInit(); + + UFUNCTION(BlueprintCallable, Category = "Lua", meta = (AutoCreateRefTerm = "Args")) + FLuaValue LuaCallFunction(const FString& Name, TArray Args, bool bGlobal); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + FLuaValue UFunctionToLuaValue(const FString& FunctionName); + + UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Lua") + TArray GetObjectUFunctions(bool bOnlyPublic=true); + +protected: + TSharedPtr AddLuaSmartReference(FLuaValue Value); + void RemoveLuaSmartReference(TSharedPtr Ref); +}; diff --git a/OmegaGameFramework/Source/LuaMachine/Public/LuaValue.h b/OmegaGameFramework/Source/LuaMachine/Public/LuaValue.h new file mode 100644 index 00000000..e551c155 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachine/Public/LuaValue.h @@ -0,0 +1,199 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "ThirdParty/lua/lua.hpp" +#include "Serialization/JsonSerializer.h" +#include "LuaValue.generated.h" + +// required for Mac +#ifdef Nil +#undef Nil +#endif + +/** + * + */ + +UENUM(BlueprintType) +enum class ELuaValueType : uint8 +{ + Nil, + Bool, + Integer, + Number, + String, + Function, + Table, + UFunction, + UObject, + Thread, + MulticastDelegate, +}; + +class ULuaState; + +USTRUCT(BlueprintType) +struct LUAMACHINE_API FLuaValue +{ + GENERATED_BODY() + + FLuaValue() + { + Type = ELuaValueType::Nil; + Object = nullptr; + LuaRef = LUA_NOREF; + LuaState = nullptr; + Bool = false; + Integer = 0; + Number = 0; + MulticastScriptDelegate = nullptr; + } + + FLuaValue(const FLuaValue& SourceValue); + FLuaValue& operator = (const FLuaValue &SourceValue); + + FLuaValue(const FString& InString) : FLuaValue() + { + Type = ELuaValueType::String; + String = InString; + } + + FLuaValue(const char* InChars) : FLuaValue(FString(InChars)) + { + } + + FLuaValue(const TCHAR* InChars) : FLuaValue(FString(InChars)) + { + } + + FLuaValue(const char* InChars, size_t Length) : FLuaValue() + { + Type = ELuaValueType::String; + for (size_t i = 0; i < Length; i++) + { + uint16 TChar = (uint16)InChars[i]; + // cleanup garbage + TChar &= 0xFF; + // hack for allowing binary data + if (TChar == 0) + TChar = 0xffff; + String += (TCHAR)TChar; + } + } + + FLuaValue(TArray InBytes) : FLuaValue((const char*)InBytes.GetData(), InBytes.Num()) + { + } + + FLuaValue(double Value) : FLuaValue() + { + Type = ELuaValueType::Number; + Number = Value; + } + + FLuaValue(float Value) : FLuaValue() + { + Type = ELuaValueType::Number; + Number = Value; + } + + FLuaValue(int32 Value) : FLuaValue() + { + Type = ELuaValueType::Integer; + Integer = Value; + } + + FLuaValue(bool bInBool) : FLuaValue() + { + Type = ELuaValueType::Bool; + Bool = bInBool; + } + + FLuaValue(UObject* InObject) : FLuaValue() + { + if (InObject) + { + Type = ELuaValueType::UObject; + Object = InObject; + } + } + + ~FLuaValue(); + + static FLuaValue Function(FName FunctionName) + { + FLuaValue LuaValue; + LuaValue.Type = ELuaValueType::UFunction; + LuaValue.FunctionName = FunctionName; + return LuaValue; + } + + static FLuaValue FunctionOfObject(UObject* InObject, FName FunctionName) + { + FLuaValue LuaValue; + LuaValue.Type = ELuaValueType::UFunction; + LuaValue.Object = InObject; + LuaValue.FunctionName = FunctionName; + return LuaValue; + } + + FString ToString() const; + FName ToName() const; + int32 ToInteger() const; + double ToFloat() const; + bool ToBool() const; + + TArray ToBytes() const; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + ELuaValueType Type; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + bool Bool; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + int32 Integer; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + double Number; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + FString String; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + UObject* Object; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Lua") + FName FunctionName; + + int LuaRef; + + TWeakObjectPtr LuaState; + + FLuaValue GetField(const FString& Key); + FLuaValue SetField(const FString& Key, FLuaValue Value); + + FLuaValue SetField(const FString& Key, lua_CFunction CFunction); + + FLuaValue GetFieldByIndex(const int32 Index); + FLuaValue SetFieldByIndex(const int32 Index, FLuaValue Value); + + FLuaValue SetMetaTable(FLuaValue MetaTable); + + bool IsReferencedInLuaRegistry() const; + + static FLuaValue FromJsonValue(ULuaState* L, FJsonValue& JsonValue); + TSharedPtr ToJsonValue(); + + static FLuaValue FromBase64(const FString& Base64); + FString ToBase64() const; + + bool IsNil() const; + + void Unref(); + + FMulticastScriptDelegate* MulticastScriptDelegate = nullptr; +}; diff --git a/OmegaGameFramework/Source/LuaMachineEditor/LuaMachineEditor.Build.cs b/OmegaGameFramework/Source/LuaMachineEditor/LuaMachineEditor.Build.cs new file mode 100644 index 00000000..3e80a110 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/LuaMachineEditor.Build.cs @@ -0,0 +1,58 @@ +// Copyright 2018-2023 - Roberto De Ioris + +using UnrealBuildTool; + +public class LuaMachineEditor : ModuleRules +{ + public LuaMachineEditor(ReadOnlyTargetRules Target) : base(Target) + { + PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; + + PublicIncludePaths.AddRange( + new string[] { + // ... add public include paths required here ... + } + ); + + + PrivateIncludePaths.AddRange( + new string[] { + // ... add other private include paths required here ... + } + ); + + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + // ... add other public dependencies that you statically link with here ... + } + ); + + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + // ... add private dependencies that you statically link with here ... + "UnrealEd", + "Projects", + "InputCore", + "EditorStyle", + "LuaMachine" + } + ); + + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + } +} diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaCodeCustomization.cpp b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaCodeCustomization.cpp new file mode 100644 index 00000000..82b45bb5 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaCodeCustomization.cpp @@ -0,0 +1,192 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaCodeCustomization.h" +#include "LuaMachineEditor.h" +#include "Runtime/Slate/Public/Widgets/Input/SMultiLineEditableTextBox.h" +#include "Editor/PropertyEditor/Public/PropertyHandle.h" +#include "Editor/PropertyEditor/Public/DetailLayoutBuilder.h" +#include "Editor/PropertyEditor/Public/DetailCategoryBuilder.h" +#include "Editor/PropertyEditor/Public/IDetailChildrenBuilder.h" +#include "Editor/PropertyEditor/Public/DetailWidgetRow.h" +#include "Runtime/Slate/Public/Widgets/Text/STextBlock.h" +#include "Runtime/SlateCore/Public/Brushes/SlateColorBrush.h" +#include "Runtime/Slate/Public/Widgets/Text/SlateEditableTextLayout.h" +#include "Runtime/SlateCore/Public/Fonts/FontMeasure.h" +#include "Runtime/Slate/Public/Framework/Application/SlateApplication.h" +#include "Runtime/Slate/Public/Framework/MultiBox/MultiBoxBuilder.h" +#include "LuaMachine/Public/LuaCode.h" +#include "LuaMachine/Public/LuaSyntaxHighlighter.h" + + +class SLuaMultiLineEditableTextBox : public SMultiLineEditableTextBox +{ +public: + SLATE_BEGIN_ARGS(SLuaMultiLineEditableTextBox) {} + + SLATE_ARGUMENT(TWeakObjectPtr, LuaCodeOwner); + + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs) + { + LuaCode = InArgs._LuaCodeOwner; + CurrentLine = 1; + CurrentColumn = 1; + + FLuaSyntaxTextStyle LuaTextStyle; + + LuaTextStyle.NormalTextStyle = FLuaMachineEditorModule::Get().GetStyleSet()->GetWidgetStyle("SyntaxHighlight.LuaMachine.Normal"); + LuaTextStyle.CommentTextStyle = FLuaMachineEditorModule::Get().GetStyleSet()->GetWidgetStyle("SyntaxHighlight.LuaMachine.Comment"); + LuaTextStyle.StringTextStyle = FLuaMachineEditorModule::Get().GetStyleSet()->GetWidgetStyle("SyntaxHighlight.LuaMachine.String"); + LuaTextStyle.KeywordTextStyle = FLuaMachineEditorModule::Get().GetStyleSet()->GetWidgetStyle("SyntaxHighlight.LuaMachine.Keyword"); + LuaTextStyle.NilTextStyle = FLuaMachineEditorModule::Get().GetStyleSet()->GetWidgetStyle("SyntaxHighlight.LuaMachine.Nil"); + LuaTextStyle.BasicTextStyle = FLuaMachineEditorModule::Get().GetStyleSet()->GetWidgetStyle("SyntaxHighlight.LuaMachine.Basic"); + LuaTextStyle.StdLibTextStyle = FLuaMachineEditorModule::Get().GetStyleSet()->GetWidgetStyle("SyntaxHighlight.LuaMachine.StdLib"); + + SyntaxHighlighter = FLuaMachineSyntaxHighlighterTextLayoutMarshaller::Create(LuaTextStyle); + + FMenuExtensionDelegate Delegate; + Delegate.BindLambda([&](FMenuBuilder &Builder) + { + Builder.AddWidget(SNew(STextBlock).Text_Lambda([&]() { + return FText::FromString(FString::Printf(TEXT("Line: %d Column: %d"), CurrentLine, CurrentColumn)); + }), FText::GetEmpty()); + + }); + + SMultiLineEditableTextBox::Construct( + SMultiLineEditableTextBox::FArguments() + .AutoWrapText(false) + .Margin(0.0f) + .Text(LuaCode->Code) + .Marshaller(SyntaxHighlighter) + .OnTextChanged(this, &SLuaMultiLineEditableTextBox::UpdateLuaCode) + .BackgroundColor(FSlateColor(FLinearColor::Black)) + .ForegroundColor(FSlateColor(FLinearColor::White)) + .ContextMenuExtender(Delegate) + .OnCursorMoved_Lambda([&](const FTextLocation& Location) { + CurrentLine = Location.GetLineIndex() + 1; + CurrentColumn = Location.GetOffset() + 1; + }) + ); + + } + + void UpdateLuaCode(const FText& InCode) + { + LuaCode->Code = InCode; + LuaCode->MarkPackageDirty(); + } + +protected: + + int32 CurrentLine; + int32 CurrentColumn; + + float GetFontHeight(const FSlateFontInfo& FontInfo) const + { + const TSharedRef FontMeasure = FSlateApplication::Get().GetRenderer()->GetFontMeasureService(); + return FontMeasure->GetMaxCharacterHeight(FontInfo); + } + + virtual FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) const override + { + float MinimumHeight = 500; + float MaxHeight = 800; + + FVector2D Size = SMultiLineEditableTextBox::ComputeDesiredSize(LayoutScaleMultiplier); + if (Size.Y < MinimumHeight) + Size.Y = MinimumHeight; + if (Size.Y > MaxHeight) + Size.Y = MaxHeight; + return Size; + } + + virtual FReply OnKeyChar(const FGeometry& InGeometry, const FCharacterEvent& InCharacterEvent) override + { + const TCHAR Character = InCharacterEvent.GetCharacter(); + if (Character == TEXT('\t')) + { + ClearSelection(); + InsertTextAtCursor(FString(" ")); + return FReply::Handled(); + } + return SMultiLineEditableTextBox::OnKeyChar(InGeometry, InCharacterEvent); + } + + virtual FReply OnKeyDown(const FGeometry& InGeometry, const FKeyEvent& InKeyEvent) override + { + + if (InKeyEvent.GetKeyCode() == 9) + { + return FReply::Handled(); + } + return SMultiLineEditableTextBox::OnKeyDown(InGeometry, InKeyEvent); + } + +private: + TWeakObjectPtr LuaCode; + TSharedPtr SyntaxHighlighter; +}; + +class SLuaEditor : public SCompoundWidget +{ +public: + SLATE_BEGIN_ARGS(SLuaEditor) {} + + SLATE_ARGUMENT(TWeakObjectPtr, LuaCodeOwner); + + SLATE_END_ARGS() + + void Construct(const FArguments& InArgs) + { + LuaCode = InArgs._LuaCodeOwner; + + BackgroundColor = FSlateColorBrush(FLinearColor::Black); + + ChildSlot.Padding(4)[ + SNew(SBorder).BorderImage(&BackgroundColor).BorderBackgroundColor(FSlateColor(FLinearColor::White)) + [ + + SNew(SLuaMultiLineEditableTextBox) + .LuaCodeOwner(LuaCode) + + ] + ]; + } + + + +private: + TWeakObjectPtr LuaCode; + FSlateBrush BackgroundColor; +}; + +void FLuaCodeCustomization::CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) +{ + TArray> Objects; + DetailBuilder.GetObjectsBeingCustomized(Objects); + + if (Objects.Num() != 1) + { + return; + } + + TWeakObjectPtr LuaCode = Cast(Objects[0].Get()); + + TSharedRef Prop = DetailBuilder.GetProperty(GET_MEMBER_NAME_CHECKED(ULuaCode, Code)); + DetailBuilder.HideProperty(Prop); + + + IDetailCategoryBuilder& Category = DetailBuilder.EditCategory("Code"); + Category.AddCustomRow(FText::FromString("Code")).WholeRowContent()[ + + SNew(SLuaEditor).LuaCodeOwner(LuaCode) + + ]; + +} + + + + diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaCodeFactory.cpp b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaCodeFactory.cpp new file mode 100644 index 00000000..a73c51a0 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaCodeFactory.cpp @@ -0,0 +1,152 @@ +// Copyright 2018-2023 - Roberto De Ioris +// Reimport system by yama2akira (Akira Yamamoto) + +#include "LuaCodeFactory.h" +#include "LuaCode.h" +#include "EditorFramework/AssetImportData.h" +#include "Misc/FileHelper.h" +#include "LuaMachineEditor.h" + +ULuaCodeFactory::ULuaCodeFactory(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { + + Formats.Add(FString("lua;Lua Script")); + + bCreateNew = true; + bEditAfterNew = true; + + bEditorImport = true; + + SupportedClass = ULuaCode::StaticClass(); +} + +UObject* ULuaCodeFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) +{ + return NewObject(InParent, InClass, InName, Flags); +} + +UObject* ULuaCodeFactory::FactoryCreateBinary(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn, bool& bOutOperationCanceled) +{ + bOutOperationCanceled = false; + FString Code = ANSI_TO_TCHAR((const char*)Buffer); + ULuaCode *NewAsset = NewObject(InParent, InClass, InName, Flags); + NewAsset->Code = FText::FromString(Code); + + if (NewAsset->AssetImportData != nullptr) { + NewAsset->AssetImportData->Update(GetCurrentFilename()); + NewAsset->MarkPackageDirty(); + } + return NewAsset; +} + +uint32 ULuaCodeFactory::GetMenuCategories() const +{ + return FLuaMachineEditorModule::Get().GetAssetCategory(); +} + +bool ULuaCodeFactory::CanReimport(UObject* Obj, TArray& OutFilenames) +{ + ULuaCode* Asset = Cast(Obj); + if (Asset && Asset->AssetImportData) + { + Asset->AssetImportData->ExtractFilenames(OutFilenames); + + for (auto FileName : OutFilenames) + { + FString FileContent; + if (FFileHelper::LoadFileToString(/*out*/ FileContent, *FileName)) + { + if (Asset->Code.ToString().Compare(FileContent) == 0) + { + return false; + } + } + } + return true; + } + return false; +} + +void ULuaCodeFactory::SetReimportPaths(UObject* Obj, const TArray& NewReimportPaths) +{ + ULuaCode* Asset = Cast(Obj); + if (Asset && ensure(NewReimportPaths.Num() == 1)) + { + Asset->AssetImportData->UpdateFilenameOnly(NewReimportPaths[0]); + } +} + +EReimportResult::Type ULuaCodeFactory::Reimport(UObject* Obj) +{ + ULuaCode* Asset = Cast(Obj); + if (!Asset) + { + return EReimportResult::Failed; + } + + const FString Filename = Asset->AssetImportData->GetFirstFilename(); + if (!Filename.Len() || IFileManager::Get().FileSize(*Filename) == INDEX_NONE) + { + return EReimportResult::Failed; + } + + EReimportResult::Type Result = EReimportResult::Failed; + if (UFactory::StaticImportObject( + Asset->GetClass(), Asset->GetOuter(), + *Asset->GetName(), RF_Public | RF_Standalone, *Filename, NULL, this)) + { + if (Asset->GetOuter()) + { + Asset->GetOuter()->MarkPackageDirty(); + } + else + { + Asset->MarkPackageDirty(); + } + return EReimportResult::Succeeded; + } + + return EReimportResult::Failed; +} + +FLuaCodeAssetTypeActions::FLuaCodeAssetTypeActions( EAssetTypeCategories::Type InAssetCategory ) +{ + +} + +FText FLuaCodeAssetTypeActions::GetName() const +{ + return NSLOCTEXT( "LuaMachine", "LuaCodeAssetActions", "Lua Code" ); +} + +FColor FLuaCodeAssetTypeActions::GetTypeColor() const +{ + return FColor::Red; +} + +UClass* FLuaCodeAssetTypeActions::GetSupportedClass() const +{ + return ULuaCode::StaticClass(); +} + +uint32 FLuaCodeAssetTypeActions::GetCategories() +{ + return FLuaMachineEditorModule::Get().GetAssetCategory(); +} + +bool FLuaCodeAssetTypeActions::IsImportedAsset() const +{ + return true; +} + +void FLuaCodeAssetTypeActions::GetResolvedSourceFilePaths( const TArray& TypeAssets, TArray& OutSourceFilePaths ) const +{ + for ( auto& Asset : TypeAssets ) + { + const auto LuaCode = CastChecked( Asset ); + if ( LuaCode->AssetImportData ) + { + LuaCode->AssetImportData->ExtractFilenames( OutSourceFilePaths ); + } + } +} + diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaMachineEditor.cpp b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaMachineEditor.cpp new file mode 100644 index 00000000..a6250a7c --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaMachineEditor.cpp @@ -0,0 +1,547 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaMachineEditor.h" +#include "Editor/UnrealEd/Public/Editor.h" +#include "Editor/PropertyEditor/Public/PropertyEditorModule.h" +#include "EditorStyleSet.h" +#include "Runtime/Projects/Public/Interfaces/IPluginManager.h" +#include "SlateCore/Public/Styling/SlateStyleRegistry.h" +#include "LuaCodeCustomization.h" +#include "LuaValueCustomization.h" +#include "Editor/WorkspaceMenuStructure/Public/WorkspaceMenuStructure.h" +#include "Editor/WorkspaceMenuStructure/Public/WorkspaceMenuStructureModule.h" +#include "Runtime/Slate/Public/Widgets/Text/STextBlock.h" +#include "Runtime/Slate/Public/Widgets/Views/STreeView.h" +#include "Runtime/Slate/Public/Widgets/Input/SButton.h" +#include "Runtime/Slate/Public/Widgets/Input/STextComboBox.h" +#include "LuaMachine/Public/LuaMachine.h" +#include "LuaMachine/Public/LuaBlueprintFunctionLibrary.h" +#include "Widgets/Layout/SScrollBox.h" +#include "LuaUserDataObject.h" +#include "LuaCodeFactory.h" + +#define LOCTEXT_NAMESPACE "FLuaMachineEditorModule" + +FLuaMachineEditorModule::FLuaMachineEditorModule() + : LuaMachineAssetCategoryBit(EAssetTypeCategories::Misc) +{ + +} + +void FLuaMachineEditorModule::StartupModule() +{ + FCoreDelegates::OnPostEngineInit.AddRaw(this, &FLuaMachineEditorModule::OnPostEngineInit); + + // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module + + StyleSet = MakeShareable(new FSlateStyleSet("LuaMachineEditor")); + StyleSet->SetContentRoot(IPluginManager::Get().FindPlugin("OmegaGameFramework")->GetBaseDir() / "Resources"); + StyleSet->Set("ClassThumbnail.LuaCode", new FSlateImageBrush(StyleSet->RootToContentDir("ico_LuaAsset.png"), FVector2D(128.0f, 128.0f))); + StyleSet->Set("ClassThumbnail.LuaTableAsset", new FSlateImageBrush(StyleSet->RootToContentDir("ico_LuaTable.png"), FVector2D(256.0f, 256.0f))); + + const FSlateFontInfo Consolas9 = FCoreStyle::GetDefaultFontStyle("Mono", 9); + + const FTextBlockStyle CodeBaseStyle = FTextBlockStyle() + .SetFont(Consolas9) + .SetColorAndOpacity(FLinearColor::White) + .SetShadowOffset(FVector2D::ZeroVector) + .SetShadowColorAndOpacity(FLinearColor::Black); + + StyleSet->Set("SyntaxHighlight.LuaMachine.Normal", CodeBaseStyle); + StyleSet->Set("SyntaxHighlight.LuaMachine.Comment", FTextBlockStyle(CodeBaseStyle).SetColorAndOpacity(FLinearColor::Green)); + StyleSet->Set("SyntaxHighlight.LuaMachine.String", FTextBlockStyle(CodeBaseStyle).SetColorAndOpacity(FLinearColor(FColor::Orange))); + StyleSet->Set("SyntaxHighlight.LuaMachine.Keyword", FTextBlockStyle(CodeBaseStyle).SetColorAndOpacity(FLinearColor(FColor::Cyan))); + StyleSet->Set("SyntaxHighlight.LuaMachine.Nil", FTextBlockStyle(CodeBaseStyle).SetColorAndOpacity(FLinearColor::Red)); + StyleSet->Set("SyntaxHighlight.LuaMachine.StdLib", FTextBlockStyle(CodeBaseStyle).SetColorAndOpacity(FLinearColor::Yellow)); + StyleSet->Set("SyntaxHighlight.LuaMachine.Basic", FTextBlockStyle(CodeBaseStyle).SetColorAndOpacity(FLinearColor::FromSRGBColor(FColor::Magenta))); + + FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get()); + + FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked(TEXT("PropertyEditor")); + + PropertyModule.RegisterCustomPropertyTypeLayout(TEXT("LuaValue"), FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FLuaValueCustomization::MakeInstance)); + PropertyModule.RegisterCustomClassLayout(TEXT("LuaCode"), FOnGetDetailCustomizationInstance::CreateStatic(&FLuaCodeCustomization::MakeInstance)); + + PropertyModule.NotifyCustomizationModuleChanged(); + + FGlobalTabmanager::Get()->RegisterNomadTabSpawner("LuaMachineDebugger", FOnSpawnTab::CreateStatic(&FLuaMachineEditorModule::CreateLuaMachineDebugger)) + .SetDisplayName(LOCTEXT("LuaMachine Debugger", "LuaMachine Debugger")) + .SetTooltipText(LOCTEXT("Open the LuaMachine Debugger", "Open the LuaMachine Debugger")) + .SetIcon(FSlateIcon( +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 1 + FAppStyle::GetAppStyleSetName() +#else + FEditorStyle::GetStyleSetName() +#endif + , "DebugTools.TabIcon")) + .SetGroup(WorkspaceMenu::GetMenuStructure().GetDeveloperToolsMiscCategory()); +} + +void FLuaMachineEditorModule::OnPostEngineInit() +{ + IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); + + LuaMachineAssetCategoryBit = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("LuaMachine")), LOCTEXT("AssetCategory", "Lua Machine")); + + //Add LuaCode to Filters. + RegisterAssetTypeAction(AssetTools, MakeShareable(new FLuaCodeAssetTypeActions(LuaMachineAssetCategoryBit))); +} + +TSharedPtr FLuaMachineEditorModule::GetStyleSet() +{ + return StyleSet; +} + +void FLuaMachineEditorModule::RegisterAssetTypeAction(IAssetTools& AssetTools, TSharedRef Action) +{ + AssetTools.RegisterAssetTypeActions(Action); + CreatedAssetTypeActions.Add(Action); +} + +struct FTableViewLuaValue : public TSharedFromThis +{ + FString LuaTableKey; + FLuaValue LuaTableValue; + bool bExpanded; + TArray> Children; +}; + +class SLuaMachineDebugger : public SCompoundWidget, public FGCObject +{ + SLATE_BEGIN_ARGS(SLuaMachineDebugger) + {} + + SLATE_END_ARGS() + + void RebuildLuaValues() + { + LuaValues.Empty(); + + if (!SelectedLuaState) + { + return; + } + + SelectedLuaState->PushGlobalTable(); + SelectedLuaState->PushNil(); // first key + while (SelectedLuaState->Next(-2)) + { + FLuaValue CurrentLuaKey = SelectedLuaState->ToLuaValue(-2); + FLuaValue CurrentLuaValue = SelectedLuaState->ToLuaValue(-1); + TSharedRef LuaItem = MakeShared(); + LuaItem->LuaTableKey = CurrentLuaKey.ToString(); + LuaItem->LuaTableValue = CurrentLuaValue; + LuaItem->bExpanded = false; + LuaValues.Add(LuaItem); // add key + SelectedLuaState->Pop(); // pop the value + } + + SelectedLuaState->Pop(); // pop the table + + LuaValues.Sort([](const TSharedRef& LHS, const TSharedRef& RHS) { return LHS->LuaTableKey < RHS->LuaTableKey; }); + } + + void OnGetChildren(TSharedRef Item, TArray>& OutChildren) + { + if (!SelectedLuaState) + return; + + if (Item->LuaTableValue.Type == ELuaValueType::Table) + { + if (!Item->bExpanded) + { + SelectedLuaState->FromLuaValue(Item->LuaTableValue); + SelectedLuaState->PushNil(); // first key + while (SelectedLuaState->Next(-2)) + { + FLuaValue CurrentLuaKey = SelectedLuaState->ToLuaValue(-2); + FLuaValue CurrentLuaValue = SelectedLuaState->ToLuaValue(-1); + TSharedRef LuaItem = MakeShared(); + LuaItem->LuaTableKey = CurrentLuaKey.ToString(); + LuaItem->LuaTableValue = CurrentLuaValue; + LuaItem->bExpanded = false; + Item->Children.Add(LuaItem); // add key + SelectedLuaState->Pop(); // pop the value + } + SelectedLuaState->Pop(); // pop the table + Item->bExpanded = true; + Item->Children.Sort([](const TSharedRef& LHS, const TSharedRef& RHS) { return LHS->LuaTableKey < RHS->LuaTableKey; }); + } + OutChildren.Append(Item->Children); + } + else if (Item->LuaTableValue.Type == ELuaValueType::UObject && Item->LuaTableValue.Object) + { + if (Item->LuaTableValue.Object->IsA()) + { + if (!Item->bExpanded) + { + ULuaUserDataObject* LuaUserDataObject = Cast(Item->LuaTableValue.Object); + if (LuaUserDataObject) + { + for (TPair Pair : LuaUserDataObject->Table) + { + TSharedRef LuaItem = MakeShared(); + LuaItem->LuaTableKey = Pair.Key; + LuaItem->LuaTableValue = Pair.Value; + LuaItem->bExpanded = false; + Item->Children.Add(LuaItem); + } + } + Item->bExpanded = true; + Item->Children.Sort([](const TSharedRef& LHS, const TSharedRef& RHS) { return LHS->LuaTableKey < RHS->LuaTableKey; }); + } + OutChildren.Append(Item->Children); + } + } + } + + void OnRegisteredLuaStatesChanged() + { + DetectedLuaStates.Empty(); + TArray States = FLuaMachineModule::Get().GetRegisteredLuaStates(); + for (ULuaState* State : States) + { + DetectedLuaStates.Add(MakeShared(State->GetClass()->GetName())); + } + + if (LuaStatesComboBox.IsValid()) + { + LuaStatesComboBox->RefreshOptions(); + } + + RefreshDebugText(); + } + + FReply CallGC() + { + GEngine->ForceGarbageCollection(true); + return RefreshDebugger(); + } + + FReply CallLuaGC() + { + // avoid calling Lua GC on invalid lua state + RefreshDebugger(); + if (SelectedLuaState && SelectedLuaState->GetInternalLuaState()) + { + SelectedLuaState->GC(LUA_GCCOLLECT); + } + return RefreshDebugger(); + } + + void RefreshDebugText() + { + DebugTextContext.Empty(); + ReferencersTextContext.Empty(); + + for (TObjectIterator StatesIterator; StatesIterator; ++StatesIterator) + { + ULuaState* LuaState = *StatesIterator; +#if ENGINE_MAJOR_VERSION > 4 + if (LuaState->IsValidLowLevel() && !IsValid(LuaState)) +#else + if (LuaState->IsValidLowLevel() && !LuaState->IsPendingKill()) +#endif + { + TArray Referencers; + FReferenceFinder Collector(Referencers, nullptr, false, true, false, false); + Collector.FindReferences(LuaState); + + if (LuaState->GetInternalLuaState()) + { + LuaState->PushRegistryTable(); + int32 RegistrySize = LuaState->ILen(-1); + LuaState->Pop(); + DebugTextContext += FString::Printf(TEXT("%s at 0x%p (%sused memory: %dk) (top of the stack: %d) (registry size: %d) (uobject refs: %d) (tracked user data: %d)\n"), *LuaState->GetName(), LuaState, LuaState->bPersistent ? TEXT("persistent, ") : TEXT(""), LuaState->GC(LUA_GCCOUNT), LuaState->GetTop(), RegistrySize, Referencers.Num(), LuaState->TrackedLuaUserDataObjects.Num()); + } + else + { + DebugTextContext += FString::Printf(TEXT("%s at 0x%p (%sinactive) (uobject refs: %d)\n"), *LuaState->GetName(), LuaState, LuaState->bPersistent ? TEXT("persistent, ") : TEXT(""), Referencers.Num()); + } + } + } + + if (SelectedLuaState) + { + TArray Referencers; + FReferenceFinder Collector(Referencers, nullptr, false, true, false, false); + Collector.FindReferences(SelectedLuaState); + + for (UObject* Referencer : Referencers) + { + ReferencersTextContext += FString::Printf(TEXT("%s\n"), *Referencer->GetFullName()); + } + } + + if (DebugText.IsValid()) + { + DebugText->SetText(FText::FromString(DebugTextContext)); + } + + if (ReferencersText.IsValid()) + { + ReferencersText->SetText(FText::FromString(ReferencersTextContext)); + } + } + + FSlateColor GetLuaTypeColor(TSharedRef Item) + { + switch (Item->LuaTableValue.Type) + { + case ELuaValueType::Nil: + case ELuaValueType::Number: + case ELuaValueType::Integer: + return FSlateColor(FColor::Red); + case ELuaValueType::String: + return FSlateColor(FColor::Orange); + case ELuaValueType::Bool: + return FSlateColor(FColor::Purple); + case ELuaValueType::UFunction: + return FSlateColor(FColor::Magenta); + case ELuaValueType::UObject: + return FSlateColor(FColor::Cyan); + case ELuaValueType::Thread: + return FSlateColor(FColor::Yellow); + default: + return FSlateColor(FLinearColor::White); + } + } + + FText GetLuaTypeText(TSharedRef Item) + { + FString Value = "nil"; + switch (Item->LuaTableValue.Type) + { + case ELuaValueType::String: + Value = "string"; + break; + case ELuaValueType::Bool: + Value = "boolean"; + break; + case ELuaValueType::Integer: + Value = "integer"; + break; + case ELuaValueType::Number: + Value = "number"; + break; + case ELuaValueType::Function: + Value = "function"; + break; + case ELuaValueType::Table: + Value = "table"; + break; + case ELuaValueType::Thread: + Value = "thread"; + break; + case ELuaValueType::UFunction: + Value = "UFunction"; + break; + case ELuaValueType::UObject: + Value = "UObject"; + break; + default: + break; + } + + return FText::FromString(Value); + } + + FText GetLuaValueText(TSharedRef Item) + { + FString Value = ""; + switch (Item->LuaTableValue.Type) + { + case ELuaValueType::String: + case ELuaValueType::Bool: + case ELuaValueType::Integer: + case ELuaValueType::Number: + case ELuaValueType::UFunction: + case ELuaValueType::UObject: + Value = Item->LuaTableValue.ToString(); + break; + case ELuaValueType::Thread: + if (SelectedLuaState == Item->LuaTableValue.LuaState) + { + Value = "status: " + FindObject(nullptr, TEXT("/Script/LuaMachine.ELuaThreadStatus"), true)->GetNameStringByIndex((int32)SelectedLuaState->GetLuaThreadStatus(Item->LuaTableValue)) + ", stack top: " + FString::FromInt(SelectedLuaState->GetLuaThreadStackTop(Item->LuaTableValue)); + } + break; + default: + break; + } + + return FText::FromString(Value); + } + + FReply RefreshDebugger() + { + if (LuaTreeView.IsValid()) + { + if (LuaStatesComboBox.IsValid()) + { + SelectedLuaState = nullptr; + TSharedPtr SelectedText = LuaStatesComboBox->GetSelectedItem(); + if (SelectedText.IsValid()) + { + TArray States = FLuaMachineModule::Get().GetRegisteredLuaStates(); + for (ULuaState* State : States) + { + if (State->GetClass()->GetName() == *SelectedText.Get()) + { + if (State->GetInternalLuaState()) + SelectedLuaState = State; + break; + } + } + } + } + RebuildLuaValues(); + LuaTreeView->RequestTreeRefresh(); + } + + RefreshDebugText(); + return FReply::Handled(); + } + + TSharedRef OnGenerateDebuggerRow(TSharedRef Item, const TSharedRef& OwnerTable) + { + return SNew(STableRow>, OwnerTable) + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot() + [ + SNew(STextBlock).Text(FText::FromString(Item->LuaTableKey)) + ] + + SHorizontalBox::Slot().FillWidth(0.2) + [ + SNew(STextBlock).Text(GetLuaTypeText(Item)) + ] + + SHorizontalBox::Slot() + [ + SNew(STextBlock).Text(GetLuaValueText(Item)).ColorAndOpacity(GetLuaTypeColor(Item)).ToolTipText(GetLuaValueText(Item)) + ] + ]; + } + + void Construct(const FArguments& InArgs) + { + SelectedLuaState = nullptr; + OnRegisteredLuaStatesChanged(); + RebuildLuaValues(); + ChildSlot[ + SNew(SVerticalBox) + + SVerticalBox::Slot().AutoHeight() + [ + SNew(SHorizontalBox) + + SHorizontalBox::Slot().AutoWidth().VAlign(EVerticalAlignment::VAlign_Center).HAlign(EHorizontalAlignment::HAlign_Left) + [ + SNew(STextBlock).Text(FText::FromString("Select LuaState to Debug: ")) + ] + + SHorizontalBox::Slot().FillWidth(0.6) + [ + SAssignNew(LuaStatesComboBox, STextComboBox).OptionsSource(&DetectedLuaStates) + ] + ] + + + SVerticalBox::Slot().AutoHeight() + [ + SNew(SButton).Text(FText::FromString("Refresh")).OnClicked(this, &SLuaMachineDebugger::RefreshDebugger) + ] + + SVerticalBox::Slot().AutoHeight() + [ + SNew(SButton).Text(FText::FromString("Call Unreal GC")).OnClicked(this, &SLuaMachineDebugger::CallGC) + ] + + SVerticalBox::Slot().AutoHeight() + [ + SNew(SButton).Text(FText::FromString("Call Lua GC")).OnClicked(this, &SLuaMachineDebugger::CallLuaGC) + ] + + SVerticalBox::Slot().FillHeight(1) + [ + SNew(SScrollBox).AllowOverscroll(EAllowOverscroll::Yes) + + SScrollBox::Slot() + [ + SAssignNew(LuaTreeView, STreeView>).TreeItemsSource(&LuaValues).OnGetChildren(this, &SLuaMachineDebugger::OnGetChildren).OnGenerateRow(this, &SLuaMachineDebugger::OnGenerateDebuggerRow) + ] + ] + + SVerticalBox::Slot().FillHeight(0.1) + [ + SNew(SBorder).BorderBackgroundColor(FColor::White).Padding(4) + [ + SNew(SScrollBox).AllowOverscroll(EAllowOverscroll::Yes) + + SScrollBox::Slot() + [ + SAssignNew(ReferencersText, STextBlock).Text(FText::FromString(ReferencersTextContext)) + ] + ] + ] + + SVerticalBox::Slot().VAlign(EVerticalAlignment::VAlign_Bottom).AutoHeight() + [ + SNew(SBorder).BorderBackgroundColor(FColor::Red).Padding(4) + [ + SAssignNew(DebugText, STextBlock).Text(FText::FromString(DebugTextContext)) + ] + ] + ]; + FLuaMachineModule::Get().OnRegisteredLuaStatesChanged.AddSP(this, &SLuaMachineDebugger::OnRegisteredLuaStatesChanged); + } + + void AddReferencedObjects(FReferenceCollector& Collector) override + { + Collector.AddReferencedObject(SelectedLuaState); + } + +#if ENGINE_MAJOR_VERSION > 4 + virtual FString GetReferencerName() const override + { + return TEXT("SLuaMachineDebugger"); + } +#endif + +protected: + TArray> LuaValues; + TSharedPtr>> LuaTreeView; + ULuaState* SelectedLuaState; + TArray> DetectedLuaStates; + TSharedPtr LuaStatesComboBox; + TSharedPtr DebugText; + FString DebugTextContext; + TSharedPtr ReferencersText; + FString ReferencersTextContext; +}; + +TSharedRef FLuaMachineEditorModule::CreateLuaMachineDebugger(const FSpawnTabArgs& Args) +{ + return SNew(SDockTab).TabRole(ETabRole::NomadTab) + [ + SNew(SLuaMachineDebugger) + ]; +} + +void FLuaMachineEditorModule::ShutdownModule() +{ + FCoreDelegates::OnPostEngineInit.RemoveAll(this); + + // Unregister all the asset types that we registered + if (FModuleManager::Get().IsModuleLoaded("AssetTools")) + { + IAssetTools& AssetTools = FModuleManager::GetModuleChecked("AssetTools").Get(); + for (int32 Index = 0; Index < CreatedAssetTypeActions.Num(); ++Index) + { + AssetTools.UnregisterAssetTypeActions(CreatedAssetTypeActions[Index].ToSharedRef()); + } + } + CreatedAssetTypeActions.Empty(); +} + +FLuaMachineEditorModule& FLuaMachineEditorModule::Get() +{ + static FLuaMachineEditorModule* Singleton = nullptr; + if (Singleton == nullptr) + { + Singleton = &FModuleManager::LoadModuleChecked("LuaMachineEditor"); + } + return *Singleton; +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FLuaMachineEditorModule, LuaMachineEditor) \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaValueCustomization.cpp b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaValueCustomization.cpp new file mode 100644 index 00000000..e0340b09 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Private/LuaValueCustomization.cpp @@ -0,0 +1,218 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#include "LuaValueCustomization.h" +#include "LuaMachine/Public/LuaValue.h" +#include "LuaMachine/Public/LuaComponent.h" +#include "GameFramework/Actor.h" +#include "Editor/PropertyEditor/Public/PropertyHandle.h" +#include "Editor/PropertyEditor/Public/DetailLayoutBuilder.h" +#include "Editor/PropertyEditor/Public/IDetailChildrenBuilder.h" +#include "Editor/PropertyEditor/Public/DetailWidgetRow.h" +#include "Runtime/Slate/Public/Widgets/Text/STextBlock.h" +#include "Runtime/Slate/Public/Widgets/Input/STextComboBox.h" +#include "Runtime/Engine/Classes/Engine/BlueprintGeneratedClass.h" +#include "Modules/ModuleManager.h" + + +void FLuaValueCustomization::CustomizeHeader(TSharedRef PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils) +{ + TSharedPtr LuaValueTypeProperty = PropertyHandle->GetChildHandle(FName(TEXT("Type"))); + + HeaderRow.NameContent() + [ + PropertyHandle->CreatePropertyNameWidget() + ].ValueContent()[ + LuaValueTypeProperty->CreatePropertyValueWidget() + ]; +} + +EVisibility FLuaValueCustomization::IsPropertyVisible(TSharedRef PropertyHandle, ELuaValueType WantedValueType) +{ + TSharedPtr LuaValueTypeProperty = PropertyHandle->GetChildHandle(FName(TEXT("Type"))); + if (!LuaValueTypeProperty.IsValid()) + return EVisibility::Hidden; + + uint8 ValueType; + LuaValueTypeProperty->GetValue(ValueType); + + if ((ELuaValueType)ValueType == WantedValueType) + return EVisibility::Visible; + + return EVisibility::Hidden; +} + +void FLuaValueCustomization::LuaFunctionChanged(TSharedPtr Value, ESelectInfo::Type SelectionType, TSharedRef PropertyHandle) +{ + TArray Objects; + PropertyHandle->GetOuterObjects(Objects); + + if (Objects.Num() != 1) + return; + + UClass* ObjectClass = Objects[0]->GetClass(); + + ULuaComponent* LuaComponent = Cast(Objects[0]); + if (LuaComponent) + { + AActor* Actor = LuaComponent->GetOwner(); + if (Actor) + { + ObjectClass = Actor->GetClass(); + } + else + { + UBlueprintGeneratedClass* BlueprintClass = Cast(LuaComponent->GetOuter()); + if (BlueprintClass) + { + ObjectClass = BlueprintClass; + } + } + } + + + UFunction* FoundFunction = ObjectClass->FindFunctionByName(FName(*(*Value.Get()))); + if (FoundFunction) + { + PropertyHandle->SetValue(FoundFunction->GetName()); + } +} + +void FLuaValueCustomization::CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& Builder, IPropertyTypeCustomizationUtils& CustomizationUtils) +{ + TArray Objects; + PropertyHandle->GetOuterObjects(Objects); + + if (Objects.Num() != 1) + return; + + TSharedPtr LuaValueBoolProperty = PropertyHandle->GetChildHandle(FName(TEXT("Bool"))); + IDetailPropertyRow& PropertyBoolRow = Builder.AddProperty(LuaValueBoolProperty.ToSharedRef()); + PropertyBoolRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateRaw(this, &FLuaValueCustomization::IsPropertyVisible, PropertyHandle, ELuaValueType::Bool))); + + TSharedPtr LuaValueStringProperty = PropertyHandle->GetChildHandle(FName(TEXT("String"))); + IDetailPropertyRow& PropertyStringRow = Builder.AddProperty(LuaValueStringProperty.ToSharedRef()); + PropertyStringRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateRaw(this, &FLuaValueCustomization::IsPropertyVisible, PropertyHandle, ELuaValueType::String))); + + TSharedPtr LuaValueIntegerProperty = PropertyHandle->GetChildHandle(FName(TEXT("Integer"))); + IDetailPropertyRow& PropertyIntegerRow = Builder.AddProperty(LuaValueIntegerProperty.ToSharedRef()); + PropertyIntegerRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateRaw(this, &FLuaValueCustomization::IsPropertyVisible, PropertyHandle, ELuaValueType::Integer))); + + TSharedPtr LuaValueNumberProperty = PropertyHandle->GetChildHandle(FName(TEXT("Number"))); + IDetailPropertyRow& PropertyNumberRow = Builder.AddProperty(LuaValueNumberProperty.ToSharedRef()); + PropertyNumberRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateRaw(this, &FLuaValueCustomization::IsPropertyVisible, PropertyHandle, ELuaValueType::Number))); + + TSharedPtr LuaValueObjectProperty = PropertyHandle->GetChildHandle(FName(TEXT("Object"))); + IDetailPropertyRow& PropertyObjectRow = Builder.AddProperty(LuaValueObjectProperty.ToSharedRef()); + PropertyObjectRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateRaw(this, &FLuaValueCustomization::IsPropertyVisible, PropertyHandle, ELuaValueType::UObject))); + + TSharedPtr LuaValueFunctionProperty = PropertyHandle->GetChildHandle(FName(TEXT("FunctionName"))); + + FString CurrentFunctionName; + LuaValueFunctionProperty->GetValue(CurrentFunctionName); + + TSharedPtr CurrentSelectedFunction; + + UClass* ObjectClass = Objects[0]->GetClass(); + + bool bAllowsRawCall = false; + + ULuaComponent* LuaComponent = Cast(Objects[0]); + if (LuaComponent) + { + AActor* Actor = LuaComponent->GetOwner(); + if (Actor) + { + ObjectClass = Actor->GetClass(); + } + else + { + UBlueprintGeneratedClass* BlueprintClass = Cast(LuaComponent->GetOuter()); + if (BlueprintClass) + { + ObjectClass = BlueprintClass; + } + } + } + else if (ULuaState* LuaState = Cast(Objects[0])) + { + bAllowsRawCall = LuaState->bRawLuaFunctionCall; + } + + for (TFieldIterator Funcs(ObjectClass); Funcs; ++Funcs) + { + UFunction* Function = *Funcs; + + /*if (!Function->HasAnyFunctionFlags(EFunctionFlags::FUNC_Public)) + continue;*/ + + bool bIsValid = true; + + if (!bAllowsRawCall) + { +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + for (TFieldIterator FArgs(Function); FArgs && FArgs->PropertyFlags & CPF_Parm; ++FArgs) +#else + for (TFieldIterator FArgs(Function); FArgs && FArgs->PropertyFlags & CPF_Parm; ++FArgs) +#endif + { +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FProperty* Prop = *FArgs; + FStructProperty* LuaProp = CastField(Prop); +#else + UProperty* Prop = *FArgs; + UStructProperty* LuaProp = Cast(Prop); +#endif + if (!LuaProp) + { + // check for array ? +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + FArrayProperty* ArrayProp = CastField(Prop); +#else + UArrayProperty* ArrayProp = Cast(Prop); +#endif + if (ArrayProp) + { +#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION >= 25 + LuaProp = CastField(ArrayProp->Inner); +#else + LuaProp = Cast(ArrayProp->Inner); +#endif + if (!LuaProp) + { + bIsValid = false; + break; + } + } + else { + bIsValid = false; + break; + } + } + if (LuaProp->Struct != FLuaValue::StaticStruct()) + { + bIsValid = false; + break; + } + } + } + + if (!bIsValid) + { + continue; + } + + TSharedPtr FunctionNameSP = MakeShareable(new FString(Function->GetName())); + + if (CurrentFunctionName == Function->GetName()) + { + CurrentSelectedFunction = FunctionNameSP; + } + + ValidLuaFunctions.Add(FunctionNameSP); + } + + + Builder.AddCustomRow(FText::FromString(TEXT("Function"))).ValueContent()[ + SNew(STextComboBox).OptionsSource(&ValidLuaFunctions).OnSelectionChanged_Raw(this, &FLuaValueCustomization::LuaFunctionChanged, LuaValueFunctionProperty.ToSharedRef()).InitiallySelectedItem(CurrentSelectedFunction) + ].Visibility(TAttribute::Create(TAttribute::FGetter::CreateRaw(this, &FLuaValueCustomization::IsPropertyVisible, PropertyHandle, ELuaValueType::UFunction))); +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaCodeCustomization.h b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaCodeCustomization.h new file mode 100644 index 00000000..1039c17a --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaCodeCustomization.h @@ -0,0 +1,23 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Editor/PropertyEditor/Public/IDetailCustomization.h" + +/** + * + */ + +class FLuaCodeCustomization : public IDetailCustomization +{ +public: + // IDetailCustomization interface + virtual void CustomizeDetails(IDetailLayoutBuilder& DetailBuilder) override; + + static TSharedRef MakeInstance() + { + return MakeShareable(new FLuaCodeCustomization()); + } +}; + diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaCodeFactory.h b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaCodeFactory.h new file mode 100644 index 00000000..1c9d8a47 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaCodeFactory.h @@ -0,0 +1,80 @@ +// Copyright 2018-2023 - Roberto De Ioris +// Reimport system by yama2akira (Akira Yamamoto) + +#pragma once + +#include "CoreMinimal.h" +#include "Factories/Factory.h" +#include "Developer/AssetTools/Public/AssetTypeCategories.h" +#include "Runtime/Engine/Classes/Engine/Level.h" +#include "EditorReimportHandler.h" +#include "AssetTypeActions_Base.h" +#include "LuaCodeFactory.generated.h" + +/** + * + */ +UCLASS() +class LUAMACHINEEDITOR_API ULuaCodeFactory : public UFactory, public FReimportHandler +{ + GENERATED_UCLASS_BODY() + + virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn, FName CallingContext) override; + virtual UObject* FactoryCreateBinary(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn, bool& bOutOperationCanceled) override; + + virtual FText GetDisplayName() const override + { + return FText::FromString("Lua Code"); + } + + virtual uint32 GetMenuCategories() const override; + + virtual UObject* ImportObject(UClass* InClass, UObject* InOuter, FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms, bool& OutCanceled) override + { + UObject* NewAsset = nullptr; + if (!Filename.IsEmpty()) + { + CurrentFilename = Filename; + return FactoryCreateFile(InClass, InOuter, InName, Flags, Filename, Parms, nullptr, OutCanceled); + } + else + { + return FactoryCreateNew(InClass, InOuter, InName, Flags, nullptr, GWarn, NAME_None); + } + + if (NewAsset) + { + NewAsset->MarkPackageDirty(); + ULevel::LevelDirtiedEvent.Broadcast(); + NewAsset->PostEditChange(); + } + + return NewAsset; + } + +public: + virtual bool CanReimport(UObject* Obj, TArray& OutFilenames) override; + virtual void SetReimportPaths(UObject* Obj, const TArray& NewReimportPaths) override; + virtual EReimportResult::Type Reimport(UObject* Obj) override; +}; + + +/** + * Add AssetType Actions, so it can show up in Filters, etc. + */ +class FLuaCodeAssetTypeActions : public FAssetTypeActions_Base +{ +public: + FLuaCodeAssetTypeActions( EAssetTypeCategories::Type InAssetCategory ); + // IAssetTypeActions interface + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override; + virtual UClass* GetSupportedClass() const override; + //virtual bool HasActions(const TArray& InObjects) const override { return true; } + //virtual void GetActions(const TArray& InObjects, FMenuBuilder& MenuBuilder) override; + //virtual void OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override; + virtual bool IsImportedAsset() const override; + virtual void GetResolvedSourceFilePaths( const TArray& TypeAssets, TArray& OutSourceFilePaths ) const override; + // End of IAssetTypeActions interface +}; diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaMachineEditor.h b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaMachineEditor.h new file mode 100644 index 00000000..7261f5c2 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaMachineEditor.h @@ -0,0 +1,41 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "Runtime/Launch/Resources/Version.h" +#include "Modules/ModuleManager.h" +#include "LuaState.h" +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 3 +#include "Styling/SlateStyle.h" +#include "Styling/SlateStyleRegistry.h" +#else +#include "SlateCore/Public/Styling/SlateStyle.h" +#endif +#include "Runtime/Slate/Public/Widgets/Docking/SDockTab.h" +#include "IAssetTools.h" +#include "IAssetTypeActions.h" +#include "AssetTypeCategories.h" + +class FLuaMachineEditorModule : public IModuleInterface +{ +public: + FLuaMachineEditorModule(); + + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + virtual void OnPostEngineInit(); + static FLuaMachineEditorModule& Get(); + + TSharedPtr GetStyleSet(); + + virtual uint32 GetAssetCategory() const { return LuaMachineAssetCategoryBit; } + void RegisterAssetTypeAction( IAssetTools& AssetTools, TSharedRef Action ); +private: + TSharedPtr StyleSet; + static TSharedRef CreateLuaMachineDebugger(const FSpawnTabArgs& Args); + EAssetTypeCategories::Type LuaMachineAssetCategoryBit; + /** All created asset type actions. Cached here so that we can unregister them during shutdown. */ + TArray< TSharedPtr > CreatedAssetTypeActions; +}; diff --git a/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaValueCustomization.h b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaValueCustomization.h new file mode 100644 index 00000000..aeba4eb6 --- /dev/null +++ b/OmegaGameFramework/Source/LuaMachineEditor/Public/LuaValueCustomization.h @@ -0,0 +1,30 @@ +// Copyright 2018-2023 - Roberto De Ioris + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/NoExportTypes.h" +#include "Editor/PropertyEditor/Public/IPropertyTypeCustomization.h" +#include "Runtime/SlateCore/Public/Layout/Visibility.h" +#include "LuaMachine/Public/LuaValue.h" + +class FLuaValueCustomization : public IPropertyTypeCustomization +{ +public: + // IPropertyTypeCustomization interface + virtual void CustomizeHeader(TSharedRef PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + + virtual void CustomizeChildren(TSharedRef PropertyHandle, IDetailChildrenBuilder& Builder, IPropertyTypeCustomizationUtils& CustomizationUtils) override; + + static TSharedRef MakeInstance() + { + return MakeShareable(new FLuaValueCustomization()); + } + + EVisibility IsPropertyVisible(TSharedRef PropertyHandle, ELuaValueType WantedValueType); + + void LuaFunctionChanged(TSharedPtr Value, ESelectInfo::Type SelectionType, TSharedRef PropertyHandle); +protected: + TArray> ValidLuaFunctions; +}; + diff --git a/OmegaGameFramework/Source/OmegaEditor/Private/OmegaEditor.cpp b/OmegaGameFramework/Source/OmegaEditor/Private/OmegaEditor.cpp index 8c3afc70..c653a39b 100644 --- a/OmegaGameFramework/Source/OmegaEditor/Private/OmegaEditor.cpp +++ b/OmegaGameFramework/Source/OmegaEditor/Private/OmegaEditor.cpp @@ -99,6 +99,7 @@ void FOmegaEditor::StartupModule() // Add Basic Thumbnail Location List TArray ThumnbailNames; + ThumnbailNames.Add(TEXT("OmegaComponent")); ThumnbailNames.Add(TEXT("OmegaAbility")); ThumnbailNames.Add(TEXT("OmegaGameplaySystem")); ThumnbailNames.Add(TEXT("OmegaGameplayModule")); diff --git a/OmegaGameFramework/Source/OmegaFlow/Private/AsyncAction_LerpCurve.cpp b/OmegaGameFramework/Source/OmegaFlow/Private/AsyncAction_LerpCurve.cpp new file mode 100644 index 00000000..b6fede80 --- /dev/null +++ b/OmegaGameFramework/Source/OmegaFlow/Private/AsyncAction_LerpCurve.cpp @@ -0,0 +1,65 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AsyncAction_LerpCurve.h" +#include "Engine/World.h" + + +void UAsyncAction_LerpCurve::Tick(float DeltaTime) +{ + if (local_playing) + { + local_reversed ? elapsed_time -= DeltaTime * local_PlayRate : elapsed_time += DeltaTime * local_PlayRate; + + if (local_curve) + { + new_value = local_curve->GetFloatValue(elapsed_time); + } + + bool should_end = local_reversed ? (elapsed_time <= 0) : (elapsed_time >= time_max); // Assuming BlendDuration is the end time + + if (should_end) + { + local_playing = false; + Finished.Broadcast(); // Make sure delegate is valid + SetReadyToDestroy(); + } + else + { + Updated.Broadcast(new_value); // Make sure delegate is valid + } + } +} + + +void UAsyncAction_LerpCurve::Activate() +{ + if(local_curve && local_PlayRate>0.0f) + { + local_curve->GetTimeRange(time_min,time_max); + + elapsed_time=0.0; + if(local_reversed) + { + elapsed_time=time_max; + } + + local_playing=true; + } + else + { + SetReadyToDestroy(); + } +} + +UAsyncAction_LerpCurve* UAsyncAction_LerpCurve::LerpAlongCurve(UObject* WorldContextObject, UCurveFloat* Curve, + float PlayRate, bool bReverse) +{ + UAsyncAction_LerpCurve* NewNode = NewObject(); + NewNode->local_curve=Curve; + NewNode->local_PlayRate=PlayRate; + NewNode->local_reversed = bReverse; + return NewNode; +} + + diff --git a/OmegaGameFramework/Source/OmegaFlow/Public/AsyncAction_LerpCurve.h b/OmegaGameFramework/Source/OmegaFlow/Public/AsyncAction_LerpCurve.h new file mode 100644 index 00000000..ae5d3be6 --- /dev/null +++ b/OmegaGameFramework/Source/OmegaFlow/Public/AsyncAction_LerpCurve.h @@ -0,0 +1,71 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintAsyncActionBase.h" +#include "AsyncAction_LerpCurve.generated.h" + + +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLerpCurveUpdate, float, LerpValue); +DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnLerpCurveFinished); +UCLASS() + +class OMEGAFLOW_API UAsyncAction_LerpCurve : public UBlueprintAsyncActionBase, public FTickableGameObject +{ + GENERATED_BODY() + +public: + + virtual void Tick(float DeltaTime) override; + + virtual ETickableTickType GetTickableTickType() const override + { + return ETickableTickType::Always; + } + virtual TStatId GetStatId() const override + { + RETURN_QUICK_DECLARE_CYCLE_STAT( FMyTickableThing, STATGROUP_Tickables ); + } + virtual bool IsTickableWhenPaused() const + { + return true; + } + virtual bool IsTickableInEditor() const + { + return false; + } + // FTickableGameObject End + + UPROPERTY(BlueprintAssignable) + FOnLerpCurveUpdate Updated; + UPROPERTY(BlueprintAssignable) + FOnLerpCurveFinished Finished; + + UPROPERTY() + bool local_playing; + + UPROPERTY() + UCurveFloat* local_curve; + + UPROPERTY() + float local_PlayRate; + UPROPERTY() + bool local_reversed; + UPROPERTY() + float elapsed_time; + + UPROPERTY() + float new_value; + UPROPERTY() + float time_min; + UPROPERTY() + float time_max; + + virtual void Activate() override; + + UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true", WorldContext="WorldContextObject", AdvancedDisplay="Player"), Category="Omega|GameplayTasks") + static UAsyncAction_LerpCurve* LerpAlongCurve(UObject* WorldContextObject, UCurveFloat* Curve, float PlayRate=1.0, bool bReverse=false); + + +}; diff --git a/OmegaGameFramework/Source/OmegaGameFramework/OmegaGameFramework.Build.cs b/OmegaGameFramework/Source/OmegaGameFramework/OmegaGameFramework.Build.cs index a1afefa8..03763b06 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/OmegaGameFramework.Build.cs +++ b/OmegaGameFramework/Source/OmegaGameFramework/OmegaGameFramework.Build.cs @@ -37,6 +37,7 @@ public OmegaGameFramework(ReadOnlyTargetRules Target) : base(Target) "CommonUI", "CommonInput", "EnhancedInput", + "LuaMachine", "Engine", "DeveloperSettings", "LevelSequence", diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaBulletActor.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaBulletActor.cpp index 8ac84463..8bf2250a 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaBulletActor.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaBulletActor.cpp @@ -60,7 +60,7 @@ void AOmegaBulletActor::local_spawnCue(TSubclassOf cue) { if(cue) { - UOmegaGameplayCueFunctions::PlayGameplayCue(this,cue,GetActorTransform(),nullptr); + UOmegaGameplayCueFunctions::PlayGameplayCue(this,cue,GetActorTransform(),FHitResult(),nullptr); } } diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaScriptedEffect.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaScriptedEffect.cpp index dab4fe50..37a5f2e5 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaScriptedEffect.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Combatant/OmegaScriptedEffect.cpp @@ -47,7 +47,7 @@ void UOmegaScriptedEffectFunctions::ApplyEffectScriptToCombatant(TArray TempCue : TempEffect->GetCuesToPlay()) { - UOmegaGameplayCueFunctions::PlayGameplayCue(Target,TempCue,FTransform(),Target->GetOwner()); + UOmegaGameplayCueFunctions::PlayGameplayCue(Target,TempCue,FTransform(), FHitResult(),Target->GetOwner()); } } } @@ -63,7 +63,7 @@ void UOmegaScriptedEffectFunctions::ApplyScriptedEffectToCombatant(UOmegaScripte //Spawn Cues for(const TSubclassOf TempCue : EffectAsset->GameplayCues) { - UOmegaGameplayCueFunctions::PlayGameplayCue(Target,TempCue,FTransform(),Target->GetOwner()); + UOmegaGameplayCueFunctions::PlayGameplayCue(Target,TempCue,FTransform(),FHitResult(),Target->GetOwner()); } } } diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantComponent.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantComponent.cpp index 240b947e..060268a4 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantComponent.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantComponent.cpp @@ -99,9 +99,12 @@ void UCombatantComponent::TickComponent(float DeltaTime, ELevelTick TickType, FA void UCombatantComponent::SetMasterDataSourceActive(UObject* Source, bool bActive) { - SetSkillSourceActive(Source, bActive); - SetAttributeModifierActive(Source, bActive); - SetDamageModifierActive(Source, bActive); + if(Source) + { + SetSkillSourceActive(Source, bActive); + SetAttributeModifierActive(Source, bActive); + SetDamageModifierActive(Source, bActive); + } } void UCombatantComponent::SetAbilityActive(bool bActive, AOmegaAbility* Ability) diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantFunctions.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantFunctions.cpp index 58395c92..ab7c325c 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantFunctions.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/CombatantFunctions.cpp @@ -170,6 +170,30 @@ UOmegaAttribute* UCombatantFunctions::GetAttributeByUniqueID(const FString& ID) } return nullptr; } + +TArray UCombatantFunctions::FlatAttributesToModifierValues( + TMap FlatAttributes,bool AsMultiplier) +{ + TArray out; + TArray local_attributes; + for(auto* a: local_attributes) + { + FOmegaAttributeModifier new_mod; + new_mod.Attribute=a; + float local_val = FlatAttributes[a]; + if(AsMultiplier) + { + new_mod.Multiplier=local_val; + } + else + { + new_mod.Incrementer=local_val; + } + out.Add(new_mod); + } + return out; +} + /* TMap UCombatantFunctions::CompareAttributeModifiers(UCombatantComponent* Combatant, UObject* ComparedModifier, UObject* UncomparedModifer) diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Components/EquipmentComponent.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Components/EquipmentComponent.cpp index 78df4700..44683a3d 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Components/EquipmentComponent.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/Components/EquipmentComponent.cpp @@ -219,8 +219,38 @@ void UEquipmentComponent::ClearLinkedAssetCollectionComponent(UDataAssetCollecti LinkedCollectionComp = nullptr; } +//############################################################################################## +// Equipment Script +//############################################################################################## + +UWorld* UEquipmentScript::GetWorld() const +{ + if(GetGameInstance()) + { + return GetGameInstance()->GetWorld(); + } + return nullptr; +} + +UGameInstance* UEquipmentScript::GetGameInstance() const +{ + return Cast(GetOuter()); +} + +UEquipmentScript::UEquipmentScript(const FObjectInitializer& ObjectInitializer) +{ + if (const UObject* Owner = GetOuter()) + { + WorldPrivate = Owner->GetWorld(); + } +} + +//############################################################################################## +// Equipment Slot +//############################################################################################## + void UEquipmentSlot::GetGeneralDataText_Implementation(const FString& Label, const UObject* Context, FText& Name, - FText& Description) + FText& Description) { Name = SlotName; Description = SlotDescription; diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/InstanceActor/OmegaInstanceActor.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/InstanceActor/OmegaInstanceActor.cpp index 36d3a3d0..7aa335dc 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/InstanceActor/OmegaInstanceActor.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/InstanceActor/OmegaInstanceActor.cpp @@ -30,7 +30,7 @@ void AOmegaInstanceActor::Tick(float DeltaTime) bool AOmegaInstanceActor::Local_SourceHasInterface() const { - return ContextObject->GetClass()->ImplementsInterface(UDataInterface_General::StaticClass()); + return ContextObject && ContextObject->GetClass()->ImplementsInterface(UDataInterface_General::StaticClass()); } void AOmegaInstanceActor::GetGeneralDataText_Implementation(const FString& Label, const UObject* Context, FText& Name, diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameMode.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameMode.cpp index c05a8b55..bf8988ca 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameMode.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameMode.cpp @@ -30,6 +30,7 @@ void AOmegaGameMode::BeginPlay() //Activate Game Systems for (const TSubclassOf TempSystem : AutoGameplaySystems) { + SystemRef->ActivateGameplaySystem(TempSystem, this, "GameMode_PreLoad"); } diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameplayCue.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameplayCue.cpp index 1545833e..7f435a10 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameplayCue.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaGameplayCue.cpp @@ -6,15 +6,23 @@ #include "Components/AudioComponent.h" #include "Engine/World.h" #include "Components/PostProcessComponent.h" +#include "Components/BillboardComponent.h" #include "Camera/CameraShakeSourceComponent.h" #include "Kismet/GameplayStatics.h" +#include "Kismet/KismetMathLibrary.h" AOmegaGameplayCue::AOmegaGameplayCue() { + RootComponent = CreateDefaultSubobject(TEXT("CueRoot")); + Niagara = CreateDefaultSubobject(TEXT("Niagara")); + Niagara->SetupAttachment(RootComponent); Audio = CreateDefaultSubobject(TEXT("Audio")); + Audio->SetupAttachment(RootComponent); PostProcess = CreateDefaultSubobject(TEXT("PostProcess")); + PostProcess->SetupAttachment(RootComponent); CameraShake = CreateDefaultSubobject(TEXT("Camera Shake")); + CameraShake->SetupAttachment(RootComponent); PostProcess->bUnbound=false; CameraShake->bAutoStart=true; @@ -23,10 +31,31 @@ AOmegaGameplayCue::AOmegaGameplayCue() void AOmegaGameplayCue::BeginPlay() { // Bind the function to the OnSystemFinished event of the Niagara component - Niagara->OnSystemFinished.AddDynamic(this, &AOmegaGameplayCue::OnFinishParticle); + // Bind the function to the OnAudioFinished event of the Audio component + + int32 temp_index=0; + + // Play Sound + temp_index = UKismetMathLibrary::RandomInteger(Sounds.Num()-1); + if (Sounds.IsValidIndex(temp_index)) + { + Audio->SetSound(Sounds[temp_index]); + } + Audio->Play(); Audio->OnAudioFinished.AddDynamic(this, &AOmegaGameplayCue::TryFinish); - //Super::BeginPlay(); + + // Play Niagara + temp_index = UKismetMathLibrary::RandomInteger(NiagaraParticles.Num()-1); + if (NiagaraParticles.IsValidIndex(temp_index)) + { + Niagara->SetAsset(NiagaraParticles[temp_index]); + } + Niagara->ResetSystem(); + Niagara->OnSystemFinished.AddDynamic(this, &AOmegaGameplayCue::OnFinishParticle); + + + Super::BeginPlay(); } void AOmegaGameplayCue::OnFinishParticle(UNiagaraComponent* Comp) @@ -36,6 +65,10 @@ void AOmegaGameplayCue::OnFinishParticle(UNiagaraComponent* Comp) void AOmegaGameplayCue::TryFinish() { + if(!bAttemptAutocomplete) + { + return; + } if(!Audio->IsPlaying() && Niagara->IsComplete()) { K2_DestroyActor(); @@ -48,11 +81,12 @@ void AOmegaGameplayCue::Tick(float DeltaTime) } void UOmegaGameplayCueFunctions::PlayGameplayCue(UObject* WorldContextObject, TSubclassOf Cue, - FTransform Origin, AActor* ActorOrigin) + FTransform Origin, FHitResult Hit, AActor* ActorOrigin) { if(Cue) { AOmegaGameplayCue* CueRef = WorldContextObject->GetWorld()->SpawnActorDeferred(Cue, Origin, nullptr); + CueRef->HitData=Hit; UGameplayStatics::FinishSpawningActor(CueRef, Origin); if(ActorOrigin) diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaScriptedTrace.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaScriptedTrace.cpp new file mode 100644 index 00000000..20e47d17 --- /dev/null +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Gameplay/OmegaScriptedTrace.cpp @@ -0,0 +1,46 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Gameplay/OmegaScriptedTrace.h" + + +const FHitResult UOmegaScriptedTraceFunctions::ScriptedTrace_Single(UObject* context, FOmegaScriptedTrace Trace,bool& Success) +{ + if(Trace.Logic) + { + return Trace.Logic->RunTrace(context,Success); + } + return FHitResult(); +} + +const TArray UOmegaScriptedTraceFunctions::ScriptedTrace_Multi(UObject* context, FOmegaScriptedTrace Trace,bool& Success) +{ + TArray out; + if(Trace.Logic) + { + return Trace.Logic->RunTrace_Multi(context,Success); + } + return out; +} + +UOmegaScriptedTraceLogic::UOmegaScriptedTraceLogic(const FObjectInitializer& ObjectInitializer) +{ + if (const UObject* Owner = GetOuter()) + { + WorldPrivate = Owner->GetWorld(); + } +} + +UWorld* UOmegaScriptedTraceLogic::GetWorld() const +{ + if(GetGameInstance()) + { + return GetGameInstance()->GetWorld(); + } + return nullptr; +} + +UGameInstance* UOmegaScriptedTraceLogic::GetGameInstance() const +{ + return Cast(GetOuter()); +} \ No newline at end of file diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaAttribute.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaAttribute.cpp index 8e77cc33..4041377b 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaAttribute.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaAttribute.cpp @@ -5,6 +5,10 @@ float UOmegaAttribute::GetAttributeValue(int32 Level, int32 AttributeRank, FGameplayTag ValueCategory) { + if(Script) + { + return Script->GetAttributeValue(Level,ValueCategory); + } float FinalValue = MaxValue; @@ -80,7 +84,7 @@ void UOmegaAttribute::GetGeneralDataText_Implementation(const FString& Label, co void UOmegaAttribute::GetGeneralDataImages_Implementation(const FString& Label, const UObject* Context, UTexture2D*& Texture, UMaterialInterface*& Material, FSlateBrush& Brush) { - IDataInterface_General::GetGeneralDataImages_Implementation(Label, Context, AttributeIcon, Material, Brush); + IDataInterface_General::GetGeneralDataImages_Implementation(Label, Context, AttributeIcon, Material, AttributeSlateIcon); } void UOmegaAttribute::GetGeneralAssetColor_Implementation(FLinearColor& Color) diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaFileSubsystem.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaFileSubsystem.cpp new file mode 100644 index 00000000..c6c4d7a0 --- /dev/null +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaFileSubsystem.cpp @@ -0,0 +1,68 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "OmegaFileSubsystem.h" +#include "HAL/FileManager.h" +#include "Misc/FileHelper.h" +#include "Kismet/KismetRenderingLibrary.h" +#include "Kismet/KismetSystemLibrary.h" + +void UOmegaFileSubsystem::Initialize(FSubsystemCollectionBase& Collection) +{ + Super::Initialize(Collection); + UE_LOG(LogTemp, Log, TEXT("get override image path: %s"), *GetOverrideDirectory_Images()); + TArray file_list = GetFilesOfExtension(GetOverrideDirectory_Images(),TEXT(".png")); + for(FString file: file_list) + { + FString loc_filename = FPaths::GetBaseFilename(file, true); + if(UTexture2D* new_image = UKismetRenderingLibrary::ImportFileAsTexture2D(GetWorld(), file)) + { + imported_images.Add(loc_filename,new_image); + } + } +} + +TArray UOmegaFileSubsystem::GetFilesOfExtension(FString path, FString extension) +{ + IFileManager & FileManager = IFileManager::Get(); + TArray FileNames; + FileManager.FindFiles(FileNames,*path,*extension); + TArray out; + for(FString fil : FileNames) + { + out.Add(path+fil); + } + return out; +} + +FString UOmegaFileSubsystem::GetOverrideDirectory() const +{ + const FString dir = UKismetSystemLibrary::GetProjectDirectory(); + //+over_path="/" + return dir+"override/"; +} + +FString UOmegaFileSubsystem::GetOverrideDirectory_Images() const +{ + return GetOverrideDirectory()+override_images_path+"/"; +} + +FString UOmegaFileSubsystem::GetOverrideDirectory_Audio() const +{ + return GetOverrideDirectory()+override_audio_path+"/"; +} + +UTexture2D* UOmegaFileFunctions::GetOverride_Texture(UObject* WorldContextObject, const FString& name) +{ + if(!WorldContextObject->GetWorld()->GetGameInstance()) + { + return nullptr; + } + if(UTexture2D* out = WorldContextObject->GetWorld()->GetGameInstance()->GetSubsystem()->imported_images.FindOrAdd(name)) + { + return out; + } + return nullptr; +} + + diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaGameFrameworkBPLibrary.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaGameFrameworkBPLibrary.cpp index f46103ee..c9083180 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaGameFrameworkBPLibrary.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaGameFrameworkBPLibrary.cpp @@ -10,6 +10,7 @@ #include "Player/OmegaInputMode.h" #include "JsonObjectWrapper.h" #include "Dom/JsonObject.h" +#include "LuaInterface.h" #include "Kismet/GameplayStatics.h" #include "Gameplay/GameplayTagsInterface.h" #include "Kismet/KismetMathLibrary.h" @@ -222,7 +223,7 @@ FGameplayTag UOmegaGameFrameworkBPLibrary::MakeGameplayTagFromString(const FStri { if(FGameplayTag::IsValidGameplayTagString(String)) { - return FGameplayTag::RequestGameplayTag(FName(*String)); + return FGameplayTag::RequestGameplayTag(FName(*String),false); } return FGameplayTag(); } @@ -357,7 +358,7 @@ AOmegaGameplaySystem* UOmegaGameFrameworkBPLibrary::GetActiveGameplaySystem(cons UOmegaGameplayModule* UOmegaGameFrameworkBPLibrary::GetGameplayModule(const UObject* WorldContextObject, TSubclassOf ModuleClass) { - if(WorldContextObject->GetWorld()->GetGameInstance()->GetSubsystem()->GetGameplayModule(ModuleClass)) + if(WorldContextObject && WorldContextObject->GetWorld()->GetGameInstance()->GetSubsystem()->GetGameplayModule(ModuleClass)) { return WorldContextObject->GetWorld()->GetGameInstance()->GetSubsystem()->GetGameplayModule(ModuleClass); } @@ -587,6 +588,15 @@ TArray UOmegaGameFrameworkBPLibrary::FilterComponentsWithTag(T return OutActors; } +AActor* UOmegaGameFrameworkBPLibrary::Quick_SpawnActor(UObject* WorldContextObject, TSubclassOf Class, + FTransform Transform, const TArray Tags) +{ + AActor* new_actor = WorldContextObject->GetWorld()->SpawnActorDeferred(Class, Transform, nullptr); + new_actor->Tags=Tags; + UGameplayStatics::FinishSpawningActor(new_actor, Transform); + return new_actor; +} + //############################################################################### @@ -718,6 +728,17 @@ FString UOmegaGameFrameworkBPLibrary::GetObjectLabel(UObject* Object) return OutName; } +UDataAsset* UOmegaGameFrameworkBPLibrary::CreateDataAssetFromLua(UObject* WorldContextObject, TSubclassOf Class, FLuaValue Value) +{ + if(Class && Class->ImplementsInterface(ULuaInterface::StaticClass())) + { + UDataAsset* new_obj = NewObject(WorldContextObject->GetWorld()->GetGameInstance(),Class); + ILuaInterface::Execute_SetValue(new_obj,Value,""); + return new_obj; + } + return nullptr; +} + float UOmegaStarRankFunctions::GetFloatFromStarRank(EOmegaStarRank Rank) { @@ -747,6 +768,11 @@ int32 UOmegaStarRankFunctions::GetIntFromStarRank(EOmegaStarRank Rank) return OutVal; } +float UOmegaCurveFunctions::GetCurveValueFromTime(FRuntimeFloatCurve curve,float time) +{ + return curve.GetRichCurve()->Eval(time); +} + diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaSettings.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaSettings.cpp index 6233ad2e..a722dc76 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaSettings.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/OmegaSettings.cpp @@ -114,11 +114,18 @@ UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Event_Combat_Impact,"Event.Combat.Impact"); UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Event_Combat_Attack,"Event.Combat.Attack"); UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Event_Combat_Defend,"Event.Combat.Defend"); +UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Event_Phys_Footstep,"Event.Physics.Footstep"); +UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Event_Phys_Hit,"Event.Physics.Hit"); +UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Event_Phys_Touch,"Event.Physics.Touch"); +UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Event_Phys_Break,"Event.Physics.Break"); + UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Pref_Game,"Preferences.Game"); UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Pref_Visual,"Preferences.Visual"); UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Pref_Audio,"Preferences.Audio"); UE_DEFINE_GAMEPLAY_TAG(Tag_Omega_Pref_Controls,"Preferences.Controls"); + + UOmegaSettings::UOmegaSettings(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Player/OmegaPlayerSubsystem.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Player/OmegaPlayerSubsystem.cpp index e62382c1..e9dac6b4 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Player/OmegaPlayerSubsystem.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Player/OmegaPlayerSubsystem.cpp @@ -218,9 +218,9 @@ UHUDLayer* UOmegaPlayerSubsystem::AddHUDLayer(TSubclassOf LayerClass, bool UOmegaPlayerSubsystem::RemoveHUDLayer(class TSubclassOf LayerClass, FString Flag) { CleanHUDLayers(); - if(GetHUDLayerByClass(LayerClass)) + if(UHUDLayer* tem_layer = GetHUDLayerByClass(LayerClass)) { - GetHUDLayerByClass(LayerClass)->RemoveHUDLayer(); + tem_layer->RemoveHUDLayer(); return true; } return false; @@ -232,7 +232,7 @@ TArray UOmegaPlayerSubsystem::GetHUDLayers() TArray TempLayers; for (UHUDLayer* TempLayer: ActiveHUDLayers) { - if(TempLayer && TempLayer->GetClass()->IsChildOf(UHUDLayer::StaticClass())) + if(TempLayer) { TempLayers.Add(TempLayer); } @@ -289,7 +289,7 @@ UHUDLayer* UOmegaPlayerSubsystem::GetHUDLayerByClass(TSubclassOf Laye { for(auto* TempLayer : GetHUDLayers()) { - if(TempLayer->GetClass() == LayerClass) + if(TempLayer->GetClass() == LayerClass && TempLayer->IsVisible()) { return TempLayer; } @@ -320,6 +320,7 @@ void UOmegaPlayerSubsystem::CleanHUDLayers() } } ActiveHUDLayers = LocalLayers; + return; } APlayerController* UOmegaPlayerSubsystem::Local_GetPlayerController() diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataList.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataList.cpp index a43d194d..91f3423d 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataList.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataList.cpp @@ -43,6 +43,11 @@ void UDataList::Native_WidgetNotify(UDataWidget* Widget, FName Notify) OnEntryNotifed.Broadcast(Widget,Notify); } +FLuaValue UDataList::GetListScript(TSubclassOf State) +{ + return ULuaObjectFunctions::RunLuaScriptContainer(this,List_Script,State); +} + void UDataList::SetNewControl(UUserWidget* NewWidget) { if(NewWidget) @@ -128,6 +133,7 @@ UDataWidget* UDataList::AddAssetToList(UObject* Asset, FString Flag) { TempEntry->ReferencedAsset = Asset; } + TempEntry->Script=Entry_Script; // Bind Delegates TempEntry->OnSelected.AddDynamic(this, &UDataList::NativeEntitySelect); @@ -256,11 +262,16 @@ TArray UDataList::GetEntries() return OutEntries; } -void UDataList::HoverEntry(int32 Index) +void UDataList::HoverEntry(int32 Index,bool UseLastIndex) { - if(GetEntry(Index)) + int32 incoming_index=Index; + if(UseLastIndex) + { + incoming_index=RememberedHoverIndex; + } + if(GetEntry(incoming_index)) { - GetEntry(Index)->Hover(); + GetEntry(incoming_index)->Hover(); } } @@ -450,30 +461,30 @@ void UDataList::InputNavigate_Implementation(FVector2D Axis) OnInputNavigate.Broadcast(Axis); //if failed cycle or not a valid input, try fo to nav overflow widget -/* + switch (AxisDirection) { case 1: - + OnNavigationOverflow.Broadcast(FVector2d(1,0)); break; case -1: // Do something for Left direction - SetNewControl(NavOverflowLeft); + OnNavigationOverflow.Broadcast(FVector2d(-1,0)); break; case 2: // Do something for Up direction - SetNewControl(NavOverflowUp); + OnNavigationOverflow.Broadcast(FVector2d(0,1)); break; case -2: // Do something for Down direction - SetNewControl(NavOverflowDown); + OnNavigationOverflow.Broadcast(FVector2d(0,-1)); break; default: ; } - */ + } void UDataList::InputPage_Implementation(float Axis) @@ -507,7 +518,7 @@ void UDataList::OnControlSetWidget_Implementation() } else { - HoverEntry(0); + HoverEntry(0,bRememberIndexOnControlSet); } } @@ -734,7 +745,7 @@ void UDataList::NativeEntityHighlight(UDataWidget* DataWidget, bool bIsHighlight void UDataList::SetEntryHighlighted(int32 Index, bool bHighlighted) { - if(GetEntries()[Index]) + if(GetEntries().IsValidIndex(Index)) { GetEntries()[Index]->SetHighlighted(bHighlighted); } diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataWidget.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataWidget.cpp index 78592b15..7b32439f 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataWidget.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/DataWidget.cpp @@ -7,6 +7,7 @@ #include "Components/TextBlock.h" #include "DataInterface_General.h" #include "CommonUILibrary.h" +#include "LuaBlueprintFunctionLibrary.h" #include "Materials/MaterialInstanceDynamic.h" #include "Blueprint/WidgetBlueprintLibrary.h" #include "Components/Image.h" @@ -55,14 +56,14 @@ void UDataWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) const float HoverVal = GetHoveredMaterialInstance()->K2_GetScalarParameterValue(HoverWidgetPropertyName); if(IsDataWidgetHovered() != static_cast(HoverVal)) { - OutVal = UKismetMathLibrary::FInterpTo_Constant(HoverVal, IsDataWidgetHovered(), InDeltaTime, HoverWidgetSpeed); + OutVal = UKismetMathLibrary::FInterpTo_Constant(HoverVal, IsDataWidgetHovered(), InDeltaTime, (1.0f/HoverWidgetSpeed)); GetHoveredMaterialInstance()->SetScalarParameterValue(HoverWidgetPropertyName,OutVal); } const float HighlightVal = GetHoveredMaterialInstance()->K2_GetScalarParameterValue(HighlightWidgetPropertyName); if(bIsHighlighted != static_cast(HighlightVal)) { - OutVal = UKismetMathLibrary::FInterpTo_Constant(HighlightVal, IsDataWidgetHovered(), InDeltaTime, HighlightWidgetSpeed); + OutVal = UKismetMathLibrary::FInterpTo_Constant(HighlightVal, IsDataWidgetHovered(), InDeltaTime, (1.0f/HighlightWidgetSpeed)); GetHoveredMaterialInstance()->SetScalarParameterValue(HighlightWidgetPropertyName,OutVal); } } @@ -70,23 +71,79 @@ void UDataWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) Super::NativeTick(MyGeometry, InDeltaTime); } +void UDataWidget::SetVisibility(ESlateVisibility InVisibility) +{ + Super::SetVisibility(InVisibility); + + bool bStopTimer=false; + switch (GetVisibility()) { + case ESlateVisibility::Visible: break; + case ESlateVisibility::Collapsed: break; + bStopTimer=true; + case ESlateVisibility::Hidden: break; + bStopTimer=true; + case ESlateVisibility::HitTestInvisible: break; + case ESlateVisibility::SelfHitTestInvisible: break; + default: ; + } + + if(bStopTimer) + { + GetWorld()->GetTimerManager().PauseTimer(refresh_timer); + } + else + { + GetWorld()->GetTimerManager().UnPauseTimer(refresh_timer); + } +} + UOmegaPlayerSubsystem* UDataWidget::GetPlayerSubsystem() const { return GetOwningLocalPlayer()->GetSubsystem(); } +FLuaValue UDataWidget::GetWidgetScript(TSubclassOf State) +{ + return ULuaObjectFunctions::RunLuaScriptContainer(this,Script,State); +} + +FLuaValue UDataWidget::WidgetScriptKeyCall(const FString& key, TArray args, TSubclassOf State) +{ + return ULuaBlueprintFunctionLibrary::LuaTableKeyCall(GetWidgetScript(State),key,args); +} + +void UDataWidget::private_refresh(UDataWidget* widget) +{ + if(widget) + { + if(ReferencedAsset != widget->ReferencedAsset) + { + ReferencedAsset=widget->ReferencedAsset; + OnSourceAssetChanged(ReferencedAsset); + } + + if (widget->ParentList && widget->ParentList != ParentList) + { + ParentList=widget->ParentList; + OnNewListOwner(ParentList); + } + + } + Refresh(); +} + void UDataWidget::Refresh() { + SetIsEnabled(GetIsEntitySelectable()); - UObject* LocalListOwner = nullptr; - if(GetOwningList() && GetOwningList()->ListOwner) { LocalListOwner = GetOwningList()->ListOwner; } OnRefreshed(ReferencedAsset, LocalListOwner); + OnWidgetRefreshed.Broadcast(this); } //----------------------NATIVE CONSTRUCT-------------------------------------------// @@ -118,10 +175,19 @@ void UDataWidget::NativeConstruct() if(Cast(UCommonUILibrary::FindParentWidgetOfType(this, UDataWidget::StaticClass()))) { OwnerDataWidget = Cast(UCommonUILibrary::FindParentWidgetOfType(this, UDataWidget::StaticClass())); - OwnerDataWidget->SourceAssetChanged.AddDynamic(this, &UDataWidget::SetSourceAsset); + OwnerDataWidget->OnWidgetRefreshed.AddDynamic(this, &UDataWidget::private_refresh); } } Local_UpdateTooltip(ReferencedAsset); + + if(IsDesignTime()) + { + + const double moddedval = FMath::RandRange(RefreshVariance*-1.0f,RefreshVariance); + refresh_val= moddedval+RefreshFrequency; + + GetWorld()->GetTimerManager().SetTimer(refresh_timer, this, &UDataWidget::Refresh, refresh_val, true); + } } void UDataWidget::WidgetNotify(FName Notify) @@ -327,9 +393,8 @@ void UDataWidget::SetSourceAsset(UObject* Asset) Local_UpdateTooltip(Asset); ReferencedAsset = Asset; - SourceAssetChanged.Broadcast(Asset); + OnSourceAssetChanged(Asset); - Refresh(); } diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/HUDLayer.cpp b/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/HUDLayer.cpp index 9ce93f05..df685a97 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/HUDLayer.cpp +++ b/OmegaGameFramework/Source/OmegaGameFramework/Private/Widget/HUDLayer.cpp @@ -32,7 +32,7 @@ void UHUDLayer::OnAnimationFinished_Implementation(const UWidgetAnimation* Anima void UHUDLayer::RemoveHUDLayer() { - if(GetRemovedAnimation() && !bRemoving) + if(this && IsVisible() && GetRemovedAnimation() && !bRemoving) { bRemoving=true; if(bReverseCloseAnim) diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/CombatantFunctions.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/CombatantFunctions.h index 1f52af83..5ad70878 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/CombatantFunctions.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/CombatantFunctions.h @@ -60,6 +60,9 @@ class OMEGAGAMEFRAMEWORK_API UCombatantFunctions : public UBlueprintFunctionLibr //----------------------------------------------------------------------------------- UFUNCTION(BlueprintPure, Category="Attributes", meta=(CompactNodeTitle="Attribute ID")) static UOmegaAttribute* GetAttributeByUniqueID(const FString& ID); + + UFUNCTION(BlueprintCallable, Category="Attributes") + static TArray FlatAttributesToModifierValues(TMap FlatAttributes,bool AsMultiplier); /* UFUNCTION(BlueprintPure, Category="Attributes") diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/Components/EquipmentComponent.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/Components/EquipmentComponent.h index 7b27003a..8ee0e1a5 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/Components/EquipmentComponent.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/Components/EquipmentComponent.h @@ -45,6 +45,9 @@ class OMEGAGAMEFRAMEWORK_API UEquipmentComponent : public UActorComponent, publi UEquipmentSlot* GetSlotFromID(const FString& ID); FString GetSlotID(UEquipmentSlot* Slot); + UPROPERTY(EditDefaultsOnly, Instanced, Category="Equipment") + UEquipmentScript* Script; + UFUNCTION(BlueprintPure, Category="Equipment", meta=(CompactNodeTitle="Equipment")) TMap GetEquipment(); @@ -86,9 +89,9 @@ class OMEGAGAMEFRAMEWORK_API UEquipmentComponent : public UActorComponent, publi virtual TArray GetModifierValues_Implementation() override; - //############################################################################################## + //---------------------- // Data Collect - //############################################################################################## + //---------------------- UPROPERTY() UDataAssetCollectionComponent* LinkedCollectionComp; @@ -99,6 +102,52 @@ class OMEGAGAMEFRAMEWORK_API UEquipmentComponent : public UActorComponent, publi void ClearLinkedAssetCollectionComponent(UDataAssetCollectionComponent* Component); }; +//############################################################################################## +// Equipment Script +//############################################################################################## + +USTRUCT(BlueprintType) +struct FOmegaEquipmentData +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Combatant") + TArray AttributesMods; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Combatant") + TArray Skills; +}; + + +UCLASS(Blueprintable, BlueprintType, EditInlineNew, Const, Abstract, CollapseCategories) +class OMEGAGAMEFRAMEWORK_API UEquipmentScript : public UObject +{ + GENERATED_BODY() +private: + virtual UWorld* GetWorld() const override; + + UFUNCTION() + virtual UGameInstance* GetGameInstance() const; + + UPROPERTY(Transient) + UWorld* WorldPrivate = nullptr; + + UEquipmentScript(const FObjectInitializer& ObjectInitializer); + +public: + UFUNCTION(BlueprintImplementableEvent, Category="Equipment") + FOmegaEquipmentData GetSlotData(const FString& Slot) const; +}; + +UCLASS(Blueprintable, BlueprintType, EditInlineNew, Const, Abstract, CollapseCategories) +class OMEGAGAMEFRAMEWORK_API UEquipmentSlotScript : public UObject +{ + GENERATED_BODY() +public: + + UFUNCTION(BlueprintNativeEvent, Category="Equipment") + bool CanEquipItem(UObject* Item, UEquipmentComponent* Component=nullptr) const; +}; + UCLASS() class OMEGAGAMEFRAMEWORK_API UEquipmentSlot : public UPrimaryDataAsset, public IDataInterface_AttributeModifier, public IDataInterface_General, public IGameplayTagsInterface { @@ -138,12 +187,3 @@ class OMEGAGAMEFRAMEWORK_API UEquipmentSlot : public UPrimaryDataAsset, public I TArray FilterEquippableItems(TArray Items, UEquipmentComponent* Component=nullptr); }; -UCLASS(Blueprintable, BlueprintType, EditInlineNew, Const, Abstract, CollapseCategories) -class OMEGAGAMEFRAMEWORK_API UEquipmentSlotScript : public UObject -{ - GENERATED_BODY() -public: - - UFUNCTION(BlueprintNativeEvent, Category="Equipment") - bool CanEquipItem(UObject* Item, UEquipmentComponent* Component=nullptr) const; -}; \ No newline at end of file diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameMode.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameMode.h index 1b564fc1..2f65ee13 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameMode.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameMode.h @@ -24,16 +24,16 @@ class OMEGAGAMEFRAMEWORK_API AOmegaGameMode : public AGameModeBase public: UPROPERTY(EditDefaultsOnly, Category="Gameplay Systems", DisplayName="Pre-Load Gameplay Systems") - TArray> AutoGameplaySystems; + TArray> AutoGameplaySystems; UPROPERTY(EditDefaultsOnly, Category="Gameplay Systems", DisplayName="Load Gameplay System") - TSubclassOf LoadGameplaySystem; + TSubclassOf LoadGameplaySystem; UFUNCTION(BlueprintImplementableEvent, Category="Omega Game Mode") void OnLoadEventFinished(); UPROPERTY(EditDefaultsOnly, Category="Gameplay Systems", DisplayName="Post-Load Gameplay Systems") - TArray> PostLoadGameplaySystems; + TArray> PostLoadGameplaySystems; protected: virtual void BeginPlay() override; diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameplayCue.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameplayCue.h index 5ff91555..f04bc5d1 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameplayCue.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaGameplayCue.h @@ -3,6 +3,7 @@ #pragma once #include "CoreMinimal.h" +#include "NiagaraSystem.h" #include "GameFramework/Actor.h" #include "Gameplay/GameplayTagsInterface.h" #include "Kismet/BlueprintFunctionLibrary.h" @@ -35,6 +36,18 @@ class OMEGAGAMEFRAMEWORK_API AOmegaGameplayCue : public AActor, public IGameplay // Called every frame virtual void Tick(float DeltaTime) override; + //If true, will destroy the cue automatically when no sound, particle, or camerashake is playing. + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cue") + bool bAttemptAutocomplete=true; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cue") + TArray NiagaraParticles; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cue") + TArray Sounds; + + UPROPERTY(BlueprintReadOnly, Category="Cue") + FHitResult HitData; + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cue") UNiagaraComponent* Niagara; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Cue") @@ -52,5 +65,5 @@ class OMEGAGAMEFRAMEWORK_API UOmegaGameplayCueFunctions : public UBlueprintFunct public: UFUNCTION(BlueprintCallable, Category="Omega|Cues", meta=(WorldContext="WorldContextObject")) - static void PlayGameplayCue(UObject* WorldContextObject, TSubclassOf Cue, FTransform Origin, AActor* ActorOrigin=nullptr); + static void PlayGameplayCue(UObject* WorldContextObject, TSubclassOf Cue, FTransform Origin, FHitResult Hit, AActor* ActorOrigin=nullptr); }; \ No newline at end of file diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaScriptedTrace.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaScriptedTrace.h new file mode 100644 index 00000000..e2d06730 --- /dev/null +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Gameplay/OmegaScriptedTrace.h @@ -0,0 +1,55 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "UObject/Object.h" +#include "Engine/EngineTypes.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "OmegaScriptedTrace.generated.h" + +UCLASS(Blueprintable,BlueprintType,EditInlineNew) +class OMEGAGAMEFRAMEWORK_API UOmegaScriptedTraceLogic : public UObject +{ + GENERATED_BODY() + + UPROPERTY(Transient) + UWorld* WorldPrivate = nullptr; + +public: + UOmegaScriptedTraceLogic(const FObjectInitializer& ObjectInitializer); + virtual UWorld* GetWorld() const override; + UFUNCTION() + virtual UGameInstance* GetGameInstance() const; + + UFUNCTION(BlueprintImplementableEvent, Category="Trace") + FHitResult RunTrace(UObject* context,bool& Success); + UFUNCTION(BlueprintImplementableEvent, Category="Trace") + TArray RunTrace_Multi(UObject* context,bool& Success); +}; + + +USTRUCT(BlueprintType) +struct FOmegaScriptedTrace +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category="Trace") + UOmegaScriptedTraceLogic* Logic; +}; + +UCLASS() +class OMEGAGAMEFRAMEWORK_API UOmegaScriptedTraceFunctions : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintCallable, Category="Omega") + static const FHitResult ScriptedTrace_Single(UObject* context, FOmegaScriptedTrace Trace,bool& Success); + + UFUNCTION(BlueprintCallable, Category="Omega") + static const TArray ScriptedTrace_Multi(UObject* context, FOmegaScriptedTrace Trace,bool& Success); +}; + + diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaAttribute.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaAttribute.h index e20d62a4..8bd1e424 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaAttribute.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaAttribute.h @@ -14,6 +14,8 @@ #include "OmegaAttribute.generated.h" +class UCombatantComponent; + UCLASS() class OMEGAGAMEFRAMEWORK_API UOmegaAttribute : public UPrimaryDataAsset, public IDataInterface_General, public IGameplayTagsInterface { @@ -37,9 +39,12 @@ class OMEGAGAMEFRAMEWORK_API UOmegaAttribute : public UPrimaryDataAsset, public UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "Label", Category = "General") FString AttributeLabel; - UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "Icon", Category = "General") + UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "Icon (Texture)", Category = "General", AdvancedDisplay) UTexture2D* AttributeIcon; + UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "Icon", Category = "General", DisplayName="Icon") + FSlateBrush AttributeSlateIcon; + UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "Color", Category = "General") FLinearColor AttributeColor; @@ -143,11 +148,14 @@ class OMEGAGAMEFRAMEWORK_API UOmegaAttribute : public UPrimaryDataAsset, public virtual void GetGeneralAssetLabel_Implementation(FString& Label); }; -UCLASS(EditInlineNew, Blueprintable, BlueprintType) -class OMEGAGAMEFRAMEWORK_API UOmegaAttributeScript : public UPrimaryDataAsset +UCLASS(EditInlineNew, Blueprintable, BlueprintType, Abstract, CollapseCategories) +class OMEGAGAMEFRAMEWORK_API UOmegaAttributeScript : public UObject { GENERATED_BODY() public: + + UFUNCTION(BlueprintImplementableEvent, Category="Attribute") + float GetAttributeValue(int32 level,FGameplayTag ValueCategory); }; \ No newline at end of file diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaFileSubsystem.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaFileSubsystem.h new file mode 100644 index 00000000..7980fdd0 --- /dev/null +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaFileSubsystem.h @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Subsystems/GameInstanceSubsystem.h" +#include "OmegaFileSubsystem.generated.h" + +/** + * + */ +UCLASS() +class OMEGAGAMEFRAMEWORK_API UOmegaFileSubsystem : public UGameInstanceSubsystem +{ + GENERATED_BODY() + + virtual void Initialize(FSubsystemCollectionBase& Collection) override; + + UFUNCTION() + TArray GetFilesOfExtension(FString path, FString extension); + + UPROPERTY() + FString over_path="ovr"; + UPROPERTY() + FString override_images_path="images"; + UPROPERTY() + FString override_audio_path="audio"; + +public: + UFUNCTION(BlueprintPure) + FString GetOverrideDirectory() const; + UFUNCTION(BlueprintPure) + FString GetOverrideDirectory_Images() const; + UFUNCTION(BlueprintPure) + FString GetOverrideDirectory_Audio() const; + + + + UPROPERTY(BlueprintReadOnly) + TMap imported_images; + UPROPERTY(BlueprintReadOnly) + TMap imported_sounds; +}; + +UCLASS() +class OMEGAGAMEFRAMEWORK_API UOmegaFileFunctions : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() +public: + UFUNCTION(BlueprintPure, Category="Omega|File", meta=(WorldContext="WorldContextObject")) + static UTexture2D* GetOverride_Texture(UObject* WorldContextObject, const FString& name); +}; \ No newline at end of file diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaGameFrameworkBPLibrary.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaGameFrameworkBPLibrary.h index b9b1fdd3..4a604789 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaGameFrameworkBPLibrary.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/OmegaGameFrameworkBPLibrary.h @@ -9,8 +9,10 @@ #include "Gameplay/OmegaGameplayModule.h" #include "Kismet/GameplayStatics.h" #include "JsonObjectWrapper.h" +#include "Curves/CurveFloat.h" #include "Engine/AssetUserData.h" #include "OmegaGeneralEnums.h" +#include "LuaValue.h" #include "AssetRegistry/AssetData.h" #include "Components/ScrollBox.h" #include "OmegaGameFrameworkBPLibrary.generated.h" @@ -182,6 +184,9 @@ class UOmegaGameFrameworkBPLibrary : public UBlueprintFunctionLibrary UFUNCTION(BlueprintPure, Category="Omega|Actors", meta=(DeterminesOutputType="Class", AdvancedDisplay="ExcludedActors")) static TArray FilterComponentsWithTag(TArray Components, FName Tag, bool bExclude,TSubclassOf Class); + + UFUNCTION(BlueprintCallable, Category="Omega|Actors", meta=(WorldContext="WorldContextObject",DeterminesOutputType="Class")) + static AActor* Quick_SpawnActor(UObject* WorldContextObject, TSubclassOf Class, FTransform Transform, const TArray Tags); //############################################################################### // InterpActor @@ -223,11 +228,16 @@ class UOmegaGameFrameworkBPLibrary : public UBlueprintFunctionLibrary static FString GetObjectLabel(UObject* Object); //############################################################################### - // MetaData - //############################################################################### + // MetaData + //############################################################################### //UFUNCTION(BlueprintPure, Category="Omega|MetaData", meta=(DeterminesOutputType="Class")) //UOmegaAssetMetadata* GetMetadataFromObject(UObject* Object, TSubclassOf Class); - + + //############################################################################### + // MetaData + //############################################################################### + UFUNCTION(BlueprintCallable,Category="Omega|Assets",meta=(WorldContext="WorldContextObject", DeterminesOutputType="Class")) + static UDataAsset* CreateDataAssetFromLua(UObject* WorldContextObject, TSubclassOf Class,FLuaValue Value); }; //-------------------------------------------------------------------------------------------------------------------- @@ -251,12 +261,14 @@ class UOmegaStarRankFunctions : public UBlueprintFunctionLibrary }; UCLASS() -class UOmegaWidgetFunctions : public UBlueprintFunctionLibrary +class UOmegaCurveFunctions : public UBlueprintFunctionLibrary { GENERATED_BODY() public: + UFUNCTION(BlueprintPure,Category="Omega|Math|Curve") + float GetCurveValueFromTime(FRuntimeFloatCurve curve,float time); }; diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Player/OmegaPlayerSubsystem.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Player/OmegaPlayerSubsystem.h index 48f94170..ed514230 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/Player/OmegaPlayerSubsystem.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Player/OmegaPlayerSubsystem.h @@ -155,6 +155,16 @@ class OMEGAGAMEFRAMEWORK_API UOmegaPlayerSubsystem : public ULocalPlayerSubsyste UPROPERTY() UDataWidget* HoveredWidget = nullptr; + UFUNCTION(BlueprintPure,Category="Widgets") + UDataWidget* GetCurrentHoverWidget() const + { + if(HoveredWidget) + { + return HoveredWidget; + } + return nullptr; + }; + /////////////////// /// Input //// diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataList.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataList.h index 622340f2..bbd05a80 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataList.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataList.h @@ -5,6 +5,7 @@ #include "CoreMinimal.h" #include "UObject/ObjectMacros.h" #include "GameplayTagContainer.h" +#include "LuaObject.h" #include "WidgetInterface_Input.h" #include "Types/SlateEnums.h" #include "Components/SlateWrapperTypes.h" @@ -117,6 +118,15 @@ class OMEGAGAMEFRAMEWORK_API UDataList : public UUserWidget, public IWidgetInter UFUNCTION(BlueprintCallable, Category="Entry") void RefreshAllEntries(); + //---------------------------------------------------------------------------------------------// + // Lua + //---------------------------------------------------------------------------------------------// + UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Lua", meta=(MultiLine)) + FLuaScriptContainer List_Script; + UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Lua", meta=(MultiLine)) + FLuaScriptContainer Entry_Script; + UFUNCTION(BlueprintCallable,Category="Lua") + FLuaValue GetListScript(TSubclassOf State); private: UFUNCTION() @@ -162,7 +172,12 @@ class OMEGAGAMEFRAMEWORK_API UDataList : public UUserWidget, public IWidgetInter //Access Entires UFUNCTION(BlueprintCallable, Category = "Ω|Widget|DataList") - void HoverEntry(int32 Index); + void HoverEntry(int32 Index,bool UseLastIndex=false); + +private: + UPROPERTY() + int32 remembered_hover_index; +public: UFUNCTION(BlueprintPure, BlueprintCallable, Category = "Ω|Widget|DataList") UDataWidget* GetHoveredEntry(); diff --git a/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataWidget.h b/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataWidget.h index 93c1fba7..69eafbb4 100644 --- a/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataWidget.h +++ b/OmegaGameFramework/Source/OmegaGameFramework/Public/Widget/DataWidget.h @@ -5,6 +5,8 @@ #include "CoreMinimal.h" #include "DataTooltip.h" #include "GameplayTagContainer.h" +#include "LuaBlueprintFunctionLibrary.h" +#include "LuaObject.h" #include "WidgetInterface_Input.h" #include "Blueprint/IUserObjectListEntry.h" #include "Blueprint/UserWidget.h" @@ -21,7 +23,7 @@ class UWidgetAnimation; DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSelected, UDataWidget*, DataWidget); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHovered, UDataWidget*, DataWidget, bool, bIsHovered); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHighlight, UDataWidget*, DataWidget, bool, bIsHighlighted); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSourceAssetChanged, UObject*, SourceAsset); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnWidgetRefreshed, UDataWidget*, DataWidget); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnWidgetNotify, UDataWidget*, DataWidget, FName, Notify); /** @@ -39,10 +41,12 @@ class OMEGAGAMEFRAMEWORK_API UDataWidget : public UUserWidget, public IUserObjec virtual void NativeOnAddedToFocusPath(const FFocusEvent& InFocusEvent) override; virtual void NativeOnRemovedFromFocusPath(const FFocusEvent& InFocusEvent) override; virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; + virtual void SetVisibility(ESlateVisibility InVisibility) override; UOmegaPlayerSubsystem* GetPlayerSubsystem() const; public: + UPROPERTY() UDataList* ParentList = nullptr; @@ -58,21 +62,57 @@ class OMEGAGAMEFRAMEWORK_API UDataWidget : public UUserWidget, public IUserObjec UFUNCTION(BlueprintImplementableEvent,Category = "DataWidget") UMaterialInstanceDynamic* GetHoveredMaterialInstance(); + //---------------------------------------------------------------------------------------------// + // Lua + //---------------------------------------------------------------------------------------------// + UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="Lua", meta=(MultiLine)) + FLuaScriptContainer Script; + + + UFUNCTION(BlueprintCallable,Category="Lua",meta=(AdvancedDisplay="State")) + FLuaValue GetWidgetScript(TSubclassOf State); + UFUNCTION(BlueprintCallable,Category="Lua",meta=(AdvancedDisplay="State")) + FLuaValue WidgetScriptKeyCall(const FString& key, TArray args, TSubclassOf State); + + //---------------------------------------------------------------------------------------------// + // Highlight + //---------------------------------------------------------------------------------------------// +private: + UFUNCTION() + void private_refresh(UDataWidget* widget); +public: UFUNCTION(BlueprintCallable, Category="DataWidget", meta=(Keywords="update")) void Refresh(); UFUNCTION(BlueprintImplementableEvent,Category = "DataWidget", meta=(Keywords="update")) void OnRefreshed(UObject* SourceAsset = nullptr, UObject* ListOwner = nullptr); - - + + //Automatically calls the "Refresh" function on a timed loop + UPROPERTY(EditDefaultsOnly, Category = "Refresh") + bool bAutoRefreshOnTimer; + + //Frequency (in seconds) at which the "Refresh + UPROPERTY(EditDefaultsOnly, Category = "Refresh") + double RefreshFrequency = 0.1; + + //Offsets the refresh variance by a random about of this multiplier. (E.G. if RefreshFrequency=0.5, RefreshVariance=0.1, the final refresh value will be between 0.4-0.6.) This will help all avoid refreshes being called on the same tick. + UPROPERTY(EditDefaultsOnly, Category = "Refresh") + double RefreshVariance = 0; +private: + UPROPERTY() + float refresh_val; + UPROPERTY() + FTimerHandle refresh_timer; + +public: //---------------------------------------------------------------------------------------------// // Highlight //---------------------------------------------------------------------------------------------// UPROPERTY(BlueprintReadOnly, Category = "DataWidget") bool bIsHighlighted; - UPROPERTY(EditDefaultsOnly, Category="Display") - float HighlightWidgetSpeed = 10; + UPROPERTY(EditDefaultsOnly, Category="Display", DisplayName="Highlight Widget Duration") + float HighlightWidgetSpeed = 1.1; UPROPERTY(EditDefaultsOnly, Category="Display", AdvancedDisplay) FName HighlightWidgetPropertyName = "Highlight"; //---------------------------------------------------------------------------------------------// @@ -81,12 +121,19 @@ class OMEGAGAMEFRAMEWORK_API UDataWidget : public UUserWidget, public IUserObjec //UPROPERTY(BlueprintReadOnly, Category = "DataWidget", meta=(DeprecatedProperty)) //bool bIsHovered; - UPROPERTY(EditDefaultsOnly, Category="Display") - float HoverWidgetSpeed = 10; + UPROPERTY(EditDefaultsOnly, Category="Display", DisplayName="Hover Widget Duration") + float HoverWidgetSpeed = 1.0; UPROPERTY(EditDefaultsOnly, Category="Display", AdvancedDisplay) FName HoverWidgetPropertyName = "Hover"; + //UFUNCTION(BlueprintImplementableEvent, Category="Hover") + //void OnHoverUpdate(float HoverValue); + +private: + UPROPERTY() + float hover_value; +public: //---------------------------------------------------------------------------------------------// - // Hover + // Notify //---------------------------------------------------------------------------------------------// UFUNCTION(BlueprintCallable, Category="Notify") void WidgetNotify(FName Notify); @@ -161,7 +208,7 @@ class OMEGAGAMEFRAMEWORK_API UDataWidget : public UUserWidget, public IUserObjec void SetSourceAsset(UObject* Asset); UPROPERTY() - FOnSourceAssetChanged SourceAssetChanged; + FOnWidgetRefreshed OnWidgetRefreshed; UFUNCTION(BlueprintImplementableEvent, Category = "Ω|Widget|DataWidget") void OnSourceAssetChanged(UObject* Asset); diff --git a/OmegaGameFramework/Source/OmegaMod/Public/OmegaModSubsystem.h b/OmegaGameFramework/Source/OmegaMod/Public/OmegaModSubsystem.h index c8d4c581..1e98b183 100644 --- a/OmegaGameFramework/Source/OmegaMod/Public/OmegaModSubsystem.h +++ b/OmegaGameFramework/Source/OmegaMod/Public/OmegaModSubsystem.h @@ -89,4 +89,26 @@ class OMEGAMOD_API UOmegaModManager : public UOmegaGameplayModule UFUNCTION(BlueprintImplementableEvent, Category="Mods") void OnModInitialized(UOmegaMod* Mod); +}; + + +UCLASS() +class OMEGAMOD_API UOmegaModFileFunctions : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + + UFUNCTION(BlueprintImplementableEvent, Category="Mods") + FString GetModFiletype(); + + UFUNCTION(BlueprintImplementableEvent, Category="Mods") + void OnSetModActive(UOmegaMod* Mod, bool IsActive); + + UFUNCTION(BlueprintImplementableEvent, Category="Mods") + bool OnGetModActive(UOmegaMod* Mod); + + UFUNCTION(BlueprintImplementableEvent, Category="Mods") + void OnModInitialized(UOmegaMod* Mod); + }; \ No newline at end of file diff --git a/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayLinearEventScript.cpp b/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayLinearEventScript.cpp index 43baf5ab..6c564774 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayLinearEventScript.cpp +++ b/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayLinearEventScript.cpp @@ -6,7 +6,7 @@ #include "Engine/World.h" #include "Parser/OmegaDataParserSubsystem.h" -void UAsyncPlayLinearEventScript::Local_NewEvent(int32 Index, UOmegaLinearEvent* EventRef) +void UAsyncPlayLinearEventScript::Local_NewEvent(UOmegaLinearEventInstance* Instance,int32 Index, UOmegaLinearEvent* EventRef) { NewEvent.Broadcast(Index,EventRef,EventInstance); } diff --git a/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayerLineEventSequence.cpp b/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayerLineEventSequence.cpp index 88b6be21..3667660d 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayerLineEventSequence.cpp +++ b/OmegaGameFramework/Source/OmegaSequence/Private/Event/AsyncPlayerLineEventSequence.cpp @@ -27,7 +27,6 @@ void UAsyncPlayLinearEventSequence::Local_NewEvent(const UOmegaLinearEventInstan void UAsyncPlayLinearEventSequence::Activate() { - if(EventData.Events.Num()<=0) { Local_Finish(nullptr,"Empty"); @@ -46,9 +45,9 @@ void UAsyncPlayLinearEventSequence::Activate() UAsyncPlayLinearEventSequence* UAsyncPlayLinearEventSequence::PlayLinearEventSequence(UObject* WorldContextObject, FLinearEventSequence Events, int32 StartingIndex) { - UAsyncPlayLinearEventSequence* NewEvent = NewObject(); - NewEvent->SubsystemRef = WorldContextObject->GetWorld()->GetSubsystem(); - NewEvent->EventData = Events; - NewEvent->Local_StartingIndex = StartingIndex; - return NewEvent; + UAsyncPlayLinearEventSequence* LocalEvent = NewObject(); + LocalEvent->SubsystemRef = WorldContextObject->GetWorld()->GetSubsystem(); + LocalEvent->EventData = Events; + LocalEvent->Local_StartingIndex = StartingIndex; + return LocalEvent; } diff --git a/OmegaGameFramework/Source/OmegaSequence/Private/OmegaLinearEventSubsystem.cpp b/OmegaGameFramework/Source/OmegaSequence/Private/OmegaLinearEventSubsystem.cpp index 457f7ef7..1b095e2f 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Private/OmegaLinearEventSubsystem.cpp +++ b/OmegaGameFramework/Source/OmegaSequence/Private/OmegaLinearEventSubsystem.cpp @@ -19,11 +19,17 @@ void UOmegaLinearEventSubsystem::Deinitialize() Super::Deinitialize(); } -void UOmegaLinearEventSubsystem::Local_EndEvent(const UOmegaLinearEventInstance* Instance, const FString& Flag) +void UOmegaLinearEventSubsystem::Local_EndEvent(const FString& Flag, UOmegaLinearEventInstance* Instance) { OnLinearEventSequenceEnd.Broadcast(Instance,Flag); } +void UOmegaLinearEventSubsystem::Local_NewEvent(UOmegaLinearEventInstance* Instance, int32 EventIndex, + UOmegaLinearEvent* Event) +{ + OnLinearEventBegin.Broadcast(Instance,Event,EventIndex); +} + UOmegaLinearEventInstance* UOmegaLinearEventSubsystem::PlayLinearEvent(FLinearEventSequence Sequence, int32 StartingEvent) { @@ -31,7 +37,16 @@ UOmegaLinearEventInstance* UOmegaLinearEventSubsystem::PlayLinearEvent(FLinearEv TempEventInst->SubsystemRef = this; TempEventInst->SequenceData = Sequence; - //TempEventInst->GetCurrentEventIndex() = StartingEvent-1; + + TempEventInst->OnEventSequenceFinish.AddDynamic(this, &UOmegaLinearEventSubsystem::Local_EndEvent); + TempEventInst->OnEventUpdated.AddDynamic(this, &UOmegaLinearEventSubsystem::Local_NewEvent); + + //set the starting event sequence to the previous event from "StartingEvent". This means when "NextEvent" fires bellow, it will run the correct starting index. + if (Sequence.Events.IsValidIndex(StartingEvent-1)) + { + TempEventInst->CurrentEvent=Sequence.Events[StartingEvent-1]; + } + TempEvents.Add(TempEventInst); TempEventInst->NextEvent("Root"); return TempEventInst; @@ -66,7 +81,10 @@ AOmegaLinearChoiceInstance* UOmegaLinearEventSubsystem::PlayLinearChoice(FOmegaL LocalInst->ChoiceData = Choices; for(auto* TempChoice : LocalInst->ChoiceData.Choices) { - TempChoice->GameInstanceRef = GetWorld()->GetGameInstance(); + if(TempChoice) + { + TempChoice->GameInstanceRef = GetWorld()->GetGameInstance(); + } } LocalInst->FinishSpawning(SpawnWorldPoint); diff --git a/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventScript.h b/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventScript.h index 2442f3d5..19b634dc 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventScript.h +++ b/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventScript.h @@ -31,7 +31,7 @@ class OMEGASEQUENCE_API UAsyncPlayLinearEventScript : public UBlueprintAsyncActi UOmegaLinearEventInstance* EventInstance; UFUNCTION() - void Local_NewEvent(int32 Index, UOmegaLinearEvent* EventRef); + void Local_NewEvent(UOmegaLinearEventInstance* Instance,int32 Index, UOmegaLinearEvent* EventRef); UPROPERTY(BlueprintAssignable) FOnAsynScriptEventUpdated NewEvent; diff --git a/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventSequence.h b/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventSequence.h index d24ad8ff..3206f99c 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventSequence.h +++ b/OmegaGameFramework/Source/OmegaSequence/Public/Event/AsyncPlayLinearEventSequence.h @@ -8,7 +8,7 @@ #include "AsyncPlayLinearEventSequence.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFinished, const FString&, Flag); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnAsynLinEventUpdated, int32, NewEventIndex, const UOmegaLinearEvent*, NewEvent, UOmegaLinearEventInstance*, Instance); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnAsynLinEventUpdated, int32, NewEventIndex, const UOmegaLinearEvent*, Event, UOmegaLinearEventInstance*, Instance); UCLASS() class OMEGASEQUENCE_API UAsyncPlayLinearEventSequence : public UBlueprintAsyncActionBase diff --git a/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEvent.h b/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEvent.h index e7a650da..824b5c3a 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEvent.h +++ b/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEvent.h @@ -3,6 +3,7 @@ #pragma once #include "CoreMinimal.h" +#include "LuaInterface.h" #include "UObject/NoExportTypes.h" #include "OmegaLinearEvent.generated.h" @@ -12,7 +13,7 @@ class UOmegaLinearEventSubsystem; DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnEventEnded, const FString&, Flag); UCLASS(BlueprintType, Blueprintable, abstract, editinlinenew, hidecategories=Object, CollapseCategories) -class OMEGASEQUENCE_API UOmegaLinearEvent : public UObject +class OMEGASEQUENCE_API UOmegaLinearEvent : public UObject, public ILuaInterface { GENERATED_BODY() public: diff --git a/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEventInstance.h b/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEventInstance.h index fc04396a..ba452b3e 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEventInstance.h +++ b/OmegaGameFramework/Source/OmegaSequence/Public/Event/OmegaLinearEventInstance.h @@ -11,7 +11,7 @@ class UOmegaLinearEventSubsystem; DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEventSequenceFinish, const FString&, Flag, UOmegaLinearEventInstance*, Instance); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEventUpdated, int32, EventIndex, UOmegaLinearEvent*, Event); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnEventUpdated, UOmegaLinearEventInstance*, Instance, int32, EventIndex, UOmegaLinearEvent*, Event); UCLASS(BlueprintType) class OMEGASEQUENCE_API UOmegaLinearEventInstance : public UObject @@ -64,6 +64,7 @@ class OMEGASEQUENCE_API UOmegaLinearEventInstance : public UObject inline void UOmegaLinearEventInstance::NextEvent(const FString& Flag) { + //Unbind last event if(SequenceData.Events.IsValidIndex(GetCurrentEventIndex())) { SequenceData.Events[GetCurrentEventIndex()]->EventEnded.RemoveDynamic(this, &UOmegaLinearEventInstance::NextEvent); @@ -78,7 +79,6 @@ inline void UOmegaLinearEventInstance::NextEvent(const FString& Flag) const int32 NextIndex = GetCurrentEventIndex() +1; - UOmegaLinearEvent* IncomingEvent = nullptr; // Try to get event from id. @@ -114,7 +114,6 @@ inline void UOmegaLinearEventInstance::EndInstance(const FString& Flag) } OnEventSequenceFinish.Broadcast(Flag,this); SubsystemRef->TempEvents.Remove(this); - } inline UOmegaLinearEvent* UOmegaLinearEventInstance::GetEventFromID(FName ID) @@ -133,11 +132,18 @@ inline void UOmegaLinearEventInstance::StartEvent(UOmegaLinearEvent* Event) { if(Event->CanPlayEvent()) { + //Bind event so when it finishes, we go to next event Event->EventEnded.AddDynamic(this, &UOmegaLinearEventInstance::NextEvent); + + //setup vars Event->GameInstanceRef = SubsystemRef->GameInstanceReference; Event->WorldPrivate = SubsystemRef->GetWorld(); - OnEventUpdated.Broadcast(GetCurrentEventIndex(),Event); - SubsystemRef->OnLinearEventBegin.Broadcast(this,Event,GetCurrentEventIndex()); + + //broadcast delegates for event start (first - from instance / second - from subsystem) + OnEventUpdated.Broadcast(this,GetCurrentEventIndex(),Event); + //SubsystemRef->OnLinearEventBegin.Broadcast(this,Event,GetCurrentEventIndex()); + + //Finally, start the event Event->Native_Begin(); } else diff --git a/OmegaGameFramework/Source/OmegaSequence/Public/OmegaLinearEventSubsystem.h b/OmegaGameFramework/Source/OmegaSequence/Public/OmegaLinearEventSubsystem.h index 75323c9b..557bb2a6 100644 --- a/OmegaGameFramework/Source/OmegaSequence/Public/OmegaLinearEventSubsystem.h +++ b/OmegaGameFramework/Source/OmegaSequence/Public/OmegaLinearEventSubsystem.h @@ -45,8 +45,9 @@ class OMEGASEQUENCE_API UOmegaLinearEventSubsystem : public UWorldSubsystem virtual void Deinitialize() override; UFUNCTION() - void Local_EndEvent(const UOmegaLinearEventInstance* Instance, const FString& Flag); - + void Local_EndEvent(const FString& Flag, UOmegaLinearEventInstance* Instance); + UFUNCTION() + void Local_NewEvent(UOmegaLinearEventInstance* Instance, int32 EventIndex, UOmegaLinearEvent* Event); public: UPROPERTY() UGameInstance* GameInstanceReference; diff --git a/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_android64.a b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_android64.a new file mode 100644 index 00000000..e23d6422 Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_android64.a differ diff --git a/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_ios.a b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_ios.a new file mode 100644 index 00000000..be209a70 Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_ios.a differ diff --git a/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_linux_aarch64.a b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_linux_aarch64.a new file mode 100644 index 00000000..ec7947cb Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_linux_aarch64.a differ diff --git a/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_win64.lib b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_win64.lib new file mode 100644 index 00000000..d1388ac4 Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/ARM64/liblua53_win64.lib differ diff --git a/OmegaGameFramework/Source/ThirdParty/ARMv7/liblua53_android.a b/OmegaGameFramework/Source/ThirdParty/ARMv7/liblua53_android.a new file mode 100644 index 00000000..764f243d Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/ARMv7/liblua53_android.a differ diff --git a/OmegaGameFramework/Source/ThirdParty/lua/lauxlib.h b/OmegaGameFramework/Source/ThirdParty/lua/lauxlib.h new file mode 100644 index 00000000..9857d3a8 --- /dev/null +++ b/OmegaGameFramework/Source/ThirdParty/lua/lauxlib.h @@ -0,0 +1,264 @@ +/* +** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + + +/* extra error code for 'luaL_loadfilex' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +/* key, in the registry, for table of loaded modules */ +#define LUA_LOADED_TABLE "_LOADED" + + +/* key, in the registry, for table of preloaded loaders */ +#define LUA_PRELOAD_TABLE "_PRELOAD" + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + diff --git a/OmegaGameFramework/Source/ThirdParty/lua/lua.h b/OmegaGameFramework/Source/ThirdParty/lua/lua.h new file mode 100644 index 00000000..c236e360 --- /dev/null +++ b/OmegaGameFramework/Source/ThirdParty/lua/lua.h @@ -0,0 +1,486 @@ +/* +** $Id: lua.h,v 1.332.1.2 2018/06/13 16:58:17 roberto Exp $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "5" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2018 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) +*/ +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 + + +typedef struct lua_State lua_State; + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTAGS 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API const lua_Number *(lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_rotate) (lua_State *L, int idx, int n); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int n); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API int (lua_getglobal) (lua_State *L, const char *name); +LUA_API int (lua_gettable) (lua_State *L, int idx); +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawget) (lua_State *L, int idx); +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); + +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API int (lua_getuservalue) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *name); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); +LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_isyieldable) (lua_State *L); + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** {============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) + +#define lua_pushglobaltable(L) \ + ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) + +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) + +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros for unsigned conversions +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif +/* }============================================================== */ + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2018 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/OmegaGameFramework/Source/ThirdParty/lua/lua.hpp b/OmegaGameFramework/Source/ThirdParty/lua/lua.hpp new file mode 100644 index 00000000..ec417f59 --- /dev/null +++ b/OmegaGameFramework/Source/ThirdParty/lua/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/OmegaGameFramework/Source/ThirdParty/lua/luaconf.h b/OmegaGameFramework/Source/ThirdParty/lua/luaconf.h new file mode 100644 index 00000000..9eeeea69 --- /dev/null +++ b/OmegaGameFramework/Source/ThirdParty/lua/luaconf.h @@ -0,0 +1,790 @@ +/* +** $Id: luaconf.h,v 1.259.1.1 2017/04/19 17:29:57 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance compiling it with 32-bit numbers or +** restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You +** can also define LUA_32BITS in the make file, but changing here you +** ensure that all software connected to Lua will be compiled with the +** same configuration. +*/ +/* #define LUA_32BITS */ + + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. +*/ +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ +#endif + + +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ +#endif + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#endif + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS +#endif + + + +/* +@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. +*/ +/* avoid undefined shifts */ +#if ((INT_MAX >> 15) >> 15) >= 1 +#define LUAI_BITSINT 32 +#else +/* 'int' always must have at least 16 bits */ +#define LUAI_BITSINT 16 +#endif + + +/* +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options (if supported +** by your C compiler). The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). +*/ + +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + +#if defined(LUA_32BITS) /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_BITSINT >= 32 /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif defined(LUA_C89_NUMBERS) /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + + +/* +** default configuration for 64-bit Lua ('long long' and 'double') +*/ +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif + +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE +#endif + +/* }================================================================== */ + + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +*/ +#define LUA_PATH_SEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXEC_DIR "!" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +** Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +** C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== +*/ + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +** that are not to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2. +@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_2) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. +*/ +#define LUA_COMPAT_BITLIB + +/* +@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod. +*/ +#define LUA_COMPAT_IPAIRS + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +*/ +#define LUA_COMPAT_APIINTCASTS + +#endif /* } */ + + +#if defined(LUA_COMPAT_5_1) /* { */ + +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#endif /* } */ + + +/* +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. +*/ +/* #define LUA_COMPAT_FLOATSTRING */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers. +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUA_NUMBER is the floating-point type used by Lua. +@@ LUAI_UACNUMBER is the result of a 'default argument promotion' +@@ over a floating number. +@@ l_mathlim(x) corrects limit name 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. +@@ lua_str2number converts a decimal numeric string to a number. +*/ + + +/* The following definitions are good for most cases here */ + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,sz,n) \ + l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) + +/* +@@ lua_numbertointeger converts a float number to an integer, or +** returns 0 if float is not within the range of a lua_Integer. +** (The range comparisons are tricky because of rounding. The tests +** here assume a two-complement representation, where MININTEGER always +** has an exact representation as a float; MAXINTEGER may not have one, +** and therefore its conversion to float may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + +/* now the variable definitions */ + +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ + +#define LUA_NUMBER float + +#define l_mathlim(n) (FLT_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" + +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_mathlim(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ + +#define LUA_NUMBER double + +#define l_mathlim(n) (DBL_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.14g" + +#define l_mathop(op) op + +#define lua_str2number(s,p) strtod((s), (p)) + +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + + +/* +@@ LUA_INTEGER is the integer type used by Lua. +** +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +** +@@ LUAI_UACINT is the result of a 'default argument promotion' +@@ over a lUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ lua_integer2str converts an integer to a string. +*/ + + +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" + +#define LUAI_UACINT LUA_INTEGER + +#define lua_integer2str(s,sz,n) \ + l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n)) + +/* +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) +*/ +#define LUA_UNSIGNED unsigned LUAI_UACINT + + +/* now the variable definitions */ + +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ + +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" + +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ + +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" + +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== +*/ + +/* +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) +*/ +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) +#else +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) +#endif + + +/* +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +/* +@@ lua_pointer2str converts a pointer to a readable string in a +** non-specified way. +*/ +#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p) + + +/* +@@ lua_number2strx converts a float to an hexadecimal numeric string. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,sz,f,n) \ + ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n))) +#endif + + +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#endif + + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif +#endif + + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). You probably do not want/need to change them. +** ===================================================================== +*/ + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + + +/* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", -1e4932)' needs 5034 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) +*/ +#if LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif + +/* }================================================================== */ + + +/* +@@ LUA_QL describes how error messages quote program elements. +** Lua does not use these macros anymore; they are here for +** compatibility only. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + + + +#endif + diff --git a/OmegaGameFramework/Source/ThirdParty/lua/lualib.h b/OmegaGameFramework/Source/ThirdParty/lua/lualib.h new file mode 100644 index 00000000..f5304aa0 --- /dev/null +++ b/OmegaGameFramework/Source/ThirdParty/lua/lualib.h @@ -0,0 +1,61 @@ +/* +** $Id: lualib.h,v 1.45.1.1 2017/04/19 17:20:42 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* version suffix for environment variable names */ +#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +LUAMOD_API int (luaopen_utf8) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/OmegaGameFramework/Source/ThirdParty/x64/liblua53_linux64.a b/OmegaGameFramework/Source/ThirdParty/x64/liblua53_linux64.a new file mode 100644 index 00000000..37547171 Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/x64/liblua53_linux64.a differ diff --git a/OmegaGameFramework/Source/ThirdParty/x64/liblua53_mac.a b/OmegaGameFramework/Source/ThirdParty/x64/liblua53_mac.a new file mode 100644 index 00000000..2a8913ee Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/x64/liblua53_mac.a differ diff --git a/OmegaGameFramework/Source/ThirdParty/x64/liblua53_win64.lib b/OmegaGameFramework/Source/ThirdParty/x64/liblua53_win64.lib new file mode 100644 index 00000000..6914d6ff Binary files /dev/null and b/OmegaGameFramework/Source/ThirdParty/x64/liblua53_win64.lib differ