How to pass arguments to draw() method - FLTK - c++

I´m new to FLTK and currently facing the following problem:
I have a class PointModel, which stores points with x- and y-coordinates, a class View, which needs to call update(), everytime the coordinates in the PointModel change (Observer Pattern) and draw them and finally a class MyBox, where the coordinates should be drawn in.
View is derived from Fl_Window. MyBox is derived from Fl_Box and part of View.
Therefore I need to know, how to pass the point coordinates from a member function (void update()) of View to the draw method of MyBox.
I´m trying to typecast the user_data pointer I get to View* in case to be able to get the PointModel, holding the point coordinates. But the window closes after calling the draw() method.
Maybe I only get a NULL-Pointer here? Unfortunately I can´t check it through debugging, because somehow Eclipse doesn´t break at the breakpoints now..
Any solutions, hints what I´m doing wrong or possible alternatives?
Thanks in advance!
Here some pieces of my code:
View.cpp:
class MyBox : public Fl_Box {
void draw() {
Fl_Box::draw();
View *v1 = (View*)this->parent();
if(v1 != NULL) {
int lastX = v1->getPointModel()->getLastX();
int lastY = v1->getPointModel()->getLastY();
int currentX = v1->getPointModel()->getCurrentX();
int currentY = v1->getPointModel()->getCurrentY();
fl_color(FL_WHITE);
fl_line(lastX, lastY, currentX, currentY);
}
}
public:
MyBox(int X,int Y,int W,int H,const char*L=0) : Fl_Box(X,Y,W,H,L) {
box(FL_FLAT_BOX);
}
};
View::View(*arguments*) :Fl_Window(540,650,"View1") {
begin();
MyBox box(20,20,500,500," ");
box.box(FL_UP_BOX);
box.color(0x00000000);
//more widgets
end();
show();
Fl::add_timeout(3.0, Timer_CB, (void*)this);
Fl::run();
}
edit: I updated the code to running version

Well, MyBox.draw() will be called before you call add_timeout(). user_data() will give you NULL most likely... You could add a check for NULL in there. Something like:
void draw() {
Fl_Box::draw();
void* ptr = user_data();
if (ptr) {
// do stuff here...
}
Second possible problem is this->parent()->user_data(); . Parent of your MyBox object is the Fl_Window object (actually, your View object, which is a Fl_Window), and user_data() will always return NULL for it I think...
The easiest way to pass any object to your widget is to use user_data() method:
box.user_data(&myview); // after this box.user_data() will return a View*

Related

Fixing an object oriented wrapper I am creating for bindbc.sfml

I am trying to create object oriented wrappers around bindbc.sfml, this is because I don't like the C-style syntax of CSFML.
The C-style syntax is not right -- in my opinion -- for an object oriented language. Dealing with pointers all the time is also unsafe.
This is not to say that CSFML isn't good -- it's great, and I've made some apps using bindbc-sfml. I just want to extend it to my liking with object oriented wrappers that can more closely match the C++ SFML syntax.
For the wrappers, I created a Shape class. This Shape class is seen in the original C++ SFML implementation:
class Shape : Transformable, Drawable {
void setTexture(sfTexture* texture, bool resetRect) {
ptr.sfShape_setTexture(texture, resetRect);
}
void setTextureRect(IntRect rect) {
ptr.sfShape_setTextureRect(rect.to_sfIntRect());
}
void setFillColor(Color color) {
ptr.sfShape_setFillColor(color.to_sfColor());
}
void setOutlineColor(Color color) {
ptr.sfShape_setOutlineColor(color.to_sfColor());
}
void setOutlineThickness(float thickness) {
ptr.sfShape_setOutlineThickness(thickness);
}
const(sfTexture)* getTexture() {
return ptr.sfShape_getTexture();
}
IntRect getTextureRect() {
return ptr.sfShape_getTextureRect().toIntRect();
}
Color getFillColor() {
return ptr.sfShape_getFillColor().toColor();
}
Color getOutlineColor() {
return ptr.sfShape_getOutlineColor().toColor();
}
float getOutlineThickness() {
return ptr.sfShape_getOutlineThickness();
}
size_t getPointCount() nothrow {
return ptr.sfShape_getPointCount();
}
Vector2f getPoint(size_t index) nothrow {
return ptr.sfShape_getPoint(index).toVector2f_noThrow();
}
FloatRect getLocalBounds() {
return ptr.sfShape_getLocalBounds().toFloatRect();
}
FloatRect getGlobalBounds() {
return ptr.sfShape_getGlobalBounds().toFloatRect();
}
private sfShape* ptr;
}
The sfShape pointer isn't currently initialized, I'll get to that issue soon.
As you can see, Shape extends the Transformable class and the Drawable interface. This again roughly matches what's seen in SFML. SFML.NET also did a similar wrapper for their CSFML C# bindings. What's great about SFML.NET is that you don't even know that you're using CSFML, this is because it feels just like C++ SFML.
Now, I will create a RectangleShape which will be a subclass of the Shape class:
(Btw I took a lot of inspiration from SFML.NET when it comes to these wrappers.)
class RectangleShape : Shape {
this(Vector2f size) {
_size = size;
setSize(_size);
}
Vector2f getSize() {
return _size;
}
void setSize(Vector2f size) {
_size = size;
}
override {
size_t getPointCount() {
return 4;
}
Vector2f getPoint(size_t index) {
final switch (index) {
case 0:
return Vector2f(0, 0);
case 1:
return Vector2f(_size.x, 0);
case 2:
return Vector2f(_size.x, _size.y);
case 3:
return Vector2f(0, _size.y);
}
}
}
private Vector2f _size;
}
As you can see, the Rectangle class only overrides the getPointCount and getPoint methods.
These are the methods that the superclass - Shape - will use to construct the shape object for it to actually be drawable.
Now, let us add the following code to the Shape class so that we can construct a Shape via these two methods, which we assume that the child provides us a good implementation for:
class Shape : Transformable, Drawable {
this() {
ptr = sfShape_create(&getPointCount, &getPoint, cast(void*)this);
}
extern(C) private static ulong getPointCount(void* data) nothrow {
return (cast(Shape)data).getPointCount();
}
extern(C) private static sfVector2f getPoint(size_t index, void* data) nothrow {
return (cast(Shape)data).getPoint(index).to_sfVector2f_noThrow();
}
I hear you asking, what's going on here?
We are providing two callbacks to the getPointCount and getPoint methods via function pointers, and we're passing in the current object to the data void* pointer. It's kind of hard to understand, but if you read through it carefully you should get a rough idea of what's going on.
Now, when we create a new instance of Rectangle, I will assume that the constructor will be called, the sf_shape ptr will be initialized correctly (as it will be utilizing the crucial getPoint and getPointCount methods) and everything will be OK.
This is the following test code I had:
void main() {
loadSFML();
RectangleShape rectangleShape = new RectangleShape(Vector2f(50, 50));
rectangleShape.setPosition(Vector2f(50, 50));
rectangleShape.setFillColor(Color.Blue);
RenderWindow renderWindow = new RenderWindow(sfVideoMode(500, 500), "Tests", sfWindowStyle.sfDefaultStyle, null);
sfEvent event;
while (renderWindow.isOpen()) {
while (renderWindow.pollEvent(&event)) {
if (event.type == sfEventType.sfEvtClosed) {
renderWindow.close();
}
}
renderWindow.clear(Color.Yellow);
renderWindow.ptr.sfRenderWindow_drawShape(rectangleShape.ptr, null);
renderWindow.display();
}
}
I would read through this line by line to get a good idea of what's going on.
Really, for demonstration purposes, we're using the renderWindow's ptr variable for drawing. When I can get this to work I will create wrapper functions so that it's nicer to use, but for now it's not important.
What I'd expect to pop up on screen is a 50x50 rectangle, filled with a blue color, at the position 50x50 on the screen.
Upon running the application, I don't see anything -- it's just a yellow screen.
I am very confused why this is the case, it seems like I've done everything fine, but I've obviously made a mistake somewhere in my implementation. I don't know specifically if it's an issue on my end, or a bug in bindbc-sfml, but this issue has infuriated me, because I am not getting what I expected to show up on screen.
Fixed it by calling sfShape_update here:
class RectangleShape : Shape {
this(Vector2f size) {
_size = size;
setSize(_size);
ptr.sfShape_update();
}

OOP in C++. How to drop the states

I am writing a simple graphics editor.
There are 3 buttons on the panel, by pressing which I draw a square, circle or line.
There are 3 button handlers that change the state and 3 mouse event handlers in the class responsible for drawing the workspace.
void Cpr111View::OnCirc()
{
state = 1;
}
void Cpr111View::OnLine()
{
state = 2;
}
void Cpr111View::OnRect()
{
state = 3;
}
To shorten the question, I will give only one handler out of 3.
void Cpr111View::OnMouseMove(UINT nFlags, CPoint point)
{
if (state==2)
{
int oldmode;
CClientDC *pDC = new CClientDC(this);
if (nFlags && MK_LBUTTON)
{
oldmode = pDC->GetROP2();
pDC->SetROP2(R2_NOT);
pDC->MoveTo(begin.x, begin.y);
pDC->LineTo(oldmouse.x, oldmouse.y);
pDC->MoveTo(begin.x, begin.y);
pDC->LineTo(point.x, point.y);
oldmouse = point;
pDC->SetROP2(oldmode);
CView::OnMouseMove(nFlags, point);
}
}
if (state == 1)
{
….
}
if (state == 3)
{
….
}
void Cpr111View::OnLButtonUp(UINT nFlags, CPoint point)
{
}
void Cpr111View::OnLButtonDown(UINT nFlags, CPoint point)
{
}
Here is a drawing system.
I want to do it without states. That is, create an abstract class Figure. With three virtual methods per render:
Class Figure
{
public:
void virtual MouseMove()=0;
void virtual ButtonUp()=0;
void virtual ButtonDown()=0;
}
And from him in the classes of figures to override these methods.
Class Recatngle:public Figure
{
public:
void MouceMove() override;
...
}
Then, when the button is clicked, create an object of the corresponding class, then the button handler will look like this:
void Cpr111View::OnRect()
{
figure = new Rectangle();
}
And when drawing, the mouse handler will simply call the method of the corresponding class:
void Cpr111View::OnMouseMove(UINT nFlags, CPoint point)
{
figure - > MouseMove();
}
In order for figure to be available in two different methods, we declare it in the class:
class Cpr111View : public CView
{
public:
Figure figure;
…
}
This is how I want to do it, but the problem is that it can't be done that way. At a minimum, you cannot declare an abstract class variable. Then what type should it be if I am going to write a pointer to different classes into it? How to implement this architecture correctly, or maybe there are better ideas?
Using this way of polymorphic calls in C++ requires to use reference sematics.
I advise to read about it. E.g.: Reference and Value Semantics
So it class Cpr111View, you have to keep your Figure member by pointer, or by refernce.
In order to avoid having to manually manage the object, you should use a smart pointer like std::unique_ptr (or std::shared_ptr if you need to share ownership):
#include <memory> // for std::unique_ptr
class Cpr111View : public CView
{
public:
std::unique_ptr<Figure> figure;
//…
}
Of course you will need to allocate it before using it.
Instead of:
figure = new Rectangle();
use:
figure = std::make_unique<Rectangle>();
The method calls stay the same as in your code, e.g.:
figure->MouseMove();
If you not familiar with smart pointers in C++, I recomend to read about it. E.g.: What is a smart pointer and when should I use one?.

Cocos2d-x PhysicsContact Object Reference

I'm trying to make a videogame with C++ in Cocos2d-x but I have an issue with PhysicContact.
In my gamescene I have a contact listener that check for collisions with the character and objects' PhysicBody of class Item. It all works fine, but now I want to recognize what object has collided because I want to call a method of the object's class called getThrow().
class Item : public cocos2d::Layer
{
public:
Sprite* itemArt;
int itemType;
PhysicsBody* itemCollider;
void createArt(int type);
void getThrow();
Item(int type);
};
I have tried it with the PhysicContact information, first I obtain the object PhysicBody and then its Node, but with this I just obtain the object's Sprite and at this point I don't know how to reach the object to call his method.
bool Level0::onContactBegin(PhysicsContact &contact)
{
auto bodyA = contact.getShapeA()->getBody()->getNode();
auto bodyB = contact.getShapeB()->getBody()->getNode();
//HERE IS WHERE I WANT TO RUN bodyB->getThrow()
return true;
}
I also have tried with getUserData() and getUserObject() but I don't know how to call a method with an object pointer.
I don't know if I'm trying something incorrectly, but I would appreciate your answers.
Thanks in advance! (If more details are needed just tell me, I'm new at this big community)
You need to do this:
((Item*) b->getNode())->getThrow();

About create method in CCSprite

I'm just training cocos2d-x.
Now,I tryed to create sprite on display using CCSprite class.
I wrote the code as follows.
Characters Class
class characters : public cocos2d::CCSprite{
public:
void setRect(CCPoint point);
CCRect getRect();
void setTag(int x,int y);
int getTag();
void setDirection(int num);
int* getDirection();
bool isTouchPoint(CCPoint point);
void animation(characters *chara,int num);
private:
CCRect m_rect;
int m_tag;
};
bool HelloWorld::init(){
for(int i=0;i<9;i++){
characters *chara = new characters;
chara->autorelease();
chara->create("char04x2.png");
x = Indexes[i]%HORIZONTAL_AXIS; //Indexes is cell number on display
y = Indexes[i]/HORIZONTAL_AXIS;
CCPoint point = ccp(MARGIN_WIDTH + PIPE_WIDTH * x,MARGIN_HEIGHT + PIPE_HEIGHT * y);
chara->setPosition(point);
chara->setRect(point);
chara->setTag(x,y);
this->addChild(chara,1);
}
}
But,this code is wrong.
It stops in CC_NODE_DRAW_SETUP() of void CCSprite::draw(void) method.
Error message is
Cocos2d: Assert failed: No shader program set for this node
Assertion failed: (getShaderProgram()), function draw, file /Users/nyoronyoro-kun/Desktop/cocos2d-x/cocos2dx/sprite_nodes/CCSprite.cpp, line 554.
When I replaced create method with initWithFile method,error don't appear.
Why this error appeared?
In lines
characters *chara = new characters;
chara->autorelease();
you create an empty sprite (with no texture). Then at line
chara->create("char04x2.png");
you create another sprite with an associated texture but you don't assign it to nothing! This line of code do nothing for you!
Result: in draw function your sprite (created in the first two lines of code) doesn't have an associated texture and it has never been initialized!
'create' function is a static function, that is a "class function":
static CCSprite* create(const char *pszFileName);
Use it in this way:
chara = CCSprite::create("char04x2.png");
and remove the first two lines.
I hope this can help you.
In init() method of your derived class (charecters) you missed calling super Class method init. call CCSprite::init() in your init method should solve your problem

Informing GUI objects about screen size - Designing

I have a problem with designing classes for my game which I create.
In my app, there is:
class CGame which contains all the information about game itself,
e.g. screen width, screen height, etc. In the main() function I
create a pointer to CGame instance.
class CGUIObject which includes fields specifying it's position and
draw() method, which should know how to draw an object according to
screen size.
class CGUIManager which is a singleton and it includes a list of
CGUIObject's. For each object in a list it just calls draw()
method.
For clarity's sake, I'll put some simple code:
class CGame
{
int screenWidth;
int screenHeight;
};
class CGUIObject
{
CPoint position;
void draw(); // this one needs to know what is a screen's width and height
};
class CGUIManager // it's a singleton
{
vector<CGUIObject*> guiObjects;
void drawObjects();
};
And the main.cpp:
CGame* g;
int main()
{
g = new CGame();
while(1)
{
CGUIManager::Instance().drawObjects();
}
return 0;
}
Now the problem is, that each CGUIObject needs to know the screen size which is held by CGame, but I find it very dumb to include pointer to CGame instance in every object.
Could anyone, please, tell me what would be the best approach to achieve this?
Is there a reason that you are needing your screen resolution in your CGUIObject's?
They have a position already, so if you have them draw themselves in local space, you can apply a transform to them in your CGUIManager in order to lay them out. You abstract your layout from the GUI objects themselves this way, and the objects don't need to know which container they are living in (the screen, a window, a tab etc).