New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Major rework into V2 #37
Conversation
When trying to build in Defold I get
In generated main.lua I have:
Looks related to https://forum.defold.com/t/including-a-lua-module-solved/2747/2
but for some reason Defold (Lua) tries to process it anyway, even if the condition is not met. Only deleting the line with |
TLDR; I pushed a fix on the v2 branch So this is a known issue for a while, the workaround is to create an empty This is because the Defold builder takes these I did however also realize that this can and should be addressed by the library - even in a workaround form, - and not be left up to the user. So I pushed a fix with the latest commit, which makes the build macro generate empty files And one more thing:
You should never have to touch generated files 😉 You should be compiling Haxe freely every time you build the game! It can even be done automatically. |
Working now, thanks
Yes, I know, temporary solution just to verify where exactly issue and run project. |
Definitely! I think currently it's Will see about adding some simple CI tests with a version matrix, and a badge showing the minimum needed version. |
Maybe add something like below to Script class (not sure about naming) for quick access?
|
What would be the benefit of that? The user would then write for example Unless you meant something else... |
I like autocomplete, to avoid typos and not to remember exact values ) |
Hi @haath
|
Hey @Eugnee, thanks a lot!
I wish... Making games is just a hobby for me so I probably won't be commercially shipping anything soon 😞 But I haven't even touched any other game engine since discovering hxdefold 5 years ago, if that counts for anything.
I hardly know any Lua either actually. 😅 If your concern is performance, then the best thing to do is run benchmarks. I actually have already rewritten the Bunnymark example in Haxe. You can try out the HTML5 build on the browser:
In my opinion the transpilation is not an issue. The main thing that I perceive as a potential risk for large-scale projects is the way that hxdefold works: your whole codebase ends up in a single Lua file called |
Sounds great! |
I wouldn't be too concerned with that honestly. A lot of these just boil down to you writing Haxe code that would produce the performant Lua you are looking for, and not so much to the Haxe compiler having to produce that good Lua for you. For every 1 line in Haxe you get 1 line in Lua more or less, so it's still you writing the program, not the compiler. Now if the compiler did in fact make some performance blunders that somebody could identify, and even if the Haxe team decided not to fix them, you can still get out of it by injecting raw Lua code into your Haxe. |
Okay, I got u. |
Hi what is status of this MR ? something still need to be done or it waits for something ? |
Hey! No, I think I'm finished with everything I wanted to add here. But I guess half a year is enough, so I'll merge it now. |
Summary
I am currently preparing a V2 release of this library with wall-to-wall breaking changes.
The main goal is to Haxify the library, to make working with classes more natural and hide certain Lua eccentricities where possible. The main changes are the following:
camelCase
on the Haxe side.THIS_CASE
toPascalCase
.Table
).@nadako I will work on this PR over time to give you or anybody else a chance to give feedback before everything goes into master 😄. I will also treat this PR as a documentation of the changes, so that I can link to it from the README when warning about the breaking changes.
Before
After
Detailed changes
Rework of Script and properties definition.
I decided to do this for the following reasons:
self
variable everywhere felt very unnatural in Haxe. If scripts are classes, then they should have their own class variables.self
, it was unclear to the user what happened with actual class variables under the old implementation. In reality only a single instance of the class got created, which effectively made everything static, but in an ambiguous way.How does the new way work?
As seen above in the summary, properties are now simply variables of the class. This is made possible with an
@:autoBuild
macro that gets called for all classes extending one of theScript
types. This new build macro takes all of the non-static variables, and replaces them withget/set
properties that effectively change all interactions to accesses of the script'sself
type on the lua side. In the example above, the generated code for theeditorProperty
variable looks like this:In my tests, the Haxe compiler will always properly inline the getter and the setter, so doing it this way introduces no overhead. Now you might be wondering: why the
_G.self
? The reason is that we want the script'sself
reference to be in scope in any function that may get called inside the script. The simplest way to do that was to adapt the script generation macro to now produce all callbacks as shown below:And voila, now the script callbacks do not require a
self
argument anymore, and all script properties can be accessed as if they were class members!Note that in this example,
nonEditorProperty
will also have the same getter and setter generated, but because it lacks the@property
tag it will not have ago.property
statement generated. This is consistent with what we were doing before, where basically you can store whatever you want on theself
object when it's not showing up in the editor or as a named property.New versioning scheme
So far we've been versioning the library by just mirroring the corresponding Defold API version.
However this has been quite limiting. Multiple times I've discovered a bug in hxdefold, but I had to wait for a new Defold version to be released before I could push a fixed version on Haxelib. So starting with
v2.0.0
, we will follow a standardMajor.Minor.Patch
scheme.Additionally, I plan to add some startup code that will check the Defold engine version and print a warning to the user if it is not supported by his hxdefold version.
Renaming to camelCase
Having the same codebase with both
camelCase
haxe function calls andsnake_case
lua API calls looked a bit uncomfortable. So using the@:native
tag, now all of the API functions will be camelCase on the Haxe side and generate the correct snake_case calls in Lua.I will also be renaming the extern enum fields that represent Defold constants. On the Lua side they are in
THIS_CASE
, and I'll rename them intoPascalCase
to match the Haxe standard for enum constants.However, I will not rename table fields and hash values like message names. This is because it would create an inconsistency from the users perspective, since in that case the message
GoMessages.setParent
would be equal tohash("set_parent")
but nothash("setParent")
.Automatically generated property hashes
Another new feature is that now for each script, a class with the list of property hashes will be generated automatically.
Again looking at the
MyScript
example above, theMyScriptProperties
class will get defined at the top-level package and will look like this:This provides pre-hashed and typed property ids which can be used to interact with the properties from another script.
I have also verified that Haxe's dead code elimination will not include unused hashes in the final build!
Type-safe factory object creation
By default when only exposing the defold
factory
API, thefactory.create()
function takes a genericTable<String, GoProperty>
as the properties argument. The first problem with that, is that this is of course not type-safe and leaves it up to the developer to manually pass the correct property names when creating an object. The second problem was that the most convenient way to use this method, was to employTable.fromDynamic({ ... })
with some typedef, and this approach uses reflection which is not very performant.My current (WIP) solution is to have the script builder macro generate a public static method on each script type, which allows the user to create a properties table in a type-safe way and as efficiently as possible. The method generated for the
MyScript
example would be the following:Then this object can be created like this:
Other minor changes
Script
,GuiScript
, andRenderScript
classes are nowabstract
, and their constructors are empty andfinal
. Instantiating script classes is not allowed, and now it will be properly blocked by the compiler.abstract MyGo(Hash)
)Resource
class and into their ownLiveUpdate
extern class. This should have been done some time ago, but I probably missed it.@readonly
orfinal
, the property will not have a setter generated. (note thatGo.set
andGo.animate
would still be possible, so this is just for convenience)luv.lua
,bit32.lua
andsocket.lua
files at the project root. This is an automated workaround to a known issue with the Defold builder, and may be what we stick with long-term.