Can anyone tell me if this is even near right?
1 | int button::logic(int msg) |
2 | { |
3 | if(is_mouse_over) |
4 | { |
5 | switch(msg) |
6 | { |
7 | case MSG_LPRESS: |
8 | { |
9 | |
10 | if(mouse_b & 1 && mouse_status != NOT_ON_FOCUS) |
11 | { |
12 | mouse_status = MOUSE_STATUS_DOWN; |
13 | draw_frame = DRAW_FRAME_DOWN; |
14 | play_sound = PLAY_SOUND_DOWN; |
15 | } |
16 | }break; |
17 | |
18 | case MSG_LRELEASE: |
19 | { |
20 | if(!(mouse_b & 1) && mouse_status == MOUSE_STATUS_DOWN) |
21 | { |
22 | mouse_status = MOUSE_STATUS_UP; |
23 | draw_frame = DRAW_FRAME_ON; |
24 | play_sound = PLAY_SOUND_ON; |
25 | |
26 | return TRUE; |
27 | } |
28 | }break; |
29 | } |
30 | } |
31 | } |
Edit:
I'm guessing I'll also need to throw MSG_IDLE in there, somewhere.
Yeah, for the most part. You don't need to check mouse_b in MSG_LRELEASE, because you wouldn't have gotten the message otherwise.
Also, make sure you get both a MSG_LPRESS and a MSG_LRELEASE. Otherwise, I can hold down the mouse button over nothing, drag to over the button, and release the mouse button, and the button would feel it had been pressed.
[append]
I am too tired. I see that you already do that
How about this:
1 | int button::logic(int msg) |
2 | { |
3 | switch(msg) |
4 | { |
5 | if(is_mouse_over) |
6 | { |
7 | case MSG_LPRESS: |
8 | { |
9 | if(mouse_b & 1 && mouse_status != NOT_ON_FOCUS) |
10 | { |
11 | mouse_status = MOUSE_STATUS_DOWN; |
12 | draw_frame = DRAW_FRAME_DOWN; |
13 | play_sound = PLAY_SOUND_DOWN; |
14 | } |
15 | }break; |
16 | |
17 | case MSG_LRELEASE: |
18 | { |
19 | if(mouse_status == NOT_ON_FOCUS) |
20 | { |
21 | mouse_status = MOUSE_STATUS_UP; |
22 | draw_frame = DRAW_FRAME_ON; |
23 | play_sound = PLAY_SOUND_ON; |
24 | } |
25 | |
26 | else if(mouse_status == MOUSE_STATUS_DOWN) |
27 | { |
28 | mouse_status = MOUSE_STATUS_UP; |
29 | draw_frame = DRAW_FRAME_ON; |
30 | play_sound = PLAY_SOUND_ON; |
31 | |
32 | return TRUE; |
33 | } |
34 | }break; |
35 | } |
36 | |
37 | case MSG_IDLE: |
38 | { |
39 | mouse_status = NOT_ON_FOCUS; |
40 | draw_frame = DRAW_FRAME_OFF; |
41 | } |
42 | } |
43 | } |
And what did you mean by "Also, make sure you get both a MSG_LPRESS and a MSG_LRELEASE"?.. I still don't understand how I'm suppose to use this function, like this (exit->logic(MSG_LPRESS))?
How about this:
Good, do the same for the MSG_LPRESS... and remove that crazy, invalid if statement.
I still don't understand how I'm suppose to use this function, like this (exit->logic(MSG_LPRESS))?
Err, you pass it to an Allegro dialog in the proc field.
DIALOG
Proc field eh. And which crazy invalid if statement?
and remove that crazy, invalid if statement.
If you mean the one I think you mean, its not invalid. It is crazy though just move it outside the switch...
You can mix statements in with a switch iirc. its used with loop unrolling lots.
edit, maybe I'm wrong, since Duff's Device seems to start after the first label.. Meh.
The if(is_mouse_over) you mean?
Yes. Besides, you won't get a MSG_LPRESS if the mouse is over a different control.
If I move it outside the switch how can I draw the button graphics when the user isn't touching it?
I think you should remove the if statement entirely. Why would you get a MSG_LPRESS if the mouse wasn't over the object?
Well I just don't understand how it knows. So more need of the "mouse_status" stuff?
Allegro only calls your update function with MSG_LPRESS when the current control receives a click.
Yes but how does it know what the user is clicking on, is there some kinda bounds checking already made?
Yes, the Allegro GUI automatically handles that. It wouldn't be very useful if it didn't lessen your work load, would it?
That's sweet so then it SHOULD look something like this?
1 | int button::logic(int msg) |
2 | { |
3 | switch(msg) |
4 | { |
5 | case MSG_LPRESS: |
6 | draw_frame = DRAW_FRAME_DOWN; |
7 | play_sound = PLAY_SOUND_DOWN; |
8 | break; |
9 | |
10 | case MSG_LRELEASE: |
11 | draw_frame = DRAW_FRAME_ON; |
12 | play_sound = PLAY_SOUND_ON; |
13 | break; |
14 | |
15 | case MSG_IDLE: |
16 | draw_frame = DRAW_FRAME_OFF; |
17 | break; |
18 | } |
19 | } |
Why does this look too simple/good to be true?
Not quite. MSG_IDLE will happen regardless of the mouse button's state. So that means that for 1 frame your button will have the DRAW_FRAME_DOWN image, then it will switch back to DRAW_FRAME_OFF. You need to check that !(mouse_b & 1) in the MSG_IDLE handler
coding doesn't have to be complicated, most great programs are written elegantly such that it is coherent and easy to understand even if you didn't code it. One step further would be to register a callback in your button so that when you click you set your variables. This makes it more flexible and not hard coded to your sound player. Then you can reuse your button for anything you need. It's really very simple as:
(*(button_callback))(params);
That's not so bad. Will I have to make different messange handlers for different objects or can I just have one.. To rule them all.
Not really sure what you mean about the callback thing..
1 | class Foo { |
2 | public: |
3 | typedef (*ButtonCallback)(); |
4 | |
5 | ButtonCallback callback; |
6 | |
7 | void foo() { callback(); } |
8 | } |
9 | |
10 | bool shit = false; |
11 | |
12 | void awShit() |
13 | { |
14 | shit = true; |
15 | } |
16 | |
17 | main() |
18 | { |
19 | Foo f; |
20 | f.callback = awShit; |
21 | f.foo(); |
22 | shit == true |
23 | } |
Thanks hmm.. Could someone whip up a quick example of how this should look using the dialog handler? I get the impression I'm probably not going to need as many classes.
Another way to handle callbacks with C++ is to have a virtual method inside your main button widget that is called on button press. This can be overloaded in a new button class which is derived from the main button widget. Then inside the overloaded method you do what you need to do.
bool shit;
that's funny man.
I was actually reading that awhile ago. So I'll need something like this?
// Copied from a random example DIALOG the_dialog[] = { /* (dialog proc) (x) (y) (w) (h) (fg)(bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ { d_clear_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { d_text_proc, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, (void*)"enter number", NULL, NULL }, { d_edit_proc, 160, 10, 160, 8, 0, 0, 0, D_EXIT, 64, 0, (void*)the_string, NULL, NULL }, { d_button_proc, 328, 6, 160, 16, 0, 0, 0, D_EXIT, 0, 0, (void*)"OK", NULL, NULL }, { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } };
I still don't understand how this works exactly, and how it will work with the graphics I want to use..
You'll have to make your own widgets if you want to use custom graphics. This is a lot of work. If you're looking to take the next step and use custom graphics I would recommend the agup library. While we're at I might as well throw in a plug for the unfinished XUI gui scripting project.
I already have my own widget classes made. I just wanted to find a cleaner way to handle them without using someone elses library. Is there any way to handle my classes with the Allegro gui or do I HAVE to scrap it and use their ugly buttons?
Yes, there are many ways.
Is there any way to handle my classes with the Allegro gui or do I HAVE to scrap it and use their ugly buttons?
Of course you can do it with Allegro. What's the problem?
The problem is I don't know how. Well I have a vague idea..
Well try, fail, and post your code when you get stuck!
The trick is to look at the extra parameter the callback gets. In that parameter pass a pointer to your class object.
I did post code, and when am I not stuck?
How is this to work with the switch(msg)?
You skipped the first two steps:
Well try, fail, ...
Very well thanks for the help everyone and you'll be sure to hear back from me very shortly
or do I HAVE to scrap it and use their ugly buttons?
Well, Allegro has some ugly buttons, but you can always use d_icon_proc() which is a button with three bitmaps, one for each state of the button (up, down, inactive). If that is still ugly, you suck with graphics.
I once made a class that created these three buttons on the fly. It took a string, a pattern bitmap and a font as parameters. Very simple. Every button looked a bit different. The pattern was seamless and the tiling started at a random point on each button.
MASkinG and NAS both use themed buttons using 9 bitmaps per button like so:
+---+-------------+---+ | | | | +---+-------------+---+ | |I'M A BUTTON!| | +---+-------------+---+ | | | | +---+-------------+---+
You have four corners, a top, bottom, left, right, and middle image. Text goes in the middle, and you can stretch or tile the other bitmaps to make the button any size. This is a much better way than a single bitmap. You can write your own Allegro Button widget by overloading the MSG draw portion of the allegro button with your own widget proc. It's not hard to do and the other messages are left alone so you won't have to recode that.
You can write your own Allegro Button widget by overloading the MSG draw portion of the allegro button with your own widget proc. It's not hard to do and the other messages are left alone so you won't have to recode that.
Yes! This is what I want to do but how? (example?)
int my_button_proc(int msg, DIALOG *d, int c) { if(msg == MSG_DRAW) { // Draw the button } else return d_button_proc(msg, d, c); }
I sorta understand that.. But I don't understand how it's suppose to work with the switch statement, or how I'm suppose to use the function in a game state, like is_clicked().
What switch statement?
It was on the previous page:
1 | int button::logic(int msg) |
2 | { |
3 | switch(msg) |
4 | { |
5 | case MSG_LPRESS: |
6 | draw_frame = DRAW_FRAME_DOWN; |
7 | play_sound = PLAY_SOUND_DOWN; |
8 | break; |
9 | |
10 | case MSG_LRELEASE: |
11 | draw_frame = DRAW_FRAME_ON; |
12 | play_sound = PLAY_SOUND_ON; |
13 | break; |
14 | |
15 | case MSG_IDLE: |
16 | draw_frame = DRAW_FRAME_OFF; |
17 | break; |
18 | } |
19 | } |
Something like that anyway.
Uhm, you don't need that to overload MSG_DRAW because you aren't checking for all those messages.
I wish I could understand. What's the point of using this MSG_DRAW when I could use this instead? I need to draw different frames of the button if it's down, up, or whatever.
Er wait a sec, how about this?
case MSG_DRAW { if(MSG_LPRESS) { draw_frame = DRAW_FRAME_DOWN; } }break;
The DIALOG object has a flags field. You can get the state of the button through the flags and draw accordingly. Here is code from NAS that does just that:
1 | if(d->flags & D_DISABLED) |
2 | { |
3 | box = NAS_BUTTON_DISABLED; |
4 | col = NAS_TEXT_DISABLED; |
5 | } |
6 | else if(d->flags & D_SELECTED) |
7 | { |
8 | box = NAS_BUTTON_PRESSED; |
9 | col = NAS_TEXT_PRESSED; |
10 | } |
11 | else if(d->flags & D_GOTMOUSE) |
12 | { |
13 | box = NAS_BUTTON_HIGHLIGHTED; |
14 | col = NAS_TEXT_HIGHLIGHTED; |
15 | } |
16 | else if(d->flags & D_GOTFOCUS) |
17 | { |
18 | box = NAS_BUTTON_FOCUSED; |
19 | col = NAS_TEXT_FOCUSED; |
20 | } |
21 | else |
22 | { |
23 | box = NAS_BUTTON_UNSELECTED; |
24 | col = NAS_TEXT_UNSELECTED; |
25 | } |
26 | drawskinnedrect(wnd, &buttons.rect[box], d->x, d->y, d->x + d->w, d->y + d->h); |
[edit]
DON'T mix MSG_DRAW with other messages ...
[/edit]
Uhm, a switch/case setup is the same as a whole bunch of nested if/else ifs. There is no reason to use a switch, case, or anything else in your case. What Steve posted here will work fine for you.
Hmm.. I'll try it out, but what is NAS_BUTTON/NAS_TEXT?.. And box and col?
Those are NAS GUI defines but you can use whatever you want... they are just indexes into an array of button images so that when I pass in buttons.rect into draw_skinned_rect I get the proper image to display. col IIRC is the color index of the text to display since each state of the button can have different text color.
Ohh okay, so I could just use my draw_frame instead? (my text is already on the graphics)
Right-o
Awesome Thanks a ton.. One last thing, what is d?
int (*proc)(int, DIALOG *, int); - dialog procedure
(message handler)
int x, y, w, h; - position and size of the object
int fg, bg; - foreground and background colors
int key; - ASCII keyboard shortcut
int flags; - flags about the status of the object
int d1, d2; - whatever you want to use them for
void *dp, *dp2, *dp3; - pointers to more object-specific data
d is a pointer to this structure, you have flags... which you can use to get the state of the widget. Positional and size values are x, y, w, h. dpX are pointers to any kind of data you wish (can include a callback function for your button).
How's this! And will I be able to use the same function for any kinda widget, like radio buttons or text fields?
1 | int button::is_clicked(void) |
2 | { |
3 | if(d->flags & D_DISABLED) |
4 | { |
5 | draw_frame = DRAW_FRAME_DISABLED |
6 | } |
7 | |
8 | else if(d->flags & D_SELECTED) |
9 | { |
10 | draw_frame = DRAW_FRAME_DOWN; |
11 | play_sound = PLAY_SOUND_DOWN; |
12 | |
13 | return TRUE; |
14 | } |
15 | |
16 | else if(d->flags & D_GOTMOUSE) |
17 | { |
18 | draw_frame = DRAW_FRAME_ON; |
19 | play_sound = PLAY_SOUND_ON; |
20 | } |
21 | |
22 | else if(d->flags & D_GOTFOCUS) |
23 | { |
24 | // ?? |
25 | } |
26 | |
27 | else |
28 | { |
29 | draw_frame = DRAW_FRAME_OFF; |
30 | } |
31 | |
32 | return FALSE; |
33 | |
34 | // what the hell is this |
35 | drawskinnedrect(wnd, &buttons.rect[box], d->x, d->y, d->x + d->w, d->y + d->h); |
36 | } |
... is that valid code???
/bawl.. What am I doing wrong?
Ok what the hell is your button class? It keeps changing but it still makes no sense. You basically copied my code I gave you and pasted it into your is_clicked method but the code I gave you was for my GUI as a demonstration on how you should handle things. It was not to be taken literally. Your button has an is_clicked method but the code you have inside it has nothing to do with it being clicked.. it's more of a draw method and yet you still use play_sound inside of it which also makes no sense. You keep hanging onto your class, we're just trying to show you how you can make pretty buttons using the Allegro built in GUI. You can pretty much take the Allegro GUI and extend the procs to make pretty nice looking GUI elements. NAS does pretty much that and it extends all the procs to have more functionality. It's up to you how you want to your buttons but the thread is labeled Allegro GUI so I assumed you wanted to use the Allegro GUI in which case your class is irrelevant and your code will need to be rewritten.
This is just getting depressing.. All I wanted was something to handle the different states for my widgets so I wouldn't have to keep rewriting the (near) same logic in each widget class, while keeping my own graphics and not using libraries other then Allegro to do it. I thought the Allegro GUI could do that, well it seems like it could. My class hasn't changed yet, I just copied the code given to me and rewrote it to the way I thought it works, then reposted it to see if I was even on the right track.
This is what I'm using now:
1 | int button::is_clicked(void) |
2 | { |
3 | if(!is_active) |
4 | { |
5 | return FALSE; |
6 | } |
7 | |
8 | if(is_mouse_over()) |
9 | { |
10 | if(!(mouse_b & 1) && mouse_status == NOT_ON_FOCUS) |
11 | { |
12 | mouse_status = MOUSE_STATUS_UP; |
13 | draw_frame = DRAW_FRAME_ON; |
14 | play_sound = PLAY_SOUND_ON; |
15 | } |
16 | |
17 | else if(mouse_b & 1 && mouse_status != NOT_ON_FOCUS) |
18 | { |
19 | mouse_status = MOUSE_STATUS_DOWN; |
20 | draw_frame = DRAW_FRAME_DOWN; |
21 | play_sound = PLAY_SOUND_DOWN; |
22 | } |
23 | |
24 | else if(!(mouse_b & 1) && mouse_status == MOUSE_STATUS_DOWN) |
25 | { |
26 | mouse_status = MOUSE_STATUS_UP; |
27 | draw_frame = DRAW_FRAME_ON; |
28 | play_sound = PLAY_SOUND_ON; |
29 | |
30 | return TRUE; |
31 | } |
32 | } |
33 | |
34 | else if(!(mouse_b & 1)) |
35 | { |
36 | mouse_status = NOT_ON_FOCUS; |
37 | draw_frame = DRAW_FRAME_OFF; |
38 | } |
39 | |
40 | else |
41 | { |
42 | draw_frame = DRAW_FRAME_OFF; |
43 | } |
44 | |
45 | return FALSE; |
46 | } |
Ok you can use your button class but it's not that flexible, I mean you can't use your button for anything else than playing a sound because that's the variable it's setting. You couldn't, for example, use your button to change the color of a box or something. You could also use the Allegro GUI which has the functionality you need but it's a bit ugly but I showed you ways to make it less ugly. Unfortunately to use the Allegro GUI you would have to rewrite your code. That said I would stick with what you have at the moment, you just need to break out your methods a bit and possibly use callbacks or overloaded methods to drive your play_sound variable.
That's all I want it to do, just draw and play a sound, or return TRUE if I want to use the function outside the class for other things. Before, everyone kept saying that I needed some kinda event handler for all my widgets and since then I've been trying to do that without much luck.
I suppose I could just try to write things like WIDGET_FOCUSED, WIDGET_PRESSED, etc myself.
A GUI is a pretty advanced and complicated project. Maybe make your user interface a bit simpler this time around and improve with your next game?
Because I'd just rather start learning it now while I'm at it since I already know how the code I'm using works throughout.
And yeah it can be complicated, depending on how versatile you want it to be. I want it to be pretty specific though, for the most part.
Hang on I'll whip up a simple widget and button class... I was doing so but accidentally hit the wrong keyboard button and lost my friggin post >:E
Thanks a bunch, hehe I've done that a lot before, which is why I started just writing it in a text file instead of the actual post, then just copy and paste it over.
1 | #define W_SELECTED 1 |
2 | #define W_DISABLED 2 |
3 | #define W_GOTMOUSE 4 |
4 | |
5 | class widget |
6 | { |
7 | public: |
8 | int x, y, w, h; // dimensions |
9 | unsigned int flags; // flags |
10 | void widget(int x, int y, int w, int h); // default constructor |
11 | virtual void ~widget(); // virtual destructor |
12 | bool mouse_over(); // true if mouse_over |
13 | void enable(); // enables a widget |
14 | void disable(); // disables a widget |
15 | virtual void init(); // method to do some initialization |
16 | virtual void draw(BITMAP *b); // method to draw |
17 | virtual void idle(); // method to do stuff during idle |
18 | virutal bool onKeyPressed(int key); // method to react to a key pressed (returns true if accepted key press) |
19 | }; |
20 | |
21 | void widget::widget(int x, int y, int w, int h) |
22 | { |
23 | this->x = x; |
24 | thix->y = y; |
25 | this->w = w; |
26 | this->h = h; |
27 | this->flags = 0; |
28 | init(); |
29 | } |
30 | |
31 | bool widget::mouse_over() |
32 | { |
33 | return flags & W_GOTMOUSE; |
34 | } |
35 | |
36 | void widget::idle() |
37 | { |
38 | if(mouse_x >= x && mouse_x <= x + w && mouse_y >= y && mouse_y <= y + h) |
39 | flags |= W_GOTMOUSE; |
40 | else |
41 | flags &= ~W_GOTMOUSE; |
42 | } |
43 | |
44 | void widget::enable() |
45 | { |
46 | flags &= ~W_DISABLED; |
47 | } |
48 | |
49 | void widget::disable() |
50 | { |
51 | flags |= W_DISABLED; |
52 | } |
53 | |
54 | class button : public widget |
55 | { |
56 | public: |
57 | void button(int x, int y, int w, int h); // default constructor |
58 | bool clicked(); // clicked method |
59 | virtual void ~button(); // virtual destructor |
60 | virtual void onButtonClickedCallback(); // clicked callback |
61 | }; |
62 | |
63 | void button::button(int x, int y, int w, int h) |
64 | { |
65 | widget::widget(x, y, w, h); |
66 | } |
67 | |
68 | void button::idle() |
69 | { |
70 | // Do some idle stuff |
71 | } |
72 | |
73 | void button::draw(BITMAP *b) |
74 | { |
75 | int draw_frame; |
76 | if(flags & W_DISABLED) |
77 | { |
78 | draw_frame = DRAW_FRAME_DISABLED; |
79 | } |
80 | else |
81 | { |
82 | if(widget::mouse_over()) |
83 | { |
84 | if(!mouse_b & 1) |
85 | draw_frame = DRAW_FRAME_HIGHLIGHTED; |
86 | else if(mouse_b & 1) |
87 | draw_frame = DRAW_FRAME_PRESSED; |
88 | } |
89 | else |
90 | draw_frame = DRAW_FRAME_OFF; |
91 | } |
92 | // draw the button using draw_frame |
93 | } |
94 | |
95 | bool button::clicked() |
96 | { |
97 | if(flags & D_DISABLED) |
98 | return false; |
99 | if(widget::mouse_over()) |
100 | { |
101 | if(mouse_b & 1) |
102 | { |
103 | onButtonClickedCallback(); |
104 | return true; |
105 | } |
106 | } |
107 | return false; |
108 | } |
109 | |
110 | class mySoundButton : button |
111 | { |
112 | private: |
113 | SOUND *my_sound; |
114 | public: |
115 | void mySoundButton(int x, int y, int w, int h); |
116 | virtual void ~mySoundButton(); |
117 | } |
118 | |
119 | void mySoundButton::mySoundButton() |
120 | { |
121 | widget::widget(x, y, w, h); |
122 | my_sound = Load_Sound("my_sound.wav"); |
123 | } |
124 | |
125 | void mySoundButton::~mySoundButton() |
126 | { |
127 | if(my_sound != NULL) |
128 | { |
129 | Unload_Sound(my_sound); |
130 | my_sound = NULL; |
131 | } |
132 | } |
133 | |
134 | void mySoundButton::onButtonClickedCallback() |
135 | { |
136 | ASSERT(my_sound); |
137 | Play_Sound(my_sound); |
138 | } |
I made three classes, one is the base widget class. The widget class is what every other GUI object is derived from. The next class is a base button class, all it is concerned about is doing a few methods essential to a button. The third class is a class derived from button which overloads a few methods and utilizes the callback to play a sound when the button is pressed. Please use this code only as a template, I have not compiled it and it probably won't work correctly but it should give you a direction. If you notice all methods do what their names imply and nothing more. They each do a small part. This code is not optimized either but as I said it's just to give a general idea.
[edit]
Also note that this widget class doesn't use messages but instead virtual methods to do the drawing, idling, and whatnot. You can have a message handler as part of the base widget I just did it the lazy way
[/edit]
Looks very promising to me, going to look it over before bed (stupid work in the morning)
Thanks a million for all your help, and everyone elses help (again) hehe tomorrow whenever I get home I'll try to fool around with it for awhile and will certainly give a heads up if I run into any problems, but I understand this a lot more then the Allergo gui stuff.
Why would you do that? You are making confusing methods again. set_enabled sets a variable wheras enable acts on that variable? Why not just have a method called set_enable(bool enable) that takes true or false and enables or disables the widget there. No need for an extra method that is seemingly pointless.
[edit]
aww you erased your post
[/edit]
Sorry hehe erased it after looking it over for a couple seconds. Thanks again though.
Sorry I made some minor tweaks to the widget and button classes because I could
Hmm.. The button is being displayed properly, but it doesn't seem to be doing the "clicked" logic. Also, what does |= and &= mean?
I've tried to read this thread some times, but can't figure out what you want to do. Do you want to create your own gui system? Or do you just want to have a button in your game? If the former, I guess it's a bit hard, if you still learn about &= and |=. If the latter, Allegro gui should do the job.
a = a & b;
is same as
a &= b;
I just wanted an event/message handler using only Allegro. What is the difference between & and && anyway?
&& is an AND comparison operator whereas & is a binary AND operator. For instance you would say if(someval == 2 && someotherval > 0) to only trigger the if statement only if both statements are true. Binary operations are completely different:
1 | #define THIS 1 |
2 | #define THAT 2 |
3 | #define OTHER 4 |
4 | char someval = 0; |
5 | someval |= THIS; // someval = 0x01 - sets bit 1 |
6 | someval |= THAT; // someval = 0x03 - sets bit 2 |
7 | someval |= OTHER; // someval = 0x07 - sets bit 3 |
8 | someval &= ~THAT; // someval = 0x05 - unsets bit 2 |
9 | someval ^= THAT; // someval = 0x07 - toggles bit 2 |
10 | if(someval & THAT) // true if bit 2 is set |
11 | { |
12 | // do something |
13 | } |
14 | if(someval & (THIS | THAT)) // true if bit 1 and bit 2 are set |
15 | { |
16 | // do something |
17 | } |
I'm using the operations to toggle bits in the flags variable. Which by posting this I realize a flaw in my W_* enumeration. You need each state to be a power of two. The changes would be:
#define W_DISABLED 1 #define W_GOTMOUSE 2 #define W_SELECTED 4
Still no luck. :/ No idea why it's not working for me, doesn't seem to like those W_'s.
Allegro's defines are the same to mine, no reason it wouldn't work. Again I never said the code would work right off the bat, it's just there as an example so you can understand how things work. How are you using the class? Just stating it doesn't work doesn't tell me you are doing something wrong elsewhere.
I just took functions from the code you did and stuck it in my own classes, modifying them slightly.
1 | void widget::logic() |
2 | { |
3 | if(flag &W_DISABLED) |
4 | { |
5 | draw_frame = DRAW_FRAME_DISABLED |
6 | } |
7 | |
8 | else |
9 | { |
10 | if(flag &W_GOTMOUSE) |
11 | { |
12 | if(!mouse_b & 1) |
13 | { |
14 | draw_frame = DRAW_FRAME_ON; |
15 | } |
16 | |
17 | else if(mouse_b & 1) |
18 | { |
19 | play(); // plays a sound when widget is pressed |
20 | draw_frame = DRAW_FRAME_DOWN; |
21 | } |
22 | } |
23 | |
24 | else |
25 | { |
26 | draw_frame = DRAW_FRAME_OFF; |
27 | } |
28 | } |
29 | } |
30 | |
31 | void widget::draw(BITMAP *dbuff) |
32 | { |
33 | if(draw_frame == DRAW_FRAME_ON) |
34 | { |
35 | if(on_bitmap != NULL) |
36 | { |
37 | acquire_screen(); |
38 | stretch_sprite(dbuff, on_bitmap, x_pos, y_pos, w_pos, h_pos); |
39 | release_screen(); |
40 | } |
41 | } |
42 | |
43 | if(draw_frame == DRAW_FRAME_OFF) |
44 | { |
45 | if(off_bitmap != NULL) |
46 | { |
47 | acquire_screen(); |
48 | stretch_sprite(dbuff, off_bitmap, x_pos, y_pos, w_pos, h_pos); |
49 | release_screen(); |
50 | } |
51 | } |
52 | |
53 | if(draw_frame == DRAW_FRAME_DOWN) |
54 | { |
55 | if(down_bitmap != NULL) |
56 | { |
57 | acquire_screen(); |
58 | stretch_sprite(dbuff, down_bitmap, x_pos, y_pos, w_pos, h_pos); |
59 | release_screen(); |
60 | } |
61 | } |
62 | |
63 | if(draw_frame == DRAW_FRAME_DISABLED) |
64 | { |
65 | if(disable_bitmap != NULL) |
66 | { |
67 | acquire_screen(); |
68 | stretch_sprite(dbuff, disabled_bitmap, x_pos, y_pos, w_pos, h_pos); |
69 | release_screen(); |
70 | } |
71 | } |
72 | } |
73 | |
74 | //================================================================= |
75 | |
76 | bool button::is_clicked() |
77 | { |
78 | if(flag &W_DISABLED) |
79 | { |
80 | return false; |
81 | } |
82 | |
83 | if(flag &W_GOTMOUSE) |
84 | { |
85 | if(mouse_over()) // i want this to be if(flag &W_PRESSED) |
86 | { |
87 | return true; |
88 | } |
89 | } |
90 | |
91 | return false; |
92 | } |
I don't know... you just aren't getting the picture here. I'm not sure if I can even help you. Take a closer look at my code instead of copying and pasting and get a good grasp of the concepts first. I give up.
Will do.. I'm sorry for bugging so much, going to just work with what you did until it works for me! Thank you.