Board index FlightGear Development Canvas

kuifje09's FGPlot Development

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Re: kuifje09's FGPlot Development

Postby kuifje09 » Wed Jul 24, 2013 4:31 pm

Hi Hooray, I am a bit further already. Problem was how to get a "fucntion-(pointer)" transported to another "class" to add a listener there.
But I fixed it by using add...('click', var[] = func 'thing to do' ) That works, but looks strange, its the only way.
Just func 'thing to do' does not work. I tried a lot of variations...

Just uploaded version 3568 or so.... I am stuck now on how to resize by mousemovement.

Moving was simple because of a ready example. but for resizing I cannot find the right example or doc's.

When you try the example file on my site... ( the tar ) then when dragging the mouse in the plotting area should respond in a resize of a lot of things.
Menubars should become longer or shorter, the canvas should resize , grow or shrink. But I miss what param or function is availeable for that.
If I have to do it myself, no point, but I can't get figgured how. For example creating the root window takes only a width and a height.
Can't position it at a position from start, and don't know how I should resize it. If that becomes clear I can go further...

Pushing the buttons does not harm a thing. The most left in the upper bar does quit, like wheel-scroll in the plot-area.
Others do draw a line or print messages...
(Buttons have to change a bit to get letters on top. minor change for later )
kuifje09
 
Posts: 579
Joined: Tue May 17, 2011 8:51 pm

Re: kuifje09's FGPlot Development

Postby Philosopher » Wed Jul 24, 2013 4:46 pm

Kuifje: if it helps, essentially everything is a pointer in Nasal: a [...],{...}, or func{...} expression creates (via malloc) a new object, and if you assign that to a variable, the variable is just a pointer to that new object - and even if you don't store it in a variable (e.g. canvas_element.addEventListener("click", func print("clicked!")) ) it still gets passed around internally as a pointer. But the thing to note is that there is no pointer datatype in Nasal, because everything (except numbers) are already pointer to objects. Does this make sense?

Try this snippet out:
Code: Select all
var me = { print: print };
foo.addEventListener("click", func me.print("clicked!")); # replace foo with a canvas element, like a button

If it doesn't work, use this (and then try the closure/caller thing in your code):
Code: Select all
var me = { print: print };
foo.addEventListener("click", func closure(caller(0)[1]).me.print("clicked"));
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: kuifje09's FGPlot Development

Postby Hooray » Wed Jul 24, 2013 5:05 pm

kuifje09 wrote in Wed Jul 24, 2013 4:31 pm:Problem was how to get a "fucntion-(pointer)" transported to another "class" to add a listener there.


Code: Select all
# a function reference that you want to 'transport'
var foo = func() {
print("Hello from foo!");
}

# our template for  a class:
var class = {};
# add a constructor function named 'new' to the class hash:
class.new = func() {
# make it return a new hash with the parents vector set to the 'class' template
return {parents:[class] };
};

# add a new member function to the class for registering an external callback, implemented as a standalone function
class.transport_callback = func(callback) {
# set up an instance variable (analogous to the this pointer in C++) that points to the callback
me.transported_callback = callback
}

##
# to test things
class.invoke = func {
me.transported_callback();
}

var test = class.new();
test.transport_callback(foo);
test.invoke();


But I fixed it by using add...('click', var[] = func 'thing to do' ) That works, but looks strange, its the only way.
Just func 'thing to do' does not work. I tried a lot of variations...

it seems like you are adding lots of strings where callbacks are expected, the syntax for passing a callback is one of these:
Code: Select all

var callback = func () {
}

setupCallback( callback );

or all inline using an anonymous func:

setupCallback( func()
{
 print("Hello");
}
 );

# You can only shorten this under certain circumstances, to read:

setupCallback( func print("Hello") );

usually, it is better to use the long form.



I am stuck now on how to resize by mousemovement.
Moving was simple because of a ready example. but for resizing I cannot find the right example or doc's.

see the 'drag' events: http://wiki.flightgear.org/Canvas_-_Eve ... vent_types

Also see the example code, which shows how to access the callbacks parameters:
http://wiki.flightgear.org/Canvas_-_Eve ... ample_Code

Code: Select all
root.addEventListener("click", func(e) { printf("click: screen(%.1f|%.1f) client(%.1f|%.1f) click count = %d", e.screenX, e.screenY, e.clientX, e.clientY, e.click_count); });
    root.addEventListener("dblclick", func(e) { printf("dblclick: screen(%.1f|%.1f) client(%.1f|%.1f)", e.screenX, e.screenY, e.clientX, e.clientY); });
    root.addEventListener("wheel", func(e) { printf("wheel: screen(%.1f|%.1f) client(%.1f|%.1f) %.1f", e.screenX, e.screenY, e.clientX, e.clientY, e.deltaY); });


these use anonymous functions that are directly embedded.

So to resize an element, group or canvas, you can directly use the .setSize() method: http://wiki.flightgear.org/Canvas_Nasal_API
Alternatively, you can also access the tf (transformation) properties.

Menubars should become longer or shorter, the canvas should resize , grow or shrink. But I miss what param or function is availeable for that.
If I have to do it myself, no point, but I can't get figgured how. For example creating the root window takes only a width and a height.
Can't position it at a position from start, and don't know how I should resize it. If that becomes clear I can go further...


that's not difficult: even without knowing Nasal: 1) start your code, 2) open the property browser - browse your canvas texture and see the tf properties for each child element and group there, you can directly change lots of attributes there - once you have found the properties that you want to change, you can directly use the .set() method.

Don't forget: it's all going through the property tree, so even without knowing Nasal, you can play around with the graphics by using the property browser, and then determine what to change. The setTranslation() method also just updated the tf properties directly IIRC.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11430
Joined: Tue Mar 25, 2008 8:40 am

Re: kuifje09's FGPlot Development

Postby kuifje09 » Wed Jul 24, 2013 8:19 pm

Thank you for your ( long ) reaction, but it did not help much. How sad.

This is my main issue:
Code: Select all
366 # This is going to be the resizer.
367 # Maby much more code is needed.
368 # Resizing the graph area , but not thicken the menubars.
369 #      me.B1.addEventListener("drag", func(e) {
370 #            root.set(size[0],me.W+e.deltaX);  # size[] x, y , w , h ?
371 #            root.set(size[1],me.H+e.deltaX);
372 #         });

Please have a look at my sourcefile if you want. It may clear up a lot !
kuifje09
 
Posts: 579
Joined: Tue May 17, 2011 8:51 pm

Re: kuifje09's FGPlot Development

Postby Hooray » Wed Jul 24, 2013 8:30 pm

if that's your only code, you cannot simply pass size[0] like that to the .set() method (unless size happens to be a vector that points to the corresponding properties...), you need to specify the property path here, i.e. based on the property browser - like I suggested earlier.

Overall, I wouldn't focus too much on those areas where you still find yourself having open questions - currently, most people here are busy with other stuff, which is why there's been so little feedback probably, but that will certainly change after the release. So, I'd suggest to continue with stuff that you know how to implement, or simply work through some of the Nasal/Canvas tutorials in the meantime.

Like previously suggested, many questions can be answered by playing around with the Nasal console, some canvas snippets and looking at the canvas textures in the property tree using the property browser.

In general, it's also helpful not just to post some snippet of code, but specify exactly the nature of the problem -otherwise, we need to guess what's going on - i.e. it isn't clear if you're getting a warning, error - or if everything compiles correctly, and you are just not getting the expected behavior ?

If that's the case, your code is at least syntactically valid and you are probably working with wrong assumptions, which can be resolved by taking things more slowly and using the Nasal console to play with tiny self-contained snippets first, to ensure that you actually understand the fundamentals.

My previous posting(s) were intended to help with that: 1) take the Nasal console, 2) paste the code, 3) read through it, 4) run it - and see if it makes sense to you or not.


I have downloaded your latest code and will try to have a look and report back soon.
@anybody else, see: http://pastebin.com/yrLu9j7W
EDIT: Actually, your code looks much better/cleaner than your questions would have suggested, playing around first with the about dialog was a good idea - and it's even OOP-style to a fair degree, good job! :D
EDIT2: I think your use of variables like me.Me could be causing some confusion, it's certainly confusing me!
EDIT3: Some more feedback:

  • your resizer method is referring to variables that don't exist - try to look up the property paths that you need, or simply look at $FG_ROOT/Nasal/canvas/gui.nas
  • which tells you how width and height are set up by the canvas.Window.new() constructor: https://gitorious.org/fg/fgdata/blobs/m ... .nas#line5
  • as you can see, the property paths are "size[0]" and "size[1]" - https://gitorious.org/fg/fgdata/blobs/m ... nas#line13
  • so to change the size of the dialog, you only need to set these properties on the WINDOW/dialog handle, which is "dlg" NOT root
  • BTW: try to get rid of the me.Me notation you are using - it's VERY confusing and error-prone, you would typically set up a temporary variable and then return that from the constructor
  • see this tutorial for a very short and simple explanation: http://wiki.flightgear.org/Object_Orien ... nstructors

(the whole tutorial is pretty good and could simplify your work quite a bit, especially once you look at the underlying code in $FG_ROOT/Nasal/canvas/gui.nas)

EDIT4: Here's a slightly-edited version of your file, that 1) gets rid of the me.Me pattern you were using - and 2) which fixes your resize callback: http://codepad.org/7jvJYJ0i
If you want to resize something else, you merely need to change the instance variable, i.e. use "me.B1", "bar" or "dlg" instead of root.
Instead of the colored boxes, you may want to use real buttons, see gui.nas - we also have a tooltip class, that shows explanations for buttons, see the canvas directory
Looking at your code, I take back my earlier comments - you seem to have worked through quite a number of tutorials already, it just wasn't clear by your questions - but your code makes it obvious now, well done!

EDIT5: I now also understand your addhandler() issue: You should have read my previous responses, you were making exactly the mistake that I tried to explain: Whenever you have a complex expression, you cannot simple specify it inline as an anonymous function, you MUST wrap it inside a real func expression, or a standalone function - your dum[0] workaround is a neat hack, but unnecessary:

Code: Select all
sidebar["start"].addhandler('click', dum[0] = func plot["line"].start());


becomes this, where you wrap your expressions in a func {} block

Code: Select all
sidebar["start"].addhandler('click',
func() {
 plot["line"].start();
}
);


The empty argument list strictly isn't required for functions that do not have any/named arguments, so you could also just use func {} here instead of func() {}.
having a single func expression without curly braces will only work for very simple expressions, for example this should work (no dum[0] needed here):

Code: Select all
menubar["chgtxt"].addhandler('click',
 func
  menubar["title"].settitle("My.Oh.My")
);


(whitespaces/indentation not relevant, just added for clarity)
Here's an updated version of your code, without the dum[0] workaround: http://codepad.org/VfdtXWYk

EDIT6: Here's all your code as a Nasal submodule: http://codepad.org/oAdeFu0Q
To download the code directly, open http://codepad.org/oAdeFu0Q/raw.txt and save it as fgplot2.nas in $FG_ROOT/Nasal/fgplot2/
http://wiki.flightgear.org/Creating_new ... ub_modules
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11430
Joined: Tue Mar 25, 2008 8:40 am

Re: kuifje09's FGPlot Development

Postby kuifje09 » Wed Jul 24, 2013 10:48 pm

Ah, thanks Hooray. That's quick.
I think this is going to make it more clear to me. Its a bit late now for me, but will read it again and try you advice tomorrow.

About the buttons, they are just a quick way to test.. I already made buttons with text , radio buttons 2-state buttons...
But that will be fixed when all basic functions are in place.
I doesn't make sense to have nice buttons and a program not functional.

But thanks again, I have a look at it tomorrow.

Edit: Did some reading over again... tested your changes. and took out the globals, needed in the first steps...
It becomes a bit more to live now, multiple instances are working as resizing is. But resizing is not how it should behave.
Now it is more like a scaling the whole. Like the main flightgear window.
The root changes ( the Window) but all parts inside are scaled !, that is not the right behavior for this app. So I have another challenge.
The eventhandler is fine now. Don't now what was wrong before, I had such coding before, maby the me.Me as a problem too. Maby a typo.
Then when you don't see the fault, you drift away.... Thanks for the fix!
kuifje09
 
Posts: 579
Joined: Tue May 17, 2011 8:51 pm

Re: kuifje09's FGPlot Development

Postby Hooray » Thu Jul 25, 2013 1:47 pm

kuifje09 wrote in Wed Jul 24, 2013 10:48 pm:About the buttons, they are just a quick way to test.. I already made buttons with text , radio buttons 2-state buttons...


If you are planning on implementing additional widgets like these, I'd suggest to get in touch with TheTom, so that he can review your code and add it directly to the canvas submodule in $FG_ROOT/Nasal/canvas/widgets - that way,all scripts can use your widgets, and your code would become more compact, too.

You will want to implement the interface specified in Widget.nas: https://gitorious.org/~tomprogs/fg/toms ... Widget.nas
For an example, see button.nas: https://gitorious.org/~tomprogs/fg/toms ... Button.nas

https://gitorious.org/~tomprogs/fg/toms ... canvas/gui
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11430
Joined: Tue Mar 25, 2008 8:40 am

Re: kuifje09's FGPlot Development

Postby TheTom » Thu Jul 25, 2013 2:22 pm

kuifje09 wrote in Wed Jul 24, 2013 10:48 pm:It becomes a bit more to live now, multiple instances are working as resizing is. But resizing is not how it should behave.

Please don't work on window resizing. I'm currently working on it and will include it in the canvas gui module, such that it will be enough to just set a single property for enabling resizing canvas windows. For correct resizing I think I will also need to do some changes to the C++ code to make it easier from Nasal.
TheTom
 
Posts: 321
Joined: Sun Oct 09, 2011 10:20 am

Re: kuifje09's FGPlot Development

Postby kuifje09 » Thu Jul 25, 2013 2:52 pm

Thanks TheTom, I also discovered a bug, while resizing.

Just to let you know :

You could make the window a mirror when going beyond 0, but then can't go back !

Still another issue. When for example the property browser is over the plotterwindow, selecting or moving the browser the plotter is selected!.
and you have sometimes to move the plotter away befor the window above ( browser window i.e. ) can beselected.
So the underlaying window has more priority in focus....
kuifje09
 
Posts: 579
Joined: Tue May 17, 2011 8:51 pm

Re: kuifje09's FGPlot Development

Postby Hooray » Thu Jul 25, 2013 2:55 pm

The PUI issue is known, the idea is to eventually phase out PUI (the old dialogs) completely and use native canvas dialogs/windows for these, which would solve the problem.
TheTom wrote in Thu Jul 25, 2013 2:22 pm:Please don't work on window resizing. I'm currently working on it and will include it in the canvas gui module, such that it will be enough to just set a single property for enabling resizing canvas windows.

Yes, that's a very good idea, thanks for the update.
From a design point of view, it would obviously be great if the underlying code could be flexible enough to also support GUI splitters for resizing elements, analogous to e.g. QSplitter, i.e. some layout-awareness/integration would seem sensible.
Image

It might be possible to directly specify properties for transformations, so that listeners are automatically registered by the canvas code - that way even complex layouts with different resizable areas could be implemented just by setting a resizable flag and setting up properties to affect transformations?
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11430
Joined: Tue Mar 25, 2008 8:40 am

Re: kuifje09's FGPlot Development

Postby kuifje09 » Thu Jul 25, 2013 3:28 pm

Hello guys, who can explane to me what I do wrong when it comes to plotting :

Talking about 2 or more instances, buttons and all actions are seperate. works as a charm, but thats not so for the plotting.
In the main routine :
Code: Select all
plot["line"] = Lplot.new();


then this routine , which I expect is a "new" one for every window: just a snipped,
Code: Select all
var Lplot = {
   Prop: {},
   lines: 0,
   running: 0,
   new: func () {
      var m = { parents: [Lplot] };
      return m;
   },
   do_plot: func () {
      # This code will draw the lines on the grph
      if(me.running==1){
         print("Plotting !!!!!!!!!");
         #
         # Here will go the big plotting routine.
         #
            for( var i = 0 ; i < size(me.Prop) ; i += 1)
               print("graph running. plotting "~me.Prop[i]);
         settimer(func () { me.do_plot() },1);
      };   
      return me;
   },


Now I can add a property for plotting ( basic, just 1 line ) but I can start it from any window. , but have to stop from the window I started it.
So this means, the me.Prop[] containing the properties to plot is not unique ? While buttons and canvas are unique.
Something I do misunderstand obviously?
kuifje09
 
Posts: 579
Joined: Tue May 17, 2011 8:51 pm

Re: kuifje09's FGPlot Development

Postby Hooray » Thu Jul 25, 2013 3:33 pm

I only looked at it very briefly, but it seems that:

  • plot is a single global hash (not a class)
  • you are adding a member to it: plot.line
  • and initialize it using Lplot.new() call ONCE
  • so all instances are probably referring to the same plot hash (?)

So you will probably want to turn it into a real class (with parents:[plot] set) and call the constructor of plot in the create() function or your App constructor, to ensure that you are getting different plot instances for each dialog.

(this would also seem to apply to your other three global hashes, menubar, sidebar etc) - so you end up with a global hash that is shared by all instances, because you are not setting up separate instances

(I didn't test this, this is just what it looks like to me currently)
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11430
Joined: Tue Mar 25, 2008 8:40 am

Re: kuifje09's FGPlot Development

Postby Philosopher » Thu Jul 25, 2013 3:39 pm

Hi Kuifje, I see the problem :D. You are correct: me.Prop is going to be the same across classes. When you make you new object:
Code: Select all
new: func () {
  var m = { parents: [Lplot] };
  return m;
}

you set the parents member (which is good), but if you want me.Prop to be unique then you have to add in into the object created in new():
Code: Select all
new: func () {
  var m = { parents: [Lplot] };
  m.Prop = {}; # create a unique one for this class
  return m;
}

(when you set the parents member, anything that is not in the instance of the class (the object) is looked for in the base class (the Lplot variable as set in the parents field). This means that Prop is still found, but it is found in Lplot - not the specific object.)
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

Re: kuifje09's FGPlot Development

Postby Hooray » Thu Jul 25, 2013 3:41 pm

right, seems I was wrong - but Philosopher described the same problem, just in a different location, I suggest to fix up all those occurences where you use shared hashes, unless you really want to have some globally shared data, usable from all instances

Whenever your hash keys are valid symbols, you can also shorten your hash lookup, i.e. instead of writing menubar["bar"] you write simply menubar.bar

And BTW: plot is a hash, but you are accessing it like a vector (think array) when you are doing this: print ( "type plot[0] : "~typeof(plot[0]))
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 11430
Joined: Tue Mar 25, 2008 8:40 am

Re: kuifje09's FGPlot Development

Postby Philosopher » Thu Jul 25, 2013 3:52 pm

Yeah, 'twould be better to have Plot = [] (square backets make vectors, curly braces make hashes).
Thanks,
Philosopher
(inactive but lurking occasionally...)
Philosopher
 
Posts: 1590
Joined: Sun Aug 12, 2012 6:29 pm
Location: Stuck in my head...
Callsign: AFTI
Version: Git
OS: Mac OS X 10.7.5

PreviousNext

Return to Canvas

Who is online

Users browsing this forum: No registered users and 1 guest