Some problems with the new MouseOverPixel system

thecaptain

04-02-2008 06:27:27

Hey I've noticed some strange behavior with the latest SVN version with the mouse over detection. For example, in the demo, when the mouse is over the dropdown box arrow button, it doesn't light up, while it does when the mouse is slightly to the left of it.

Also, occasionally, there is a crash on the getColourAt(actualX,actualY,0) line because this code sometimes produces an X or Y that is outside of the 1024x1024 skinset image:

bool SkinSet::overTransparentPixel(const std::string& skinComponent, int xPos, int yPos)
{
Vector4 UVCoords = getTextureCoordinates(mSkinName + skinComponent + getImageExtension());

int actualX = (mTextureWidth * UVCoords.x) + xPos;
int actualY = (mTextureHeight * UVCoords.y) + yPos;

Ogre::ColourValue cv = mSkinSetImage->getColourAt(actualX,actualY,0);
return (cv.a < 0.01);
}


Are you aware of these issues/is this still a work in progress? Either way, here are a couple things that might help. For example, I think that code that checks to see if the mouse is within a parent widget calls this:

bool Widget::isPointWithinBounds(const Point& pixelPosition)
{
if(!mQuad->visible())
return false;

if(!mQuad->isPointWithinBounds(pixelPosition))
return false;

if(overTransparentPixel(pixelPosition))
return false;

return true;
}


The problem is that this code should return whether the mouse is within bounds of the widget, not whether it is over a transparent pixel or not. So the last if statement should probably be replaced by a more straight-forward rectangular position check.

I'll look more into this and see what I can find, but let me know if you're aware of these problems as well.

Thanks!

thecaptain

04-02-2008 07:01:57

Aha! I think I've found the problem :D

In the code:

bool Widget::overTransparentPixel(const Point& mousePixelPosition)
{
if(!mUseTransparencyPicking)
return false;

Point pt = mousePixelPosition - (getScreenPosition() + getScrollOffset());


if (pt.x < 0.01 || pt.y < 0.01)
{
// something is wrong here
Ogre::LogManager::getSingletonPtr()->logMessage("Quickgui : error in Widget::overTransparentPixel getting correct Mouse to widget position");
return false;
}

return mSkinSet->overTransparentPixel(mSkinComponent,pt.x,pt.y);
}


pt is not scaled according to the size of the image on the skinset. For example, if the qgui.button.png image file is 135x40, but the button is sized to 200x50 in the demo, then the point should be converted by that ratio before being sent to the skinset. Otherwise, it goes out of bounds/looks at other skin elements and screws up.

I'm not sure if there is any way to retreive the original image size from the skinset, but if there is, then it's really easy to fix this. I'll continue looking into it...

kungfoomasta

04-02-2008 07:26:07

Awesome, I'm glad you found the issue! I made a function SkinSet::getImageHeight/Width which will give you dimensions of a texture. I'm busy moving into my new house, so I don't have access to the code at the moment.

isPointWithinBounds needs an update, it shouldn't have the call to overTransparentPixel at all. I will move the call to that into the getTargetWidget function, there is some logic that needs to be fixed in that function.

thecaptain

04-02-2008 07:36:46

Hey, I think I've fixed it! I just found those functions as well :)

Anyway, I've also fixed everything relating to this issue, including fixing the isPointWithinBounds and now it's working perfectly (as far as I can tell).

Here's a patch so you can see my changes before committing if you want:

http://web.mit.edu/estafl/www/sc/TransparencyFix.patch

FYI: Before I was looking at this problem, I added setBorderThickness and setBorderOverlap functions to Widget, so I could create windows with various border sizes. This is also included in the patch.

thecaptain

04-02-2008 07:39:32

Oh... I've noticed that the textcursor image is still in the upper left of the screen at the beginning of running the demo. Do you have a way you'd like to fix this?

I came up with a little hacky fix earlier (using another visible variable in quads, called mOverrideVisible, that would only be user set, instead of clipping set), but I never committed that change.

Let me know what you'd like to do here.

kungfoomasta

05-02-2008 06:17:14

I don't see what text cursor image you're referring to. Can you post a screenshot?

I committed your patch, it looks like its working, thanks a lot! Regarding the border changes, I agree we need that functionality, but I want to make things more flexible. Instead of a global overlap and thickness, I want to allow the user to get access to any border they want, and set the overlap/thickness directly. This allows for really custom looking borders, if you so desired. 8)

kungfoomasta

05-02-2008 07:26:41

Ok I modified borders to how I suggested. Now that I think about it, Border size should be dictated by the size of its image within the skinset. Although there is no reason to remove the ability to manually set border size, now that its already in. Plus the skinset doesn't define how much to overlap, so that's a plus.

I kept in your setBorderThickness/Overlap functions, but really they're just convenience functions to call the Border functions that I've created. Now you can have custom overlapping that doesn't have to be the same on all sides. (this applies to thickness as well) 8)

thecaptain

05-02-2008 22:41:04

Excellent! Thanks for expanding that border functionality. I'll check out the new code soon. I'll also post a screenshot of that text cursor I'm talking about.