We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProcessing DevelopmentLibraries,  Tool Development › Help with Library - Accessing PApplet
Page Index Toggle Pages: 1
Help with Library - Accessing PApplet (Read 2436 times)
Help with Library - Accessing PApplet
Nov 27th, 2006, 11:43pm
 
This is about a Libraries Authoring. How could I have acces to the PAplet methods inside a Library? To express the problem, I give an example of a class:

Here, the proto-class require a PApplet to draw() an ellipse for each points.
Code:

public class Vertex{
PApplet p5;
float x,y,z;

Vertex(PApplet p5){this.p5=p5;}
Vertex(float _x, float _y, float _z, PApplet p5){
x=_x;
y=_y;
z=_z;
this.p5=p5;
}

public void add(float k){ x+=k; y+=k; z+=k;}
public void add(float k, float l){ x+=k; y+=l; }
public void add(float k, float l, float m){ x+=k; y+=l; z+=l;}

//...

public void draw(){
p5.ellipse(x,y,z); //Will use PApplet to draw an ellipse.
}

}

Here's would be an example of use:
Code:

Vertex[] v = new Vertex[100];

for(int i=0; i<v.length; i++)
{
v[i] = new Vertex(i,i,i,this);
v[i].draw();
}


But, how should I setup the class to have acces to the PApplet methods without explicitly passing the PApplet to each objects? Like in this example:
Code:

Vertex[] v = new Vertex[100];

for(int i=0; i<v.length; i++)
{
v[i] = new Vertex(i,i,i); //note'this' have been removed.
v[i].draw(); //where could I access draw() now?
}



I'm trying to figure a way to do this. Extends PApplet? I don't see how, but passing PApplet each time seems that I'm missing something.
Re: Help with Library - Accessing PApplet
Reply #1 - Nov 28th, 2006, 12:22am
 
Hi Guillaume. You're already doing it correctly by passing a PApplet reference in the constructor of Vertex. After that you won't need to pass the reference again. Extending PApplet is wrong, since then all your Vertex objects would work as independent sketches, drawing to separate canvases.
Re: Help with Library - Accessing PApplet
Reply #2 - Nov 28th, 2006, 5:32am
 
Hi Marius! Nice to see you... I remember that we had a talk about this in Barcelona. I did work on a sceneGraph. I still have problems on some basic elements, on how you link the Library with the PApplet, so it's hard to start to put the things all together.

The problem is that I'll have to pass PApplet to every constructor. I'm not fine with this way to declare objects. I know that the first solution above will work, but I want to remove the PApplet reference each time I create Object. It might seems too much esthetic, but I can't imagine working with this in design.

Code:

Vertex(x,y,z,this);
Face(Vertex[], this);
Cube(x,y,z,dx,dy,dz,this);
Pyramid(x,y,z,dx,dy,dz,this);
Scene(this);

//....
//so on, this, this, this...

I would prefer something like:
Code:

Vertex(x,y,z);
Face(Vertex[]);
Cube(x,y,z,dx,dy,dz);
Pyramid(x,y,z,dx,dy,dz);
Scene();

//or, at least, myGeo.Vertex(x,y,z);


As you know PovRAY, you probably remember great things with the pseudoCode like:
Code:

Vertex a,b;
Vertex c = a+b;

I'm still thinking that it's more easy to read that way. At the end, I left that way to do it in Java, but I might still be nostalgic. Again, passing PApplet on every new object, since I don't have a 'this' key on my keyboard yet, I won't be happy with this Library for everyday design.

There's an anonther way to do it?


...
I tried something else (Make a superClass where you pass PApplet only once and where everything would be inner, but again, I feel that it's a wrong way:
Code:

public class SuperGeo {

public PApplet p5;

public SuperGeo(PApplet p5){
this.p5 = p5;
}


public class Vertex{

float x,y,z;

Vertex(){}

Vertex(float _x, float _y, float _z){
x=_x;
y=_y;
z=_z;
}

public void add(float k){ x+=k; y+=k; z+=k;}
public void add(float k, float l){ x+=k; y+=l; }
public void add(float k, float l, float m){ x+=k; y+=l; z+=l;}
//...

public void draw(){
p5.ellipse(x,y,3,3); //Will use PApplet to draw an ellipse.
}
}


}
Re: Help with Library - Accessing PApplet
Reply #3 - Nov 28th, 2006, 6:34am
 
I can understand the "aesthetic" concern, but this is the correct practice according to OOP philosophy.

The only reason why PApplet's methods are available to classes when running inside Processing is that all classes are local classes of your sketch. In that case you can safely make the assumption that a "global" PApplet object exists, and that there is no ambiguity as to which one should be called.

Another option would be to have a utility class in your library which contains a static reference to a PApplet parent. Then you could pass this class a reference to your PApplet class, and have all other classes use the utility class to get their copy.

Code:
Vertex v;

void setup() {
Util.init(this); // initialize utility class
v=new Vertex(10,10,50);
}

void draw() {
v.draw();
}

class Util {
static public PApplet p5;

static public init(PApplet _p5) {
p5=_p5;
}

static public PApplet getParent() {
return p5;
}
}

class Vertex {
PApplet p5;

public Vertex(float _x, float _y, float _z){
x=_x;
y=_y;
z=_z;

p5=Util.getParent();
}

public void draw() {
p5.pushMatrix();
p5.translate(x,y,z);
p5.box(5);
p5.popMatrix();
}
}


See what I mean? Note that you should probably create a proper package hierarchy for your classes.
Re: Help with Library - Accessing PApplet
Reply #4 - Nov 28th, 2006, 1:41pm
 
using "static" is even uglier and should be avoided. this will cause conflicts if you have multiple applets running at a time and is generally bad practice.

the other model is to pass the PApplet object to the draw() methods of each of the objects. this is often much cleaner. if it's a scene graph, you'll only need to call draw(this) on the topmost object, which can then call draw(parent) on each of its children in the scene graph.

this also prevents the other objects from calling PApplet methods when they're not allowed to (i.e. outside the draw() method, which can cause problems for renderers like opengl).

as marius says, this is indeed simply how oop is done. in the p5 code we get around this (somewhat) by using createImage() and createGraphics(), but it's still frustrating for libraries that we have to pass "this" to the constructor of, say, the Camera or Movie classes.

regarding the createXxxx() method, you could also have a base class that handles creation:

Scene s = new Scene(this);
Vertex c = s.createVertex(x, y, z);
Group gr = s.createGroup();
gr.createBox(x, y, z);
gr.createEllipse(x, y, w, h);
...etc

under this model, this also helps you specify the hierarchy of your objects, where createBox(), having been created by the "Group" object, is a child of that item in the tree.
Re: Help with Library - Accessing PApplet
Reply #5 - Nov 28th, 2006, 3:19pm
 
Yes, using a static class with a static reference is an ugly hack. More commonly I set up a hierchical class structure like you suggest with Scene etc, with the PApplet reference percolating down the line.

Of course, in "pure" OOP each class is supposed to hide its structure from the world around it and communicate it through method calls rather than public variables. But that lofty goal is usually lost to optimization and frustration with overly verbose code...
Re: Help with Library - Accessing PApplet
Reply #6 - Nov 28th, 2006, 10:30pm
 
If I get this right, "Vertex" implies there will always be more than one of these objects created by the user. The user will logically contain them in an array or linked-list for house-keeping if you don't already provide a wrapper for that array.

Why not provide a class which manages the drawing to which a reference of the collection of Vertexes is passed, and let that be the ugly one, freeing up Vertex to be a purer idea.
Page Index Toggle Pages: 1