Ok, Spent the morning playing with this. I dont actually think the problem is in the creation of the texture. In fact (using a debugger) I verified that the texture seems to have the correct size.
I have three images to display (I built in a function to display the loaded image at 1x, 2x, and 0.5x).
Here is the 1x image displayed within the CEGUI staticimage window (the staticimage window is 500x500 in size):
here is the 0.5x image displayed within the same window (now the staticimage window is 250x250 in size):
Both of these images look fine to me.
Lastly I will display the image at 2x (now the staticimage should be 1000x1000 in size - notice that the scrollbars for the scollablepane kick in):
Notice that in this last image the circle no longer looks like a cirlce.. its now stretched horizontally. This effect is more pronounced with an even larger image window (I'll see if I can post another image).
Here is the source image:
Here is the code that I use to "zoom", as you can see (within the last method applyImageZoom) all i really do is increase the size of the CEGUI window (the staticimage highlighted in the layout window above), that has the image as its background.
Code: Select all
bool FocusImage::handleZoomFactorChanged(const CEGUI::EventArgs& e)
{
const CEGUI::WindowEventArgs& windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>(e);
CEGUI::Window *w = windowEventArgs.window;
assert(WidgetMaker::getSingleton().isType(*w, WidgetMaker::DIALOGRADIOBUTTON) && "FocusImage::handleZoomFactorChanged: window type mismatch");
CEGUI::RadioButton *rb = static_cast<CEGUI::RadioButton*>(w);
if(!rb->isSelected())
{
return true;
}
float zoom;
try
{
std::string widgetName(w->getName().c_str());
std::string type = getZoomType(widgetName);
if(type.compare(sZoom100RadioButton)==0)
{
zoom = 1.0;
}
else if(type.compare(sZoom200RadioButton)==0)
{
zoom = 2.0;
}
else if(type.compare(sZoom50RadioButton)==0)
{
zoom = 0.5;
}
else if(type.compare(sZoom400RadioButton)==0)
{
zoom = 4.0;
}
else
{
assert(0 && "FocusImage::handleZoomFactorChanged: unexpected zoom type");
}
applyImageZoom(zoom);
}
catch(SVTException se)
{
SVTConsole::getSingleton().printError(se);
}
return true;
}
std::string FocusImage::getZoomType(const std::string& widgetName)
{
std::string::size_type f = widgetName.rfind("/");
assert((f != std::string::npos) && "FocusImage::getZoomType: Failed to extract zoom type");
std::string zoomType = widgetName.substr(f+1);
return zoomType;
}
void FocusImage::applyImageZoom(float zoomFactor)
{
int width = zoomFactor * mImgWindowWidth;
int height = zoomFactor * mImgWindowHeight;
CEGUI::URect a(CEGUI::UDim(0.0, 0), CEGUI::UDim(0.0, 0), CEGUI::UDim(0.0, width), CEGUI::UDim(0.0, height));
getDialogBaseRef().setWidgetArea(sIW, a);
CEGUI::ScrollablePane *sp = static_cast<CEGUI::ScrollablePane *>(getDialogBaseRef().getNamedWidget(sSP));
sp->setContentPaneAutoSized(false);
sp->setContentPaneArea(CEGUI::Rect(0, 0, width, height));
}
Another interesting thing to keep in mind. I added the ability to display the pixel location of the cursor.. its the pair of numbers you see in the lower left of the first three images (tough to see in white on the grey background).
The code that I use to display the pixel location is:
Code: Select all
bool FocusImage::handleImageWindowCursorMove(const CEGUI::EventArgs& e)
{
const CEGUI::MouseEventArgs& mouseEventArgs = static_cast<const CEGUI::MouseEventArgs&>(e);
CEGUI::Window *window = mouseEventArgs.window;
CEGUI::Point mousePos = mouseEventArgs.position;
CEGUI::Point wndPos = CEGUI::CoordConverter::screenToWindow(*window, mousePos);
int wndWidth = window->getWidth().asAbsolute(window->getParentPixelWidth());
int wndHeight = window->getHeight().asAbsolute(window->getParentPixelHeight());
float xScale = (float) mImgWidth / (float) wndWidth;
float yScale = (float) mImgHeight / (float) wndHeight;
CEGUI::Vector2 scale(xScale, yScale);
CEGUI::Point imgPos = wndPos * scale;
std::stringstream ssXCur;
ssXCur << (int)(imgPos.d_x+0.5);
getDialogBaseRef().getNamedWidget(sCursorXPosLabel)->setText(ssXCur.str());
std::stringstream ssYCur;
ssYCur << (int)(imgPos.d_y+0.5);
getDialogBaseRef().getNamedWidget(sCursorYPosLabel)->setText(ssYCur.str());
return true;
}
I compare the pixel location displayed in this fashion to the pixel location drawn when I use a tool such as GIMP to display the image (and to view pixel level detail). The displayed location is correct for the first 2 images, but for the third case (once the scrollable pane kicks in) the pixel location is off. I'm pretty sure this is because the screenToWindow function is not accounting for the staticimage windows positional offset into the scrollablepane, and perhaps that is by design. I know this is a separate issue, but perhaps they are related somehow.
So I think the image squashing arises when the scrollable pane scrollbars kick in. I'm pretty sure it looks reasonable otherwise.
Any ideas for me to try?
Thanks.
---
Edit: I just put in a 4x option as well. As I suggested the stretching just becomes more pronounced. The odd thing is that though with the 2x and the 4x the image window should be 1000x1000 and 2000x2000 respectively it seems to be getting "cropped". I can tell this by printing out the window cursor position (in pixels - i.e. the value returned by CEGUI::CoordConverter::screenToWindow(*window, mousePos)) and I see that the cursor exits the imagewindow at a lower right hand corner of approximately 1020x760 pixels (at 4x), 1000x760 (at 2x). The lower right hand corner should be 2000x2000 (for 4x) and 1000x1000 (for the 2x).
Another indicator that the lower right hand corner is "cropped" relates to the EventMouseLeaves event that I capture. This event fires "prematurely" when I move the mouse down or to the right in the 2x and 4x windows.
I have no idea what is causing this, but I'm sure this is related to the stretching. This is awfully close to the 1024x768 which is the current resolution of my main window; can't imagine that this is mere coincidence. I do think this is the first time I've tried to size a CEGUI window to larger than the actual visible window.. is there something that I should keep in mind when doing this?
----Second Edit----
Ok Now I did exactly what you probably would have suggested. I upped the application resolution to 1920x1200. Now the 0.5x, 1.0x, and 2.0x images all look fine. The 4.0x image, which takes me beyond the 1920x1200, looks stretched... im onto something, but dont know what the fix is.
The key, or threshold, seems to be when the CEGUI::Window (the staticimage) is sized to be larger than the main application window... I'm pretty sure that somewhere under the covers the cegui window is "truncated" or "cropped" to be no larger than the application window. On top of this the truncation seems to be a hard limit applied independently in each direction (x/y). This is where the stretching comes in.