Jump to content

Josh

Staff
  • Posts

    23,123
  • Joined

  • Last visited

Everything posted by Josh

  1. 1.0.2 Added C++ control over Lua with new functions and methods: SetGlobal GetGlobal CallFunction CallMethod Object::SetField Object::GetField
  2. The C implementation of variadic functions is really bad. You have to specify the number of parameters, which makes it more code than just passing a vector.
  3. JSON example. The only thing missing are key/value pairs. The reason this is so cool is because it allows Lua to modify JSON data stored in C++ without having to pass the entire structure back and forth between nlohmann::json and Lua for each change. So this can be used to read and write values to scene files, insert custom user data into glTF files, and add custom user settings in the editor. local j3array = JsonArray() j3array[1] = "test value 1" j3array[2] = "test value 2" j3array[3] = "test value 3" j3array[4] = "test value 4" j3array[5] = "test value 5" --Array for n = 1, #j3array do Print(tostring(n)..": "..j3array[n]) end --iPairs for k, v in ipairs(j3array) do Print(tostring(k)..": "..tostring(v)) end local j3object = Json() j3object["color"] = "blue" j3object["weight"] = 100 j3object["happy"] = true --Pairs for k, v in pairs(j3object) do Print(tostring(k)..": "..tostring(v)) end The Lua component save / load methods can work just like C++: function component:Save(J3) j3["health"] = self.health return true end Of course with Lua that can be pre-serialized, and then the function would just be used for any adjustments you want to make, like saving data of loaded resources, and other things that don't get saved automatically. JSON objects can only store numbers, strings, booleans, and other JSON objects, so they can always be saved to a file and loaded back the same.
  4. You can use Lua and JSON together now. The same JSON objects are accessible to both C++ and Lua with no fiddling around with stacks and things: local j3 = Json() j3.key1 = "value" j3.key2 = 3 j3["key3"] = true Print(tostring(j3)) This prints out: { "key1": "value", "key2": 3, "key3": true } LoadJson() and SaveJson() are also available. This is how I plan on handling user-defined settings in the editor: program.settings.mainwindow.position.x = 50 program.settings.mainwindow.position.y = 100 That will directly modify the program->settings json object and those changes will be saved to the settings file. I'm shocked that it worked so neatly. Other stuff to try: https://www.ultraengine.com/learn/Component_Connect?lang=lua https://www.ultraengine.com/learn/Component_Collide?lang=lua
  5. 1.0.2 Added Component:Connect in Lua Integrated nlohmann::json into Lua(!). Json structures can be easily accessed by both C++ and Lua, and changes in one environment are instantly available in the other. Removed the ability to add a component from a table, as this was causing problems. Components must be modules.
  6. Adding Component:Connect in Lua. This gives you the ability to create flowgraph connections in code, with any number of arbitrary arguments, including tables, functions, and other special Lua stuff: sender:Connect(sender.Send, receiver, receiver.Receive, { true, 2, "Hello!" }) Whenever the send method is called, whether it is by code or another flowgraph input, at the end of it the receiver will be triggered to execute the Receive method, with the supplied arguments. https://www.ultraengine.com/learn/Component_Connect?lang=lua
  7. Apparently not. It's okay, I don't think I am going to use this anyways.
  8. Every example I can find online uses a chr*. You can't call ++ on an std::any. Does anyone know how to correctly iterate this to get all the arguments?: bool LuaComponent::CallMethod(const WString& name, const std::any& args...) { std::vector<std::any> v; auto vargs = va_list(); va_start(vargs, args); while (args.has_value()) { v.push_back(args); args++;//??? this does not compile } va_end(vargs); return CallMethod(name, v); }
  9. I think that's no problem. It's mostly just a matter of deciding how the user interface should work. Lua Collide function is working now. Here's an example: https://www.ultraengine.com/learn/Component_Collide?lang=lua
  10. You can now create Lua components from a table as well: local component = {} function component:Update() self.entity:Turn(10,0,0) end box:AddComponent(component, "MyComponent") You need to go through the AddComponent() command, not just add tables to your entity, because this creates the C++ component and handles a bunch of stuff. I did this primarily for ease of showing things in the documentation. If a special component is needed it's easy to just add it into the documentation example. It looks like std::any will probably work for functions-as-arguments as well: int FUNC() { return 3; } int main(int argc, const char* argv[]) { std::any thing = FUNC; Print(thing.type().name()); auto f = std::any_cast<int(__cdecl*)(void)>(thing); Print(f()); return 0; }
  11. 1.0.2 Component connections are added, with arguments. Arguments won't work in Lua yet, but connections should. Added LuaGetState
  12. Component connections are added now, with arguments. Here is a working example. A lot of stuff has to be defined manually in C++. In Lua this is all automated, including the output firing: #include "UltraEngine.h" using namespace UltraEngine; struct Sender : public Component { virtual void MyMethod() { //---------------------------------------------------- // You probably want to execute some other code here //---------------------------------------------------- Print("Firing output MyMethod"); FireOutputs("MyMethod"); } }; struct Receiver : public Component { virtual void AnotherMethod(const int i) { Print("Executing method with argument: " + String(i)); //---------------------------------------------------- // You probably want to execute some other code here //---------------------------------------------------- } virtual void ReceiveSignal(shared_ptr<Component> sender, const WString& input, std::vector<std::any> args) { Print("Signal received: " + input); //Choose the method to call if (input == "AnotherMethod") { //Fix arguments args.resize(1); if (strcmp(args[0].type().name(), "int") != 0) args[0] = 0; //Call the method AnotherMethod(std::any_cast<int>(args[0])); } else { Print("Unknown method " + input); } } }; int main(int argc, const char* argv[]) { //Create sending object auto box1 = CreateBox(NULL); auto sender = box1->AddComponent<Sender>(); //Create receiving object auto box2 = CreateBox(NULL); auto receiver = box2->AddComponent<Receiver>(); //Add connection sender->Connect("MyMethod", receiver, "AnotherMethod", { 3 }); //Trigger the connection sender->MyMethod(); return 0; } I think the same thing in Lua will work like this, without any manual processing or firing: Sender = {} function Sender:MyMethod() Print("Firing output MyMethod"); end Receiver = {} function Receiver:AnotherMethod(i) Print("Executing method with argument: "..tostring(i)) end --Create sending object auto box1 = CreateBox(NULL) auto sender = box1->AddComponent(Sender) --Create receiving object auto box2 = CreateBox(NULL) auto receiver = box2->AddComponent(Receiver) --Add connection sender->Connect(Sender.MyMethod, receiver, Receiver.AnotherMethod, { 3 }) --Trigger the connection sender->MyMethod()
  13. Here's a quick test using std::any: #include "UltraEngine.h" #include <any> using namespace UltraEngine; int main(int argc, const char* argv[]) { std::any thing = 3; //thing = String("test"); //thing = 5u; if (thing.has_value()) { auto name = String(thing.type().name()); if (name == "int") { Print(std::any_cast<int>(thing)); } else if (name == "float") { Print(std::any_cast<float>(thing)); } else if (name == "class UltraEngine::String") { Print(std::any_cast<String>(thing)); } else { Print("Unknown type \"" + name + "\""); } } else { Print("thing is empty."); } return 0; }
  14. I've worked out the basic flowgraph system: https://www.ultraengine.com/learn/Component_Connect?lang=cpp https://www.ultraengine.com/learn/Component_FireOutputs?lang=cpp https://www.ultraengine.com/learn/Component_ReceiveSignal?lang=cpp I don't know yet exactly how std::any works, or how functions as arguments will work. I doubt I can really work that out until the visual interface is usable, but the basic implementation is done.
  15. The Lua component system stuff is now stored in a single table: ComponentSystem = {}-- global variable ComponentSystem.mode = "ECS"-- default behavior --ComponentSystem.mode = "OOP"-- experimental, will break compatibility with ECS-style scripts --This function is called when a component is attached to an entity function ComponentSystem:AddComponent(entity, component, name) local table = require("Components."..name) if table == nil then return false end blah blah blah... The script itself is now responsible for the execution of the component script. It uses require() so the component script only gets executed once and the same table's values are copied to the C++ component object each time. Since it uses require() it expects a Lua module name, not a script name, so the usage will look like this: entity:AddComponent("Mover") I plan to organize components into subfolders one layer deep, so the final usage will be more like this: entity:AddComponent("Motion.Mover") I have no idea how or if this will interact with C#. What will the user syntax to add a C# component look like? Will it use a string like this, or something else? Do we plan on Lua ever working with a C# game? I'm leaning towards no, because C# users aren't going to be coming from that mindset or have that expectation.
  16. 1.0.2 "require" will now load scripts relative to "./Scripts" and DLLs relative to "./Modules". Script structure in the game template is changed. C++ interpreter for Lua code is updated here: https://github.com/UltraEngine/Documentation/blob/master/CPP/Scripting.md#c-interpreter-for-lua socket/core.dll now just renamed to "luasocket.dll" Compiled .luac files can now be run with RunScript().
  17. 1.0.2 I found a lot of settings to move all the garbage files VS creates into the hidden .vs folder. This is what a project looks like now, after compiling and closing visual studio. The only file it save in your game folder is the vxproj.user file, which I could not find a way to eliminate:
  18. The secret is that the icon file must contain multiple "mipmaps". It's not enough for it to be a large icon. This program is the only way I know to create these: http://www.aha-soft.com/anytoicon/
  19. Why is Windows Explorer showing my EXE as if it has a small icon? The icon size is 256x256 and the icon file itself appears correctly: Here is the icon section of the .rc resource file: ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON "projecticon.ico"
  20. 1.0.2 UPX post-build process is added back into new Visual Studio projects, but this time it's done correctly. Command: "$(UltraEnginePath)\Tools\upx.exe" "$(TargetName)$(TargetExt)" Disabled by default, can be easily enabled in project settings (release mode only) Newton debug DLLs are eliminated. I'm using a static library, so Newton can still be debugged externally. DLLs are now only used for optional plugins and Lua modules. Resource files moved to /Source to try to keep as much garbage as possible out of the main folder. Removed Warn() function. Removed Microsecs() function.
  21. 1.0.2 Since the Lua stuff is stable now, I was able to compile Lua as a static lib, which means no DLL is needed. Lua 5.4 repo here is updated: https://github.com/UltraEngine/Lua5.4 Scripts/Modules/Socket/core.dll is recompiled with Lua static lib.
  22. How about this? #include "UltraEngine.h" using namespace UltraEngine; bool PrintColorHook(const Event& e, shared_ptr<Object> extra) { //https://learn.microsoft.com/en-us/windows/console/getstdhandle#handle-disposal HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); if (e.text.Left(8) == "Warning:") { SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); } else if (e.text.Left(6) == "Error:") { SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY); } else { SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } return true; } int main(int argc, const char* argv[]) { ListenEvent(EVENT_PRINT, NULL, PrintColorHook); Print("Here is a normal text message."); Print("Warning: Here is a warning."); Print("Here is a normal text message."); Print("Error: Here is an error."); Print("Here is a normal text message."); return 0; }
  23. 1.0.2 New Visual Studio projects are now set up to compile with the new good icon. I guess it needs both an .ico and a .png? I don't know why. Future builds of the client app will load the file projecticon.png to display in the projects list. Added "/delayload:lua54.dll" in release mode settings so you can distribute C++ programs without including the Lua DLL if you don't use it.
  24. 1.0.2 Added String and WString constructors that play nice with nlohmann::json and eliminate the need for the horrible SetJsonString/GetJsonString functions I was using. This allows you to easily get strings from JSON structures without producing errors: j3["name"] = "Frank"; j3["number"] = 462; String s1 = j3["name"]; String s2 = j3["number"]; Removed DebugLog function Remove Language class since it's not tested and superfluous
  25. 1.0.2 New entity component system is integrated in C++ and Lua Preprocessor removed Added String and WString::Data() which is the same as .c_str() Documentation mostly updated, mostly: https://www.ultraengine.com/learn/Scripting?lang=cpp https://www.ultraengine.com/learn/Entity_AddComponent?lang=cpp https://www.ultraengine.com/learn/Component?lang=cpp
×
×
  • Create New...