Panel event runs only for one frame?

Posted By: Logan

Panel event runs only for one frame? - 01/12/11 03:19

Hi, I'm Logan. I used to post on here 3-4 years ago, and then kinda moved on in life--but now I'm back, kinda, itching to noodle around at least until school starts up again.

I'm working on an adventure game with some RPG elements. Yeah, the same one as waaaay long ago. Trying to finish it so I can finally die happy.

I'm working on a click-n-drag feature for a specific panel, and I wrote this code:
Code:
function popupbox_click_event();
PANEL* popupbox = 
{
	bmap = popupbox_map;
	layer = 4;
	event = popupbox_click_event;
}

function popupbox_click_event()
{
	while(mouse_left)
	{
		popupbox.pos_x += mickey.x;
		popupbox.pos_y += mickey.y;
		wait(1);
	}
}



It doesn't work. If I am dragging the mouse AS I click on it, it moves a few pixels in the direction the mouse was moving. That's evidence to me that the while loop ran, but only once. I've tried proc_mode = PROC_GLOBAL; as well as changing the loop to while(1) just for experimentation's sake. Even worse, if I add a wait(1) to the beginning of the event function, nothing happens at all. This looks like a bug to me, but I thought I would run it by here before posting in the Bug Hunt forum in case I am missing something obvious, or if this has already been discussed, or something.

I really appreciate anyone's help. This community is awesome.
Posted By: GorNaKosh

Re: Panel event runs only for one frame? - 01/12/11 08:34

Hello out there,

I throw some code together, to give xou an example. Here it comes:
Code:
BMAP *testPanel = "test.png";
BMAP *mousePointer = "arrow.pcx";

function popupbox_click_event(PANEL* pPanel);
PANEL* popupbox = 
{
	pos_x = 10;
	pos_y = 10;
	bmap = testPanel;
	event = popupbox_click_event;
	flags = VISIBLE;
}

function popupbox_click_event(PANEL* pPanel)
{
	while(mouse_left)
	{
		pPanel.pos_x = mouse_pos.x;
		pPanel.pos_y = mouse_pos.y;
		wait(1);
	}
}

function main() {
	mouse_mode = 2;
	mouse_map = mousePointer;
	while(mouse_mode > 0) {
		vec_set(mouse_pos, mouse_cursor);
		wait(1);
	}
}


This script is tested and works fine for me. I think the problem are this lines of your script:
Code:
popupbox.pos_x += mickey.x;
popupbox.pos_y += mickey.y;


I fairly don't know how to deal with the mickey var, but to set the panel position to the mouse position every frame, is a handy solution as well. Just try it.

Hope it helps in spite of my bad english wink
Gor Na Kosh
Posted By: Schubido

Re: Panel event runs only for one frame? - 01/12/11 11:17

Hi,

I had a similar problem doing a while(...) {... wait(1) ...} within an entity event. It seemed that it ran just for one frame. The manual says that you should not use wait(1) in entity events - maybe thats also true for panel events.
So maybe it could help to do the panel movement in a seperate function and just set a trigger in the panel event. Something like ...

Code:
var popupboxDrag = 0;

function popupbox_click_event();
PANEL* popupbox = 
{
	bmap = popupbox_map;
	layer = 4;
	event = popupbox_click_event;
}

function popupbox_click_event()
{
	popupboxDrag = 1
}

function popupboxAction()
{
  while(1)
  {
    if(popupboxDrag)
    {
        popupboxDrag = 0;
	while(mouse_left)
	{
		popupbox.pos_x += mickey.x;
		popupbox.pos_y += mickey.y;
		wait(1);
	}
    }
    wait(1);
  }
}

main()
{

  ...
  popupboxAction();
  ...

}


Posted By: MrGuest

Re: Panel event runs only for one frame? - 01/12/11 11:38

Originally Posted By: Schubido
Hi,

I had a similar problem doing a while(...) {... wait(1) ...} within an entity event. It seemed that it ran just for one frame. The manual says that you should not use wait(1) in entity events - maybe thats also true for panel events.
So maybe it could help to do the panel movement in a seperate function and just set a trigger in the panel event. Something like ...

Code:
var popupboxDrag = 0;

function popupbox_click_event();
PANEL* popupbox = 
{
	bmap = popupbox_map;
	layer = 4;
	event = popupbox_click_event;
}

function popupbox_click_event()
{
	popupboxDrag = 1
}

function popupboxAction()
{
  while(1)
  {
    if(popupboxDrag)
    {
        popupboxDrag = 0;
	while(mouse_left)
	{
		popupbox.pos_x += mickey.x;
		popupbox.pos_y += mickey.y;
		wait(1);
	}
    }
    wait(1);
  }
}

main()
{

  ...
  popupboxAction();
  ...

}


as GorNaKosh said you shouldn't be using += for the position.

Though neither of you take account for moving it from where is was click and always aligning directly to the mouse position.

Try this. It uses a button rather than giving the whole panel the click event, just change it as required.
Code:
#include <acknex.h>
#include <default.c>

PANEL* pnl_dummy;

void move_panel(var id, PANEL* pnl){
	
	int x = mouse_pos.x - pnl.pos_x;
	int y = mouse_pos.y - pnl.pos_y;
	
	while(mouse_left){
		pnl.pos_x = mouse_pos.x - x;
		pnl.pos_y = mouse_pos.y - y;
		wait(1);
	}
}

void main(){
	
	mouse_mode = 4;
	wait(1);
	
	pnl_dummy = pan_create("", 1);
	pnl_dummy.bmap = bmap_createblack(100, 60, 32);
	bmap_fill(pnl_dummy.bmap, COLOR_GREEN, 100);
	set(pnl_dummy, SHOW);

	BMAP* bmp_moveBtn = bmap_createblack(100, 10, 32);
	bmap_fill(bmp_moveBtn, COLOR_RED, 100);
	
	pan_setbutton(pnl_dummy, 0, 0, 0, 0, bmp_moveBtn, bmp_moveBtn, bmp_moveBtn, bmp_moveBtn, move_panel, NULL, NULL);
}


Posted By: Logan

Re: Panel event runs only for one frame? - 01/12/11 17:31

Thanks everyone. I know the mickey.x..y might not have been the best choice but it DOES work crudely in a test level, and I'm not so worried about the exact mechanics right now as I am just trying to make the function run for more than one frame!

All of your code works in small test levels but then stops working when I put it in my project. There is something else going on that I don't get.

Schubido, your idea is interesting. I'll give it a shot.
Posted By: Logan

Re: Panel event runs only for one frame? - 01/14/11 09:39

Figured it out finally, it had to do with freeze_mode. I thought I was being clever by setting freeze_mode = is(panel1,SHOW). That messed it up but it was very well disguised as working for a while. I changed it to freeze_mode = (freeze_mode==0) and now it works perfectly.

Moral of the story is that the is() macro doesn't return 1's and 0's per se, so don't set a variable to it as though it returns a numerical value. Lesson learned.

Thanks for everyone's help. MrGuest, I was able to use bits of your code to really improve the movement and make the box not "snap" to the mouse in the upper left corner. Thank you--I really appreciate that.
Posted By: Superku

Re: Panel event runs only for one frame? - 01/14/11 16:13

Quote:
Moral of the story is that the is() macro doesn't return 1's and 0's per se, so don't set a variable to it as though it returns a numerical value.

Short explanation:

The macro "is" is defined as follows:
#define is(obj,flag) (obj->flags & (flag))

The flag "SHOW" is defined as follows:
#define SHOW (1<<14)

That means if you write
is(panel1,SHOW),

that translates to
(panel1->flags & SHOW)

what is equal to 2^14.
Posted By: MrGuest

Re: Panel event runs only for one frame? - 01/14/11 23:31

Originally Posted By: Superku
Quote:
Moral of the story is that the is() macro doesn't return 1's and 0's per se, so don't set a variable to it as though it returns a numerical value.

Short explanation:

The macro "is" is defined as follows:
#define is(obj,flag) (obj->flags & (flag))

The flag "SHOW" is defined as follows:
#define SHOW (1<<14)

That means if you write
is(panel1,SHOW),

that translates to
(panel1->flags & SHOW)

what is equal to 2^14.
lol, that's one way to confuse the forumees... if that's a word crazy

you could just try
Code:
freeze_mode = 2-freeze_mode;


© 2024 lite-C Forums