Merge branch 'master' into tables

deque
Marc Zinnschlag 10 years ago
commit f4c9897bbd

@ -607,8 +607,8 @@ if (WIN32)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)\" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(ProjectDir)$(Configuration)\" )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(ProjectDir)$(Configuration)" )
endforeach( OUTPUTCONFIG )
if (USE_DEBUG_CONSOLE)

File diff suppressed because it is too large Load Diff

@ -412,7 +412,7 @@ void Record<ESM::Armor>::print()
std::cout << " Armor: " << mData.mData.mArmor << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++)
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{
std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl;
@ -484,7 +484,7 @@ void Record<ESM::BirthSign>::print()
std::cout << " Texture: " << mData.mTexture << std::endl;
std::cout << " Description: " << mData.mDescription << std::endl;
std::vector<std::string>::iterator pit;
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); pit++)
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); ++pit)
std::cout << " Power: " << *pit << std::endl;
}
@ -554,7 +554,7 @@ void Record<ESM::Clothing>::print()
std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++)
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{
std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl;
@ -574,7 +574,7 @@ void Record<ESM::Container>::print()
std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl;
std::cout << " Weight: " << mData.mWeight << std::endl;
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++)
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
}
@ -619,12 +619,12 @@ void Record<ESM::Creature>::print()
std::cout << " Gold: " << mData.mData.mGold << std::endl;
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++)
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++)
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
@ -639,7 +639,7 @@ void Record<ESM::Creature>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++)
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit);
}
@ -706,7 +706,7 @@ void Record<ESM::Faction>::print()
<< mData.mData.mRankData[i].mFactReaction << std::endl;
}
std::map<std::string, int>::iterator rit;
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); rit++)
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); ++rit)
std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
}
@ -763,7 +763,7 @@ void Record<ESM::DialInfo>::print()
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
std::vector<ESM::DialInfo::SelectStruct>::iterator sit;
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); sit++)
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); ++sit)
std::cout << " Select Rule: " << ruleString(*sit) << std::endl;
if (mData.mResultScript != "")
@ -835,7 +835,7 @@ void Record<ESM::CreatureLevList>::print()
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++)
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Creature: Level: " << iit->mLevel
<< " Creature: " << iit->mId << std::endl;
}
@ -847,7 +847,7 @@ void Record<ESM::ItemLevList>::print()
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++)
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Inventory: Level: " << iit->mLevel
<< " Item: " << iit->mId << std::endl;
}
@ -1031,16 +1031,16 @@ void Record<ESM::NPC>::print()
}
std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++)
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++)
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit;
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); dit++)
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); ++dit)
{
std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << ","
@ -1066,7 +1066,7 @@ void Record<ESM::NPC>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++)
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit);
}
@ -1140,7 +1140,7 @@ void Record<ESM::Race>::print()
<< mData.mData.mBonus[i].mBonus << std::endl;
std::vector<std::string>::iterator sit;
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); sit++)
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); ++sit)
std::cout << " Power: " << *sit << std::endl;
}
@ -1164,7 +1164,7 @@ void Record<ESM::Region>::print()
if (mData.mSleepList != "")
std::cout << " Sleep List: " << mData.mSleepList << std::endl;
std::vector<ESM::Region::SoundRef>::iterator sit;
for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); sit++)
for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); ++sit)
std::cout << " Sound: " << (int)sit->mChance << " = " << sit->mSound.toString() << std::endl;
}
@ -1181,12 +1181,12 @@ void Record<ESM::Script>::print()
std::vector<std::string>::iterator vit;
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); vit++)
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); ++vit)
std::cout << " Variable: " << *vit << std::endl;
std::cout << " ByteCode: ";
std::vector<unsigned char>::iterator cit;
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); cit++)
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); ++cit)
std::cout << boost::format("%02X") % (int)(*cit);
std::cout << std::endl;

@ -15,6 +15,7 @@ namespace bfs = boost::filesystem;
MwIniImporter::MwIniImporter()
: mVerbose(false)
, mEncoding(ToUTF8::WINDOWS_1250)
{
const char *map[][2] =
{
@ -709,8 +710,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
continue;
}
multistrmap::iterator it;
if((it = map.find(key)) == map.end()) {
if(map.find(key) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) );
}
map[key].push_back(value);
@ -746,8 +746,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filenam
std::string key(line.substr(0,pos));
std::string value(line.substr(pos+1));
multistrmap::iterator it;
if((it = map.find(key)) == map.end()) {
if(map.find(key) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) );
}
map[key].push_back(value);

@ -37,6 +37,8 @@ public:
char **get() const { return const_cast<char **>(argv); }
private:
utf8argv(const utf8argv&);
utf8argv& operator=(const utf8argv&);
const char **argv;
std::vector<std::string> args;

@ -103,11 +103,6 @@ namespace CSMDoc
if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly)
{
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic (change ESMWriter interface?)
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId);
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
mCollection.getRecord (stage).mModified.save (mState.getWriter());

@ -71,6 +71,14 @@ namespace CSMWorld
record.load (reader);
if (index==-1)
{
std::string newId = IdAccessorT().getId(record);
int newIndex = this->searchId(newId);
if (newIndex != -1 && id != newId)
index = newIndex;
}
load (record, base, index);
}
}

@ -6,18 +6,20 @@
void CSMWorld::ResourcesManager::addResources (const Resources& resources)
{
mResources.insert (std::make_pair (resources.getType(), resources));
mResources.insert (std::make_pair (UniversalId::getParentType (resources.getType()),
resources));
}
void CSMWorld::ResourcesManager::listResources()
{
static const char * const sMeshTypes[] = { "nif", 0 };
addResources (Resources ("meshes", UniversalId::Type_Meshes, sMeshTypes));
addResources (Resources ("icons", UniversalId::Type_Icons));
addResources (Resources ("music", UniversalId::Type_Musics));
addResources (Resources ("sound", UniversalId::Type_SoundsRes));
addResources (Resources ("textures", UniversalId::Type_Textures));
addResources (Resources ("videos", UniversalId::Type_Videos));
addResources (Resources ("meshes", UniversalId::Type_Mesh, sMeshTypes));
addResources (Resources ("icons", UniversalId::Type_Icon));
addResources (Resources ("music", UniversalId::Type_Music));
addResources (Resources ("sound", UniversalId::Type_SoundRes));
addResources (Resources ("textures", UniversalId::Type_Texture));
addResources (Resources ("videos", UniversalId::Type_Video));
}
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const

@ -11,9 +11,14 @@ float CSVRender::Navigation::getFactor (bool mouse) const
return factor;
}
CSVRender::Navigation::Navigation()
: mFastModeFactor(1)
{
}
CSVRender::Navigation::~Navigation() {}
void CSVRender::Navigation::setFastModeFactor (float factor)
{
mFastModeFactor = factor;
}
}

@ -20,6 +20,7 @@ namespace CSVRender
public:
Navigation();
virtual ~Navigation();
void setFastModeFactor (float factor);

@ -361,11 +361,6 @@ namespace CSVRender
}
}
int SceneWidget::getFastFactor() const
{
return mFast ? mFastFactor : 1;
}
void SceneWidget::setLighting (Lighting *lighting)
{
if (mLighting)

@ -80,8 +80,6 @@ namespace CSVRender
void updateOgreWindow();
int getFastFactor() const;
void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this.

@ -38,7 +38,7 @@ void CSVWorld::DataDisplayDelegate::buildPixmaps ()
}
}
void CSVWorld::DataDisplayDelegate::setIconSize(const QSize size)
void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size)
{
mIconSize = size;
buildPixmaps();

@ -50,7 +50,7 @@ namespace CSVWorld
virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
/// pass a QSize defining height / width of icon. Default is QSize (16,16).
void setIconSize (const QSize icon);
void setIconSize (const QSize& icon);
/// offset the horizontal position of the icon from the left edge of the cell. Default is 3 pixels.
void setIconLeftOffset (int offset);

@ -32,7 +32,7 @@ add_openmw_dir (mwinput
add_openmw_dir (mwgui
textinput widgets race class birth review windowmanagerimp console dialogue
windowbase statswindow messagebox journalwindow charactercreation
mapwindow windowpinnablebase tooltips scrollwindow bookwindow list
mapwindow windowpinnablebase tooltips scrollwindow bookwindow
formatting inventorywindow container hud countdialog tradewindow settingswindow
confirmationdialog alchemywindow referenceinterface spellwindow mainmenu quickkeysmenu
itemselection spellbuyingwindow loadingscreen levelupdialog waitdialog spellcreationdialog
@ -40,7 +40,7 @@ add_openmw_dir (mwgui
merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks
keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
recharge mode videowidget backgroundimage itemwidget screenfader
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow
)
add_openmw_dir (mwdialogue

@ -127,7 +127,6 @@ static int (*cc_user_info)(char*, char*);
static void gdb_info(pid_t pid)
{
char respfile[64];
char cmd_buf[128];
FILE *f;
int fd;
@ -156,6 +155,7 @@ static void gdb_info(pid_t pid)
fclose(f);
/* Run gdb and print process info. */
char cmd_buf[128];
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf);
fflush(stdout);

@ -62,7 +62,6 @@ void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap
FallbackMap *map = boost::any_cast<FallbackMap>(&v);
std::map<std::string,std::string>::iterator mapIt;
for(std::vector<std::string>::const_iterator it=tokens.begin(); it != tokens.end(); ++it)
{
int sep = it->find(",");
@ -76,7 +75,7 @@ void validate(boost::any &v, std::vector<std::string> const &tokens, FallbackMap
std::string key(it->substr(0,sep));
std::string value(it->substr(sep+1));
if((mapIt = map->mMap.find(key)) == map->mMap.end())
if(map->mMap.find(key) == map->mMap.end())
{
map->mMap.insert(std::make_pair (key,value));
}

@ -128,7 +128,8 @@ namespace MWBase
OffenseType type, int arg=0) = 0;
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0) = 0;
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
/// @return false if the attack was considered a "friendly hit" and forgiven
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
/// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so

@ -225,7 +225,6 @@ namespace MWBase
virtual void showCrosshair(bool show) = 0;
virtual bool getSubtitlesEnabled() = 0;
virtual void toggleHud() = 0;
virtual bool toggleGui() = 0;
virtual void disallowMouse() = 0;
@ -338,6 +337,8 @@ namespace MWBase
virtual void fadeScreenTo(const int percent, const float time) = 0;
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor) = 0;
virtual void toggleDebugWindow() = 0;
};
}

@ -338,11 +338,12 @@ namespace MWClass
getCreatureStats(ptr).setAttacked(true);
// Self defense
bool setOnPcHitMe = true; // Note OnPcHitMe is not set for friendly hits.
if ((canWalk(ptr) || canFly(ptr) || canSwim(ptr)) // No retaliation for totally static creatures
// (they have no movement or attacks anyway)
&& !attacker.isEmpty())
{
MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
}
if(!successful)
@ -357,7 +358,7 @@ namespace MWClass
if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object));
if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
{
const std::string &script = ptr.get<ESM::Creature>()->mBase->mScript;
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */

@ -644,11 +644,13 @@ namespace MWClass
bool wasDead = getCreatureStats(ptr).isDead();
// Note OnPcHitMe is not set for friendly hits.
bool setOnPcHitMe = true;
if (!attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker))
{
getCreatureStats(ptr).setAttacked(true);
MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
setOnPcHitMe = MWBase::Environment::get().getMechanicsManager()->actorAttacked(ptr, attacker);
}
if(!successful)
@ -663,7 +665,7 @@ namespace MWClass
if(!object.isEmpty())
getCreatureStats(ptr).setLastHitObject(object.getClass().getId(object));
if(!attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
if(setOnPcHitMe && !attacker.isEmpty() && attacker.getRefData().getHandle() == "player")
{
const std::string &script = ptr.getClass().getScript(ptr);
/* Set the OnPCHitMe script variable. The script is responsible for clearing it. */
@ -1123,10 +1125,13 @@ namespace MWClass
return cast.cast(id);
}
void Npc::skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType) const
void Npc::skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor) const
{
MWMechanics::NpcStats& stats = getNpcStats (ptr);
if (stats.isWerewolf())
return;
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
const ESM::Class *class_ =
@ -1134,7 +1139,7 @@ namespace MWClass
ref->mBase->mClass
);
stats.useSkill (skill, *class_, usageType);
stats.useSkill (skill, *class_, usageType, extraFactor);
}
float Npc::getArmorRating (const MWWorld::Ptr& ptr) const
@ -1185,13 +1190,6 @@ namespace MWClass
+ shield;
}
void Npc::adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const
{
y = 0;
x = 0;
}
void Npc::adjustScale(const MWWorld::Ptr &ptr, float &scale) const
{
MWWorld::LiveCellRef<ESM::NPC> *ref =

@ -136,11 +136,9 @@ namespace MWClass
virtual void adjustScale (const MWWorld::Ptr &ptr, float &scale) const;
virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType) const;
virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor=1.f) const;
///< Inform actor \a ptr that a skill use has succeeded.
virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const;
virtual bool isEssential (const MWWorld::Ptr& ptr) const;
///< Is \a ptr essential? (i.e. may losing \a ptr make the game unwinnable)

@ -729,10 +729,10 @@ namespace MWDialogue
{
std::vector<HyperTextToken> result;
MyGUI::UString utext(text);
size_t pos_begin, pos_end, iteration_pos = 0;
size_t pos_end, iteration_pos = 0;
for(;;)
{
pos_begin = utext.find('@', iteration_pos);
size_t pos_begin = utext.find('@', iteration_pos);
if (pos_begin != std::string::npos)
pos_end = utext.find('#', pos_begin);
@ -758,12 +758,12 @@ namespace MWDialogue
size_t RemovePseudoAsterisks(std::string& phrase)
{
size_t pseudoAsterisksCount = 0;
const char specialPseudoAsteriskCharacter = 127;
if( !phrase.empty() )
{
std::string::reverse_iterator rit = phrase.rbegin();
const char specialPseudoAsteriskCharacter = 127;
while( rit != phrase.rend() && *rit == specialPseudoAsteriskCharacter )
{
pseudoAsterisksCount++;

@ -70,11 +70,6 @@ namespace MWGui
void BookWindow::clearPages()
{
for (std::vector<MyGUI::Widget*>::iterator it=mPages.begin();
it!=mPages.end(); ++it)
{
MyGUI::Gui::getInstance().destroyWidget(*it);
}
mPages.clear();
}
@ -89,25 +84,9 @@ namespace MWGui
MWWorld::LiveCellRef<ESM::Book> *ref = mBook.get<ESM::Book>();
BookTextParser parser;
std::vector<std::string> results = parser.split(ref->mBase->mText, mLeftPage->getSize().width, mLeftPage->getSize().height);
int i=0;
for (std::vector<std::string>::iterator it=results.begin();
it!=results.end(); ++it)
{
MyGUI::Widget* parent;
if (i%2 == 0)
parent = mLeftPage;
else
parent = mRightPage;
MyGUI::Widget* pageWidget = parent->createWidgetReal<MyGUI::Widget>("", MyGUI::FloatCoord(0.0,0.0,1.0,1.0), MyGUI::Align::Default, "BookPage" + boost::lexical_cast<std::string>(i));
pageWidget->setNeedMouseFocus(false);
parser.parsePage(*it, pageWidget, mLeftPage->getSize().width);
mPages.push_back(pageWidget);
++i;
}
Formatting::BookFormatter formatter;
mPages = formatter.markupToWidget(mLeftPage, ref->mBase->mText);
formatter.markupToWidget(mRightPage, ref->mBase->mText);
updatePages();
@ -164,19 +143,6 @@ namespace MWGui
mLeftPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 1) );
mRightPageNumber->setCaption( boost::lexical_cast<std::string>(mCurrentPage*2 + 2) );
unsigned int i=0;
for (std::vector<MyGUI::Widget*>::iterator it = mPages.begin();
it != mPages.end(); ++it)
{
if (mCurrentPage*2 == i || mCurrentPage*2+1 == i)
(*it)->setVisible(true);
else
{
(*it)->setVisible(false);
}
++i;
}
//If it is the last page, hide the button "Next Page"
if ( (mCurrentPage+1)*2 == mPages.size()
|| (mCurrentPage+1)*2 == mPages.size() + 1)
@ -191,6 +157,27 @@ namespace MWGui
} else {
mPrevPageButton->setVisible(true);
}
if (mPages.empty())
return;
MyGUI::Widget * paper;
paper = mLeftPage->getChildAt(0);
paper->setCoord(paper->getPosition().left, -mPages[mCurrentPage*2].first,
paper->getWidth(), mPages[mCurrentPage*2].second);
paper = mRightPage->getChildAt(0);
if ((mCurrentPage+1)*2 <= mPages.size())
{
paper->setCoord(paper->getPosition().left, -mPages[mCurrentPage*2+1].first,
paper->getWidth(), mPages[mCurrentPage*2+1].second);
paper->setVisible(true);
}
else
{
paper->setVisible(false);
}
}
void BookWindow::adjustButton (Gui::ImageButton* button)

@ -34,17 +34,21 @@ namespace MWGui
void adjustButton(Gui::ImageButton* button);
private:
typedef std::pair<int, int> Page;
typedef std::vector<Page> Pages;
Gui::ImageButton* mCloseButton;
Gui::ImageButton* mTakeButton;
Gui::ImageButton* mNextPageButton;
Gui::ImageButton* mPrevPageButton;
MyGUI::TextBox* mLeftPageNumber;
MyGUI::TextBox* mRightPageNumber;
MyGUI::Widget* mLeftPage;
MyGUI::Widget* mRightPage;
unsigned int mCurrentPage; // 0 is first page
std::vector<MyGUI::Widget*> mPages;
Pages mPages;
MWWorld::Ptr mBook;

@ -277,7 +277,6 @@ namespace MWGui
InfoBoxDialog::InfoBoxDialog()
: WindowModal("openmw_infobox.layout")
, mCurrentButton(-1)
{
getWidget(mTextBox, "TextBox");
getWidget(mText, "Text");
@ -306,7 +305,6 @@ namespace MWGui
MyGUI::Gui::getInstance().destroyWidget(*it);
}
this->mButtons.clear();
mCurrentButton = -1;
// TODO: The buttons should be generated from a template in the layout file, ie. cloning an existing widget
MyGUI::Button* button;
@ -336,11 +334,6 @@ namespace MWGui
center();
}
int InfoBoxDialog::getChosenButton() const
{
return mCurrentButton;
}
void InfoBoxDialog::onButtonClicked(MyGUI::Widget* _sender)
{
std::vector<MyGUI::Button*>::const_iterator end = mButtons.end();
@ -349,7 +342,6 @@ namespace MWGui
{
if (*it == _sender)
{
mCurrentButton = i;
eventButtonSelected(i);
return;
}
@ -671,8 +663,6 @@ namespace MWGui
// Centre dialog
center();
setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationMenu1", ""));
getWidget(mSpecialization0, "Specialization0");
getWidget(mSpecialization1, "Specialization1");
getWidget(mSpecialization2, "Specialization2");
@ -694,7 +684,6 @@ namespace MWGui
MyGUI::Button* cancelButton;
getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSpecializationDialog::onCancelClicked);
}
@ -737,8 +726,6 @@ namespace MWGui
// Centre dialog
center();
setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sAttributesMenu1", ""));
for (int i = 0; i < 8; ++i)
{
Widgets::MWAttributePtr attribute;
@ -752,7 +739,6 @@ namespace MWGui
MyGUI::Button* cancelButton;
getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectAttributeDialog::onCancelClicked);
}
@ -788,11 +774,6 @@ namespace MWGui
// Centre dialog
center();
setText("LabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSkillsMenu1", ""));
setText("CombatLabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationCombat", ""));
setText("MagicLabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationMagic", ""));
setText("StealthLabelT", MWBase::Environment::get().getWindowManager()->getGameSettingString("sSpecializationStealth", ""));
for(int i = 0; i < 9; i++)
{
char theIndex = '0'+i;
@ -849,7 +830,6 @@ namespace MWGui
MyGUI::Button* cancelButton;
getWidget(cancelButton, "CancelButton");
cancelButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sCancel", ""));
cancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SelectSkillDialog::onCancelClicked);
}

@ -24,7 +24,6 @@ namespace MWGui
void setButtons(ButtonList &buttons);
virtual void open();
int getChosenButton() const;
// Events
typedef MyGUI::delegates::CMultiDelegate1<int> EventHandle_Int;
@ -41,7 +40,6 @@ namespace MWGui
void fitToText(MyGUI::TextBox* widget);
void layoutVertically(MyGUI::Widget* widget, int margin);
int mCurrentButton;
MyGUI::Widget* mTextBox;
MyGUI::TextBox* mText;
MyGUI::Widget* mButtonBar;

@ -155,11 +155,6 @@ namespace MWGui
mCommandLine->setFontName(fntName);
}
void Console::clearHistory()
{
mHistory->setCaption("");
}
void Console::print(const std::string &msg)
{
mHistory->addText(msg);

@ -48,8 +48,6 @@ namespace MWGui
void onResChange(int width, int height);
void clearHistory();
// Print a message to the console. Messages may contain color
// code, eg. "#FFFFFF this is white".
void print(const std::string &msg);

@ -2,6 +2,8 @@
#include <boost/lexical_cast.hpp>
#include <components/widgets/numericeditbox.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
@ -19,7 +21,7 @@ namespace MWGui
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onCancelButtonClicked);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &CountDialog::onOkButtonClicked);
mItemEdit->eventEditTextChange += MyGUI::newDelegate(this, &CountDialog::onEditTextChange);
mItemEdit->eventValueChanged += MyGUI::newDelegate(this, &CountDialog::onEditValueChanged);
mSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &CountDialog::onSliderMoved);
// make sure we read the enter key being pressed to accept multiple items
mItemEdit->eventEditSelectAccept += MyGUI::newDelegate(this, &CountDialog::onEnterKeyPressed);
@ -46,7 +48,10 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mItemEdit);
mSlider->setScrollPosition(maxCount-1);
mItemEdit->setCaption(boost::lexical_cast<std::string>(maxCount));
mItemEdit->setMinValue(1);
mItemEdit->setMaxValue(maxCount);
mItemEdit->setValue(maxCount);
}
void CountDialog::cancel() //Keeping this here as I don't know if anything else relies on it.
@ -80,30 +85,13 @@ namespace MWGui
setVisible(false);
}
void CountDialog::onEditTextChange(MyGUI::EditBox* _sender)
void CountDialog::onEditValueChanged(int value)
{
if (_sender->getCaption() == "")
return;
unsigned int count;
try
{
count = boost::lexical_cast<unsigned int>(_sender->getCaption());
}
catch (std::bad_cast&)
{
count = 1;
}
if (count > mSlider->getScrollRange())
{
count = mSlider->getScrollRange();
}
mSlider->setScrollPosition(count-1);
onSliderMoved(mSlider, count-1);
mSlider->setScrollPosition(value-1);
}
void CountDialog::onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position)
{
mItemEdit->setCaption(boost::lexical_cast<std::string>(_position+1));
mItemEdit->setValue(_position+1);
}
}

@ -3,6 +3,11 @@
#include "windowbase.hpp"
namespace Gui
{
class NumericEditBox;
}
namespace MWGui
{
class CountDialog : public WindowModal
@ -22,7 +27,7 @@ namespace MWGui
private:
MyGUI::ScrollBar* mSlider;
MyGUI::EditBox* mItemEdit;
Gui::NumericEditBox* mItemEdit;
MyGUI::TextBox* mItemText;
MyGUI::TextBox* mLabelText;
MyGUI::Button* mOkButton;
@ -30,7 +35,7 @@ namespace MWGui
void onCancelButtonClicked(MyGUI::Widget* _sender);
void onOkButtonClicked(MyGUI::Widget* _sender);
void onEditTextChange(MyGUI::EditBox* _sender);
void onEditValueChanged(int value);
void onSliderMoved(MyGUI::ScrollBar* _sender, size_t _position);
void onEnterKeyPressed(MyGUI::EditBox* _sender);
};

@ -0,0 +1,116 @@
#include "debugwindow.hpp"
#include <LinearMath/btQuickprof.h>
namespace
{
void bulletDumpRecursive(CProfileIterator* pit, int spacing, std::stringstream& os)
{
pit->First();
if (pit->Is_Done())
return;
float accumulated_time=0,parent_time = pit->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : pit->Get_Current_Parent_Total_Time();
int i,j;
int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
for (i=0;i<spacing;i++) os << ".";
os << "----------------------------------\n";
for (i=0;i<spacing;i++) os << ".";
std::string s = "Profiling: "+
std::string(pit->Get_Current_Parent_Name())+" (total running time: "+MyGUI::utility::toString(parent_time,3)+" ms) ---\n";
os << s;
//float totalTime = 0.f;
int numChildren = 0;
for (i = 0; !pit->Is_Done(); i++,pit->Next())
{
numChildren++;
float current_total_time = pit->Get_Current_Total_Time();
accumulated_time += current_total_time;
float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
for (j=0;j<spacing;j++) os << ".";
double ms = (current_total_time / (double)frames_since_reset);
s = MyGUI::utility::toString(i)+" -- "+pit->Get_Current_Name()+" ("+MyGUI::utility::toString(fraction,2)+" %) :: "+MyGUI::utility::toString(ms,3)+" ms / frame ("+MyGUI::utility::toString(pit->Get_Current_Total_Calls())+" calls)\n";
os << s;
//totalTime += current_total_time;
//recurse into children
}
if (parent_time < accumulated_time)
{
os << "what's wrong\n";
}
for (i=0;i<spacing;i++) os << ".";
double unaccounted= parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f;
s = "Unaccounted: ("+MyGUI::utility::toString(unaccounted,3)+" %) :: "+MyGUI::utility::toString(parent_time - accumulated_time,3)+" ms\n";
os << s;
for (i=0;i<numChildren;i++)
{
pit->Enter_Child(i);
bulletDumpRecursive(pit, spacing+3, os);
pit->Enter_Parent();
}
}
void bulletDumpAll(std::stringstream& os)
{
CProfileIterator* profileIterator = 0;
profileIterator = CProfileManager::Get_Iterator();
bulletDumpRecursive(profileIterator, 0, os);
CProfileManager::Release_Iterator(profileIterator);
}
}
namespace MWGui
{
DebugWindow::DebugWindow()
: WindowBase("openmw_debug_window.layout")
{
getWidget(mTabControl, "TabControl");
// Ideas for other tabs:
// - Texture / compositor texture viewer
// - Log viewer
// - Material editor
// - Shader editor
MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler");
mBulletProfilerEdit = item->createWidgetReal<MyGUI::EditBox>
("LogEdit", MyGUI::FloatCoord(0,0,1,1), MyGUI::Align::Stretch);
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
mMainWidget->setSize(viewSize);
}
void DebugWindow::onFrame(float dt)
{
if (!isVisible())
return;
static float timer = 0;
timer -= dt;
if (timer > 0)
return;
timer = 1;
std::stringstream stream;
bulletDumpAll(stream);
if (mBulletProfilerEdit->isTextSelection()) // pause updating while user is trying to copy text
return;
size_t previousPos = mBulletProfilerEdit->getVScrollPosition();
mBulletProfilerEdit->setCaption(stream.str());
mBulletProfilerEdit->setVScrollPosition(std::min(previousPos, mBulletProfilerEdit->getVScrollRange()-1));
}
}

@ -0,0 +1,24 @@
#ifndef OPENMW_MWGUI_DEBUGWINDOW_H
#define OPENMW_MWGUI_DEBUGWINDOW_H
#include "windowbase.hpp"
namespace MWGui
{
class DebugWindow : public WindowBase
{
public:
DebugWindow();
void onFrame(float dt);
private:
MyGUI::TabControl* mTabControl;
MyGUI::EditBox* mBulletProfilerEdit;
};
}
#endif

@ -3,6 +3,8 @@
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <components/widgets/list.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
@ -17,7 +19,6 @@
#include "../mwdialogue/dialoguemanagerimp.hpp"
#include "widgets.hpp"
#include "list.hpp"
#include "tradewindow.hpp"
#include "spellbuyingwindow.hpp"
#include "travelwindow.hpp"
@ -124,10 +125,10 @@ namespace MWGui
// We need this copy for when @# hyperlinks are replaced
std::string text = mText;
size_t pos_begin, pos_end;
size_t pos_end;
for(;;)
{
pos_begin = text.find('@');
size_t pos_begin = text.find('@');
if (pos_begin != std::string::npos)
pos_end = text.find('#', pos_begin);
@ -561,12 +562,11 @@ namespace MWGui
MyGUI::Button* byeButton;
getWidget(byeButton, "ByeButton");
if(MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye) {
byeButton->setEnabled(false);
}
else {
byeButton->setEnabled(true);
}
bool goodbyeEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() || mGoodbye;
byeButton->setEnabled(goodbyeEnabled);
bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye;
mTopicsList->setEnabled(topicsEnabled);
}
void DialogueWindow::notifyLinkClicked (TypesetBook::InteractiveId link)
@ -656,7 +656,6 @@ namespace MWGui
{
mLinks.push_back(new Goodbye());
mGoodbye = true;
mTopicsList->setEnabled(false);
mEnabled = false;
updateHistory();
}

@ -8,14 +8,14 @@
#include "keywordsearch.hpp"
namespace Gui
{
class MWList;
}
namespace MWGui
{
class WindowManager;
namespace Widgets
{
class MWList;
}
}
/*
@ -169,7 +169,7 @@ namespace MWGui
KeywordSearchT mKeywordSearch;
BookPage* mHistory;
Widgets::MWList* mTopicsList;
Gui::MWList* mTopicsList;
MyGUI::ScrollBar* mScrollBar;
MyGUI::Progress* mDispositionBar;
MyGUI::EditBox* mDispositionText;

@ -2,401 +2,404 @@
#include <components/interpreter/defines.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/misc/stringops.hpp>
#include "../mwscript/interpretercontext.hpp"
#include <boost/algorithm/string/replace.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string/trim.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <OgreUTFString.h>
#include <OgreUTFString.h>
#include <OgreResourceGroupManager.h>
namespace
{
int convertFromHex(std::string hex)
{
int value = 0;
int a = 0;
int b = hex.length() - 1;
for (; b >= 0; a++, b--)
{
if (hex[b] >= '0' && hex[b] <= '9')
{
value += (hex[b] - '0') * (1 << (a * 4));
}
else
{
switch (hex[b])
{
case 'A':
case 'a':
value += 10 * (1 << (a * 4));
break;
case 'B':
case 'b':
value += 11 * (1 << (a * 4));
break;
case 'C':
case 'c':
value += 12 * (1 << (a * 4));
break;
case 'D':
case 'd':
value += 13 * (1 << (a * 4));
break;
case 'E':
case 'e':
value += 14 * (1 << (a * 4));
break;
case 'F':
case 'f':
value += 15 * (1 << (a * 4));
break;
default:
throw std::runtime_error("invalid character in hex number");
break;
}
}
}
return value;
}
Ogre::UTFString::unicode_char unicodeCharFromChar(char ch)
{
std::string s;
s += ch;
Ogre::UTFString string(s);
return string.getChar(0);
}
bool is_not_empty(const std::string& s) {
std::string temp = s;
boost::algorithm::trim(temp);
return !temp.empty();
}
}
#include <MyGUI_EditText.h>
namespace MWGui
{
std::vector<std::string> BookTextParser::split(std::string utf8Text, const int width, const int height)
namespace Formatting
{
using Ogre::UTFString;
std::vector<std::string> result;
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
utf8Text = Interpreter::fixDefinesBook(utf8Text, interpreterContext);
/* BookTextParser */
BookTextParser::BookTextParser(const std::string & text)
: mIndex(0), mText(text), mIgnoreNewlineTags(true), mIgnoreLineEndings(true)
{
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
mText = Interpreter::fixDefinesBook(mText, interpreterContext);
boost::algorithm::replace_all(utf8Text, "\n", "");
boost::algorithm::replace_all(utf8Text, "\r", "");
boost::algorithm::replace_all(utf8Text, "<BR>", "\n");
boost::algorithm::replace_all(utf8Text, "<P>", "\n\n");
boost::algorithm::replace_all(mText, "\r", "");
UTFString text(utf8Text);
const int spacing = 48;
registerTag("br", Event_BrTag);
registerTag("p", Event_PTag);
registerTag("img", Event_ImgTag);
registerTag("div", Event_DivTag);
registerTag("font", Event_FontTag);
}
const UTFString::unicode_char LEFT_ANGLE = unicodeCharFromChar('<');
const UTFString::unicode_char NEWLINE = unicodeCharFromChar('\n');
const UTFString::unicode_char SPACE = unicodeCharFromChar(' ');
void BookTextParser::registerTag(const std::string & tag, BookTextParser::Events type)
{
mTagTypes[tag] = type;
}
while (!text.empty())
std::string BookTextParser::getReadyText()
{
// read in characters until we have exceeded the size, or run out of text
int currentWidth = 0;
int currentHeight = 0;
return mReadyText;
}
size_t currentWordStart = 0;
size_t index = 0;
{
std::string texToTrim = text.asUTF8();
boost::algorithm::trim( texToTrim );
text = UTFString(texToTrim);
}
while (currentHeight <= height - spacing && index < text.size())
BookTextParser::Events BookTextParser::next()
{
while (mIndex < mText.size())
{
const UTFString::unicode_char ch = text.getChar(index);
if (ch == LEFT_ANGLE)
char ch = mText[mIndex];
if (ch == '<')
{
const size_t tagStart = index + 1;
const size_t tagEnd = text.find('>', tagStart);
if (tagEnd == UTFString::npos)
const size_t tagStart = mIndex + 1;
const size_t tagEnd = mText.find('>', tagStart);
if (tagEnd == std::string::npos)
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
const std::string tag = text.substr(tagStart, tagEnd - tagStart).asUTF8();
parseTag(mText.substr(tagStart, tagEnd - tagStart));
mIndex = tagEnd;
if (boost::algorithm::starts_with(tag, "IMG"))
if (mTagTypes.find(mTag) != mTagTypes.end())
{
const int h = mHeight;
parseImage(tag, false);
currentHeight += (mHeight - h);
currentWidth = 0;
}
else if (boost::algorithm::starts_with(tag, "FONT"))
{
parseFont(tag);
if (currentWidth != 0) {
currentHeight += currentFontHeight();
Events type = mTagTypes.at(mTag);
if (type == Event_BrTag || type == Event_PTag)
{
if (!mIgnoreNewlineTags)
{
if (type == Event_BrTag)
mBuffer.push_back('\n');
else
{
mBuffer.append("\n\n");
}
}
mIgnoreLineEndings = true;
}
currentWidth = 0;
}
else if (boost::algorithm::starts_with(tag, "DIV"))
{
parseDiv(tag);
if (currentWidth != 0) {
currentHeight += currentFontHeight();
currentWidth = 0;
else
flushBuffer();
if (type == Event_ImgTag)
{
mIgnoreLineEndings = false;
mIgnoreNewlineTags = false;
}
++mIndex;
return type;
}
index = tagEnd;
}
else if (ch == NEWLINE)
else
{
currentHeight += currentFontHeight();
currentWidth = 0;
currentWordStart = index;
if (!mIgnoreLineEndings || ch != '\n')
{
mBuffer.push_back(ch);
mIgnoreLineEndings = false;
mIgnoreNewlineTags = false;
}
}
else if (ch == SPACE)
++mIndex;
}
flushBuffer();
return Event_EOF;
}
void BookTextParser::flushBuffer()
{
mReadyText = mBuffer;
mBuffer.clear();
}
const BookTextParser::Attributes & BookTextParser::getAttributes() const
{
return mAttributes;
}
void BookTextParser::parseTag(std::string tag)
{
size_t tagNameEndPos = tag.find(' ');
mTag = tag.substr(0, tagNameEndPos);
Misc::StringUtils::toLower(mTag);
mAttributes.clear();
if (tagNameEndPos == std::string::npos)
return;
tag.erase(0, tagNameEndPos+1);
while (!tag.empty())
{
size_t sepPos = tag.find('=');
if (sepPos == std::string::npos)
return;
std::string key = tag.substr(0, sepPos);
Misc::StringUtils::toLower(key);
tag.erase(0, sepPos+1);
std::string value;
if (tag.empty())
return;
if (tag[0] == '"')
{
currentWidth += 3; // keep this in sync with the font's SpaceWidth property
currentWordStart = index;
size_t quoteEndPos = tag.find('"', 1);
if (quoteEndPos == std::string::npos)
throw std::runtime_error("BookTextParser Error: Missing end quote in tag");
value = tag.substr(1, quoteEndPos-1);
tag.erase(0, quoteEndPos+2);
}
else
{
currentWidth += widthForCharGlyph(ch);
size_t valEndPos = tag.find(' ');
if (valEndPos == std::string::npos)
{
value = tag;
tag.erase();
}
else
{
value = tag.substr(0, valEndPos);
tag.erase(0, valEndPos+1);
}
}
if (currentWidth > width)
{
currentHeight += currentFontHeight();
currentWidth = 0;
// add size of the current word
UTFString word = text.substr(currentWordStart, index - currentWordStart);
for (UTFString::const_iterator it = word.begin(), end = word.end(); it != end; ++it)
currentWidth += widthForCharGlyph(it.getCharacter());
}
index += UTFString::_utf16_char_length(ch);
mAttributes[key] = value;
}
const size_t pageEnd = (currentHeight > height - spacing && currentWordStart != 0)
? currentWordStart : index;
result.push_back(text.substr(0, pageEnd).asUTF8());
text.erase(0, pageEnd);
}
std::vector<std::string> nonEmptyPages;
boost::copy(result | boost::adaptors::filtered(is_not_empty), std::back_inserter(nonEmptyPages));
return nonEmptyPages;
}
float BookTextParser::widthForCharGlyph(unsigned unicodeChar) const
{
std::string fontName(mTextStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mTextStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName)
->getGlyphInfo(unicodeChar)->width;
}
/* BookFormatter */
Paginator::Pages BookFormatter::markupToWidget(MyGUI::Widget * parent, const std::string & markup, const int pageWidth, const int pageHeight)
{
Paginator pag(pageWidth, pageHeight);
float BookTextParser::currentFontHeight() const
{
std::string fontName(mTextStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mTextStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight();
}
while (parent->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(parent->getChildAt(0));
}
MyGUI::IntSize BookTextParser::parsePage(std::string text, MyGUI::Widget* parent, const int width)
{
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
text = Interpreter::fixDefinesBook(text, interpreterContext);
MyGUI::Widget * paper = parent->createWidget<MyGUI::Widget>("Widget", MyGUI::IntCoord(0, 0, pag.getPageWidth(), pag.getPageHeight()), MyGUI::Align::Left | MyGUI::Align::Top);
paper->setNeedMouseFocus(false);
mParent = parent;
mWidth = width;
mHeight = 0;
BookTextParser parser(markup);
for (;;)
{
BookTextParser::Events event = parser.next();
if (event == BookTextParser::Event_BrTag || event == BookTextParser::Event_PTag)
continue;
assert(mParent);
while (mParent->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0));
}
std::string plainText = parser.getReadyText();
if (!plainText.empty())
{
// if there's a newline at the end of the box caption, remove it
if (plainText[plainText.size()-1] == '\n')
plainText.erase(plainText.end()-1);
#if (MYGUI_VERSION < MYGUI_DEFINE_VERSION(3, 2, 2))
// splitting won't be fully functional until 3.2.2 (see TextElement::pageSplit())
// hack: prevent newlines at the end of the book possibly creating unnecessary pages
if (event == BookTextParser::Event_EOF)
{
while (plainText.size() && plainText[plainText.size()-1] == '\n')
plainText.erase(plainText.end()-1);
}
#endif
// remove trailing "
if (text[text.size()-1] == '\"')
text.erase(text.size()-1);
TextElement elem(paper, pag, mTextStyle, plainText);
elem.paginate();
}
parseSubText(text);
return MyGUI::IntSize(mWidth, mHeight);
}
MyGUI::IntSize BookTextParser::parseScroll(std::string text, MyGUI::Widget* parent, const int width)
{
MWScript::InterpreterContext interpreterContext(NULL, MWWorld::Ptr()); // empty arguments, because there is no locals or actor
text = Interpreter::fixDefinesBook(text, interpreterContext);
if (event == BookTextParser::Event_EOF)
break;
mParent = parent;
mWidth = width;
mHeight = 0;
switch (event)
{
case BookTextParser::Event_ImgTag:
{
const BookTextParser::Attributes & attr = parser.getAttributes();
assert(mParent);
while (mParent->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mParent->getChildAt(0));
}
if (attr.find("src") == attr.end() || attr.find("width") == attr.end() || attr.find("height") == attr.end())
continue;
boost::algorithm::replace_all(text, "<BR>", "\n");
boost::algorithm::replace_all(text, "<P>", "\n\n");
boost::algorithm::trim_left(text);
std::string src = attr.at("src");
int width = boost::lexical_cast<int>(attr.at("width"));
int height = boost::lexical_cast<int>(attr.at("height"));
// remove trailing "
if (text[text.size()-1] == '\"')
text.erase(text.size()-1);
ImageElement elem(paper, pag, src, width, height);
elem.paginate();
break;
}
case BookTextParser::Event_FontTag:
handleFont(parser.getAttributes());
break;
case BookTextParser::Event_DivTag:
handleDiv(parser.getAttributes());
break;
default:
break;
}
}
parseSubText(text);
return MyGUI::IntSize(mWidth, mHeight);
}
// insert last page
if (pag.getStartTop() != pag.getCurrentTop())
pag << Paginator::Page(pag.getStartTop(), pag.getStartTop() + pag.getPageHeight());
void BookTextParser::parseImage(std::string tag, bool createWidget)
{
int src_start = tag.find("SRC=")+5;
paper->setSize(paper->getWidth(), pag.getCurrentTop());
int width_start = tag.find("WIDTH=")+7;
int width = boost::lexical_cast<int>(tag.substr(width_start, tag.find('"', width_start)-width_start));
return pag.getPages();
}
int height_start = tag.find("HEIGHT=")+8;
int height = boost::lexical_cast<int>(tag.substr(height_start, tag.find('"', height_start)-height_start));
Paginator::Pages BookFormatter::markupToWidget(MyGUI::Widget * parent, const std::string & markup)
{
return markupToWidget(parent, markup, parent->getWidth(), parent->getHeight());
}
if (createWidget)
void BookFormatter::handleDiv(const BookTextParser::Attributes & attr)
{
MyGUI::ImageBox* box = mParent->createWidget<MyGUI::ImageBox> ("ImageBox",
MyGUI::IntCoord(0, mHeight, width, height), MyGUI::Align::Left | MyGUI::Align::Top,
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
if (attr.find("align") == attr.end())
return;
std::string image = Misc::ResourceHelpers::correctBookartPath(tag.substr(src_start, tag.find('"', src_start)-src_start), width, height);
box->setImageTexture(image);
box->setProperty("NeedMouse", "false");
std::string align = attr.at("align");
if (Misc::StringUtils::ciEqual(align, "center"))
mTextStyle.mTextAlign = MyGUI::Align::HCenter;
else if (Misc::StringUtils::ciEqual(align, "left"))
mTextStyle.mTextAlign = MyGUI::Align::Left;
}
mWidth = std::max(mWidth, width);
mHeight += height;
}
void BookFormatter::handleFont(const BookTextParser::Attributes & attr)
{
if (attr.find("color") != attr.end())
{
int color;
std::stringstream ss;
ss << attr.at("color");
ss >> std::hex >> color;
mTextStyle.mColour = MyGUI::Colour(
(color>>16 & 0xFF) / 255.f,
(color>>8 & 0xFF) / 255.f,
(color & 0xFF) / 255.f);
}
if (attr.find("face") != attr.end())
{
std::string face = attr.at("face");
void BookTextParser::parseDiv(std::string tag)
{
if (tag.find("ALIGN=") == std::string::npos)
return;
int align_start = tag.find("ALIGN=")+7;
std::string align = tag.substr(align_start, tag.find('"', align_start)-align_start);
if (align == "CENTER")
mTextStyle.mTextAlign = MyGUI::Align::HCenter;
else if (align == "LEFT")
mTextStyle.mTextAlign = MyGUI::Align::Left;
}
if (face != "Magic Cards")
mTextStyle.mFont = face;
}
if (attr.find("size") != attr.end())
{
/// \todo
}
}
void BookTextParser::parseFont(std::string tag)
{
if (tag.find("COLOR=") != std::string::npos)
/* GraphicElement */
GraphicElement::GraphicElement(MyGUI::Widget * parent, Paginator & pag)
: mParent(parent), mPaginator(pag)
{
int color_start = tag.find("COLOR=")+7;
std::string color = tag.substr(color_start, tag.find('"', color_start)-color_start);
}
mTextStyle.mColour = MyGUI::Colour(
convertFromHex(color.substr(0, 2))/255.0,
convertFromHex(color.substr(2, 2))/255.0,
convertFromHex(color.substr(4, 2))/255.0);
void GraphicElement::paginate()
{
int newTop = mPaginator.getCurrentTop() + getHeight();
while (newTop-mPaginator.getStartTop() > mPaginator.getPageHeight())
{
int newStartTop = pageSplit();
mPaginator << Paginator::Page(mPaginator.getStartTop(), newStartTop);
mPaginator.setStartTop(newStartTop);
}
mPaginator.setCurrentTop(newTop);
}
if (tag.find("FACE=") != std::string::npos)
int GraphicElement::pageSplit()
{
int face_start = tag.find("FACE=")+6;
std::string face = tag.substr(face_start, tag.find('"', face_start)-face_start);
return mPaginator.getStartTop() + mPaginator.getPageHeight();
}
if (face != "Magic Cards")
mTextStyle.mFont = face;
/* TextElement */
TextElement::TextElement(MyGUI::Widget * parent, Paginator & pag,
const TextStyle & style, const std::string & text)
: GraphicElement(parent, pag),
mStyle(style)
{
MyGUI::EditBox* box = parent->createWidget<MyGUI::EditBox>("NormalText",
MyGUI::IntCoord(0, pag.getCurrentTop(), pag.getPageWidth(), 0), MyGUI::Align::Left | MyGUI::Align::Top,
parent->getName() + boost::lexical_cast<std::string>(parent->getChildCount()));
box->setProperty("Static", "true");
box->setProperty("MultiLine", "true");
box->setProperty("WordWrap", "true");
box->setProperty("NeedMouse", "false");
box->setMaxTextLength(text.size());
box->setTextAlign(mStyle.mTextAlign);
box->setTextColour(mStyle.mColour);
box->setFontName(mStyle.mFont);
box->setCaption(MyGUI::TextIterator::toTagsString(text));
box->setSize(box->getSize().width, box->getTextSize().height);
mEditBox = box;
}
if (tag.find("SIZE=") != std::string::npos)
int TextElement::currentFontHeight() const
{
/// \todo
std::string fontName(mStyle.mFont == "Default" ? MyGUI::FontManager::getInstance().getDefaultFont() : mStyle.mFont);
return MyGUI::FontManager::getInstance().getByName(fontName)->getDefaultHeight();
}
}
void BookTextParser::parseSubText(std::string text)
{
if (text[0] == '<')
int TextElement::getHeight()
{
const size_t tagStart = 1;
const size_t tagEnd = text.find('>', tagStart);
if (tagEnd == std::string::npos)
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
const std::string tag = text.substr(tagStart, tagEnd - tagStart);
if (boost::algorithm::starts_with(tag, "IMG"))
parseImage(tag);
if (boost::algorithm::starts_with(tag, "FONT"))
parseFont(tag);
if (boost::algorithm::starts_with(tag, "DIV"))
parseDiv(tag);
text.erase(0, tagEnd + 1);
return mEditBox->getTextSize().height;
}
size_t tagStart = std::string::npos;
std::string realText; // real text, without tags
for (size_t i = 0; i<text.size(); ++i)
int TextElement::pageSplit()
{
char c = text[i];
if (c == '<')
// split lines
const int lineHeight = currentFontHeight();
unsigned int lastLine = (mPaginator.getStartTop() + mPaginator.getPageHeight() - mPaginator.getCurrentTop()) / lineHeight;
int ret = mPaginator.getCurrentTop() + lastLine * lineHeight;
// first empty lines that would go to the next page should be ignored
// unfortunately, getLineInfo method won't be available until 3.2.2
#if (MYGUI_VERSION >= MYGUI_DEFINE_VERSION(3, 2, 2))
const MyGUI::VectorLineInfo & lines = mEditBox->getSubWidgetText()->castType<MyGUI::EditText>()->getLineInfo();
for (unsigned int i = lastLine; i < lines.size(); ++i)
{
if ((i + 1 < text.size()) && text[i+1] == '/') // ignore closing tags
{
while (c != '>')
{
if (i >= text.size())
throw std::runtime_error("BookTextParser Error: Tag is not terminated");
++i;
c = text[i];
}
continue;
}
if (lines[i].width == 0)
ret += lineHeight;
else
{
tagStart = i;
break;
}
}
else
realText += c;
#endif
return ret;
}
MyGUI::EditBox* box = mParent->createWidget<MyGUI::EditBox>("NormalText",
MyGUI::IntCoord(0, mHeight, mWidth, 24), MyGUI::Align::Left | MyGUI::Align::Top,
mParent->getName() + boost::lexical_cast<std::string>(mParent->getChildCount()));
box->setProperty("Static", "true");
box->setProperty("MultiLine", "true");
box->setProperty("WordWrap", "true");
box->setProperty("NeedMouse", "false");
box->setMaxTextLength(realText.size());
box->setTextAlign(mTextStyle.mTextAlign);
box->setTextColour(mTextStyle.mColour);
box->setFontName(mTextStyle.mFont);
box->setCaption(MyGUI::TextIterator::toTagsString(realText));
box->setSize(box->getSize().width, box->getTextSize().height);
mHeight += box->getTextSize().height;
if (tagStart != std::string::npos)
/* ImageElement */
ImageElement::ImageElement(MyGUI::Widget * parent, Paginator & pag,
const std::string & src, int width, int height)
: GraphicElement(parent, pag),
mImageHeight(height)
{
parseSubText(text.substr(tagStart, text.size()));
mImageBox = parent->createWidget<MyGUI::ImageBox> ("ImageBox",
MyGUI::IntCoord(0, pag.getCurrentTop(), width, mImageHeight), MyGUI::Align::Left | MyGUI::Align::Top,
parent->getName() + boost::lexical_cast<std::string>(parent->getChildCount()));
std::string image = Misc::ResourceHelpers::correctBookartPath(src, width, mImageHeight);
mImageBox->setImageTexture(image);
mImageBox->setProperty("NeedMouse", "false");
}
}
int ImageElement::getHeight()
{
return mImageHeight;
}
int ImageElement::pageSplit()
{
// if the image is larger than the page, fall back to the default pageSplit implementation
if (mImageHeight > mPaginator.getPageHeight())
return GraphicElement::pageSplit();
return mPaginator.getCurrentTop();
}
}
}

@ -2,66 +2,150 @@
#define MWGUI_FORMATTING_H
#include <MyGUI.h>
#include <map>
namespace MWGui
{
struct TextStyle
namespace Formatting
{
TextStyle() :
mColour(0,0,0)
, mFont("Default")
, mTextSize(16)
, mTextAlign(MyGUI::Align::Left | MyGUI::Align::Top)
struct TextStyle
{
}
TextStyle() :
mColour(0,0,0)
, mFont("Default")
, mTextSize(16)
, mTextAlign(MyGUI::Align::Left | MyGUI::Align::Top)
{
}
MyGUI::Colour mColour;
std::string mFont;
int mTextSize;
MyGUI::Align mTextAlign;
};
MyGUI::Colour mColour;
std::string mFont;
int mTextSize;
MyGUI::Align mTextAlign;
};
/// \brief utilities for parsing book/scroll text as mygui widgets
class BookTextParser
{
public:
/**
* Parse markup as MyGUI widgets
* @param markup to parse
* @param parent for the created widgets
* @param maximum width
* @return size of the created widgets
*/
MyGUI::IntSize parsePage(std::string text, MyGUI::Widget* parent, const int width);
/**
* Parse markup as MyGUI widgets
* @param markup to parse
* @param parent for the created widgets
* @param maximum width
* @return size of the created widgets
*/
MyGUI::IntSize parseScroll(std::string text, MyGUI::Widget* parent, const int width);
/**
* Split the specified text into pieces that fit in the area specified by width and height parameters
*/
std::vector<std::string> split(std::string text, const int width, const int height);
protected:
float widthForCharGlyph(unsigned unicodeChar) const;
float currentFontHeight() const;
void parseSubText(std::string text);
void parseImage(std::string tag, bool createWidget=true);
void parseDiv(std::string tag);
void parseFont(std::string tag);
private:
MyGUI::Widget* mParent;
int mWidth; // maximum width
int mHeight; // current height
TextStyle mTextStyle;
};
class BookTextParser
{
public:
typedef std::map<std::string, std::string> Attributes;
enum Events
{
Event_None = -2,
Event_EOF = -1,
Event_BrTag,
Event_PTag,
Event_ImgTag,
Event_DivTag,
Event_FontTag
};
BookTextParser(const std::string & text);
void registerTag(const std::string & tag, Events type);
std::string getReadyText();
Events next();
void flushBuffer();
const Attributes & getAttributes() const;
void parseTag(std::string tag);
private:
size_t mIndex;
std::string mText;
std::string mReadyText;
bool mIgnoreNewlineTags;
bool mIgnoreLineEndings;
Attributes mAttributes;
std::string mTag;
std::map<std::string, Events> mTagTypes;
std::string mBuffer;
};
class Paginator
{
public:
typedef std::pair<int, int> Page;
typedef std::vector<Page> Pages;
Paginator(int pageWidth, int pageHeight)
: mStartTop(0), mCurrentTop(0),
mPageWidth(pageWidth), mPageHeight(pageHeight)
{
}
int getStartTop() const { return mStartTop; }
int getCurrentTop() const { return mCurrentTop; }
int getPageWidth() const { return mPageWidth; }
int getPageHeight() const { return mPageHeight; }
Pages getPages() const { return mPages; }
void setStartTop(int top) { mStartTop = top; }
void setCurrentTop(int top) { mCurrentTop = top; }
Paginator & operator<<(const Page & page)
{
mPages.push_back(page);
return *this;
}
private:
int mStartTop, mCurrentTop;
int mPageWidth, mPageHeight;
Pages mPages;
};
/// \brief utilities for parsing book/scroll text as mygui widgets
class BookFormatter
{
public:
Paginator::Pages markupToWidget(MyGUI::Widget * parent, const std::string & markup, const int pageWidth, const int pageHeight);
Paginator::Pages markupToWidget(MyGUI::Widget * parent, const std::string & markup);
protected:
void handleImg(const BookTextParser::Attributes & attr);
void handleDiv(const BookTextParser::Attributes & attr);
void handleFont(const BookTextParser::Attributes & attr);
private:
TextStyle mTextStyle;
};
class GraphicElement
{
public:
GraphicElement(MyGUI::Widget * parent, Paginator & pag);
virtual int getHeight() = 0;
virtual void paginate();
virtual int pageSplit();
protected:
MyGUI::Widget * mParent;
Paginator & mPaginator;
};
class TextElement : public GraphicElement
{
public:
TextElement(MyGUI::Widget * parent, Paginator & pag, const TextStyle & style, const std::string & text);
virtual int getHeight();
virtual int pageSplit();
private:
int currentFontHeight() const;
TextStyle mStyle;
MyGUI::EditBox * mEditBox;
};
class ImageElement : public GraphicElement
{
public:
ImageElement(MyGUI::Widget * parent, Paginator & pag, const std::string & src, int width, int height);
virtual int getHeight();
virtual int pageSplit();
private:
int mImageHeight;
MyGUI::ImageBox * mImageBox;
};
}
}
#endif

@ -278,14 +278,14 @@ namespace MWGui
if (item.mType == ItemStack::Type_Barter)
{
// this was an item borrowed to us by the merchant
MWBase::Environment::get().getWindowManager()->getTradeWindow()->returnItem(mSelectedItem, count);
mTradeModel->returnItemBorrowedToUs(mSelectedItem, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->returnItem(mSelectedItem, count);
}
else
{
// borrow item to the merchant
MWBase::Environment::get().getWindowManager()->getTradeWindow()->borrowItem(mSelectedItem, count);
mTradeModel->borrowItemFromUs(mSelectedItem, count);
MWBase::Environment::get().getWindowManager()->getTradeWindow()->borrowItem(mSelectedItem, count);
}
mItemView->update();

@ -36,7 +36,8 @@ namespace MWGui
Misc::StringUtils::toLower(currentGMSTID);
// Don't bother checking this GMST if it's not a sMagicBound* one.
if (currentGMSTID.find("smagicbound") != 0)
const std::string& toFind = "smagicbound";
if (currentGMSTID.compare(0, toFind.length(), toFind) != 0)
continue;
// All sMagicBound* GMST's should be of type string

@ -113,10 +113,10 @@ struct JournalViewModelImpl : JournalViewModel
utf8text = getText ();
size_t pos_begin, pos_end;
size_t pos_end = 0;
for(;;)
{
pos_begin = utf8text.find('@');
size_t pos_begin = utf8text.find('@');
if (pos_begin != std::string::npos)
pos_end = utf8text.find('#', pos_begin);
@ -223,15 +223,6 @@ struct JournalViewModelImpl : JournalViewModel
}
}
void visitQuestName (QuestId questId, boost::function <void (Utf8Span)> visitor) const
{
MWDialogue::Quest const * quest = reinterpret_cast <MWDialogue::Quest const *> (questId);
std::string name = quest->getName ();
visitor (toUtf8Span (name));
}
template <typename iterator_t>
struct JournalEntryImpl : BaseEntry <iterator_t, JournalEntry>
{
@ -301,11 +292,6 @@ struct JournalViewModelImpl : JournalViewModel
}
}
void visitTopics (boost::function <void (TopicId, Utf8Span)> visitor) const
{
throw std::runtime_error ("not implemented");
}
void visitTopicName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const
{
MWDialogue::Topic const & topic = * reinterpret_cast <MWDialogue::Topic const *> (topicId);

@ -67,9 +67,6 @@ namespace MWGui
/// returns true if their are no journal entries to display
virtual bool isEmpty () const = 0;
/// provides access to the name of the quest with the specified identifier
virtual void visitQuestName (TopicId topicId, boost::function <void (Utf8Span)> visitor) const = 0;
/// walks the active and optionally completed, quests providing the name
virtual void visitQuestNames (bool active_only, boost::function <void (const std::string&)> visitor) const = 0;

@ -4,7 +4,6 @@
#include "../mwbase/soundmanager.hpp"
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/journal.hpp"
#include "list.hpp"
#include <sstream>
#include <set>
@ -16,12 +15,12 @@
#include "boost/lexical_cast.hpp"
#include <components/widgets/imagebutton.hpp>
#include <components/widgets/list.hpp>
#include "bookpage.hpp"
#include "windowbase.hpp"
#include "journalviewmodel.hpp"
#include "journalbooks.hpp"
#include "list.hpp"
namespace
{
@ -111,10 +110,10 @@ namespace
adviseButtonClick (ShowAllBTN, &JournalWindowImpl::notifyShowAll );
adviseButtonClick (ShowActiveBTN, &JournalWindowImpl::notifyShowActive);
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(QuestsList);
Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
list->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyQuestClicked);
MWGui::Widgets::MWList* topicsList = getWidget<MWGui::Widgets::MWList>(TopicsList);
Gui::MWList* topicsList = getWidget<Gui::MWList>(TopicsList);
topicsList->eventItemSelected += MyGUI::newDelegate(this, &JournalWindowImpl::notifyTopicSelected);
{
@ -394,25 +393,13 @@ namespace
popBook ();
}
void showList (char const * listId, char const * pageId, Book book)
{
std::pair <int, int> size = book->getSize ();
getPage (pageId)->showPage (book, 0);
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
getWidget <MyGUI::ScrollView> (listId)->setVisibleVScroll(false);
getWidget <MyGUI::ScrollView> (listId)->setCanvasSize (size.first, size.second);
getWidget <MyGUI::ScrollView> (listId)->setVisibleVScroll(true);
}
void notifyIndexLinkClicked (MWGui::TypesetBook::InteractiveId character)
{
setVisible (LeftTopicIndex, false);
setVisible (RightTopicIndex, false);
setVisible (TopicsList, true);
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(TopicsList);
Gui::MWList* list = getWidget<Gui::MWList>(TopicsList);
list->clear();
AddNamesToList add(list);
@ -435,9 +422,9 @@ namespace
struct AddNamesToList
{
AddNamesToList(MWGui::Widgets::MWList* list) : mList(list) {}
AddNamesToList(Gui::MWList* list) : mList(list) {}
MWGui::Widgets::MWList* mList;
Gui::MWList* mList;
void operator () (const std::string& name)
{
mList->addItem(name);
@ -455,7 +442,7 @@ namespace
setVisible (ShowAllBTN, !mAllQuests);
setVisible (ShowActiveBTN, mAllQuests);
MWGui::Widgets::MWList* list = getWidget<MWGui::Widgets::MWList>(QuestsList);
Gui::MWList* list = getWidget<Gui::MWList>(QuestsList);
list->clear();
AddNamesToList add(list);

@ -5,6 +5,7 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/fallback.hpp"
@ -139,7 +140,7 @@ namespace MWGui
// Vanilla uses thief.dds for custom classes.
// Choosing Stealth specialization and Speed/Agility as attributes, if possible. Otherwise fall back to first class found.
MWWorld::SharedIterator<ESM::Class> it = world->getStore().get<ESM::Class>().begin();
for(; it != world->getStore().get<ESM::Class>().end(); it++)
for(; it != world->getStore().get<ESM::Class>().end(); ++it)
{
if(it->mData.mIsPlayable && it->mData.mSpecialization == 2 && it->mData.mAttribute[0] == 4 && it->mData.mAttribute[1] == 3)
break;
@ -191,6 +192,9 @@ namespace MWGui
setAttributeValues();
center();
// Play LevelUp Music
MWBase::Environment::get().getSoundManager()->streamMusic("Special/MW_Triumph.mp3");
}
void LevelupDialog::onOkButtonClicked(MyGUI::Widget* sender)

@ -1,169 +0,0 @@
#include "list.hpp"
#include <MyGUI_Gui.h>
#include <MyGUI_Button.h>
#include <MyGUI_ImageBox.h>
#include <MyGUI_ScrollBar.h>
namespace MWGui
{
namespace Widgets
{
MWList::MWList() :
mClient(0)
, mScrollView(0)
, mItemHeight(0)
{
}
void MWList::initialiseOverride()
{
Base::initialiseOverride();
assignWidget(mClient, "Client");
if (mClient == 0)
mClient = this;
mScrollView = mClient->createWidgetReal<MyGUI::ScrollView>(
"MW_ScrollView", MyGUI::FloatCoord(0.0, 0.0, 1.0, 1.0),
MyGUI::Align::Top | MyGUI::Align::Left | MyGUI::Align::Stretch, getName() + "_ScrollView");
}
void MWList::addItem(const std::string& name)
{
mItems.push_back(name);
}
void MWList::addSeparator()
{
mItems.push_back("");
}
void MWList::adjustSize()
{
redraw();
}
void MWList::redraw(bool scrollbarShown)
{
const int _scrollBarWidth = 20; // fetch this from skin?
const int scrollBarWidth = scrollbarShown ? _scrollBarWidth : 0;
const int spacing = 3;
size_t viewPosition = -mScrollView->getViewOffset().top;
while (mScrollView->getChildCount())
{
MyGUI::Gui::getInstance().destroyWidget(mScrollView->getChildAt(0));
}
mItemHeight = 0;
int i=0;
for (std::vector<std::string>::const_iterator it=mItems.begin();
it!=mItems.end(); ++it)
{
if (*it != "")
{
if (mListItemSkin.empty())
throw std::runtime_error("MWList needs a ListItemSkin property");
MyGUI::Button* button = mScrollView->createWidget<MyGUI::Button>(
mListItemSkin, MyGUI::IntCoord(0, mItemHeight, mScrollView->getSize().width - scrollBarWidth - 2, 24),
MyGUI::Align::Left | MyGUI::Align::Top, getName() + "_item_" + (*it));
button->setCaption((*it));
button->getSubWidgetText()->setWordWrap(true);
button->getSubWidgetText()->setTextAlign(MyGUI::Align::Left);
button->eventMouseWheel += MyGUI::newDelegate(this, &MWList::onMouseWheel);
button->eventMouseButtonClick += MyGUI::newDelegate(this, &MWList::onItemSelected);
int height = button->getTextSize().height;
button->setSize(MyGUI::IntSize(button->getSize().width, height));
button->setUserData(i);
mItemHeight += height + spacing;
}
else
{
MyGUI::ImageBox* separator = mScrollView->createWidget<MyGUI::ImageBox>("MW_HLine",
MyGUI::IntCoord(2, mItemHeight, mScrollView->getWidth() - scrollBarWidth - 4, 18),
MyGUI::Align::Left | MyGUI::Align::Top | MyGUI::Align::HStretch);
separator->setNeedMouseFocus(false);
mItemHeight += 18 + spacing;
}
++i;
}
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
mScrollView->setVisibleVScroll(false);
mScrollView->setCanvasSize(mClient->getSize().width, std::max(mItemHeight, mClient->getSize().height));
mScrollView->setVisibleVScroll(true);
if (!scrollbarShown && mItemHeight > mClient->getSize().height)
redraw(true);
size_t viewRange = mScrollView->getCanvasSize().height;
if(viewPosition > viewRange)
viewPosition = viewRange;
mScrollView->setViewOffset(MyGUI::IntPoint(0, viewPosition * -1));
}
void MWList::setPropertyOverride(const std::string &_key, const std::string &_value)
{
if (_key == "ListItemSkin")
mListItemSkin = _value;
else
Base::setPropertyOverride(_key, _value);
}
bool MWList::hasItem(const std::string& name)
{
return (std::find(mItems.begin(), mItems.end(), name) != mItems.end());
}
unsigned int MWList::getItemCount()
{
return mItems.size();
}
std::string MWList::getItemNameAt(unsigned int at)
{
assert(at < mItems.size() && "List item out of bounds");
return mItems[at];
}
void MWList::removeItem(const std::string& name)
{
assert( std::find(mItems.begin(), mItems.end(), name) != mItems.end() );
mItems.erase( std::find(mItems.begin(), mItems.end(), name) );
}
void MWList::clear()
{
mItems.clear();
}
void MWList::onMouseWheel(MyGUI::Widget* _sender, int _rel)
{
//NB view offset is negative
if (mScrollView->getViewOffset().top + _rel*0.3 > 0)
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
else
mScrollView->setViewOffset(MyGUI::IntPoint(0, mScrollView->getViewOffset().top + _rel*0.3));
}
void MWList::onItemSelected(MyGUI::Widget* _sender)
{
std::string name = _sender->castType<MyGUI::Button>()->getCaption();
int id = *_sender->getUserData<int>();
eventItemSelected(name, id);
eventWidgetSelected(_sender);
}
MyGUI::Widget* MWList::getItemWidget(const std::string& name)
{
return mScrollView->findWidget (getName() + "_item_" + name);
}
}
}

@ -1,74 +0,0 @@
#ifndef MWGUI_LIST_HPP
#define MWGUI_LIST_HPP
#include <MyGUI_ScrollView.h>
namespace MWGui
{
namespace Widgets
{
/**
* \brief a very simple list widget that supports word-wrapping entries
* \note if the width or height of the list changes, you must call adjustSize() method
*/
class MWList : public MyGUI::Widget
{
MYGUI_RTTI_DERIVED(MWList)
public:
MWList();
typedef MyGUI::delegates::CMultiDelegate2<const std::string&, int> EventHandle_StringInt;
typedef MyGUI::delegates::CMultiDelegate1<MyGUI::Widget*> EventHandle_Widget;
/**
* Event: Item selected with the mouse.
* signature: void method(std::string itemName, int index)
*/
EventHandle_StringInt eventItemSelected;
/**
* Event: Item selected with the mouse.
* signature: void method(MyGUI::Widget* sender)
*/
EventHandle_Widget eventWidgetSelected;
/**
* Call after the size of the list changed, or items were inserted/removed
*/
void adjustSize();
void addItem(const std::string& name);
void addSeparator(); ///< add a seperator between the current and the next item.
void removeItem(const std::string& name);
bool hasItem(const std::string& name);
unsigned int getItemCount();
std::string getItemNameAt(unsigned int at); ///< \attention if there are separators, this method will return "" at the place where the separator is
void clear();
MyGUI::Widget* getItemWidget(const std::string& name);
///< get widget for an item name, useful to set up tooltip
virtual void setPropertyOverride(const std::string& _key, const std::string& _value);
protected:
void initialiseOverride();
void redraw(bool scrollbarShown = false);
void onMouseWheel(MyGUI::Widget* _sender, int _rel);
void onItemSelected(MyGUI::Widget* _sender);
private:
MyGUI::ScrollView* mScrollView;
MyGUI::Widget* mClient;
std::string mListItemSkin;
std::vector<std::string> mItems;
int mItemHeight; // height of all items
};
}
}
#endif

@ -26,15 +26,55 @@ namespace
const int cellSize = 8192;
enum WidgetDepth
enum LocalMapWidgetDepth
{
CompassLayer = 0,
MarkerAboveFogLayer = 1,
FogLayer = 2,
MarkerLayer = 3,
MapLayer = 4
Local_CompassLayer = 0,
Local_MarkerAboveFogLayer = 1,
Local_FogLayer = 2,
Local_MarkerLayer = 3,
Local_MapLayer = 4
};
enum GlobalMapWidgetDepth
{
Global_CompassLayer = 0,
Global_MarkerLayer = 1,
Global_ExploreOverlayLayer = 2,
Global_MapLayer = 3
};
/// @brief A widget that changes its color when hovered.
class MarkerWidget: public MyGUI::Widget
{
MYGUI_RTTI_DERIVED(MarkerWidget)
public:
void setNormalColour(const MyGUI::Colour& colour)
{
mNormalColour = colour;
setColour(colour);
}
void setHoverColour(const MyGUI::Colour& colour)
{
mHoverColour = colour;
}
private:
MyGUI::Colour mNormalColour;
MyGUI::Colour mHoverColour;
void onMouseLostFocus(MyGUI::Widget* _new)
{
setColour(mNormalColour);
}
void onMouseSetFocus(MyGUI::Widget* _old)
{
setColour(mHoverColour);
}
};
}
namespace MWGui
@ -140,7 +180,7 @@ namespace MWGui
mLocalMap = widget;
mCompass = compass;
mCompass->setDepth(CompassLayer);
mCompass->setDepth(Local_CompassLayer);
mCompass->setNeedMouseFocus(false);
// create 3x3 map widgets, 512x512 each, holding a 1024x1024 texture each
@ -151,12 +191,12 @@ namespace MWGui
MyGUI::ImageBox* map = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize),
MyGUI::Align::Top | MyGUI::Align::Left);
map->setDepth(MapLayer);
map->setDepth(Local_MapLayer);
MyGUI::ImageBox* fog = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
MyGUI::IntCoord(mx*widgetSize, my*widgetSize, widgetSize, widgetSize),
MyGUI::Align::Top | MyGUI::Align::Left);
fog->setDepth(FogLayer);
fog->setDepth(Local_FogLayer);
map->setNeedMouseFocus(false);
fog->setNeedMouseFocus(false);
@ -273,16 +313,17 @@ namespace MWGui
MyGUI::IntCoord widgetCoord(widgetPos.left - 4,
widgetPos.top - 4,
8, 8);
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
MarkerWidget* markerWidget = mLocalMap->createWidget<MarkerWidget>("MarkerButton",
widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerAboveFogLayer);
markerWidget->setImageResource("DoorMarker");
markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote));
markerWidget->setColour(MyGUI::Colour(1.0,0.3,0.3));
markerWidget->setNormalColour(MyGUI::Colour(1.0,0.3,0.3));
markerWidget->setHoverColour(MyGUI::Colour(1.0,0.5,0.5));
markerWidget->setUserData(marker);
markerWidget->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &LocalMapBase::onCustomMarkerDoubleClicked);
markerWidget->setNeedMouseFocus(true);
customMarkerCreated(markerWidget);
mCustomMarkerWidgets.push_back(markerWidget);
}
redraw();
@ -357,16 +398,19 @@ namespace MWGui
widgetPos.top - 4,
8, 8);
++counter;
MyGUI::Button* markerWidget = mLocalMap->createWidget<MyGUI::Button>("ButtonImage",
MarkerWidget* markerWidget = mLocalMap->createWidget<MarkerWidget>("MarkerButton",
widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerLayer);
markerWidget->setImageResource("DoorMarker");
markerWidget->setNormalColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}")));
markerWidget->setHoverColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal_over}")));
markerWidget->setDepth(Local_MarkerLayer);
markerWidget->setNeedMouseFocus(true);
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", marker.name);
// Used by tooltips to not show the tooltip if marker is hidden by fog of war
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
doorMarkerCreated(markerWidget);
mDoorMarkerWidgets.push_back(markerWidget);
}
@ -458,7 +502,7 @@ namespace MWGui
++counter;
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerAboveFogLayer);
markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setImageTexture(markerTexture);
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
@ -503,7 +547,7 @@ namespace MWGui
8, 8);
MyGUI::ImageBox* markerWidget = mLocalMap->createWidget<MyGUI::ImageBox>("ImageBox",
widgetCoord, MyGUI::Align::Default);
markerWidget->setDepth(MarkerAboveFogLayer);
markerWidget->setDepth(Local_MarkerAboveFogLayer);
markerWidget->setImageTexture("textures\\menu_map_smark.dds");
markerWidget->setUserString("IsMarker", "true");
markerWidget->setUserData(markerPos);
@ -523,7 +567,18 @@ namespace MWGui
, mGlobalMap(0)
, mGlobalMapRender(0)
, mEditNoteDialog()
, mEventBoxGlobal(NULL)
, mEventBoxLocal(NULL)
, mGlobalMapImage(NULL)
, mGlobalMapOverlay(NULL)
{
static bool registered = false;
if (!registered)
{
MyGUI::FactoryManager::getInstance().registerFactory<MarkerWidget>("Widget");
registered = true;
}
mEditNoteDialog.setVisible(false);
mEditNoteDialog.eventOkClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditOk);
mEditNoteDialog.eventDeleteClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditDelete);
@ -537,6 +592,11 @@ namespace MWGui
getWidget(mPlayerArrowLocal, "CompassLocal");
getWidget(mPlayerArrowGlobal, "CompassGlobal");
mPlayerArrowGlobal->setDepth(Global_CompassLayer);
mPlayerArrowGlobal->setNeedMouseFocus(false);
mGlobalMapImage->setDepth(Global_MapLayer);
mGlobalMapOverlay->setDepth(Global_ExploreOverlayLayer);
mLastScrollWindowCoordinates = mLocalMap->getCoord();
mLocalMap->eventChangeCoord += MyGUI::newDelegate(this, &MapWindow::onChangeScrollWindowCoord);
@ -549,6 +609,8 @@ namespace MWGui
getWidget(mEventBoxGlobal, "EventBoxGlobal");
mEventBoxGlobal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
mEventBoxGlobal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
mEventBoxGlobal->setDepth(Global_ExploreOverlayLayer);
getWidget(mEventBoxLocal, "EventBoxLocal");
mEventBoxLocal->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
mEventBoxLocal->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
@ -672,34 +734,32 @@ namespace MWGui
void MapWindow::addVisitedLocation(const std::string& name, int x, int y)
{
float worldX, worldY;
mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY);
MyGUI::IntCoord widgetCoord(
worldX * mGlobalMapRender->getWidth()+6,
worldY * mGlobalMapRender->getHeight()+6,
12, 12);
static int _counter=0;
MyGUI::Button* markerWidget = mGlobalMapOverlay->createWidget<MyGUI::Button>("ButtonImage",
widgetCoord, MyGUI::Align::Default);
markerWidget->setImageResource("DoorMarker");
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
++_counter;
markerWidget = mEventBoxGlobal->createWidget<MyGUI::Button>("",
widgetCoord, MyGUI::Align::Default);
markerWidget->setNeedMouseFocus (true);
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
CellId cell;
cell.first = x;
cell.second = y;
mMarkers.push_back(cell);
if (mMarkers.insert(cell).second)
{
float worldX, worldY;
mGlobalMapRender->cellTopLeftCornerToImageSpace (x, y, worldX, worldY);
int markerSize = 12;
int offset = mGlobalMapRender->getCellSize()/2 - markerSize/2;
MyGUI::IntCoord widgetCoord(
worldX * mGlobalMapRender->getWidth()+offset,
worldY * mGlobalMapRender->getHeight()+offset,
markerSize, markerSize);
MyGUI::Widget* markerWidget = mGlobalMap->createWidget<MyGUI::Widget>("MarkerButton",
widgetCoord, MyGUI::Align::Default);
markerWidget->setNeedMouseFocus(true);
markerWidget->setColour(MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=normal}")));
markerWidget->setUserString("ToolTipType", "Layout");
markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine");
markerWidget->setUserString("Caption_TextOneLine", name);
markerWidget->setDepth(Global_MarkerLayer);
markerWidget->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
markerWidget->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
}
}
void MapWindow::cellExplored(int x, int y)
@ -827,8 +887,6 @@ namespace MWGui
while (mEventBoxGlobal->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mEventBoxGlobal->getChildAt(0));
while (mGlobalMapOverlay->getChildCount())
MyGUI::Gui::getInstance().destroyWidget(mGlobalMapOverlay->getChildAt(0));
}
void MapWindow::write(ESM::ESMWriter &writer, Loading::Listener& progress)
@ -853,7 +911,7 @@ namespace MWGui
mGlobalMapRender->read(map);
for (std::vector<ESM::GlobalMap::CellId>::iterator it = map.mMarkers.begin(); it != map.mMarkers.end(); ++it)
for (std::set<ESM::GlobalMap::CellId>::iterator it = map.mMarkers.begin(); it != map.mMarkers.end(); ++it)
{
const ESM::Cell* cell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Cell>().search(it->first, it->second);
if (cell && !cell->mName.empty())
@ -871,6 +929,19 @@ namespace MWGui
(*it)->setVisible(alpha == 1);
}
void MapWindow::customMarkerCreated(MyGUI::Widget *marker)
{
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
marker->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &MapWindow::onCustomMarkerDoubleClicked);
}
void MapWindow::doorMarkerCreated(MyGUI::Widget *marker)
{
marker->eventMouseDrag += MyGUI::newDelegate(this, &MapWindow::onMouseDrag);
marker->eventMouseButtonPressed += MyGUI::newDelegate(this, &MapWindow::onDragStart);
}
// -------------------------------------------------------------------
EditNoteDialog::EditNoteDialog()

@ -119,7 +119,8 @@ namespace MWGui
virtual void notifyPlayerUpdate() {}
virtual void notifyMapChanged() {}
virtual void onCustomMarkerDoubleClicked(MyGUI::Widget* sender) {}
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
void updateMagicMarkers();
void addDetectionMarkers(int type);
@ -199,6 +200,7 @@ namespace MWGui
void onMouseDrag(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onWorldButtonClicked(MyGUI::Widget* _sender);
void onMapDoubleClicked(MyGUI::Widget* sender);
void onCustomMarkerDoubleClicked(MyGUI::Widget* sender);
void onNoteEditOk();
void onNoteEditDelete();
void onNoteEditDeleteConfirm();
@ -219,7 +221,7 @@ namespace MWGui
// Markers on global map
typedef std::pair<int, int> CellId;
std::vector<CellId> mMarkers;
std::set<CellId> mMarkers;
// Cells that should be explored in the next frame (i.e. their map revealed on the global map)
// We can't do this immediately, because the map update is not immediate either (see mNeedMapUpdate in scene.cpp)
@ -235,7 +237,9 @@ namespace MWGui
virtual void onPinToggled();
virtual void onTitleDoubleClicked();
virtual void onCustomMarkerDoubleClicked(MyGUI::Widget* sender);
virtual void doorMarkerCreated(MyGUI::Widget* marker);
virtual void customMarkerCreated(MyGUI::Widget *marker);
virtual void notifyPlayerUpdate();

@ -139,11 +139,6 @@ namespace MWGui
return false;
}
void MessageBoxManager::setMessageBoxSpeed (int speed)
{
mMessageBoxSpeed = speed;
}
int MessageBoxManager::readPressedButton ()
{
int pressed = mLastButtonPressed;
@ -218,7 +213,6 @@ namespace MWGui
MyGUI::IntSize gameWindowSize = MyGUI::RenderManager::getInstance().getViewSize();
int biggestButtonWidth = 0;
int buttonWidth = 0;
int buttonsWidth = 0;
int buttonsHeight = 0;
int buttonHeight = 0;
@ -241,7 +235,7 @@ namespace MWGui
if (buttonsWidth != 0)
buttonsWidth += buttonLeftPadding;
buttonWidth = button->getTextSize().width + 2*buttonPadding;
int buttonWidth = button->getTextSize().width + 2*buttonPadding;
buttonsWidth += buttonWidth;
buttonHeight = button->getTextSize().height + 2*buttonPadding;

@ -34,7 +34,6 @@ namespace MWGui
void clear();
bool removeMessageBox (MessageBox *msgbox);
void setMessageBoxSpeed (int speed);
int readPressedButton ();

@ -393,7 +393,6 @@ namespace MWGui
if (mCurrentRaceId.empty())
return;
Widgets::MWSpellPtr spellPowerWidget;
const int lineHeight = 18;
MyGUI::IntCoord coord(0, 0, mSpellPowerList->getWidth(), 18);
@ -405,7 +404,7 @@ namespace MWGui
for (int i = 0; it != end; ++it)
{
const std::string &spellpower = *it;
spellPowerWidget = mSpellPowerList->createWidget<Widgets::MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast<std::string>(i));
Widgets::MWSpellPtr spellPowerWidget = mSpellPowerList->createWidget<Widgets::MWSpell>("MW_StatName", coord, MyGUI::Align::Default, std::string("SpellPower") + boost::lexical_cast<std::string>(i));
spellPowerWidget->setSpellId(spellpower);
spellPowerWidget->setUserString("ToolTipType", "Spell");
spellPowerWidget->setUserString("Spell", spellpower);

@ -322,7 +322,8 @@ namespace MWGui
if (i == pos)
mCurrentSlot = &*it;
}
assert(mCurrentSlot && "Can't find selected slot");
if (!mCurrentSlot)
throw std::runtime_error("Can't find selected slot");
std::stringstream text;
time_t time = mCurrentSlot->mTimeStamp;

@ -54,8 +54,9 @@ namespace MWGui
MWWorld::LiveCellRef<ESM::Book> *ref = mScroll.get<ESM::Book>();
BookTextParser parser;
MyGUI::IntSize size = parser.parseScroll(ref->mBase->mText, mTextView, 390);
Formatting::BookFormatter formatter;
formatter.markupToWidget(mTextView, ref->mBase->mText, 390, mTextView->getHeight());
MyGUI::IntSize size = mTextView->getChildAt(0)->getSize();
// Canvas size must be expressed with VScroll disabled, otherwise MyGUI would expand the scroll area when the scrollbar is hidden
mTextView->setVisibleVScroll(false);

@ -362,8 +362,7 @@ namespace MWGui
void SettingsWindow::onShaderModeToggled(MyGUI::Widget* _sender)
{
std::string val = _sender->castType<MyGUI::Button>()->getCaption();
val = hlslGlsl();
std::string val = hlslGlsl();
_sender->castType<MyGUI::Button>()->setCaption(val);

@ -39,6 +39,7 @@ namespace MWGui
EditEffectDialog::EditEffectDialog()
: WindowModal("openmw_edit_effect.layout")
, mEditing(false)
, mMagicEffect(NULL)
{
getWidget(mCancelButton, "CancelButton");
getWidget(mOkButton, "OkButton");
@ -181,7 +182,7 @@ namespace MWGui
{
mAreaBox->setPosition(mAreaBox->getPosition().left, curY);
mAreaBox->setVisible (true);
curY += mAreaBox->getSize().height;
//curY += mAreaBox->getSize().height;
}
}
@ -522,7 +523,7 @@ namespace MWGui
updateEffectsView ();
}
void EffectEditorBase::setWidgets (Widgets::MWList *availableEffectsList, MyGUI::ScrollView *usedEffectsView)
void EffectEditorBase::setWidgets (Gui::MWList *availableEffectsList, MyGUI::ScrollView *usedEffectsView)
{
mAvailableEffectsList = availableEffectsList;
mUsedEffectsView = usedEffectsView;

@ -1,9 +1,10 @@
#ifndef MWGUI_SPELLCREATION_H
#define MWGUI_SPELLCREATION_H
#include <components/widgets/list.hpp>
#include "windowbase.hpp"
#include "referenceinterface.hpp"
#include "list.hpp"
#include "widgets.hpp"
namespace MWGui
@ -97,7 +98,7 @@ namespace MWGui
protected:
std::map<int, short> mButtonMapping; // maps button ID to effect ID
Widgets::MWList* mAvailableEffectsList;
Gui::MWList* mAvailableEffectsList;
MyGUI::ScrollView* mUsedEffectsView;
EditEffectDialog mAddEffectDialog;
@ -124,7 +125,7 @@ namespace MWGui
void updateEffectsView();
void startEditing();
void setWidgets (Widgets::MWList* availableEffectsList, MyGUI::ScrollView* usedEffectsView);
void setWidgets (Gui::MWList* availableEffectsList, MyGUI::ScrollView* usedEffectsView);
virtual void notifyEffectsChanged () {}
@ -157,8 +158,6 @@ namespace MWGui
MyGUI::Button* mCancelButton;
MyGUI::TextBox* mPriceLabel;
Widgets::MWEffectList* mUsedEffectsList;
ESM::Spell mSpell;
};

@ -2,6 +2,8 @@
#include <boost/lexical_cast.hpp>
#include <components/widgets/numericeditbox.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/soundmanager.hpp"
@ -86,7 +88,7 @@ namespace MWGui
mDecreaseButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &TradeWindow::onDecreaseButtonPressed);
mDecreaseButton->eventMouseButtonReleased += MyGUI::newDelegate(this, &TradeWindow::onBalanceButtonReleased);
mTotalBalance->eventEditTextChange += MyGUI::newDelegate(this, &TradeWindow::onBalanceEdited);
mTotalBalance->eventValueChanged += MyGUI::newDelegate(this, &TradeWindow::onBalanceValueChanged);
setCoord(400, 0, 400, 300);
}
@ -324,12 +326,12 @@ namespace MWGui
const MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
const MWMechanics::CreatureStats &playerStats = player.getClass().getCreatureStats(player);
float a1 = std::min(player.getClass().getSkill(player, ESM::Skill::Mercantile), 100);
float b1 = std::min(0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
float c1 = std::min(0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
float d1 = std::min(mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile), 100);
float e1 = std::min(0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified(), 10.f);
float f1 = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
float a1 = player.getClass().getSkill(player, ESM::Skill::Mercantile);
float b1 = 0.1f * playerStats.getAttribute(ESM::Attribute::Luck).getModified();
float c1 = 0.2f * playerStats.getAttribute(ESM::Attribute::Personality).getModified();
float d1 = mPtr.getClass().getSkill(mPtr, ESM::Skill::Mercantile);
float e1 = 0.1f * sellerStats.getAttribute(ESM::Attribute::Luck).getModified();
float f1 = 0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified();
float pcTerm = (clampedDisposition - 50 + a1 + b1 + c1) * playerStats.getFatigueTerm();
float npcTerm = (d1 + e1 + f1) * sellerStats.getFatigueTerm();
@ -352,7 +354,15 @@ namespace MWGui
}
//skill use!
player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0);
float skillGain = 0.f;
int finalPrice = std::abs(mCurrentBalance);
int initialMerchantOffer = std::abs(mCurrentMerchantOffer);
if (!buying && (finalPrice > initialMerchantOffer) && finalPrice > 0)
skillGain = int(100 * (finalPrice - initialMerchantOffer) / float(finalPrice));
else if (buying && (finalPrice < initialMerchantOffer) && initialMerchantOffer > 0)
skillGain = int(100 * (initialMerchantOffer - finalPrice) / float(initialMerchantOffer));
player.getClass().skillUsageSucceeded(player, ESM::Skill::Mercantile, 0, skillGain);
}
int iBarterSuccessDisposition = gmst.find("iBarterSuccessDisposition")->getInt();
@ -425,21 +435,14 @@ namespace MWGui
MyGUI::ControllerManager::getInstance().removeItem(_sender);
}
void TradeWindow::onBalanceEdited(MyGUI::EditBox *_sender)
void TradeWindow::onBalanceValueChanged(int value)
{
try
{
unsigned int count = boost::lexical_cast<unsigned int>(_sender->getCaption());
mCurrentBalance = count * (mCurrentBalance >= 0 ? 1 : -1);
updateLabels();
}
catch (std::bad_cast&)
{
if (_sender->getCaption().empty())
mTotalBalance->setCaption("0");
else
mTotalBalance->setCaption(boost::lexical_cast<std::string>(std::abs(mCurrentBalance)));
}
// Entering a "-" sign inverts the buying/selling state
mCurrentBalance = (mCurrentBalance >= 0 ? 1 : -1) * value;
updateLabels();
if (value != std::abs(value))
mTotalBalance->setValue(std::abs(value));
}
void TradeWindow::onIncreaseButtonTriggered()
@ -463,41 +466,52 @@ namespace MWGui
mPlayerGold->setCaptionWithReplacing("#{sYourGold} " + boost::lexical_cast<std::string>(playerGold));
std::string balanceCaption;
if (mCurrentBalance > 0)
{
mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalSold}");
balanceCaption = boost::lexical_cast<std::string>(mCurrentBalance);
}
else
{
mTotalBalanceLabel->setCaptionWithReplacing("#{sTotalCost}");
balanceCaption = boost::lexical_cast<std::string>(-mCurrentBalance);
}
if (balanceCaption != mTotalBalance->getCaption().asUTF8()) // Don't reset text cursor if text doesn't need to be changed
mTotalBalance->setCaption(balanceCaption);
mTotalBalance->setValue(std::abs(mCurrentBalance));
mMerchantGold->setCaptionWithReplacing("#{sSellerGold} " + boost::lexical_cast<std::string>(getMerchantGold()));
}
void TradeWindow::sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem)
void TradeWindow::updateOffer()
{
int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(item, count), boughtItem);
TradeItemModel* playerTradeModel = MWBase::Environment::get().getWindowManager()->getInventoryWindow()->getTradeModel();
mCurrentBalance += diff;
mCurrentMerchantOffer += diff;
int merchantOffer = 0;
std::vector<ItemStack> playerBorrowed = playerTradeModel->getItemsBorrowedToUs();
for (std::vector<ItemStack>::const_iterator it = playerBorrowed.begin(); it != playerBorrowed.end(); ++it)
{
merchantOffer -= MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(it->mBase, it->mCount), true);
}
std::vector<ItemStack> merchantBorrowed = mTradeModel->getItemsBorrowedToUs();
for (std::vector<ItemStack>::const_iterator it = merchantBorrowed.begin(); it != merchantBorrowed.end(); ++it)
{
merchantOffer += MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(it->mBase, it->mCount), false);
}
int diff = merchantOffer - mCurrentMerchantOffer;
mCurrentMerchantOffer = merchantOffer;
mCurrentBalance += diff;
updateLabels();
}
void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem)
void TradeWindow::sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem)
{
int diff = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(item, count), !soldItem);
mCurrentBalance -= diff;
mCurrentMerchantOffer -= diff;
updateOffer();
}
updateLabels();
void TradeWindow::buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem)
{
updateOffer();
}
void TradeWindow::onReferenceUnavailable()

@ -3,10 +3,9 @@
#include "container.hpp"
namespace MyGUI
namespace Gui
{
class Gui;
class Widget;
class NumericEditBox;
}
namespace MWGui
@ -54,7 +53,7 @@ namespace MWGui
MyGUI::Button* mIncreaseButton;
MyGUI::Button* mDecreaseButton;
MyGUI::TextBox* mTotalBalanceLabel;
MyGUI::EditBox* mTotalBalance;
Gui::NumericEditBox* mTotalBalance;
MyGUI::Widget* mBottomPane;
@ -72,6 +71,8 @@ namespace MWGui
void sellToNpc(const MWWorld::Ptr& item, int count, bool boughtItem); ///< only used for adjusting the gold balance
void buyFromNpc(const MWWorld::Ptr& item, int count, bool soldItem); ///< only used for adjusting the gold balance
void updateOffer();
void onItemSelected (int index);
void sellItem (MyGUI::Widget* sender, int count);
@ -82,7 +83,7 @@ namespace MWGui
void onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onBalanceButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onBalanceEdited(MyGUI::EditBox* _sender);
void onBalanceValueChanged(int value);
void onRepeatClick(MyGUI::Widget* widget, MyGUI::ControllerItem* controller);
void addRepeatController(MyGUI::Widget* widget);

@ -225,11 +225,10 @@ namespace MWGui
const ESM::Spell *spell = store.get<ESM::Spell>().search(mId);
MYGUI_ASSERT(spell, "spell with id '" << mId << "' not found");
MWSpellEffectPtr effect = NULL;
std::vector<ESM::ENAMstruct>::const_iterator end = spell->mEffects.mList.end();
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != end; ++it)
{
effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
MWSpellEffectPtr effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
SpellEffectParams params;
params.mEffectID = it->mEffectID;
params.mSkill = it->mSkill;
@ -565,22 +564,6 @@ namespace MWGui
}
}
void MWScrollBar::setEnableRepeat(bool enable)
{
mEnableRepeat = enable;
}
bool MWScrollBar::getEnableRepeat()
{
return mEnableRepeat;
}
void MWScrollBar::getRepeat(float &trigger, float &step)
{
trigger = mRepeatTriggerTime;
step = mRepeatStepTime;
}
void MWScrollBar::setRepeat(float trigger, float step)
{
mRepeatTriggerTime = trigger;

@ -307,9 +307,6 @@ namespace MWGui
MWScrollBar();
virtual ~MWScrollBar();
void setEnableRepeat(bool enable);
bool getEnableRepeat();
void getRepeat(float &trigger, float &step);
void setRepeat(float trigger, float step);
protected:

@ -76,6 +76,8 @@ void WindowModal::close()
NoDrop::NoDrop(DragAndDrop *drag, MyGUI::Widget *widget)
: mDrag(drag), mWidget(widget), mTransparent(false)
{
if (!mWidget)
throw std::runtime_error("NoDrop needs a non-NULL widget!");
}
void NoDrop::onFrame(float dt)

@ -18,7 +18,8 @@
#include <components/fontloader/fontloader.hpp>
#include <components/widgets/box.hpp>
#include <components/widgets/widgets.hpp>
#include <components/widgets/tags.hpp>
#include "../mwbase/inputmanager.hpp"
#include "../mwbase/statemanager.hpp"
@ -71,6 +72,7 @@
#include "backgroundimage.hpp"
#include "itemwidget.hpp"
#include "screenfader.hpp"
#include "debugwindow.hpp"
namespace MWGui
{
@ -119,6 +121,7 @@ namespace MWGui
, mVideoBackground(NULL)
, mVideoWidget(NULL)
, mScreenFader(NULL)
, mDebugWindow(NULL)
, mTranslationDataStorage (translationDataStorage)
, mCharGen(NULL)
, mInputBlocker(NULL)
@ -164,13 +167,6 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWList>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::HBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::VBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::AutoSizedTextBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::AutoSizedEditBox>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::AutoSizedButton>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<Gui::ImageButton>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget");
@ -178,6 +174,7 @@ namespace MWGui
BookPage::registerMyGUIComponents ();
ItemView::registerComponents();
ItemWidget::registerComponents();
Gui::registerAllWidgets();
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatEvent>("Controller");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
@ -271,6 +268,7 @@ namespace MWGui
mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager);
trackWindow(mCompanionWindow, "companion");
mScreenFader = new ScreenFader();
mDebugWindow = new DebugWindow();
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"Overlay");
@ -362,6 +360,7 @@ namespace MWGui
delete mRecharge;
delete mCompanionWindow;
delete mScreenFader;
delete mDebugWindow;
cleanupGarbage();
@ -864,6 +863,8 @@ namespace MWGui
mCompanionWindow->onFrame();
mScreenFader->update(frameDuration);
mDebugWindow->onFrame(frameDuration);
}
void WindowManager::changeCell(MWWorld::CellStore* cell)
@ -991,50 +992,13 @@ namespace MWGui
std::string tokenToFind = "sCell=";
size_t tokenLength = tokenToFind.length();
std::string fontcolour = "fontcolour=";
size_t fontcolourLength = fontcolour.length();
std::string fontcolourhtml = "fontcolourhtml=";
size_t fontcolourhtmlLength = fontcolourhtml.length();
if (tag.compare(0, tokenLength, tokenToFind) == 0)
{
_result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength));
}
else if (tag.compare(0, fontcolourLength, fontcolour) == 0)
else if (Gui::replaceTag(tag, _result, mFallbackMap))
{
std::string fallbackName = "FontColor_color_" + tag.substr(fontcolourLength);
std::map<std::string, std::string>::const_iterator it = mFallbackMap.find(fallbackName);
if (it == mFallbackMap.end())
throw std::runtime_error("Unknown fallback name: " + fallbackName);
std::string str = it->second;
std::string ret[3];
unsigned int j=0;
for(unsigned int i=0;i<str.length();++i){
if(str[i]==',') j++;
else if (str[i] != ' ') ret[j]+=str[i];
}
MyGUI::Colour col (MyGUI::utility::parseInt(ret[0])/255.f,MyGUI::utility::parseInt(ret[1])/255.f,MyGUI::utility::parseInt(ret[2])/255.f);
_result = col.print();
}
else if (tag.compare(0, fontcolourhtmlLength, fontcolourhtml) == 0)
{
std::string fallbackName = "FontColor_color_" + tag.substr(fontcolourhtmlLength);
std::map<std::string, std::string>::const_iterator it = mFallbackMap.find(fallbackName);
if (it == mFallbackMap.end())
throw std::runtime_error("Unknown fallback name: " + fallbackName);
std::string str = it->second;
std::string ret[3];
unsigned int j=0;
for(unsigned int i=0;i<str.length();++i){
if(str[i]==',') j++;
else if (str[i] != ' ') ret[j]+=str[i];
}
std::stringstream html;
html << "#" << std::hex << MyGUI::utility::parseInt(ret[0]) << MyGUI::utility::parseInt(ret[1]) << MyGUI::utility::parseInt(ret[2]);
_result = html.str();
return;
}
else
{
@ -1390,12 +1354,6 @@ namespace MWGui
return mSubtitlesEnabled;
}
void WindowManager::toggleHud ()
{
mHudEnabled = !mHudEnabled;
mHud->setVisible (mHudEnabled);
}
bool WindowManager::toggleGui()
{
mGuiEnabled = !mGuiEnabled;
@ -1711,7 +1669,7 @@ namespace MWGui
WindowModal* WindowManager::getCurrentModal() const
{
if(mCurrentModals.size() > 0)
if(!mCurrentModals.empty())
return mCurrentModals.top();
else
return NULL;
@ -1721,7 +1679,7 @@ namespace MWGui
{
// Only remove the top if it matches the current pointer. A lot of things hide their visibility before showing it,
//so just popping the top would cause massive issues.
if(mCurrentModals.size() > 0)
if(!mCurrentModals.empty())
if(input == mCurrentModals.top())
mCurrentModals.pop();
}
@ -1797,4 +1755,9 @@ namespace MWGui
SDL_free(text);
}
void WindowManager::toggleDebugWindow()
{
mDebugWindow->setVisible(!mDebugWindow->isVisible());
}
}

@ -89,6 +89,7 @@ namespace MWGui
class VideoWidget;
class WindowModal;
class ScreenFader;
class DebugWindow;
class WindowManager : public MWBase::WindowManager
{
@ -222,7 +223,6 @@ namespace MWGui
virtual void showCrosshair(bool show);
virtual bool getSubtitlesEnabled();
virtual void toggleHud();
/// Turn visibility of *all* GUI elements on or off (HUD and all windows, except the console)
virtual bool toggleGui();
@ -334,6 +334,8 @@ namespace MWGui
/// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading.
virtual void setScreenFactor (float factor);
virtual void toggleDebugWindow();
private:
bool mConsoleOnlyScripts;
@ -387,6 +389,7 @@ namespace MWGui
MyGUI::ImageBox* mVideoBackground;
VideoWidget* mVideoWidget;
ScreenFader* mScreenFader;
DebugWindow* mDebugWindow;
Translation::Storage& mTranslationDataStorage;
Cursor* mSoftwareCursor;

@ -279,6 +279,9 @@ namespace MWInput
case A_ToggleHUD:
MWBase::Environment::get().getWindowManager()->toggleGui();
break;
case A_ToggleDebug:
MWBase::Environment::get().getWindowManager()->toggleDebugWindow();
break;
case A_QuickSave:
quickSave();
break;
@ -902,6 +905,7 @@ namespace MWInput
defaultKeyBindings[A_QuickKey10] = SDL_SCANCODE_0;
defaultKeyBindings[A_Screenshot] = SDL_SCANCODE_F12;
defaultKeyBindings[A_ToggleHUD] = SDL_SCANCODE_F11;
defaultKeyBindings[A_ToggleDebug] = SDL_SCANCODE_F10;
defaultKeyBindings[A_AlwaysRun] = SDL_SCANCODE_CAPSLOCK;
defaultKeyBindings[A_QuickSave] = SDL_SCANCODE_F5;
defaultKeyBindings[A_QuickLoad] = SDL_SCANCODE_F9;

@ -259,6 +259,8 @@ namespace MWInput
A_ToggleHUD,
A_ToggleDebug,
A_Last // Marker for the last item
};
};

@ -275,7 +275,7 @@ namespace MWMechanics
void Actors::engageCombat (const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2, bool againstPlayer)
{
CreatureStats& creatureStats = actor1.getClass().getCreatureStats(actor1);
if (actor2.getClass().getCreatureStats(actor2).isDead()
|| actor1.getClass().getCreatureStats(actor1).isDead())
return;
@ -296,7 +296,7 @@ namespace MWMechanics
bool aggressive;
if (againstPlayer)
if (againstPlayer)
{
// followers with high fight should not engage in combat with the player (e.g. bm_bear_black_summon)
const std::list<MWWorld::Ptr>& followers = getActorsFollowing(actor2);
@ -323,8 +323,9 @@ namespace MWMechanics
for (std::list<MWWorld::Ptr>::const_iterator it = followers.begin(); it != followers.end(); ++it)
{
// need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(*it)
if ((creatureStats2.getAiSequence().isInCombat(*it)
|| it->getClass().getCreatureStats(*it).getAiSequence().isInCombat(actor2))
&& !creatureStats.getAiSequence().isInCombat(*it))
aggressive = true;
}
@ -337,6 +338,9 @@ namespace MWMechanics
if (followTarget.isEmpty())
continue;
if (creatureStats.getAiSequence().isInCombat(followTarget))
continue;
// need to check both ways since player doesn't use AI packages
if (creatureStats2.getAiSequence().isInCombat(followTarget)
|| followTarget.getClass().getCreatureStats(followTarget).getAiSequence().isInCombat(actor2))
@ -466,13 +470,13 @@ namespace MWMechanics
return;
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats (ptr);
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
int endurance = stats.getAttribute (ESM::Attribute::Endurance).getModified ();
// restore fatigue
float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
const MWWorld::Store<ESM::GameSetting>& settings = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fFatigueReturnBase = settings.find("fFatigueReturnBase")->getFloat ();
static const float fFatigueReturnMult = settings.find("fFatigueReturnMult")->getFloat ();
float x = fFatigueReturnBase + fFatigueReturnMult * endurance;
@ -1099,7 +1103,7 @@ namespace MWMechanics
void Actors::update (float duration, bool paused)
{
if(!paused)
{
{
static float timerUpdateAITargets = 0;
// target lists get updated once every 1.0 sec
@ -1175,14 +1179,26 @@ namespace MWMechanics
iter->second->updateContinuousVfx();
// Animation/movement update
CharacterController* playerCharacter = NULL;
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (iter->first.getClass().getCreatureStats(iter->first).getMagicEffects().get(
ESM::MagicEffect::Paralyze).getMagnitude() > 0)
iter->second->skipAnim();
// Handle player last, in case a cell transition occurs by casting a teleportation spell
// (would invalidate the iterator)
if (iter->first.getCellRef().getRefId() == "player")
{
playerCharacter = iter->second;
continue;
}
iter->second->update(duration);
}
if (playerCharacter)
playerCharacter->update(duration);
for(PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
@ -1207,26 +1223,27 @@ namespace MWMechanics
// check if we still have any player enemies to switch music
static bool isBattleMusic = false;
if (isBattleMusic && hostilesCount == 0)
if (isBattleMusic && hostilesCount == 0 && !(player.getClass().getCreatureStats(player).isDead() &&
MWBase::Environment::get().getSoundManager()->isMusicPlaying()))
{
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Explore"));
isBattleMusic = false;
}
else if (!isBattleMusic && hostilesCount > 0)
else if (!isBattleMusic && hostilesCount > 0)
{
MWBase::Environment::get().getSoundManager()->playPlaylist(std::string("Battle"));
isBattleMusic = true;
}
static float sneakTimer = 0.f; // times update of sneak icon
static float sneakSkillTimer = 0.f; // times sneak skill progress from "avoid notice"
// if player is in sneak state see if anyone detects him
if (player.getClass().getCreatureStats(player).getMovementFlag(MWMechanics::CreatureStats::Flag_Sneak))
{
static float sneakSkillTimer = 0.f; // times sneak skill progress from "avoid notice"
const MWWorld::ESMStore& esmStore = MWBase::Environment::get().getWorld()->getStore();
const int radius = esmStore.get<ESM::GameSetting>().find("fSneakUseDist")->getInt();
bool detected = false;
static float fSneakUseDelay = esmStore.get<ESM::GameSetting>().find("fSneakUseDelay")->getFloat();
@ -1238,6 +1255,8 @@ namespace MWMechanics
// Set when an NPC is within line of sight and distance, but is still unaware. Used for skill progress.
bool avoidedNotice = false;
bool detected = false;
for (PtrControllerMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (iter->first == player) // not the player
@ -1405,7 +1424,7 @@ namespace MWMechanics
std::list<MWWorld::Ptr> Actors::getActorsFollowing(const MWWorld::Ptr& actor)
{
std::list<MWWorld::Ptr> list;
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++)
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{
const MWWorld::Class &cls = iter->first.getClass();
CreatureStats &stats = cls.getCreatureStats(iter->first);
@ -1437,7 +1456,7 @@ namespace MWMechanics
getObjectsInRange(position,
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fAlarmRadius")->getFloat(),
neighbors); //only care about those within the alarm disance
for(std::vector<MWWorld::Ptr>::iterator iter(neighbors.begin());iter != neighbors.end();iter++)
for(std::vector<MWWorld::Ptr>::iterator iter(neighbors.begin());iter != neighbors.end();++iter)
{
const MWWorld::Class &cls = iter->getClass();
CreatureStats &stats = cls.getCreatureStats(*iter);

@ -35,8 +35,6 @@ namespace MWMechanics
private:
std::string mObjectId;
int mCellX;
int mCellY;
};
}
#endif // GAME_MWMECHANICS_AIACTIVATE_H

@ -64,7 +64,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor,float duration
// Make all nearby actors also avoid the door
std::vector<MWWorld::Ptr> actors;
MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(pos.pos[0],pos.pos[1],pos.pos[2]),100,actors);
for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); it++) {
for(std::vector<MWWorld::Ptr>::iterator it = actors.begin(); it != actors.end(); ++it) {
if(*it != MWBase::Environment::get().getWorld()->getPlayerPtr()) { //Not the player
MWMechanics::AiSequence& seq = it->getClass().getCreatureStats(*it).getAiSequence();
if(seq.getTypeId() != MWMechanics::AiPackage::TypeIdAvoidDoor) { //Only add it once

@ -301,18 +301,20 @@ namespace MWMechanics
if (!target.isEmpty() && target.getClass().getCreatureStats(target).getAttribute(effect.mAttribute).getModified() <= 0)
return 0.f;
{
const float attributePriorities[ESM::Attribute::Length] = {
1.f, // Strength
0.5, // Intelligence
0.6, // Willpower
0.7, // Agility
0.5, // Speed
0.8, // Endurance
0.7, // Personality
0.3 // Luck
};
if (effect.mAttribute >= 0 && effect.mAttribute < ESM::Attribute::Length)
{
const float attributePriorities[ESM::Attribute::Length] = {
1.f, // Strength
0.5, // Intelligence
0.6, // Willpower
0.7, // Agility
0.5, // Speed
0.8, // Endurance
0.7, // Personality
0.3 // Luck
};
rating *= attributePriorities[effect.mAttribute];
}
}
break;

@ -54,6 +54,7 @@ namespace MWMechanics
, mCellY(std::numeric_limits<int>::max())
, mCellId(escort->mCellId)
, mRemainingDuration(escort->mRemainingDuration)
, mMaxDist(450)
{
}
@ -91,7 +92,11 @@ namespace MWMechanics
if(distanceBetweenResult <= mMaxDist * mMaxDist)
{
if(pathTo(actor,ESM::Pathgrid::Point(mX,mY,mZ),duration)) //Returns true on path complete
ESM::Pathgrid::Point point(mX,mY,mZ);
point.mAutogenerated = 0;
point.mConnectionNum = 0;
point.mUnknown = 0;
if(pathTo(actor,point,duration)) //Returns true on path complete
return true;
mMaxDist = 450;
}

@ -50,11 +50,6 @@ bool MWMechanics::AiFollow::execute (const MWWorld::Ptr& actor,float duration)
)
return true; //Target doesn't exist
// Only the player can be actively followed. AiFollow packages with targets other than the player
// are only used for defining combat alliances, since NPCs will defend whoever they are following or being followed by.
if (target != MWBase::Environment::get().getWorld()->getPlayerPtr())
return false;
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
ESM::Position pos = actor.getRefData().getPosition(); //position of the actor

@ -69,7 +69,6 @@ namespace MWMechanics
PathFinder mPathFinder;
ObstacleCheck mObstacleCheck;
float mDoorCheckDuration;
float mTimer;
float mStuckTimer;

@ -41,8 +41,6 @@ namespace MWMechanics
private:
int mTargetActorId; // The actor to pursue
int mCellX;
int mCellY;
};
}
#endif

@ -31,9 +31,11 @@ void AiSequence::copy (const AiSequence& sequence)
AiSequence::AiSequence() : mDone (false), mLastAiPackage(-1) {}
AiSequence::AiSequence (const AiSequence& sequence) : mDone (false)
AiSequence::AiSequence (const AiSequence& sequence)
{
copy (sequence);
mDone = sequence.mDone;
mLastAiPackage = sequence.mLastAiPackage;
}
AiSequence& AiSequence::operator= (const AiSequence& sequence)
@ -43,6 +45,7 @@ AiSequence& AiSequence::operator= (const AiSequence& sequence)
clear();
copy (sequence);
mDone = sequence.mDone;
mLastAiPackage = sequence.mLastAiPackage;
}
return *this;
@ -120,33 +123,6 @@ bool AiSequence::isInCombat(const MWWorld::Ptr &actor) const
return false;
}
bool AiSequence::canAddTarget(const ESM::Position& actorPos, float distToTarget) const
{
bool firstCombatFound = false;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
for(std::list<AiPackage*>::const_iterator it = mPackages.begin(); it != mPackages.end(); ++it)
{
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
{
firstCombatFound = true;
const AiCombat *combat = static_cast<const AiCombat *>(*it);
if (combat->getTarget() != player ) return false; // only 1 non-player target allowed
else
{
// add new target only if current target (player) is farther
const ESM::Position &targetPos = combat->getTarget().getRefData().getPosition();
float distToCurrTarget = (Ogre::Vector3(targetPos.pos) - Ogre::Vector3(actorPos.pos)).length();
return (distToCurrTarget > distToTarget);
}
}
else if (firstCombatFound) break; // assumes combat packages go one-by-one in packages list
}
return true;
}
void AiSequence::stopCombat()
{
while (getTypeId() == AiPackage::TypeIdCombat)
@ -295,11 +271,6 @@ void AiSequence::stack (const AiPackage& package, const MWWorld::Ptr& actor)
mPackages.push_front (package.clone());
}
void AiSequence::queue (const AiPackage& package)
{
mPackages.push_back (package.clone());
}
AiPackage* MWMechanics::AiSequence::getActivePackage()
{
if(mPackages.empty())

@ -98,10 +98,6 @@ namespace MWMechanics
@param actor The actor that owns this AiSequence **/
void stack (const AiPackage& package, const MWWorld::Ptr& actor);
/// Add \a package to the end of the sequence
/** Executed after all other packages have been completed **/
void queue (const AiPackage& package);
/// Return the current active package.
/** If there is no active package, it will throw an exception **/
AiPackage* getActivePackage();

@ -686,16 +686,15 @@ namespace MWMechanics
}
AiWander::AiWander (const ESM::AiSequence::AiWander* wander)
: mDistance(wander->mData.mDistance)
, mDuration(wander->mData.mDuration)
, mStartTime(MWWorld::TimeStamp(wander->mStartTime))
, mTimeOfDay(wander->mData.mTimeOfDay)
, mRepeat(wander->mData.mShouldRepeat)
{
mDistance = wander->mData.mDistance;
mDuration = wander->mData.mDuration;
mStartTime = MWWorld::TimeStamp(wander->mStartTime);
mTimeOfDay = wander->mData.mTimeOfDay;
for (int i=0; i<8; ++i)
mIdle.push_back(wander->mData.mIdle[i]);
mRepeat = wander->mData.mShouldRepeat;
init();
}
}

@ -27,6 +27,11 @@
#include "creaturestats.hpp"
#include "npcstats.hpp"
MWMechanics::Alchemy::Alchemy()
: mValue(0)
{
}
std::set<MWMechanics::EffectKey> MWMechanics::Alchemy::listEffects() const
{
std::map<EffectKey, int> effects;

@ -22,6 +22,8 @@ namespace MWMechanics
{
public:
Alchemy();
typedef std::vector<MWWorld::Ptr> TToolsContainer;
typedef TToolsContainer::const_iterator TToolsIterator;

@ -220,7 +220,7 @@ namespace MWMechanics
if (spell->mData.mFlags & ESM::Spell::F_Always)
return 100.f;
float skillTerm;
float skillTerm = 0;
if (effectiveSchool != -1)
skillTerm = 2.f * actorSkills[mapSchoolToSkill(effectiveSchool)];
else

@ -1611,7 +1611,7 @@ void CharacterController::update(float duration)
if(mMovementAnimationControlled && mPtr.getClass().isActor())
world->queueMovement(mPtr, moved);
}
else if (mAnimation)
else
mAnimation->updateEffects(duration);
mSkipAnim = false;
@ -1703,6 +1703,10 @@ bool CharacterController::kill()
mIdleState = CharState_None;
mCurrentIdle.clear();
// Play Death Music if it was the player dying
if(mPtr.getRefData().getHandle()=="player")
MWBase::Environment::get().getSoundManager()->streamMusic("Special/MW_Death.mp3");
return true;
}

@ -193,13 +193,11 @@ namespace MWMechanics
return;
}
float damage = 0.0f;
float fDamageStrengthBase = gmst.find("fDamageStrengthBase")->getFloat();
float fDamageStrengthMult = gmst.find("fDamageStrengthMult")->getFloat();
const unsigned char* attack = weapon.get<ESM::Weapon>()->mBase->mData.mChop;
damage = attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); // Bow/crossbow damage
float damage = attack[0] + ((attack[1]-attack[0])*attackerStats.getAttackStrength()); // Bow/crossbow damage
if (weapon != projectile)
{
// Arrow/bolt damage

@ -120,11 +120,6 @@ namespace MWMechanics
return mSpells;
}
void CreatureStats::setSpells(const Spells &spells)
{
mSpells = spells;
}
ActiveSpells &CreatureStats::getActiveSpells()
{
return mActiveSpells;
@ -200,11 +195,6 @@ namespace MWMechanics
mLevel = level;
}
void CreatureStats::setActiveSpells(const ActiveSpells &active)
{
mActiveSpells = active;
}
void CreatureStats::modifyMagicEffects(const MagicEffects &effects)
{
if (effects.get(ESM::MagicEffect::FortifyMaximumMagicka).getModifier()
@ -536,7 +526,6 @@ namespace MWMechanics
mLastRestock = MWWorld::TimeStamp(state.mTradeTime);
mGoldPool = state.mGoldPool;
mFallHeight = state.mFallHeight;
mDead = state.mDead;
mDied = state.mDied;

@ -40,7 +40,6 @@ namespace MWMechanics
bool mTalkedTo;
bool mAlarmed;
bool mAttacked;
bool mHostile;
bool mAttackingOrSpell;
bool mKnockdown;
bool mKnockdownOneFrame;
@ -138,10 +137,6 @@ namespace MWMechanics
void setDynamic (int index, const DynamicStat<float> &value);
void setSpells(const Spells &spells);
void setActiveSpells(const ActiveSpells &active);
/// Set Modifier for each magic effect according to \a effects. Does not touch Base values.
void modifyMagicEffects(const MagicEffects &effects);

@ -166,16 +166,15 @@ namespace MWMechanics
float enchantmentCost = 0;
int effectsLeftCnt = mEffects.size();
float baseCost, magnitudeCost, areaCost;
int magMin, magMax, area;
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it)
{
baseCost = (store.get<ESM::MagicEffect>().find(it->mEffectID))->mData.mBaseCost;
float baseCost = (store.get<ESM::MagicEffect>().find(it->mEffectID))->mData.mBaseCost;
// To reflect vanilla behavior
magMin = (it->mMagnMin == 0) ? 1 : it->mMagnMin;
magMax = (it->mMagnMax == 0) ? 1 : it->mMagnMax;
area = (it->mArea == 0) ? 1 : it->mArea;
int magMin = (it->mMagnMin == 0) ? 1 : it->mMagnMin;
int magMax = (it->mMagnMax == 0) ? 1 : it->mMagnMax;
int area = (it->mArea == 0) ? 1 : it->mArea;
float magnitudeCost = 0;
if (mCastStyle == ESM::Enchantment::ConstantEffect)
{
magnitudeCost = (magMin + magMax) * baseCost * 2.5;
@ -187,7 +186,7 @@ namespace MWMechanics
magnitudeCost *= 1.5;
}
areaCost = area * 0.025 * baseCost;
float areaCost = area * 0.025 * baseCost;
if (it->mRange == ESM::RT_Target)
areaCost *= 1.5;

@ -566,11 +566,14 @@ namespace MWMechanics
MWWorld::LiveCellRef<ESM::NPC>* player = playerPtr.get<ESM::NPC>();
const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr);
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fDispRaceMod = gmst.find("fDispRaceMod")->getFloat();
if (Misc::StringUtils::ciEqual(npc->mBase->mRace, player->mBase->mRace))
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispRaceMod")->getFloat();
x += fDispRaceMod;
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityMult")->getFloat()
* (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispPersonalityBase")->getFloat());
static const float fDispPersonalityMult = gmst.find("fDispPersonalityMult")->getFloat();
static const float fDispPersonalityBase = gmst.find("fDispPersonalityBase")->getFloat();
x += fDispPersonalityMult * (playerStats.getAttribute(ESM::Attribute::Personality).getModified() - fDispPersonalityBase);
float reaction = 0;
int rank = 0;
@ -606,16 +609,23 @@ namespace MWMechanics
reaction = 0;
rank = 0;
}
x += (MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankMult")->getFloat() * rank
+ MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionRankBase")->getFloat())
* MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispFactionMod")->getFloat() * reaction;
x -= MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispCrimeMod")->getFloat() * playerStats.getBounty();
static const float fDispFactionRankMult = gmst.find("fDispFactionRankMult")->getFloat();
static const float fDispFactionRankBase = gmst.find("fDispFactionRankBase")->getFloat();
static const float fDispFactionMod = gmst.find("fDispFactionMod")->getFloat();
x += (fDispFactionRankMult * rank
+ fDispFactionRankBase)
* fDispFactionMod * reaction;
static const float fDispCrimeMod = gmst.find("fDispCrimeMod")->getFloat();
static const float fDispDiseaseMod = gmst.find("fDispDiseaseMod")->getFloat();
x -= fDispCrimeMod * playerStats.getBounty();
if (playerStats.hasCommonDisease() || playerStats.hasBlightDisease())
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispDiseaseMod")->getFloat();
x += fDispDiseaseMod;
static const float fDispWeaponDrawn = gmst.find("fDispWeaponDrawn")->getFloat();
if (playerStats.getDrawState() == MWMechanics::DrawState_Weapon)
x += MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fDispWeaponDrawn")->getFloat();
x += fDispWeaponDrawn;
x += ptr.getClass().getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Charm).getMagnitude();
@ -1111,10 +1121,10 @@ namespace MWMechanics
}
}
void MechanicsManager::actorAttacked(const MWWorld::Ptr &ptr, const MWWorld::Ptr &attacker)
bool MechanicsManager::actorAttacked(const MWWorld::Ptr &ptr, const MWWorld::Ptr &attacker)
{
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
return;
return false;
std::list<MWWorld::Ptr> followers = getActorsFollowing(attacker);
if (std::find(followers.begin(), followers.end(), ptr) != followers.end())
@ -1124,13 +1134,25 @@ namespace MWMechanics
if (ptr.getClass().getCreatureStats(ptr).getFriendlyHits() < 4)
{
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
return;
return false;
}
}
// Attacking an NPC that is already in combat with any other NPC is not a crime
AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence();
bool isFightingNpc = false;
for (std::list<AiPackage*>::const_iterator it = seq.begin(); it != seq.end(); ++it)
{
if ((*it)->getTypeId() == AiPackage::TypeIdCombat)
{
MWWorld::Ptr target = static_cast<AiCombat*>(*it)->getTarget();
if (!target.isEmpty() && target.getClass().isNpc())
isFightingNpc = true;
}
}
// Attacking peaceful NPCs is a crime
if (ptr.getClass().isNpc() && !attacker.isEmpty() && !ptr.getClass().getCreatureStats(ptr).getAiSequence().isInCombat(attacker)
&& !isAggressive(ptr, attacker))
&& !isAggressive(ptr, attacker) && !isFightingNpc)
commitCrime(attacker, ptr, MWBase::MechanicsManager::OT_Assault);
if (!attacker.isEmpty() && (attacker.getClass().getCreatureStats(attacker).getAiSequence().isInCombat(ptr)
@ -1141,6 +1163,8 @@ namespace MWMechanics
// Note: accidental or collateral damage attacks are ignored.
startCombat(ptr, attacker);
}
return true;
}
bool MechanicsManager::awarenessCheck(const MWWorld::Ptr &ptr, const MWWorld::Ptr &observer)

@ -120,7 +120,8 @@ namespace MWMechanics
OffenseType type, int arg=0);
virtual void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
OffenseType type, int arg=0);
virtual void actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// @return false if the attack was considered a "friendly hit" and forgiven
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
/// Utility to check if taking this item is illegal and calling commitCrime if so
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count);
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so

@ -107,7 +107,7 @@ bool MWMechanics::NpcStats::isSameFaction (const NpcStats& npcStats) const
}
float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& class_, int usageType,
int level) const
int level, float extraFactor) const
{
if (level<0)
level = static_cast<int> (getSkill (skillIndex).getBase());
@ -131,6 +131,8 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
return 0;
}
skillFactor *= extraFactor;
const MWWorld::Store<ESM::GameSetting> &gmst =
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
@ -167,7 +169,7 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
return 1.0 / ((level+1) * (1.0/skillFactor) * typeFactor * specialisationFactor);
}
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType)
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType, float extraFactor)
{
// Don't increase skills as a werewolf
if(mIsWerewolf)
@ -175,7 +177,7 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
MWMechanics::SkillValue& value = getSkill (skillIndex);
value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType));
value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType, -1, extraFactor));
if (value.getProgress()>=1)
{

@ -81,12 +81,12 @@ namespace MWMechanics
///< Do *this and \a npcStats share a faction?
float getSkillGain (int skillIndex, const ESM::Class& class_, int usageType = -1,
int level = -1) const;
int level = -1, float extraFactor=1.f) const;
///< \param usageType: Usage specific factor, specified in the respective skill record;
/// -1: use a factor of 1.0 instead.
/// \param level Level to base calculation on; -1: use current level.
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1);
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f);
///< Increase skill by usage.
void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress);

@ -283,13 +283,6 @@ namespace MWMechanics
return Ogre::Radian(Ogre::Math::ACos(directionY / directionResult) * sgn(Ogre::Math::ASin(directionX / directionResult))).valueDegrees();
}
// Used by AiCombat, use Euclidean distance
float PathFinder::getDistToNext(float x, float y, float z)
{
ESM::Pathgrid::Point nextPoint = *mPath.begin();
return distance(nextPoint, x, y, z);
}
bool PathFinder::checkWaypoint(float x, float y, float z)
{
if(mPath.empty())

@ -47,8 +47,6 @@ namespace MWMechanics
float getZAngleToNext(float x, float y) const;
float getDistToNext(float x, float y, float z);
bool isPathConstructed() const
{
return mIsPathConstructed;

@ -521,7 +521,7 @@ float Animation::getVelocity(const std::string &groupname) const
{
/* Look in reverse; last-inserted source has priority. */
AnimSourceList::const_reverse_iterator animsrc(mAnimSources.rbegin());
for(;animsrc != mAnimSources.rend();animsrc++)
for(;animsrc != mAnimSources.rend();++animsrc)
{
const NifOgre::TextKeyMap &keys = (*animsrc)->mTextKeys;
if(findGroupStart(keys, groupname) != keys.end())
@ -831,8 +831,7 @@ void Animation::handleTextKey(AnimState &state, const std::string &groupname, co
void Animation::changeGroups(const std::string &groupname, int groups)
{
AnimStateMap::iterator stateiter = mStates.begin();
stateiter = mStates.find(groupname);
AnimStateMap::iterator stateiter = mStates.find(groupname);
if(stateiter != mStates.end())
{
if(stateiter->second.mGroups != groups)

@ -26,7 +26,6 @@ namespace MWRender
mNearest(30.f),
mFurthest(800.f),
mIsNearest(false),
mIsFurthest(false),
mHeight(128.f),
mCameraDistance(300.f),
mDistanceAdjusted(false),
@ -292,7 +291,6 @@ namespace MWRender
if(mFirstPersonView && !mPreviewMode && !mVanity.enabled)
return;
mIsFurthest = false;
mIsNearest = false;
Ogre::Vector3 v(0.f, 0.f, dist);
@ -301,7 +299,6 @@ namespace MWRender
}
if (v.z >= mFurthest) {
v.z = mFurthest;
mIsFurthest = true;
} else if (!override && v.z < 10.f) {
v.z = 10.f;
} else if (override && v.z <= mNearest) {
@ -389,9 +386,4 @@ namespace MWRender
{
return mIsNearest;
}
bool Camera::isFurthest()
{
return mIsFurthest;
}
}

@ -36,7 +36,6 @@ namespace MWRender
float mNearest;
float mFurthest;
bool mIsNearest;
bool mIsFurthest;
struct {
bool enabled, allowed;
@ -118,8 +117,6 @@ namespace MWRender
bool isVanityOrPreviewModeEnabled();
bool isNearest();
bool isFurthest();
};
}

@ -281,9 +281,9 @@ namespace MWRender
RaceSelectionPreview::RaceSelectionPreview()
: CharacterPreview(MWBase::Environment::get().getWorld()->getPlayerPtr(),
512, 512, "CharacterHeadPreview", Ogre::Vector3(0, 6, -35), Ogre::Vector3(0,125,0))
, mBase (*mCharacter.get<ESM::NPC>()->mBase)
, mRef(&mBase)
{
mBase = *mCharacter.get<ESM::NPC>()->mBase;
mCharacter = MWWorld::Ptr(&mRef, NULL);
}

@ -150,7 +150,7 @@ void CreatureWeaponAnimation::updatePart(NifOgre::ObjectScenePtr& scene, int slo
}
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(scene->mControllers.begin());
for(;ctrl != scene->mControllers.end();ctrl++)
for(;ctrl != scene->mControllers.end();++ctrl)
{
if(ctrl->getSource().isNull())
{

@ -29,6 +29,7 @@ namespace MWRender
, mWidth(0)
, mHeight(0)
{
mCellSize = Settings::Manager::getInt("global map cell size", "Map");
}
GlobalMap::~GlobalMap()
@ -57,9 +58,8 @@ namespace MWRender
mMaxY = it->getGridY();
}
int cellSize = 24;
mWidth = cellSize*(mMaxX-mMinX+1);
mHeight = cellSize*(mMaxY-mMinY+1);
mWidth = mCellSize*(mMaxX-mMinX+1);
mHeight = mCellSize*(mMaxY-mMinY+1);
loadingListener->loadingOn();
loadingListener->setLabel("Creating map");
@ -90,29 +90,29 @@ namespace MWRender
land->loadData(mask);
}
for (int cellY=0; cellY<cellSize; ++cellY)
for (int cellY=0; cellY<mCellSize; ++cellY)
{
for (int cellX=0; cellX<cellSize; ++cellX)
for (int cellX=0; cellX<mCellSize; ++cellX)
{
int vertexX = float(cellX)/float(cellSize) * ESM::Land::LAND_SIZE;
int vertexY = float(cellY)/float(cellSize) * ESM::Land::LAND_SIZE;
int vertexX = float(cellX)/float(mCellSize) * ESM::Land::LAND_SIZE;
int vertexY = float(cellY)/float(mCellSize) * ESM::Land::LAND_SIZE;
int texelX = (x-mMinX) * cellSize + cellX;
int texelY = (mHeight-1) - ((y-mMinY) * cellSize + cellY);
int texelX = (x-mMinX) * mCellSize + cellX;
int texelY = (mHeight-1) - ((y-mMinY) * mCellSize + cellY);
unsigned char r,g,b;
if (land)
{
const float landHeight = land->mLandData->mHeights[vertexY * ESM::Land::LAND_SIZE + vertexX];
const float mountainHeight = 15000.f;
const float hillHeight = 2500.f;
if (landHeight >= 0)
{
const float hillHeight = 2500.f;
if (landHeight >= hillHeight)
{
const float mountainHeight = 15000.f;
float factor = std::min(1.f, float(landHeight-hillHeight)/mountainHeight);
r = (hillColour.r * (1-factor) + mountainColour.r * factor) * 255;
g = (hillColour.g * (1-factor) + mountainColour.g * factor) * 255;
@ -197,11 +197,9 @@ namespace MWRender
void GlobalMap::exploreCell(int cellX, int cellY)
{
const int size = 24;
float originX = (cellX - mMinX) * size;
float originX = (cellX - mMinX) * mCellSize;
// NB y + 1, because we want the top left corner, not bottom left where the origin of the cell is
float originY = mHeight - (cellY+1 - mMinY) * size;
float originY = mHeight - (cellY+1 - mMinY) * mCellSize;
if (cellX > mMaxX || cellX < mMinX || cellY > mMaxY || cellY < mMinY)
return;
@ -213,17 +211,17 @@ namespace MWRender
{
mOverlayTexture->load();
mOverlayTexture->getBuffer()->blit(localMapTexture->getBuffer(), Ogre::Image::Box(0,0,512,512),
Ogre::Image::Box(originX,originY,originX+size,originY+size));
Ogre::Image::Box(originX,originY,originX+mCellSize,originY+mCellSize));
Ogre::Image backup;
std::vector<Ogre::uchar> data;
data.resize(size*size*4, 0);
backup.loadDynamicImage(&data[0], size, size, Ogre::PF_A8B8G8R8);
data.resize(mCellSize*mCellSize*4, 0);
backup.loadDynamicImage(&data[0], mCellSize, mCellSize, Ogre::PF_A8B8G8R8);
localMapTexture->getBuffer()->blitToMemory(Ogre::Image::Box(0,0,512,512), backup.getPixelBox());
for (int x=0; x<size; ++x)
for (int y=0; y<size; ++y)
for (int x=0; x<mCellSize; ++x)
for (int y=0; y<mCellSize; ++y)
{
assert (originX+x < mOverlayImage.getWidth());
assert (originY+y < mOverlayImage.getHeight());
@ -292,7 +290,7 @@ namespace MWRender
// If cell bounds of the currently loaded content and the loaded savegame do not match,
// we need to resize source/dest boxes to accommodate
// This means nonexisting cells will be dropped silently
int cellImageSizeDst = 24;
int cellImageSizeDst = mCellSize;
// Completely off-screen? -> no need to blit anything
if (bounds.mMaxX < mMinX
@ -326,7 +324,8 @@ namespace MWRender
mOverlayTexture->getBuffer()->blit(tex->getBuffer(), srcBox, destBox);
if (srcBox.left == destBox.left && srcBox.right == destBox.right
&& srcBox.top == destBox.top && srcBox.bottom == destBox.bottom)
&& srcBox.top == destBox.top && srcBox.bottom == destBox.bottom
&& int(image.getWidth()) == mWidth && int(image.getHeight()) == mHeight)
mOverlayImage = image;
else
mOverlayTexture->convertToImage(mOverlayImage);

@ -26,8 +26,10 @@ namespace MWRender
void render(Loading::Listener* loadingListener);
int getWidth() { return mWidth; }
int getHeight() { return mHeight; }
int getWidth() const { return mWidth; }
int getHeight() const { return mHeight; }
int getCellSize() const { return mCellSize; }
void worldPosToImageSpace(float x, float z, float& imageX, float& imageY);
@ -46,6 +48,8 @@ namespace MWRender
private:
std::string mCacheDir;
int mCellSize;
std::vector< std::pair<int,int> > mExploredCells;
Ogre::TexturePtr mOverlayTexture;

@ -410,15 +410,18 @@ void NpcAnimation::updateParts()
// Remember body parts so we only have to search through the store once for each race/gender/viewmode combination
static std::map< std::pair<std::string,int>,std::vector<const ESM::BodyPart*> > sRaceMapping;
static const int Flag_Female = 1<<0;
static const int Flag_FirstPerson = 1<<1;
bool isWerewolf = (mNpcType == Type_Werewolf);
int flags = (isWerewolf ? -1 : 0);
if(!mNpc->isMale())
{
static const int Flag_Female = 1<<0;
flags |= Flag_Female;
}
if(mViewMode == VM_FirstPerson)
{
static const int Flag_FirstPerson = 1<<1;
flags |= Flag_FirstPerson;
}
std::string race = (isWerewolf ? "werewolf" : Misc::StringUtils::lowerCase(mNpc->mRace));
std::pair<std::string, int> thisCombination = std::make_pair(race, flags);
@ -604,7 +607,7 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
if (mObjectParts[i].isNull())
continue;
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[i]->mControllers.begin());
for(;ctrl != mObjectParts[i]->mControllers.end();ctrl++)
for(;ctrl != mObjectParts[i]->mControllers.end();++ctrl)
ctrl->update();
Ogre::Entity *ent = mObjectParts[i]->mSkelBase;
@ -678,7 +681,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
}
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[type]->mControllers.begin());
for(;ctrl != mObjectParts[type]->mControllers.end();ctrl++)
for(;ctrl != mObjectParts[type]->mControllers.end();++ctrl)
{
if(ctrl->getSource().isNull())
{
@ -715,7 +718,7 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
std::vector<ESM::PartReference>::const_iterator part(parts.begin());
for(;part != parts.end();part++)
for(;part != parts.end();++part)
{
const ESM::BodyPart *bodypart = 0;
if(!mNpc->isMale() && !part->mFemale.empty())

@ -574,24 +574,6 @@ void RenderingManager::configureAmbient(MWWorld::CellStore &mCell)
sunEnable(false);
}
}
// Switch through lighting modes.
void RenderingManager::toggleLight()
{
if (mAmbientMode==2)
mAmbientMode = 0;
else
++mAmbientMode;
switch (mAmbientMode)
{
case 0: std::cout << "Setting lights to normal\n"; break;
case 1: std::cout << "Turning the lights up\n"; break;
case 2: std::cout << "Turning the lights to full\n"; break;
}
setAmbientMode();
}
void RenderingManager::setSunColour(const Ogre::ColourValue& colour)
{
@ -695,11 +677,6 @@ void RenderingManager::enableLights(bool sun)
sunEnable(sun);
}
Shadows* RenderingManager::getShadows()
{
return mShadows;
}
void RenderingManager::notifyWorldSpaceChanged()
{
mEffectManager->clear();

@ -93,7 +93,6 @@ public:
MWRender::Camera* getCamera() const;
void toggleLight();
bool toggleRenderMode(int mode);
void removeCell (MWWorld::CellStore *store);
@ -157,8 +156,6 @@ public:
float getTerrainHeightAt (Ogre::Vector3 worldPos);
Shadows* getShadows();
void notifyWorldSpaceChanged();
void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches);

@ -41,6 +41,9 @@ public:
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
private:
RippleSimulation(const RippleSimulation&);
RippleSimulation& operator=(const RippleSimulation&);
std::vector<Emitter> mEmitters;
Ogre::RenderTexture* mRenderTargets[4];

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save