Omnimaga
Calculator Community => TI Calculators => Lua => Topic started by: Frog on September 02, 2011, 11:25:19 am
-
Hi everyone! I've been following this forum for quite some time now, but never actually posted something. I guess this is the first time: I've got a question... :)
I'm trying to add methods and properties to the default gc class. I know that in "normal" lua you can just do something like this: function table.method(). So I tried the following:
function gc:method(x, y, width, height)
self:drawRect(x, y, width, height)
end
This didn't work though. I also tried to create a new class called screen that inherits from gc, but that didn't work either. Finally I tried "screen = gc:begin()", but that was no solution as well.
So my question is: how can I add my own method to the default gc class? Thanks! :)
-
I've seen 3 solutions :
* You can put gc as an argument :
function on.paint(gc)
method(gc)
end
function method(gc)
[...]
end
* You can also use platform.gc() instead of gc. For example : platform.gc():drawString(...
But I've had some problem with this method.. Some functions as setFont if I remember don't work well..
* Or you can copy gc in a global variable at the beginning of the on.paint function.
function on.paint(gc)
gc2=gc
end
function method()
gc2:drawString(...
end
Adriweb do this in the last version of better Lua (https://github.com/adriweb/BetterLuaAPI-for-TI-Nspire/blob/master/BetterLuaAPI.lua).
:)
-
Thanks for your answer! That's not exactly what I mean though. I'm trying to add a new method to the gc, so that I can (for example) call gc:drawButton(). In other languages I would extend/subclass the gc class, but I'm not sure how to do that in TI-Lua. At first I thought I should do newGC = class(gc), but that didn't work, just like defining the function: function gc:drawButton(). How can I do this?
-
I think you could achieve the same effect by doing as Loulou showed, where you basically create a whole separate function that uses the gc variable. Such as:
function on.paint(gc)
method(gc) --is called in on.paint and is passed the gc var
end
function method(gc)
gc:drawRect(...) --note the gc:
end
you could perhaps try calling the function
gc:method(gc) --pass the gc variable
--Do stuff here
Though I don't know if that would work. :/
-
I know a separate function is possible, but I think it's way cleaner to make it part of the actual gc, so that the drawButton() method sits prettily next to the drawRect() method. It sounds way more logical to me. ;)
The latter is exactly what I'm trying to achieve, but that's unfortunately not possible using your code...
-
gc = getmetatable(platform.gc())
function gc:test()
self:setColorRGB(0,0,0)
self:fillRect(10,10,10,10)
end
function on.paint(gc)
gc:test()
end
That should do the trick :)
-
Good ideas in this topic !
However, I should point out that using platform.gc() is discouraged, and is generally a bad idea.
(multiple reasons like the fact that it's not working the exact same way as the 'normal' gc, and for future compatibility matters... ;) )
-
Thanks a lot, that's works like a charm! I need to improve my understanding of metatables though...
-
Would this work?
function on.paint(gc)
gc2 = getmetatable(gc)
function gc2:method(x, y, height, width)
self:setColorRGB(0,0,0)
self:fillRect(x, y, height, width)
end
--more methods to define here
function on.paint(gc) --Your normal on.paint(gc) goes in here
gc:method(10,10,10,10)
end
end
It would use the normal gc to define all the methods the first time on.paint is called then when it is done it would redefine itself.
-
Good ideas in this topic !
However, I should point out that using platform.gc() is discouraged, and is generally a bad idea.
(multiple reasons like the fact that it's not working the exact same way as the 'normal' gc, and for future compatibility matters... ;) )
Somehow I overlooked your post... Anyways, isn't it true that the usage of platform.gc() in jimbauwens' example is no bad practice, since getmetatables is just a reference to the original metatable shared by all gc objects? I mean, you do use the passed gc in the on.paint() function, so that shouldn't give unexpected results?
Don't you agree that this way looks like a better method for a GUI library?
-
Good ideas in this topic !
However, I should point out that using platform.gc() is discouraged, and is generally a bad idea.
(multiple reasons like the fact that it's not working the exact same way as the 'normal' gc, and for future compatibility matters... ;) )
Somehow I overlooked your post... Anyways, isn't it true that the usage of platform.gc() in jimbauwens' example is no bad practice, since getmetatables is just a reference to the original metatable shared by all gc objects? I mean, you do use the passed gc in the on.paint() function, so that shouldn't give unexpected results?
Don't you agree that this way looks like a better method for a GUI library?
platform.gc() is a constructor of a new independant gc object.
What does the TINspire framework do :
local gc=platform.gc()
gc:begin()
on.paint(gc)
gc:finish()
What does that mean ? On each screen refresh, it recreate an independant gc object that has a different reference.
And since it is a different object, using methods such as setFont/setColor won't change gc, but your new object you define each time you use platform.gc.
If you want to store this gc in on.paint(), it won't be drawn as it, since it has a different reference/address
In Jim method, you define, yes, one time a new object, but you pick up its meta table. It is not the same. Each gc object has the same metatable, but not the same properties.
Would this work?
It would use the normal gc to define all the methods the first time on.paint is called then when it is done it would redefine itself.
Ouch :p
Just use a boolean, like if not gc2 then ..... end in your on.paint()
but anyway, look at the fisrt part of my post, you can't do so :p
-
Good ideas in this topic !
However, I should point out that using platform.gc() is discouraged, and is generally a bad idea.
(multiple reasons like the fact that it's not working the exact same way as the 'normal' gc, and for future compatibility matters... ;) )
Somehow I overlooked your post... Anyways, isn't it true that the usage of platform.gc() in jimbauwens' example is no bad practice, since getmetatables is just a reference to the original metatable shared by all gc objects? I mean, you do use the passed gc in the on.paint() function, so that shouldn't give unexpected results?
Don't you agree that this way looks like a better method for a GUI library?
platform.gc() is a constructor of a new independant gc object.
What does the TINspire framework is :
local gc=platform.gc()
gc:begin()
on.paint(gc)
gc:finish()
What does that mean ? On each screen refresh, it recreate an independant gc object that has a different reference.
And since it is a different object, using methods such as setFont/setColor won't change gc, but your new object you define each time you use platform.gc.
If you want to store this gc in on.paint(), it won't be drawn as it, since it has a different reference/address
In Jim method, you define, yes, one time a new object, but you pick up its meta table. It is not the same. Each gc object has the same metatable, but not the same properties.
Yes, I understand. The metatable is basically the blueprint and obviously every instance has different properties. I'm using to Jim's method to create a simple graphics library now. Should I release the code when I'm finished?
-
I'm glad I could be of help :)
You don't need to release your source, but it would be nice :D
-
If I think it's worth it, I'll release it. ;)
Now that I'm busy I've actually got one more question... ::) Can you get the currently set color property from the gc? I've tried showing the table on the screen to show all properties, but that didn't work. Maybe someone knows what property the set RGB color is stored in, so I can calculate the opposite color for my fillButton function?
-
I don't think that that is possible.
What I would do is create a new gc:setColorRGB (with another name) and store the current color information to a table.
However, the color can be changed when you draw an image, so you need to watch out with that.
-
Shouldn't that be possible? Isn't it just stored in a property of the object? Your workaround is also a good solution, but not as clean as I'd like. :p
What do you mean, the color can be changed when drawing an image?
-
Well, the gc object stores stuff in places we can't reach (its C based I guess).
After drawing an image, the current color is the color of the last pixel in the image. This mean that it uses setColorRGB somehow (or setColorRGB uses the same color memory location or whatever)
-
Shouldn't that be possible? Isn't it just stored in a property of the object? Your workaround is also a good solution, but not as clean as I'd like. :p
What do you mean, the color can be changed when drawing an image?
There is a glitch in OS 3.01 and 3.0.2 (understand what you want with this sentence ;) ).
When you draw an image, the last pixel affect the global color and global alpha
-
Mmm, okay. Than I'll have to create my own setColor function, and actually also a custom image function to solve that bug... Well, let's get back to work. :D
-
About your graphics library, maybe we can merge our project together ?
I mean put your library in the BetterLuaAPI project, which is open to everybody who wants to improve it.
Of course your name would appear on the top :)
-
Mmm, I'm not really sure about that. On one side I think it's a great idea: it's always better to have more people working on something and your BetterLuaAPI has a couple of great functions. On the other hand your library takes a different approach than the one I'm working on: I'm trying to keep all drawing code in the graphic context object, all logic (like clicks) in a to-be-created screen object and I've got a couple of other different ideas... Furthermore I'm a bit like a minimalist programmer, for example (to be blunt): I don't see the point in your color table or a square function...
Not to mention that I've got just 50 lines of code... What do you think?
-
Heya Frog by the way and welcome to the forums. Glad to see another TI-Nspire programmer around.
-
Thanks, this sure is a warm welcome. :)
-
Mmm, I'm not really sure about that. On one side I think it's a great idea: it's always better to have more people working on something and your BetterLuaAPI has a couple of great functions. On the other hand your library takes a different approach than the one I'm working on: I'm trying to keep all drawing code in the graphic context object, all logic (like clicks) in a to-be-created screen object and I've got a couple of other different ideas... Furthermore I'm a bit like a minimalist programmer, for example (to be blunt): I don't see the point in your color table or a square function...
Not to mention that I've got just 50 lines of code... What do you think?
Well I could (and I probably will, one day) rewrite how my "library" works.
Maybe I'll do something like you.
However, about that colortable, you know, I just put some things there and people can take whatever functions they want, that's all. If they don't need some stuff they just don't take it :P
-
Yeah, you're right. People don't have to take everything, they can just take the functions they need. I'll just continue writing my library from the ground up for now, and I'll post it when it's largely finished.
-
Great, good luck :)
And btw, about that ti.timage color leak, TI knows about it, it's been reported.
-
I feel kind of stupid to ask this, but how do you add a property to platform.window? I'm currently using a custom window class, but that class has just one property called screen. Obviously it's a bit strange to have a custom window class with just one property while there's already a window class available. I tried the same thing as described above among other things, but nothing works. How can I do this? ;)
-
Hmm, it works for me the same way.
Here is an examle:
window = getmetatable(platform.window)
function window:pixels()
return self:height()*self:width()
end
function on.paint(gc)
gc:drawString(tostring(platform.window:pixels()),10,10,"top")
end
-
Yes, that's true. But I somehow can't add new properties. For example I'm trying to do this:
-- Doesn't work: attempt to index local 'self' (a user data value)
platform.window.screen = main
-- Doesn't work, I can call the function but the function throws the same error.
function window:setScreen(screen)
self.screen = screen
end
platform.window:setScreen(main)
But both methods don't work. The only thing that does work is modifying to metatable directly, so by doing window.screen = main, but I don't really like doing that (except for the default value).
Am I doing something wrong?
-
Well, I think platform.window.screen is equivalent to platform.window["screen"], and platform.window isn't a table as far as I know.
-
But why can I then get platform.window.screen when I set it using window.screen? And platform.window does have methods, doesn't that mean it is actually a table? Also, I can get the metatable, doesn't that mean the same?
-
The metatable is not the same like the object itself, but you can use it in this case.
I tried this, and it works:
window = getmetatable(platform.window)
window.screen = 123
platform.window.screen will then have the value 123.
-
Sorry, maybe I wasn't clear enough. I understand that works, but why does it work? Why can't I just set the screen using platform.window.screen? That's more logical...
-
platform.window itself is not a table, but userdata. userdata is controlled from C, and we can't touch it. Thats why we use the metatable of it :)
-
Owh okay, thanks a lot again! This helped me a lot. May I ask how you know this? I couldn't find anything on it... Or did you take a detailed look at the OS installation files?
-
I didn't look at the os files ;)
I just scan, search and poke through the Lua environment because I love to do that so much :)
-
But how does that work? ??? Do you output the _G variable?
-
_G is a table and contains everything.
We just loop through the table recursively and check the types of stuff.
Here is an example of a dump: http://paste.bwns.be/p/m22cc805b.
-
Wow, so that's how you found out about every function. One last question: how did you create this dump? I have been trying to output a really big table I created for debugging purposes, but I can't find a good method since I can only use gc:drawString. Is there a different method? The print() output isn't showed anywhere...
-
With 3.01 and 3.02, print outputted to the computer console with the computer software, and to the serial port with the calculator.
However the day before yesterday TI released a new OS, and they made that print() isn't functional anymore. This is probably because they didn't like thing that we did with it (controlling external hardware, outputting sound)
Anyway, what we did was make a fake print function that puts everything in a string, and then we put it in the clipboard using clipboard.addText. Then we pasted it, and we got the dump :)
-
Wow, that's smart! :o I've still got 3.01 on my nSpire CX and 3.02 on my desktop software. Is there an easy way to get the print output (either on the desktop or calculator)? Could you maybe add the custom print() function to the inspired-lua wiki?
-
Try running the software from cmd, and look at the output when running a lua script with print(). You should see it in the console :)
And yes, I could put the print functions we created on inspired-lua :D
-
Yeah, it would be great if you put it on inspired-lue!
I can't use the cmd, because I'm using a mac. I didn't find a way to run the TI-Nspire software from the terminal, or are you talking about the third-party emulator for windows?
-
You can run the mac version from the terminal, but I don't know right away how to do that.
Lemme poke someone who knows it :)
-
Yeah, it would be great if you put it on inspired-lue!
I can't use the cmd, because I'm using a mac. I didn't find a way to run the TI-Nspire software from the terminal, or are you talking about the third-party emulator for windows?
You have to browse to where you installed the software.
Then right-click the app -> Show Package Contents -> open the "Contents" folder -> go to the "MacOS" folder, and drag and drop the JavaApplicationSTub file to a terminal window
Then press Enter on that terminal window
all the debugging output will be printed into the console instead of logs and/or /dev/null or seomthing.
Screenshot :
(http://i.imgur.com/s9CJz.jpg)
-
Wow, this works great! Thanks a lot, adriweb!
-
necroposting for the good cause
http://inspired-lua.org/index.php/2013/05/how-to-add-your-own-functions-to-gc/ :)
This code, by Jim Bauwens, is simply very neat and clean :)
-
Just read throught this, very usefule :) Though shouldn't
function on.paint(gc)
drawRoundRect(gc, 100, 50, 20, 15, 5)
...
end
in the second code block be gc:drawRoundRect(100, 50, 20, 15, 5)
then? Because it doesn't seem any different to me ??? (I may as well be wrong, I'm not that good yet :P )
-
Arg, well, yeah, obviously :D
Thanks ^^