SFGUI rendering issue c++ - c++

I'm making a server menu system however when I remove all the items from the sfgui system and move on to another game state the labels from the previous game state are visible under a circumstance which I will explain in a minute, first let me show you the issue.
Server Menu:
Here you can see the issue:
The code for removal is as follows.
void S_ServerMenu::Exit() {
ServerSelectWindow->Show(false);
desktop.RemoveAll();
desktop.Refresh();
}
However this issue only occurs on refresh of servers here is the code for refresh.
void S_ServerMenu::RefreshServers() {
Document d;
d.Parse<0>(LoadInServers().c_str());
servers = ServerParser(d);
ServerListTable->RemoveAll();
ServerListTable->RefreshAll();
for(int i = 0; i < servers.size(); i++) {
auto label = sfg::Label::Create();
label->SetText(servers[i].Name);
MenuItem utm;
utm.lbl = label;
utm.index = i;
utm.owner = this;
label->SetAlignment(sf::Vector2f(0, 0));
label->FontSize = 16;
label->SetParent(ServerListTable);
label->cont = ServerSelectWindowContainer;
ServerListTable->Attach(label, sf::Rect<sf::Uint32>(1, i, 1, 1), sfg::Table::FILL | sfg::Table::EXPAND);
label->GetSignal(sfg::Label::OnLeftClick).Connect(std::bind(&MenuItem::Clicked, utm));
}
ServerSelectWindow->RefreshAll();
}
Do any of you know how to solve this if so that would be great.

I fixed this by creating a separate Desktop for each screen.

Related

Update/modify QListWidgetItem

I would like to use QWidgetList to create a list where I can add and delete items automatically, without the user having to interact with the graphical interface. I have this done, but I can't update/modify the text I put in the item when I created it. I have created four items like this:
for (int i = 0; i < 4; i++)
{
QListWidgetItem *lwi = new QListWidgetItem();
lwi->setSizeHint(QSize(200, 20));
lwi->setTextAlignment(Qt::AlignCenter);
lwi->setText(QString("Obstacle ") + QString::number(i));
ui_.list->addItem(lwi);
}
And I have seen that I can modify the text like this:
ui_.list->item(0)->setText(QString::number(updateItem, 'f', 2));
Where updateitem is constantly changing its value.
The problem is that it seems that although the text is modified, but it is updated on screen only when I interact with the window.
Is there any way to update it directly without having to interact? For example, if I do the same with a Label it works correctly and the Label changes its text constantly without the need to interact with it.
I am working with the rqt library for ROS, to develop a plugin created with Qt. Although I believe my problem is directly related to Qt and not to ROS.
Thank you.
EDIT1: I added ui_.list_movil->update() but is not working for me.
void MyPlugin::update_list()
{
if (flagFirstItem == false)
{
for (int i = 0; i < 4; i++)
{
QListWidgetItem *lwi = new QListWidgetItem();
lwi->setSizeHint(QSize(200, 20));
lwi->setTextAlignment(Qt::AlignCenter);
lwi->setText(QString("Obstacle ") + QString::number(i));
ui_.list_movil->addItem(lwi);
}
flagFirstItem = true;
}
if (flagFirstItem == true)
{
for (int i = 0; i < ui_.list_movil->count(); ++i)
{
ui_.list_movil->item(i)->setText(QString::number(updateItem, 'f', 2));
ui_.list_movil->update();
}
}
}
I am adding four items just one time and after that I am trying to modify them. It is not working fine for me because I must click on an item to see the changed text. If I am doing it right, maybe it should be an error with rqt library.
By the way, I am modifying labels like that:
void MyPlugin::imuEuler_callback(const sensor_msgs::Imu msg)
{
if ((ros::Time::now().toSec() - updateTimeImuEuler) >= updateTime)
{
ui_.label_rollValue->setText(QString::number(msg.orientation.x, 'f', 2));
ui_.label_pitchValue->setText(QString::number(msg.orientation.y, 'f', 2));
ui_.label_yawValue->setText(QString::number(msg.orientation.z, 'f', 2));
updateTimeImuEuler = ros::Time::now().toSec();
}
}
And they are all working fine, I dont need to click on them to see the changed text.

How to persist document tab order when using EnableMDITabbedGroups in C++ MFC

VS2010 with an MDI document layout using tabs along the top to switch between documents. Each document is a "live" view into a database, where the persistent data per document is a group of configuration settings.
We would like to allow the user to rearrange the tabs (this functionality is built in), but need to persist this new order. Right now it appears the document z-order is not affected by moving the tabs around. when closing the app, the documents close in the order they were opened so this is not helpful in determining the final tab order on close.
We are using the EnableMDITabbedGroups(TRUE, mdiTabParams) with m_bEnableTabSwap = TRUE which is the default.
Thanks! Ended up with the following solution in the MainFrame::OnClose() method.
Note that this code example uses two custom classes of 1) CSpectraAnalysisUtilityView which inherits from CView and 2) CReviewDataFolder which is our object that we needed to update the recent Tab Order.
This code solution also implements the GetMDITabGroups in case there are multiple group windows open.
void CMainFrame::OnClose()
{
iReviewDataFolderOrder = 1;
const CObList& tabGroups =m_wndClientArea.GetMDITabGroups();
if (0 < tabGroups.GetCount())
{
POSITION pos = tabGroups.GetHeadPosition();
CMFCTabCtrl* pCrtTabCtrl;
while(pos != NULL)
{
pCrtTabCtrl=DYNAMIC_DOWNCAST(CMFCTabCtrl, tabGroups.GetNext(pos));
int count = pCrtTabCtrl->GetTabsNum();
for(int i = 0; i < count; i++)
{
CWnd* pWnd = pCrtTabCtrl->GetTabWndNoWrapper(i);
CMDIChildWnd *pChild = ((CMDIChildWnd*)(pWnd));
if (pChild)
{
CView *pView = pChild->GetActiveView();
if (pView)
{
if (pView->IsKindOf(RUNTIME_CLASS(CSpectraAnalysisUtilityView)))
{
CSpectraAnalysisUtilityView* specUtilView;
specUtilView = (CSpectraAnalysisUtilityView*)pView;
CReviewDataFolder* pDataFolder = specUtilView->GetSpecReviewDataFolder();
if(pDataFolder)
{
pDataFolder->SetRecentOrder(iReviewDataFolderOrder);
iReviewDataFolderOrder++;
}
}
}
}
}
}
}
CMDIFrameWnd::OnClose();
}
Upon destruction of the outer main frame (OnDestroy) you can access the the CMFCTabCtrl members and can loop over each tab and determine the current sequence stored in the tab. GetTabWnd will allow you to access each tab by its index.
To access the tab control use CMDIClientAreaWnd::GetMDITab.

(Virtual) ListView items get wrong content when hovering over them, from bottom to top

I use C++ Builder 2009 and have implemented a Listview virtually.
Recently I learned of an issue that (so far) only happens for 3 people out of thousands. (Obviously there must be more instances, but they remain unreported so far).
What happens is that when the user hovers over the items in the ListView control, from bottom to top, the items in the list change.
Since the control is implemented virtually the software provides the information via an event and for 'a' reason the software gets the wrong index to work with when hovering from bottom to top.
See this little video to understand the behaviour better:
https://www.youtube.com/watch?v=jNZkaBH24PY
I have been searching for a reason, on and off, for some time, hampered by the fact that I cannot repeat this problem myself, so I needed to send special builds to 1 of the 3 willing to help. And I was finally able to pinpoint it to the use of Overlay icons !
I assign an icon to the items in the list by asking Windows what icon is relevant via SHGetFileInfo
The event:
void __fastcall TFinder::ListViewData(TObject *Sender, TListItem *Item)
{
DListView->OnData(Item, DirInListView->Object(Item->Index)) ;
}
Code called by the event:
HANDLE ObjectDisplayInListView::OnData (TListItem *ListItem, DataObject *Object)
{
ListItem->Data = (void*) Object ;
ListItem->Caption = String(Object->DisplayName().c_str()) ;
if (!SystemIconsSet)
{
ListItem->ImageIndex = Object->Icon() ;
ListItem->OverlayIndex = Object->IconOverlay() ;
}
else
{
int Icon = SystemIcon(Object) ;
ListItem->ImageIndex = (Icon & 0x00FFFFFF) ;
ListItem->OverlayIndex = (Icon >> 24) - 1 ;
}
ListItem->Cut = Object->IconGreyed() ;
ListItem->StateIndex = Object->IconState() ;
return (HANDLE) ListItem ;
}
// The SystemIcon() routine:
int ObjectDisplayInListView::SystemIcon (DataObject *Object)
{
// SHFILEINFO info ; The class declared one will do !
info.hIcon = NULL ; // Just making sure
DWORD Res = SHGetFileInfoW( Object->DisplayName().c_str(),
FILE_ATTRIBUTE_NORMAL,
&info,
sizeof(SHFILEINFO) ,
SHGFI_ICON |
SHGFI_USEFILEATTRIBUTES |
SHGFI_OVERLAYINDEX
) ;
DestroyIcon(info.hIcon) ;
return info.iIcon ;
}
The subclass code (which can be removed completely and the problem still exists !!)
void __fastcall TFinder::LVNewWindowProc(Messages::TMessage &Msg)
{
if( LVOldWindowProc ) LVOldWindowProc( Msg );
if (Msg.Msg == WM_NOTIFY) // Sort arrows
{
// Not relevant for this Q but added since it is in my code
switch(((LPNMHDR)Msg.LParam)->code)
{
case HDN_ENDTRACKA:
case HDN_ENDTRACKW:
case HDN_ITEMCHANGEDA:
case HDN_ITEMCHANGEDW:
{
if(((LPNMHDR)Msg.LParam)->hwndFrom == ListView_GetHeader(ListView->Handle))
{
if (ObjInListView && dynamic_cast<FileDirObject*>(ObjInListView) && ListView->Items->Count)
{
SetSortArrow(SortingTypeToDesignColumn(UISortingType), UISortingDirection) ; // Show the arrow based on what sorting was used
}
}
}
break;
}
}
else if (Msg.Msg == CN_NOTIFY && Platform > OS_PLATF_WINXP)
{
if (reinterpret_cast<LPNMHDR>(Msg.LParam)->code == LVN_GETDISPINFOW)
{
LV_ITEM &item = reinterpret_cast<LV_DISPINFO*>(Msg.LParam)->item ;
int OverlayIndex = -1 ;
TListItem *ListItem = ListView->Items->Item[item.iItem] ;
if (ListItem) OverlayIndex = ListItem->OverlayIndex ;
if (OverlayIndex >= 0)
{
item.mask |= LVIF_STATE ;
item.state |= INDEXTOOVERLAYMASK(OverlayIndex + 1) ;
item.stateMask |= LVIS_OVERLAYMASK ;
}
}
}
}
I implemented this based on an older question, asked here as well: Can't get Windows Overlay icons to work in TListView
To be more precise, this function has been working great for me for over 10 years, but about a year ago I added SHGFI_OVERLAYINDEX as well
The issue, as explained and as can be seen in the video, disappears entirely when I simply and only remove SHGFI_OVERLAYINDEX from the function call.
For whatever reason also asking for the overlay icon, causes the weird behaviour.
Even when I completely disable the CN_NOTIFY message subclassing that goes along with this functionality (see: Can't get Windows Overlay icons to work in TListView ) but call SHGetFileInfo() with SHGFI_OVERLAYINDEX, the problem happens !
Does anybody have an idea what this could be ?
A solution could be to not ask for the overlay icon on these problematic systems, but then I need to find a way to actually detect that the problem is going to happen (or is happening) somehow.

RTS style of drag and select system

I'm trying to make a click and drag selection system in c++ and SDL2 like the kind used in real time strategy games. You click with the mouse and drag it over what you want to select. How can I go about making it?
Edit: I know how to handle the mouse inputs. I have used a Rect structure to track the size of the selection zone. However while the zone draws correctly, the objects inside the zone don't react at all. However individually clicking on them works fine every time.
I guess my question is what is the best way to check for a group selection vs individual object selection?
You have to check what's inside the rect you are gonna drag (the test depends on the shapes that are included) and the drag those shapes aswell
I can describe how i have implemented this.
In the event handling routine, do something like the code below. I think the method names explain quite well what's happening and how i'm thinking (this is copied from my hobby-hack-RTS-engine which is based on SDL2):
case SDL_MOUSEBUTTONDOWN:
{
// Calculate index, x and y for the tile that was clicked in the map.
int iClick = m_Map.getTileIndex(event.button.x, event.button.y);
if(iClick >= 0)
{
int xClick = m_Map.getTileX(iClick);
int yClick = m_Map.getTileY(iClick);
if((int)event.button.button == 1)
{
// Unmark all MO..
for(std::list<MGMovingObject>::iterator it = m_MO.begin(); it != m_MO.end(); it++)
{
it->unMark();
}
activateFraming(event.button.x, event.button.y);
}
else
{
...
}
}
break;
}
case SDL_MOUSEBUTTONUP:
{
if((int)event.button.button == 1)
{
int endClickX = m_Map.getTileX(m_Map.getTileIndex(getFrameEndX(), getFrameEndY()));
int endClickY = m_Map.getTileY(m_Map.getTileIndex(getFrameEndX(), getFrameEndY()));
int startClickX = m_Map.getTileX(m_Map.getTileIndex(getFrameStartX(), getFrameStartY()));
int startClickY = m_Map.getTileY(m_Map.getTileIndex(getFrameStartX(), getFrameStartY()));
if(endClickX > 0 && endClickY > 0 && startClickX > 0 && startClickY > 0)
{
for(int x = std::min(startClickX, endClickX); x <= std::max(startClickX, endClickX); x++)
{
for(int y = std::min(startClickY, endClickY); y <= std::max(startClickY, endClickY); y++)
{
for(std::list<MGMovingObject>::iterator it = m_MO.begin(); it != m_MO.end(); it++)
{
if(it->getTileX() == x && it->getTileY() == y)
{
it->mark();
}
}
}
}
}
deactivateFraming();
}
else
{
...
}
break;
}
My selectable objects are stored as std::list<MGMovingObject> in m_MO.
The idea is that i save tile coordinates of the start of the selection frame and the end of the selection frame. I then iterate over the selectable objects and detect the ones inside the selection frame. I select these (mark()) and when i iterate over the objsects at a later stage, say during rendering, i can read out if they are selected (isMarked()).
If you want to steal code or ideas, here is the actual source file i copied it from: https://github.com/qmargyl/mgframework/blob/master/src/mgframework/mgframework.cpp

Animation using .png files cocos2dx

I have 34 .png image files for 9 different scenarios. Each time the user picks 1 of those 9 scenarios and according to that I generate animation using the following
std::string name;
MixingScreen::animation = CCAnimation::create();
// load image file from local file system to CCSpriteFrame, then add into CCAnimation
for (int i = 0; i < 34; i++)
{
std::stringstream st,ii;
st << Constants::flav;
if (i<10)
{
ii<<i;
name="screen/screen02/fx/sugar/0" + st.str()+"/a_0000"+ii.str()+".png";
}
else
{
ii<<i;
name="screen/screen02/fx/sugar/0" + st.str()+"/a_000"+ii.str()+".png";
}
//sprintf(szImageFileName, "Images/grossini_dance_%02d.png", i);
MixingScreen::animation->addSpriteFrameWithFileName(name.c_str());
}
MixingScreen::animation->setDelayPerUnit(5.0f / 34.0f);
action = CCAnimate::create(MixingScreen::animation);
CCCallFunc *done = CCCallFunc::create(this, callfunc_selector(MixingScreen::doneMixing));
CCSequence *readySequence = CCSequence::create(action,done,NULL);
particles->runAction(readySequence);
The problem I am facing is that when this animation runs, there is a time lag(everything stops for few seconds) and then the animation starts. Any solution?
Every time you call animation->addSpriteFrameWithFileName() a new "CCSpriteFrame" is created.
Instead you should first add the sprite frames to CCSpriteFrameCache and use
animation->addSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameWithName(""))
Ps: these function names might be a little different but i hope you get the idea.