Omnimaga

Calculator Community => TI Calculators => Lua => Topic started by: Frog on September 02, 2011, 11:25:19 am

Title: Add function to the gc class
Post 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:

Code: [Select]
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! :)
Title: Re: Add function to the gc class
Post by: Loulou 54 on September 02, 2011, 11:42:03 am
I've seen 3 solutions :
* You can put gc as an argument :

Code: [Select]
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.

Code: [Select]
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).

:)
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 11:46:35 am
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?
Title: Re: Add function to the gc class
Post by: Scipi on September 02, 2011, 11:54:26 am
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:

Code: [Select]
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
Code: [Select]
gc:method(gc) --pass the gc variable
    --Do stuff here

Though I don't know if that would work. :/
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 12:00:09 pm
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...
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 02, 2011, 12:21:00 pm
Code: (Lua) [Select]
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 :)
Title: Re: Add function to the gc class
Post by: Adriweb on September 02, 2011, 12:26:06 pm
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... ;)  )
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 12:30:06 pm
Thanks a lot, that's works like a charm! I need to improve my understanding of metatables though...
Title: Re: Add function to the gc class
Post by: 3rik on September 02, 2011, 12:55:29 pm
Would this work?

Code: [Select]
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.
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 12:56:55 pm
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?
Title: Re: Add function to the gc class
Post by: Levak on September 02, 2011, 01:12:10 pm
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 :

Code: [Select]
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
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 01:15:28 pm
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 :

Code: [Select]
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?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 02, 2011, 01:32:12 pm
I'm glad I could be of help :)
You don't need to release your source, but it would be nice :D
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 01:41:58 pm
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?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 02, 2011, 01:44:22 pm
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.
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 01:55:46 pm
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?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 02, 2011, 02:00:35 pm
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)
Title: Re: Add function to the gc class
Post by: Levak on September 02, 2011, 02:01:31 pm
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
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 02:05:39 pm
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
Title: Re: Add function to the gc class
Post by: Adriweb on September 02, 2011, 02:42:47 pm
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 :)
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 02:57:54 pm
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?
Title: Re: Add function to the gc class
Post by: DJ Omnimaga on September 02, 2011, 04:03:43 pm
Heya Frog by the way and welcome to the forums. Glad to see another TI-Nspire programmer around.
Title: Re: Add function to the gc class
Post by: Frog on September 02, 2011, 04:40:08 pm
Thanks, this sure is a warm welcome. :)
Title: Re: Add function to the gc class
Post by: Adriweb on September 02, 2011, 04:43:11 pm
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
Title: Re: Add function to the gc class
Post by: Frog on September 03, 2011, 04:16:59 am
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.
Title: Re: Add function to the gc class
Post by: Adriweb on September 03, 2011, 06:14:11 pm
Great, good luck :)

And btw, about that ti.timage color leak, TI knows about it, it's been reported.
Title: Re: Add function to the gc class
Post by: Frog on September 08, 2011, 01:27:59 pm
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? ;)
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 08, 2011, 03:38:32 pm
Hmm, it works for me the same way.
Here is an examle:
Code: (Lua) [Select]
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
Title: Re: Add function to the gc class
Post by: Frog on September 08, 2011, 04:31:35 pm
Yes, that's true. But I somehow can't add new properties. For example I'm trying to do this:

Code: [Select]
-- 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?
Title: Re: Add function to the gc class
Post by: calc84maniac on September 08, 2011, 05:16:38 pm
Well, I think platform.window.screen is equivalent to platform.window["screen"], and platform.window isn't a table as far as I know.
Title: Re: Add function to the gc class
Post by: Frog on September 09, 2011, 05:37:15 am
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?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 09, 2011, 01:21:29 pm
The metatable is not the same like the object itself, but you can use it in this case.
I tried this, and it works:
Code: (Lua) [Select]
window = getmetatable(platform.window)
window.screen = 123
platform.window.screen will then have the value 123.
Title: Re: Add function to the gc class
Post by: Frog on September 09, 2011, 01:24:21 pm
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...
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 09, 2011, 01:26:28 pm
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 :)
Title: Re: Add function to the gc class
Post by: Frog on September 09, 2011, 01:39:32 pm
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?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 09, 2011, 01:41:11 pm
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 :)
Title: Re: Add function to the gc class
Post by: Frog on September 09, 2011, 01:45:43 pm
But how does that work? ??? Do you output the _G variable?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 09, 2011, 01:49:24 pm
_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.
Title: Re: Add function to the gc class
Post by: Frog on September 09, 2011, 01:56:26 pm
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...
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 09, 2011, 02:01:07 pm
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 :)
Title: Re: Add function to the gc class
Post by: Frog on September 09, 2011, 02:12:24 pm
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?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 09, 2011, 02:38:01 pm
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
Title: Re: Add function to the gc class
Post by: Frog on September 09, 2011, 02:45:00 pm
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?
Title: Re: Add function to the gc class
Post by: Jim Bauwens on September 09, 2011, 05:11:29 pm
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 :)
Title: Re: Add function to the gc class
Post by: Adriweb on September 09, 2011, 05:16:52 pm
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)
Title: Re: Add function to the gc class
Post by: Frog on September 10, 2011, 02:40:19 pm
Wow, this works great! Thanks a lot, adriweb!
Title: Re: Add function to the gc class
Post by: Adriweb on May 10, 2013, 04:53:38 pm
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 :)
Title: Re: Add function to the gc class
Post by: ElementCoder on May 13, 2013, 02:33:01 am
Just read throught this, very usefule :) Though shouldn't
Code: [Select]
function on.paint(gc)
        drawRoundRect(gc, 100, 50, 20, 15, 5)
        ...
end
in the second code block be
Code: [Select]
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 )
Title: Re: Add function to the gc class
Post by: Adriweb on May 13, 2013, 03:18:16 am
Arg, well, yeah, obviously :D
Thanks ^^