Thread Tools Display Modes
09-25-16, 09:55 PM   #21
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Kagura View Post
To visualize how the UI element is setup you are going through 32 lines of code just to realise it won't work (You can figure out why).
Reading through code is never a good way to "visualize how the UI element is setup", in any programming language. Even an XML-style markup language like HTML or JSX quickly becomes too long for that in for a UI of any complexity.

(Also, the code I posted was a drycoded example. It wasn't meant to be used as-is, and it certainly wasn't tested. Any typographical errors in it are totally irrelevant to the actual discussion.)

Originally Posted by Kagura View Post
Let's now say I want to split my window into two panels and all I had in the first one goes into second one and on the left one I want buttons. In Phanx's example, I'd have to go through the created ui elements that are a 'child' of my original one and change either the creation of all these elements or the parenting (SetParent) for each of the created UI element. In my original example, I would change nothing except the indenting after (I am referring to the JSX here, not LUA)
You're making this sound like way more work than it actually is:

Code:
local frame1 = New("Frame")
frame1:SetParent(window)
frame1:SetPoint("TOPLEFT")
frame1:SetPoint("BOTTOMLEFT", "$parent", "BOTTOM")

local button1 = New("SmallButton")
button1:SetParent(frame1)
Nothing needs to be moved around, re-indented, or wrapped in a new scope, and it's still straighforward, readable, and efficient code that isn't generating a bunch of extra tables or functions.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
09-25-16, 11:02 PM   #22
EyalSK
A Deviate Faerie Dragon
 
EyalSK's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 13
BTW in my previous reply I forgot to add something.

I chose time over space since I care about performance and the extra table entry per method to accomodate easy super calls is not that big of a price to pay.
Can't see this from the generated code, do you imply that just because you use a table and a table is a dictionary like then you assume that this is the case? did you benchmark it? otherwise, can you elaborate more on this?

Last edited by EyalSK : 09-25-16 at 11:24 PM.
  Reply With Quote
09-26-16, 12:47 AM   #23
Kagura
A Fallenroot Satyr
Join Date: Nov 2008
Posts: 21
Originally Posted by SDPhantom View Post
Something I just spotted, your backslashes aren't escaped.
Code:
prettyPrint("Components\Test.js:17", "You pressed ok")
Should be:
Code:
prettyPrint("Components\\Test.js:17", "You pressed ok")
Thanks you very much, an oversight on my part.
  Reply With Quote
09-26-16, 12:58 AM   #24
Kagura
A Fallenroot Satyr
Join Date: Nov 2008
Posts: 21
Originally Posted by Lynxium View Post
BTW in my previous reply I forgot to add something.

Can't see this from the generated code, do you imply that just because you use a table and a table is a dictionary like then you assume that this is the case? did you benchmark it? otherwise, can you elaborate more on this?
In my given example, I use the classic metatable class implementation with a slight twist to support super calls. These are only used in Components that are usually set up once. If I didn't use a table in this case, supporting super calls would have been a nightmare. If you do have an implementation that would actually be able to do this, I would really love to add this to my compiler (I say compiler because I do not only transpile code, but use small optimizations on things like unpacking tables depending on their size)

And yes, I did benchmarks on different class implementations, the next two are the ones I support (stripped down)
Lua Code:
  1. function createObj2(self)
  2.   self = self or {}
  3.   local a = 0
  4.  
  5.   self.increment = function()
  6.     a = a + 1
  7.   end
  8.  
  9.   return self
  10. end
  11.  
  12. local class = {
  13.   new = function (self)
  14.     local instance = {}
  15.     setmetatable(instance, {__index = self})
  16.     self.a = 0
  17.     return instance
  18.   end,
  19.   increment = function (self)
  20.     self.a = self.a + 1
  21.   end,
  22. }
  23.  
  24. -- Things do get a little more complicated with constructors.

Next links more or less share my findings:
https://www.lua.org/gems/sample.pdf
https://springrts.com/wiki/Lua_Performance
http://lua-users.org/wiki/ObjectOrie...losureApproach

Last edited by Kagura : 09-26-16 at 01:15 AM.
  Reply With Quote
09-26-16, 01:04 AM   #25
Kagura
A Fallenroot Satyr
Join Date: Nov 2008
Posts: 21
Originally Posted by Phanx View Post
You're making this sound like way more work than it actually is:
Maybe I am, maybe it's a personal preference. To provide modularity here while using the original Frame methods (SetParent in this particular case), one would have to either pollute the Frame metamethods or add information about the created ui element's children to the parent frame (to be able to access them from somewhere else in case it's needed. local bags = New('Bags'); Bags.update()/Bags:update() for example). I personally chose composition (those tables people have so many problems with :O) so I wouldn't have to touch the host objects/classes/tables (prototypejs did this with their implementation for example and the rest is history).

Originally Posted by Phanx View Post
Nothing needs to be moved around, re-indented, or wrapped in a new scope, and it's still straighforward, readable, and efficient code that isn't generating a bunch of extra tables or functions.
Again, sorry if I insulted anyone, but I think this thread is derailing a little I could have my compiler (transpiler for nonbelivers!) generate exactly the code that you write here, I chose not to because I personally don't think it's modular, reusable or easily maintained.

Again, I really couldn't care if the finally generated lua code isn't readable and I do actually mimify the final code for production. I do care if it's slow/uses considerably more memory than other addons that provide the same functionality (which it doesn't so far).

p.s. I really think you have to change all the SetParent calls (or creation of textures/fontstrings) if you decide to put these buttons and text and textures in a new frame, no? Is there something I am missing here?

Last edited by Kagura : 09-26-16 at 02:04 AM.
  Reply With Quote
09-26-16, 01:07 AM   #26
Kagura
A Fallenroot Satyr
Join Date: Nov 2008
Posts: 21
Originally Posted by Lynxium View Post

Code:
{ 
	SmallButton, 
	{ 
		anchors = "BOTTOMLEFT", 
		onClick = function()
			self:ok()
		end
	}, 
	{ 
		Text, 
		anchors = "*", 
		"OK" 
	} 
},
But then again, this is just a hunch because this change might complicate the rendering logic and buy nothing so to really provide insights to how you can improve performance one needs to know the full story beyond the generated code.
It actually won't. Thanks for this, I improved this part. It was fairly trivial to achieve next
lua Code:
  1. -- js -> lua
  2. frame.SetPoint('*') -> frame:SetAllPoints()
  3. frame.SetPoint('TOPLEFT') -> frame:SetPoint('TOPLEFT')
  4. frame.SetPoint(['TOPLEFT', 'parent', 'TOPLEFT']) -> frame:SetPoint('TOPLEFT')
  5. frame.SetPoint(['TOPLEFT', 'parent', 'TOPRIGHT']) -> frame:SetPoint('TOPLEFT', frame:GetParent(), 'TOPRIGHT')
  6. frame.SetPoint(['TOPLEFT', 20, 20]) -> frame:SetPoint('TOPLEFT', 20, 20)
  7. frame.SetPoint(someVariable) -> frame:SetPoint(unpack(someVariable))

Originally Posted by Lynxium View Post
p.s. Just a minor note Lua isn't an acronym but a word so you actually need to write Lua instead of LUA.
Again: thanks for this

Last edited by Kagura : 09-26-16 at 01:27 AM.
  Reply With Quote
09-26-16, 01:29 AM   #27
EyalSK
A Deviate Faerie Dragon
 
EyalSK's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 13
Is it open source? did you publish this on GitHub or somewhere else? and I wonder whether you're planning to? yes I'm a compiler geek haha...

p.s. Are you using CoffeeScript?

Last edited by EyalSK : 09-26-16 at 01:32 AM.
  Reply With Quote
09-26-16, 01:39 AM   #28
Kagura
A Fallenroot Satyr
Join Date: Nov 2008
Posts: 21
Originally Posted by SDPhantom View Post
If you're interested in trimming down your CPU usage, the most expensive Lua operations are function calls followed by table indexing. Indexing operations are what surprise a lot of people because of how much they can stack up. Accessing a global is an indexing operation on Lua's environment table. Metatables add at least two indexing operations each whenever they need to be accessed if __index is another table. If it's a function, then it's an indexing operation plus the function call.

You should also keep an eye on memory usage. Garbage collection cycles are notorious for causing large amounts of framerate drops. Because of this, avoid creating dynamic tables and functions and releasing them very often.
I linked to some resources in another reply, but yes: I am very well aware of this. The difference though is: trying to optimize code that gets run once vs trying to optimize code that gets run every frame. 100 extra function calls per lifetime of the application isn't something to worry about imho.

I do things like in : https://gist.github.com/Nimaear/e267...311b6f70eadd17 where I dynamically load addons depending on an event to speed up boot times. I personally think the added extra memory (around 23k) from this is nothing compared to the benefit you get: almost instant load screens.

I don't create any dynamic tables in code that gets rerun more than once unless I have to. I do admit that this is a really hard area to try to automate for a compiler.

Last edited by Kagura : 09-26-16 at 01:50 AM.
  Reply With Quote
09-26-16, 01:52 AM   #29
Kagura
A Fallenroot Satyr
Join Date: Nov 2008
Posts: 21
Originally Posted by Lynxium View Post
Is it open source? did you publish this on GitHub or somewhere else? and I wonder whether you're planning to? yes I'm a compiler geek haha...

p.s. Are you using CoffeeScript?
It's in a private repository, but I will opensource it once I properly split the parts.

And no I don't use CoffeeScript
  Reply With Quote
09-26-16, 02:12 AM   #30
EyalSK
A Deviate Faerie Dragon
 
EyalSK's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 13
Originally Posted by Kagura View Post
It's in a private repository, but I will opensource it once I properly split the parts
Nice.

And no I don't use CoffeeScript
ah.. I thought so because I saw you posted this 'frame.SetPoint('*') -> frame:SetAllPoints()' and the lambda expression just got me that I overlooked everything else.
  Reply With Quote
09-26-16, 02:19 AM   #31
Kagura
A Fallenroot Satyr
Join Date: Nov 2008
Posts: 21
How would you go around creating a UI component library/anything in LUA that allows you to do exactly this (with exactly I don't mean JSX markup, but the parenting/anchoring nightmare)?
I finally know how to formulate my question I think and this will maybe also answer it itself, but let's see. How would one go around creating frame templates programmatically?

(I now realize I can have my compiler generate XML frame templates................ )
  Reply With Quote
09-26-16, 03:13 AM   #32
EyalSK
A Deviate Faerie Dragon
 
EyalSK's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 13
Originally Posted by Kagura View Post
I finally know how to formulate my question I think and this will maybe also answer it itself, but let's see. How would one go around creating frame templates programmatically?

(I now realize I can have my compiler generate XML frame templates................ )
Exactly, that's how Babel and TypeScript and iirc Flow do it too so this is no different.

Last edited by EyalSK : 09-26-16 at 04:13 AM.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » Journey to developing a complete UI in JS

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off