mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-07-21 03:44:05 +00:00
provide incremental update of SpellWindow (Fixes #2411)
When SpellWindow is visible, every 0.5 seconds update the cost/changes for spells/enchanted items shown. Also, check to see if more substantial update of the window is required.
This commit is contained in:
parent
6b6bed520d
commit
52de622e97
4 changed files with 113 additions and 19 deletions
|
@ -10,6 +10,8 @@
|
||||||
namespace MWGui
|
namespace MWGui
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const char* SpellView::sSpellModelIndex = "SpellModelIndex";
|
||||||
|
|
||||||
SpellView::SpellView()
|
SpellView::SpellView()
|
||||||
: mShowCostColumn(true)
|
: mShowCostColumn(true)
|
||||||
, mHighlightSelected(true)
|
, mHighlightSelected(true)
|
||||||
|
@ -113,10 +115,10 @@ namespace MWGui
|
||||||
group.push_back(costChance);
|
group.push_back(costChance);
|
||||||
Gui::SharedStateButton::createButtonGroup(group);
|
Gui::SharedStateButton::createButtonGroup(group);
|
||||||
|
|
||||||
mLines.push_back(std::make_pair(t, costChance));
|
mLines.push_back(boost::make_tuple(t, costChance, true));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mLines.push_back(std::make_pair(t, (MyGUI::Widget*)NULL));
|
mLines.push_back(boost::make_tuple(t, (MyGUI::Widget*)NULL, true));
|
||||||
|
|
||||||
t->setStateSelected(spell.mSelected);
|
t->setStateSelected(spell.mSelected);
|
||||||
}
|
}
|
||||||
|
@ -124,30 +126,85 @@ namespace MWGui
|
||||||
layoutWidgets();
|
layoutWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpellView::incrementalUpdate()
|
||||||
|
{
|
||||||
|
if (!mModel.get())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mModel->update();
|
||||||
|
bool fullUpdateRequired = false;
|
||||||
|
SpellModel::ModelIndex maxSpellIndexFound = -1;
|
||||||
|
for (std::vector< LineInfo >::iterator it = mLines.begin(); it != mLines.end(); ++it)
|
||||||
|
{
|
||||||
|
// only update the lines that are "updateable"
|
||||||
|
if (it->get<2>())
|
||||||
|
{
|
||||||
|
Gui::SharedStateButton* nameButton = reinterpret_cast<Gui::SharedStateButton*>(it->get<0>());
|
||||||
|
|
||||||
|
// match model against line
|
||||||
|
// if don't match, then major change has happened, so do a full update
|
||||||
|
SpellModel::ModelIndex spellIndex = getSpellModelIndex(nameButton);
|
||||||
|
if (mModel->getItemCount() <= static_cast<unsigned>(spellIndex))
|
||||||
|
{
|
||||||
|
fullUpdateRequired = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// more checking for major change.
|
||||||
|
const Spell& spell = mModel->getItem(spellIndex);
|
||||||
|
if (nameButton->getCaption() != spell.mName)
|
||||||
|
{
|
||||||
|
fullUpdateRequired = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxSpellIndexFound = spellIndex;
|
||||||
|
Gui::SharedStateButton* costButton = reinterpret_cast<Gui::SharedStateButton*>(it->get<1>());
|
||||||
|
if ((costButton != NULL) && (costButton->getCaption() != spell.mCostColumn))
|
||||||
|
{
|
||||||
|
costButton->setCaption(spell.mCostColumn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// special case, look for spells added to model that are beyond last updatable item
|
||||||
|
SpellModel::ModelIndex topSpellIndex = mModel->getItemCount() - 1;
|
||||||
|
if (fullUpdateRequired ||
|
||||||
|
((0 <= topSpellIndex) && (maxSpellIndexFound < topSpellIndex)))
|
||||||
|
{
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpellView::layoutWidgets()
|
void SpellView::layoutWidgets()
|
||||||
{
|
{
|
||||||
int height = 0;
|
int height = 0;
|
||||||
for (std::vector< std::pair<MyGUI::Widget*, MyGUI::Widget*> >::iterator it = mLines.begin();
|
for (std::vector< LineInfo >::iterator it = mLines.begin();
|
||||||
it != mLines.end(); ++it)
|
it != mLines.end(); ++it)
|
||||||
{
|
{
|
||||||
height += (it->first)->getHeight();
|
height += (it->get<0>())->getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scrollVisible = height > mScrollView->getHeight();
|
bool scrollVisible = height > mScrollView->getHeight();
|
||||||
int width = mScrollView->getWidth() - (scrollVisible ? 18 : 0);
|
int width = mScrollView->getWidth() - (scrollVisible ? 18 : 0);
|
||||||
|
|
||||||
height = 0;
|
height = 0;
|
||||||
for (std::vector< std::pair<MyGUI::Widget*, MyGUI::Widget*> >::iterator it = mLines.begin();
|
for (std::vector< LineInfo >::iterator it = mLines.begin();
|
||||||
it != mLines.end(); ++it)
|
it != mLines.end(); ++it)
|
||||||
{
|
{
|
||||||
int lineHeight = (it->first)->getHeight();
|
int lineHeight = (it->get<0>())->getHeight();
|
||||||
(it->first)->setCoord(4, height, width-8, lineHeight);
|
(it->get<0>())->setCoord(4, height, width - 8, lineHeight);
|
||||||
if (it->second)
|
if (it->get<1>())
|
||||||
{
|
{
|
||||||
(it->second)->setCoord(4, height, width-8, lineHeight);
|
(it->get<1>())->setCoord(4, height, width - 8, lineHeight);
|
||||||
MyGUI::TextBox* second = (it->second)->castType<MyGUI::TextBox>(false);
|
MyGUI::TextBox* second = (it->get<1>())->castType<MyGUI::TextBox>(false);
|
||||||
if (second)
|
if (second)
|
||||||
(it->first)->setSize(width-8-second->getTextSize().width, lineHeight);
|
(it->get<0>())->setSize(width - 8 - second->getTextSize().width, lineHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
height += lineHeight;
|
height += lineHeight;
|
||||||
|
@ -167,7 +224,7 @@ namespace MWGui
|
||||||
MyGUI::IntCoord(0, 0, mScrollView->getWidth(), 18),
|
MyGUI::IntCoord(0, 0, mScrollView->getWidth(), 18),
|
||||||
MyGUI::Align::Left | MyGUI::Align::Top);
|
MyGUI::Align::Left | MyGUI::Align::Top);
|
||||||
separator->setNeedMouseFocus(false);
|
separator->setNeedMouseFocus(false);
|
||||||
mLines.push_back(std::make_pair(separator, (MyGUI::Widget*)NULL));
|
mLines.push_back(boost::make_tuple(separator, (MyGUI::Widget*)NULL, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::TextBox* groupWidget = mScrollView->createWidget<MyGUI::TextBox>("SandBrightText",
|
MyGUI::TextBox* groupWidget = mScrollView->createWidget<MyGUI::TextBox>("SandBrightText",
|
||||||
|
@ -186,10 +243,10 @@ namespace MWGui
|
||||||
groupWidget2->setTextAlign(MyGUI::Align::Right);
|
groupWidget2->setTextAlign(MyGUI::Align::Right);
|
||||||
groupWidget2->setNeedMouseFocus(false);
|
groupWidget2->setNeedMouseFocus(false);
|
||||||
|
|
||||||
mLines.push_back(std::make_pair(groupWidget, groupWidget2));
|
mLines.push_back(boost::make_tuple(groupWidget, groupWidget2, false));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mLines.push_back(std::make_pair(groupWidget, (MyGUI::Widget*)NULL));
|
mLines.push_back(boost::make_tuple(groupWidget, (MyGUI::Widget*)NULL, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -222,16 +279,20 @@ namespace MWGui
|
||||||
widget->setUserString("Spell", spell.mId);
|
widget->setUserString("Spell", spell.mId);
|
||||||
}
|
}
|
||||||
|
|
||||||
widget->setUserString("SpellModelIndex", MyGUI::utility::toString(index));
|
widget->setUserString(sSpellModelIndex, MyGUI::utility::toString(index));
|
||||||
|
|
||||||
widget->eventMouseWheel += MyGUI::newDelegate(this, &SpellView::onMouseWheel);
|
widget->eventMouseWheel += MyGUI::newDelegate(this, &SpellView::onMouseWheel);
|
||||||
widget->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellView::onSpellSelected);
|
widget->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellView::onSpellSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpellModel::ModelIndex SpellView::getSpellModelIndex(MyGUI::Widget* widget)
|
||||||
|
{
|
||||||
|
return MyGUI::utility::parseInt(widget->getUserString(sSpellModelIndex));
|
||||||
|
}
|
||||||
|
|
||||||
void SpellView::onSpellSelected(MyGUI::Widget* _sender)
|
void SpellView::onSpellSelected(MyGUI::Widget* _sender)
|
||||||
{
|
{
|
||||||
SpellModel::ModelIndex i = MyGUI::utility::parseInt(_sender->getUserString("SpellModelIndex"));
|
eventSpellClicked(getSpellModelIndex(_sender));
|
||||||
eventSpellClicked(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpellView::onMouseWheel(MyGUI::Widget* _sender, int _rel)
|
void SpellView::onMouseWheel(MyGUI::Widget* _sender, int _rel)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef OPENMW_GUI_SPELLVIEW_H
|
#ifndef OPENMW_GUI_SPELLVIEW_H
|
||||||
#define OPENMW_GUI_SPELLVIEW_H
|
#define OPENMW_GUI_SPELLVIEW_H
|
||||||
|
|
||||||
|
#include <boost/tuple/tuple.hpp>
|
||||||
|
|
||||||
#include <MyGUI_Widget.h>
|
#include <MyGUI_Widget.h>
|
||||||
|
|
||||||
#include "spellmodel.hpp"
|
#include "spellmodel.hpp"
|
||||||
|
@ -37,6 +39,9 @@ namespace MWGui
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
/// simplified update called each frame
|
||||||
|
void incrementalUpdate();
|
||||||
|
|
||||||
typedef MyGUI::delegates::CMultiDelegate1<SpellModel::ModelIndex> EventHandle_ModelIndex;
|
typedef MyGUI::delegates::CMultiDelegate1<SpellModel::ModelIndex> EventHandle_ModelIndex;
|
||||||
/// Fired when a spell was clicked
|
/// Fired when a spell was clicked
|
||||||
EventHandle_ModelIndex eventSpellClicked;
|
EventHandle_ModelIndex eventSpellClicked;
|
||||||
|
@ -51,7 +56,13 @@ namespace MWGui
|
||||||
|
|
||||||
std::auto_ptr<SpellModel> mModel;
|
std::auto_ptr<SpellModel> mModel;
|
||||||
|
|
||||||
std::vector< std::pair<MyGUI::Widget*, MyGUI::Widget*> > mLines;
|
/// tracks an item in the spell view
|
||||||
|
/// element<0> is the left column GUI object (usually holds the name)
|
||||||
|
/// element<1> is the right column (charge or cost info)
|
||||||
|
/// element<2> is if line needs to be checked during incremental update
|
||||||
|
typedef boost::tuple<MyGUI::Widget*, MyGUI::Widget*, bool> LineInfo;
|
||||||
|
|
||||||
|
std::vector< LineInfo > mLines;
|
||||||
|
|
||||||
bool mShowCostColumn;
|
bool mShowCostColumn;
|
||||||
bool mHighlightSelected;
|
bool mHighlightSelected;
|
||||||
|
@ -62,6 +73,10 @@ namespace MWGui
|
||||||
|
|
||||||
void onSpellSelected(MyGUI::Widget* _sender);
|
void onSpellSelected(MyGUI::Widget* _sender);
|
||||||
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
|
||||||
|
|
||||||
|
SpellModel::ModelIndex getSpellModelIndex(MyGUI::Widget* _sender);
|
||||||
|
|
||||||
|
static const char* sSpellModelIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ namespace MWGui
|
||||||
: WindowPinnableBase("openmw_spell_window.layout")
|
: WindowPinnableBase("openmw_spell_window.layout")
|
||||||
, NoDrop(drag, mMainWidget)
|
, NoDrop(drag, mMainWidget)
|
||||||
, mSpellView(NULL)
|
, mSpellView(NULL)
|
||||||
|
, mUpdateTimer(0.0f)
|
||||||
{
|
{
|
||||||
mSpellIcons = new SpellIcons();
|
mSpellIcons = new SpellIcons();
|
||||||
|
|
||||||
|
@ -60,6 +61,20 @@ namespace MWGui
|
||||||
updateSpells();
|
updateSpells();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpellWindow::onFrame(float dt)
|
||||||
|
{
|
||||||
|
if (mMainWidget->getVisible())
|
||||||
|
{
|
||||||
|
NoDrop::onFrame(dt);
|
||||||
|
mUpdateTimer += dt;
|
||||||
|
if (0.5f < mUpdateTimer)
|
||||||
|
{
|
||||||
|
mUpdateTimer = 0;
|
||||||
|
mSpellView->incrementalUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SpellWindow::updateSpells()
|
void SpellWindow::updateSpells()
|
||||||
{
|
{
|
||||||
mSpellIcons->updateWidgets(mEffectBox, false);
|
mSpellIcons->updateWidgets(mEffectBox, false);
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace MWGui
|
||||||
|
|
||||||
void updateSpells();
|
void updateSpells();
|
||||||
|
|
||||||
void onFrame(float dt) { NoDrop::onFrame(dt); }
|
void onFrame(float dt);
|
||||||
|
|
||||||
/// Cycle to next/previous spell
|
/// Cycle to next/previous spell
|
||||||
void cycle(bool next);
|
void cycle(bool next);
|
||||||
|
@ -41,6 +41,9 @@ namespace MWGui
|
||||||
|
|
||||||
SpellView* mSpellView;
|
SpellView* mSpellView;
|
||||||
SpellIcons* mSpellIcons;
|
SpellIcons* mSpellIcons;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float mUpdateTimer;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue