SFML - Center view after window resize - c++

I'm trying to make a simple application using c++ and SFML. I would like for the application to work at any resolution - windowed or fullscreen.
The closest thing to a solution I've found in documentation is this simple snippet of code.
if (event.type == sf::Event::Resized)
{
// update the view to the new size of the window
sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height);
window.setView(sf::View(visibleArea));
}
This creates an effect that looks like this http://i.imgur.com/RvCOuKi.png.
This is a start - but it's not exactly what I'm looking for. When I resize the window, the "original" viewing space is in the top left, with the newly visible objects all below or to the right of the original rectangle.
I think this method of resizing is ugly. When I put something at the center of the screen at one resolution, it should stay in the center even at another resolution. How do I center the view in such a way that this occurs?
A great example of this is minecraft. In minecraft, when you resize the window, the "original" viewport is in the very center and newly visible objects appear around the edges. How can I recreate this in SFML?

Just use another constructor and pass the center of the current view:
if (event.type == sf::Event::Resized)
{
// update the view to the new size of the window and keep the center
window.setView(sf::View(window.getView().getCenter(), sf::Vector2f((float)event.size.width, (float)event.size.height)));
}

Related

How to clip the corner rectangle created by two scrollbar controls

Let's say you have a resizable window with child scrollbar controls, and the scrollbars come and go depending on whether the window contents are large enough to require scrolling.
When both scrollbars are present, a small rectangle is effectively created in the bottom right corner of the window, at their intersection. Is there a clean strategy for clipping that rectangle when drawing on the window, so that you don't paint on it?
I guess my current approach is to obtain the rectangles for each scrollbar, and if those rectangles are not null, then use the rectangles' locations to determine the rectangle that we want to clip. And then call ExcludeClipRect for that rectangle. I guess a similar approach could be used, except with GetSystemMetrics(SM_CXVSCROLL) and GetSystemMetrics(SM_CYVSCROLL) to get the rectangle dimensions.
But is there a more accepted way of doing this, perhaps using some helpful clipping API functions? Thank you for any input.

C++ How do I stop resizing Sf :: Text on screen resize ( but at the same position)

Im making map editor and i want to add resizing window but when i resize window my gui elements are resizing too how can i stop that,
i stop resizing map surface with set new size of map view but i cant do it with gui elements because it changes positions of gui elements
if(events.type == sf::Event::Resized)
{
m_defaultViewSize.x = events.size.width;
m_defaultViewSize.y = events.size.height;
m_mapView.setSize(m_defaultViewSize);
m_mapView.setSize(m_mapView.getSize() / m_zoomScale);// Apply the zoom level
m_stateData->window->setView(m_mapView);
}
sorry for my poor english
If you currently DO NOT have a GUI view your rendering code might look something like:
m_stateData->window->clear();
m_stateData->window->setView(m_mapView);
m_stateData->window->draw(m_map);
m_stateData->window->draw(m_gui);
m_stateData->window->display();
This is drawing the GUI on the same view as the map, so if the map view changes so does the GUI. This might be fine if the map does not change, but if you are planning on moving, scaling or rotating the map it would be best to create a GUI view.
Now rendering might look like this:
m_stateData->window->clear();
m_stateData->window->setView(m_mapView);
m_stateData->window->draw(m_map);
m_stateData->window->setView(m_guiView);
m_stateData->window->draw(m_gui);
m_stateData->window->display();
This is fine until we resize the window.
After resizing the window the view stays the same even though the viewport has changed size. If the window has been made larger twice horizontally but not vertically, the GUI is going to be stretched horizontally.
I personally do not like stretching, I do not think it looks nice. We should resize the view.
You could resize the view the same way you resized the map view.
m_guiView.setSize(m_defaultViewSize);
m_guiView.setSize(m_guiView.getSize() / m_zoomScale);
This will stop resizing the GUI elements, but their position will be the same as if we had not resized the window. You might want to reposition the GUI elements. One simple way of doing this is by storing the GUI elements position as a ratio along the screen horizontally and vertically. So, the top left might be (-0.5, -0.5) and the bottom right might be (0.5, 0.5).
This might look like (with a view centered on (0, 0)):
// get ratio position of gui element
sf::Vector2f ratio_position = {
(m_gui.getPosition().x) / m_guiView.getSize().x,
(m_gui.getPosition().y) / m_guiView.getSize().y
};
// resize view
m_guiView.setSize(m_defaultViewSize);
m_guiView.setSize(m_guiView.getSize() / m_zoomScale);
// set position of gui element
m_gui.setPosition(
(ratio_position.x)* m_guiView.getSize().x,
(ratio_position.y) * m_guiView.getSize().y
);
You could also have this be functionality of a class.
You can use things other than ratios as well.
You could make GUI elements relative to corners of the screen, or other ratios. So You could have Health bar, Stamina bar, Mana bar all relative to the top left of the view. This would just be calculating the top left position (view center - half of the view size) and then adding on some relative position (for example, (0, 0) for health bar, (0, 32) for stamina bar etc).
I suggest you look at how other Game Engines handle GUI. Unity uses Anchor Points. Godot uses containers. Try and recreate a system you like.

MFC getting mouse pointer coordinate problem

I'm trying to get coordinate of the Rect (Picture control) but It's a bit glitchy.
So here're the process that I've done.
1st. made a picture control
2nd. I've earned WindowRect through GetWindowRect
// myDialogDlg.cpp
CRect m_rcDisp // (is acually in myDialogDlg.h)
BOOL myDialogDlg::OnInitDialog()
{
// IDC_PIC1 == ID of the (static) picture control
GetDlgItem(IDC_PIC1)->GetWindowRect(m_rcDisp);
...
}
3rd. I've made OnMouseMove event, and used PtInRect to make some action while mouse pointer is inside the picture control.
// myDialogDlg.cpp
void myDialogDlg::OnMouseMove(UINT nFlags, CPoint point)
{
CString debug;
{
if (m_rcDisp.PtInRect(point))
{
// my event starts
OutputDebugString(_T("here"));
if (m_CamTrig == CAMERA_TRIG_SW)
{
m_CurSor.x = point.x;
m_CurSor.y = point.y;
InvalidateRect(m_rcDisp, NULL);
}
// my event ends
}
}
CDialogEx::OnMouseMove(nFlags, point);
}
and... where actually PtInRect works is about here inside the red box
:( Hope I get the best answer.
thx!
GetWindowRect returns the window dimensions in screen coordinates. WM_MOUSEMOVE reports the mouse position in client coordinates. ScreenToClient1 can be used to translate from screen coordinates to client coordinates, making the picture control's window rectangle coordinates and hit testing function agree on a common origin.
This needs to be done whenever the picture control is moved relative to its parent dialog. If the picture control is never moved you only need to adjust the rectangle once.
This answer links to the Windows API documentation, since it's generally more informative and better maintained than the respective MFC entries. You can call either one from MFC code, though it's usually more convenient to just call into the CWnd members.
1 Use MapWindowPoints instead if you plan on supporting RTL and LTR layouts. See Window Layout and Mirroring for guidance.

MFC selection of a user drawn rectangle on picture control

I'm trying to create an interface that allows the user to draw a rectangle over a picture control box. I have a picture control class and used CRectTracker to allow the user to draw a rectangle. I want the user to also be able to select a previously drawn rectangle but I don't know how to handle the selection of a drawn rectangle.
I want to be able to select the rectangle and also add resize handlers on it.
Here is my code for drawing the rect.
void PictureCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// If mouse click is outside of rectangle
if(m_drawRect.m_tracker.HitTest(point) < 0 ) {
if(m_drawRect.m_tracker.TrackRubberBand(this, point, TRUE)) {
CDC* pDC = GetDC();
m_drawRect.m_tracker.m_nStyle &= CRectTracker::resizeInside;
// Paint transparent rectangle
pDC->SelectStockObject(NULL_BRUSH);
pDC->Rectangle(m_drawRect.m_tracker.m_rect);
ReleaseDC(pDC);
}
}
CStatic::OnLButtonDown(nFlags, point);
}
Any help would be appreciated. Thank you.
You will need to store the coordinates of the rectangle in your class (also save/load) and perform a HitTest during mouse-down.
To implement the resize handles, you will need a boolean to denote that the rectangle is selected (set boolean to FALSE if the click is not on the rectangle) and draw grab handles during paint if the boolean is TRUE; if the mouse moves over the grab handles, change the mouse-cursor, perform the resize during mouse-down and mouse-up in this case.
It's all quite complicated and gets more so if you have more than just one rectangle!
Here is a DrawCLI MSDN example which does all of that with rectangles, rounded rectangles, ellipses, lines and polylines plus support for OLE -- maybe this will help, it's probably easier to delete classes/functions from DrawCLI before it's in a state to merge with your application...

Reposition graphics items on window resize

Ok, I basically have randomly placed graphics items on a graphics scene. I open a window and display these items. When I resize the window, I want this items to stay the same size but reposition proportionally to the window size. How I did this was I subclassed the graphics view and then when there was a resize event, it sent the resize object to my graphicsscene object. I was then able to do something like this:
double scaleX = double(event->size().width())/double(event->oldSize().width());
double scaleY = double(event->size().height())/double(event->oldSize().height());
Then I used these values to do this:
derivedPointItem->setPos( derivedPointItem->pos().x() * scaleX,
derivedPointItem->pos().y() * scaleY );
This works ok, but it's not quite right if I resize the window really small or large. I think the problem is that the graphicsscene rect and the graphics view rect are not the same or something. Furthermore, I have a background which resizes to window size:
void roiwindow::drawBackground( QPainter* painter, const QRectF& rect )
{
this->setSceneRect(0,0,rect.width(),rect.height());
painter->save();
painter->drawImage(rect, *refimage);
painter->restore();
}
This is something I need in the program I'm writing. Also, it allows me to see if the resizing works. I basically can set the background to be a polygon, then place points on the edges of the polygon. When I resize the image to be very large or small the points are no longer on the vertices of the polygon althought they are somewhat close. Anyone know a better way to do this or a way to fix it? Thanks.
EDIT: Here's the project I'm working on:
dropbox.com/s/myxi8kvdl7x9ye2/ncorr.tar.gz
This method actually works (although I'm not sure if it's the best method to use...). Anyway, it ended up being a coding error due to the setPos() function. The setPos() function in my program worked by specifying the coordinates of the top left corner of the image rather than the center. This ended up causing some errors.