Notifications
Clear all

[Closed] SDK: HitTest.. what am I doing wrong?

Working on a helper object and having trouble getting the HitTest bounds working properly. I have my helper object set to change its size based on a separate scene object. The draw and display reflect the updated helper size, and if I output the size value from the HitTest function (as shown below) it likewise shows the updated “size” value. However, when I try to select the resized helper, I have no luck.

 I don't really understand how the graphics window methods inside the HitTest function work. The ones I am currently using are taken from the Point Helper sample cpp file. I have tried modifying the setRndLimits parameters according to the "list of rendering limits" entry in the help file, but without luck.
 
 I have found that if I draw a rectangle around the helper in the viewport, it not only selects the helper, but updates something internally so that future hit tests work for as long as it remains at the current size. However, I can't figure out exactly what causes that to happen.
int TargetHelper::HitTest(TimeValue t, INode *inode, int  type, int crossing, int flags, IPoint2 *p, ViewExp *vpt) {
       HitRegion hitRegion;
       GraphicsWindow *gw = vpt->getGW();
       MakeHitRegion(hitRegion, type, crossing, 4, p);
       Matrix3 tm = inode->GetObjectTM(t);
       gw->setTransform (tm);
       int limits = gw->getRndLimits();
       gw->setRndLimits((limits | GW_PICK) & ~GW_ILLUM);
       gw->setHitRegion(&hitRegion);
       gw->clearHitCode();
     
       mprintf(" size: %f
", size);
       Draw(gw, size, t);
       gw->setRndLimits(limits);
       return gw->checkHitCode();
     }

EDIT:
I’ve determined that the issue is that the area being checked is initially tiny, i.e. it only performs the hit test when the mouse is very close to the midpoint of the helper. Once the area to be checked has been made to update by drawing a selection around the helper, it will work as long as the helper is made /smaller/. But if it is made larger, the area to be checked does not update.

EDIT AGAIN:
Near as I can tell the source of the problem lies either with the HitRegion class and the MakeHitRegion function, or with the getRndLimits and setRndLimits functions. Unfortunately, I don’t think I’m going to be able to figure out anything further on my own, as the documentation doesn’t really have anything helpful to say.

FURTHER EDIT:
Okay no. It can’t be any of those things, because those are all called from the HitTest method, which is never getting called in the first place.

1 Reply

I am currently working on similar thing and had this same problem, but after a couple of hours finally found the solution

The problem was in Bounding Box areas that should be also override, I found this solutino in this example:
samples\objects\helpers\Character

These methods should be ovveriten as well:

virtual void myObject::GetWorldBoundBox(TimeValue t, INode *inode, ViewExp* vpt, Box3& abox);
virtual void myObject::GetLocalBoundBox(TimeValue t, INode *inode, ViewExp* vpt, Box3& abox);
virtual void myObject::GetDeformBBox(TimeValue t, Box3& abox, Matrix3 *tm, BOOL useSel = FALSE);
virtual int myObject::HitTest(TimeValue t, INode *inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)


void myObject::GetWorldBoundBox(TimeValue t, INode *inode, ViewExp*, Box3& abox)
{
	Matrix3 mat = inode->GetObjectTM(t);
	UpdateMesh(t);
	abox = iconMesh.getBoundingBox();
	abox = abox * mat;
}

void myObject::GetLocalBoundBox(TimeValue t, INode *inode, ViewExp *, Box3& abox)
{
	UpdateMesh(t);
	abox = iconMesh.getBoundingBox();
}

void myObject::GetDeformBBox(TimeValue t, Box3& abox, Matrix3 *tm, BOOL useSel)
{
	UpdateMesh(t);
	abox = iconMesh.getBoundingBox(tm);
}


int myObject::HitTest(TimeValue t, INode *inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)
{
	if (!vpt || !vpt->IsAlive())
	{
		// why are we here
		DbgAssert(!_T("Invalid viewport!"));
		return FALSE;
	}

 	HitRegion hitRegion;
	GraphicsWindow *gw = vpt->getGW();
	Matrix3 m = inode->GetObjectTM(t);
	DWORD savedLimits;

	MakeHitRegion(hitRegion, type, crossing, 4, p);
	
	UpdateMesh(t);

	gw->setTransform(m);
	gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
	gw->setHitRegion(&hitRegion);
	gw->clearHitCode();

	iconMesh.render(gw, inode->Mtls(), (flags&USE_DAMAGE_RECT) ? &vpt->GetDammageRect() : NULL,	COMP_ALL, inode->NumMtls());

	gw->setRndLimits(savedLimits);

	return gw->checkHitCode();
}