Add OpenMW commits up to 6 June 2019

# Conflicts:
#	apps/openmw/mwgui/hud.cpp
#	apps/openmw/mwgui/jailscreen.cpp
#	apps/openmw/mwgui/waitdialog.cpp
#	apps/openmw/mwinput/inputmanagerimp.cpp
#	apps/openmw/mwworld/worldimp.hpp
pull/541/head
David Cernat 5 years ago
commit b57c0bcafe

@ -73,10 +73,10 @@ Programmers
Finbar Crago(finbar-crago) Finbar Crago(finbar-crago)
Florian Weber (Florianjw) Florian Weber (Florianjw)
Gašper Sedej Gašper Sedej
Gijsbert ter Horst (Ghostbird)
Gohan1989 Gohan1989
gugus/gus gugus/gus
guidoj guidoj
Hallfaer Tuilinn
Haoda Wang (h313) Haoda Wang (h313)
hristoast hristoast
Internecine Internecine

@ -1,6 +1,7 @@
0.46.0 0.46.0
------ ------
Bug #1515: Opening console masks dialogue, inventory menu
Bug #2969: Scripted items can stack Bug #2969: Scripted items can stack
Bug #2987: Editor: some chance and AI data fields can overflow Bug #2987: Editor: some chance and AI data fields can overflow
Bug #3006: 'else if' operator breaks script compilation Bug #3006: 'else if' operator breaks script compilation
@ -12,7 +13,9 @@
Bug #3765: DisableTeleporting makes Mark/Recall/Intervention effects undetectable Bug #3765: DisableTeleporting makes Mark/Recall/Intervention effects undetectable
Bug #3778: [Mod] Improved Thrown Weapon Projectiles - weapons have wrong transformation during throw animation Bug #3778: [Mod] Improved Thrown Weapon Projectiles - weapons have wrong transformation during throw animation
Bug #3812: Wrong multiline tooltips width when word-wrapping is enabled Bug #3812: Wrong multiline tooltips width when word-wrapping is enabled
Bug #4240: Ash storm origin coordinates and hand shielding animation behavior are incorrect
Bug #4329: Removed birthsign abilities are restored after reloading the save Bug #4329: Removed birthsign abilities are restored after reloading the save
Bug #4341: Error message about missing GDB is too vague
Bug #4383: Bow model obscures crosshair when arrow is drawn Bug #4383: Bow model obscures crosshair when arrow is drawn
Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons
Bug #4411: Reloading a saved game while falling prevents damage in some cases Bug #4411: Reloading a saved game while falling prevents damage in some cases
@ -35,6 +38,7 @@
Bug #4768: Fallback numerical value recovery chokes on invalid arguments Bug #4768: Fallback numerical value recovery chokes on invalid arguments
Bug #4775: Slowfall effect resets player jumping flag Bug #4775: Slowfall effect resets player jumping flag
Bug #4778: Interiors of Illusion puzzle in Sotha Sil Expanded mod is broken Bug #4778: Interiors of Illusion puzzle in Sotha Sil Expanded mod is broken
Bug #4787: Sneaking makes 1st person walking/bobbing animation super-slow
Bug #4797: Player sneaking and running stances are not accounted for when in air Bug #4797: Player sneaking and running stances are not accounted for when in air
Bug #4800: Standing collisions are not updated immediately when an object is teleported without a cell change Bug #4800: Standing collisions are not updated immediately when an object is teleported without a cell change
Bug #4803: Stray special characters before begin statement break script compilation Bug #4803: Stray special characters before begin statement break script compilation
@ -50,14 +54,17 @@
Bug #4828: Potion looping effects VFX are not shown for NPCs Bug #4828: Potion looping effects VFX are not shown for NPCs
Bug #4837: CTD when a mesh with NiLODNode root node with particles is loaded Bug #4837: CTD when a mesh with NiLODNode root node with particles is loaded
Bug #4841: Russian localization ignores implicit keywords Bug #4841: Russian localization ignores implicit keywords
Bug #4844: Data race in savegame loading / GlobalMap render
Bug #4847: Idle animation reset oddities Bug #4847: Idle animation reset oddities
Bug #4851: No shadows since switch to OSG Bug #4851: No shadows since switch to OSG
Bug #4860: Actors outside of processing range visible for one frame after spawning Bug #4860: Actors outside of processing range visible for one frame after spawning
Bug #4867: Arbitrary text after local variable declarations breaks script compilation Bug #4867: Arbitrary text after local variable declarations breaks script compilation
Bug #4876: AI ratings handling inconsistencies Bug #4876: AI ratings handling inconsistencies
Bug #4877: Startup script executes only on a new game start Bug #4877: Startup script executes only on a new game start
Bug #4879: SayDone returns 0 on the frame Say is called
Bug #4888: Global variable stray explicit reference calls break script compilation Bug #4888: Global variable stray explicit reference calls break script compilation
Bug #4896: Title screen music doesn't loop Bug #4896: Title screen music doesn't loop
Bug #4902: Using scrollbars in settings causes resolution to change
Bug #4911: Editor: QOpenGLContext::swapBuffers() warning with Qt5 Bug #4911: Editor: QOpenGLContext::swapBuffers() warning with Qt5
Bug #4916: Specular power (shininess) material parameter is ignored when shaders are used. Bug #4916: Specular power (shininess) material parameter is ignored when shaders are used.
Bug #4918: Abilities don't play looping VFX when they're initially applied Bug #4918: Abilities don't play looping VFX when they're initially applied
@ -71,6 +78,7 @@
Bug #4945: Poor random magic magnitude distribution Bug #4945: Poor random magic magnitude distribution
Bug #4947: Player character doesn't use lip animation Bug #4947: Player character doesn't use lip animation
Bug #4948: Footstep sounds while levitating on ground level Bug #4948: Footstep sounds while levitating on ground level
Bug #4961: Flying creature combat engagement takes z-axis into account
Bug #4963: Enchant skill progress is incorrect Bug #4963: Enchant skill progress is incorrect
Bug #4964: Multiple effect spell projectile sounds play louder than vanilla Bug #4964: Multiple effect spell projectile sounds play louder than vanilla
Bug #4965: Global light attenuation settings setup is lacking Bug #4965: Global light attenuation settings setup is lacking
@ -82,7 +90,15 @@
Bug #4984: "Friendly hits" feature should be used only for player's followers Bug #4984: "Friendly hits" feature should be used only for player's followers
Bug #4989: Object dimension-dependent VFX scaling behavior is inconsistent Bug #4989: Object dimension-dependent VFX scaling behavior is inconsistent
Bug #4990: Dead bodies prevent you from hitting Bug #4990: Dead bodies prevent you from hitting
Bug #4999: Drop instruction behaves differently from vanilla
Bug #5001: Possible data race in the Animation::setAlpha()
Bug #5004: Werewolves shield their eyes during storm Bug #5004: Werewolves shield their eyes during storm
Bug #5018: Spell tooltips don't support purely negative magnitudes
Bug #5025: Data race in the ICO::setMaximumNumOfObjectsToCompilePerFrame()
Bug #5028: Offered price caps are not trading-specific
Bug #5038: Enchanting success chance calculations are blatantly wrong
Bug #5047: # in cell names sets color
Bug #5050: Invalid spell effects are not handled gracefully
Feature #1774: Handle AvoidNode Feature #1774: Handle AvoidNode
Feature #2229: Improve pathfinding AI Feature #2229: Improve pathfinding AI
Feature #3025: Analogue gamepad movement controls Feature #3025: Analogue gamepad movement controls
@ -90,12 +106,16 @@
Feature #3610: Option to invert X axis Feature #3610: Option to invert X axis
Feature #3893: Implicit target for "set" function in console Feature #3893: Implicit target for "set" function in console
Feature #3980: In-game option to disable controller Feature #3980: In-game option to disable controller
Feature #3999: Shift + Double Click should maximize/restore menu size
Feature #4001: Toggle sneak controller shortcut Feature #4001: Toggle sneak controller shortcut
Feature #4209: Editor: Faction rank sub-table Feature #4209: Editor: Faction rank sub-table
Feature #4255: Handle broken RepairedOnMe script function
Feature #4316: Implement RaiseRank/LowerRank functions properly
Feature #4360: Improve default controller bindings Feature #4360: Improve default controller bindings
Feature #4673: Weapon sheathing Feature #4673: Weapon sheathing
Feature #4675: Support for NiRollController Feature #4675: Support for NiRollController
Feature #4730: Native animated containers support Feature #4730: Native animated containers support
Feature #4784: Launcher: Duplicate Content Lists
Feature #4812: Support NiSwitchNode Feature #4812: Support NiSwitchNode
Feature #4836: Daytime node switch Feature #4836: Daytime node switch
Feature #4859: Make water reflections more configurable Feature #4859: Make water reflections more configurable
@ -106,6 +126,12 @@
Feature #4968: Scalable UI widget skins Feature #4968: Scalable UI widget skins
Feature #4994: Persistent pinnable windows hiding Feature #4994: Persistent pinnable windows hiding
Feature #5000: Compressed BSA format support Feature #5000: Compressed BSA format support
Feature #5010: Native graphics herbalism support
Feature #5031: Make GetWeaponType function return different values for tools
Feature #5033: Magic armor mitigation for creatures
Feature #5034: Make enchanting window stay open after a failed attempt
Feature #5036: Allow scripted faction leaving
Feature #5051: Provide a separate textures for scrollbars
Task #4686: Upgrade media decoder to a more current FFmpeg API Task #4686: Upgrade media decoder to a more current FFmpeg API
Task #4695: Optimize Distant Terrain memory consumption Task #4695: Optimize Distant Terrain memory consumption
Task #4721: Add NMake support to the Windows prebuild script Task #4721: Add NMake support to the Windows prebuild script

@ -12,7 +12,7 @@
#include <components/esm/loadspel.hpp> #include <components/esm/loadspel.hpp>
#include <components/esm/loadweap.hpp> #include <components/esm/loadweap.hpp>
#include <boost/format.hpp> #include <components/misc/stringops.hpp>
std::string bodyPartLabel(int idx) std::string bodyPartLabel(int idx)
{ {
@ -659,7 +659,7 @@ std::string bodyPartFlags(int flags)
(ESM::BodyPart::BPF_Female| (ESM::BodyPart::BPF_Female|
ESM::BodyPart::BPF_NotPlayable)); ESM::BodyPart::BPF_NotPlayable));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -680,7 +680,7 @@ std::string cellFlags(int flags)
ESM::Cell::QuasiEx| ESM::Cell::QuasiEx|
0x00000040)); 0x00000040));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -696,7 +696,7 @@ std::string containerFlags(int flags)
ESM::Container::Organic| ESM::Container::Organic|
ESM::Container::Respawn)); ESM::Container::Respawn));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -722,7 +722,7 @@ std::string creatureFlags(int flags)
ESM::Creature::Weapon| ESM::Creature::Weapon|
ESM::Creature::Essential)); ESM::Creature::Essential));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%02X)") % flags); properties += Misc::StringUtils::format("(0x%02X)", flags);
return properties; return properties;
} }
@ -737,7 +737,7 @@ std::string landFlags(int flags)
if (flags & 0x00000004) properties += "Unknown3 "; if (flags & 0x00000004) properties += "Unknown3 ";
if (flags & 0x00000002) properties += "Unknown2 "; if (flags & 0x00000002) properties += "Unknown2 ";
if (flags & 0xFFFFFFF8) properties += "Invalid "; if (flags & 0xFFFFFFF8) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -751,7 +751,7 @@ std::string itemListFlags(int flags)
(ESM::ItemLevList::AllLevels| (ESM::ItemLevList::AllLevels|
ESM::ItemLevList::Each)); ESM::ItemLevList::Each));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -762,7 +762,7 @@ std::string creatureListFlags(int flags)
if (flags & ESM::CreatureLevList::AllLevels) properties += "AllLevels "; if (flags & ESM::CreatureLevList::AllLevels) properties += "AllLevels ";
int unused = (0xFFFFFFFF ^ ESM::CreatureLevList::AllLevels); int unused = (0xFFFFFFFF ^ ESM::CreatureLevList::AllLevels);
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -790,7 +790,7 @@ std::string lightFlags(int flags)
ESM::Light::Negative| ESM::Light::Negative|
ESM::Light::OffDefault)); ESM::Light::OffDefault));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -816,7 +816,7 @@ std::string magicEffectFlags(int flags)
if (flags & ESM::MagicEffect::NegativeLight) properties += "NegativeLight "; if (flags & ESM::MagicEffect::NegativeLight) properties += "NegativeLight ";
if (flags & 0xFFFC0000) properties += "Invalid "; if (flags & 0xFFFC0000) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -838,7 +838,7 @@ std::string npcFlags(int flags)
ESM::NPC::Respawn| ESM::NPC::Respawn|
ESM::NPC::Essential)); ESM::NPC::Essential));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%02X)") % flags); properties += Misc::StringUtils::format("(0x%02X)", flags);
return properties; return properties;
} }
@ -853,7 +853,7 @@ std::string raceFlags(int flags)
(ESM::Race::Playable| (ESM::Race::Playable|
ESM::Race::Beast)); ESM::Race::Beast));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -869,7 +869,7 @@ std::string spellFlags(int flags)
ESM::Spell::F_PCStart| ESM::Spell::F_PCStart|
ESM::Spell::F_Always)); ESM::Spell::F_Always));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }
@ -886,6 +886,6 @@ std::string weaponFlags(int flags)
(ESM::Weapon::Magical| (ESM::Weapon::Magical|
ESM::Weapon::Silver)); ESM::Weapon::Silver));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += Misc::StringUtils::format("(0x%08X)", flags);
return properties; return properties;
} }

@ -4,7 +4,7 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <boost/format.hpp> #include <components/misc/stringops.hpp>
namespace namespace
{ {
@ -12,7 +12,7 @@ namespace
void printAIPackage(ESM::AIPackage p) void printAIPackage(ESM::AIPackage p)
{ {
std::cout << " AI Type: " << aiTypeLabel(p.mType) std::cout << " AI Type: " << aiTypeLabel(p.mType)
<< " (" << boost::format("0x%08X") % p.mType << ")" << std::endl; << " (" << Misc::StringUtils::format("0x%08X", p.mType) << ")" << std::endl;
if (p.mType == ESM::AI_Wander) if (p.mType == ESM::AI_Wander)
{ {
std::cout << " Distance: " << p.mWander.mDistance << std::endl; std::cout << " Distance: " << p.mWander.mDistance << std::endl;
@ -46,7 +46,7 @@ void printAIPackage(ESM::AIPackage p)
std::cout << " Activate Unknown: " << p.mActivate.mUnk << std::endl; std::cout << " Activate Unknown: " << p.mActivate.mUnk << std::endl;
} }
else { else {
std::cout << " BadPackage: " << boost::format("0x%08x") % p.mType << std::endl; std::cout << " BadPackage: " << Misc::StringUtils::format("0x%08X", p.mType) << std::endl;
} }
if (!p.mCellName.empty()) if (!p.mCellName.empty())
@ -64,7 +64,7 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
char indicator = rule[2]; char indicator = rule[2];
std::string type_str = "INVALID"; std::string type_str = "INVALID";
std::string func_str = str(boost::format("INVALID=%s") % rule.substr(1,3)); std::string func_str = Misc::StringUtils::format("INVALID=%s", rule.substr(1,3));
int func; int func;
std::istringstream iss(rule.substr(2,2)); std::istringstream iss(rule.substr(2,2));
iss >> func; iss >> func;
@ -104,7 +104,7 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
// for all types not qual to one. If this wasn't true, go back to // for all types not qual to one. If this wasn't true, go back to
// the error message. // the error message.
if (type != '1' && rule[3] != 'X') if (type != '1' && rule[3] != 'X')
func_str = str(boost::format("INVALID=%s") % rule.substr(1,3)); func_str = Misc::StringUtils::format("INVALID=%s", rule.substr(1,3));
char oper = rule[4]; char oper = rule[4];
std::string oper_str = "??"; std::string oper_str = "??";
@ -122,8 +122,7 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
std::ostringstream stream; std::ostringstream stream;
stream << ss.mValue; stream << ss.mValue;
std::string result = str(boost::format("%-12s %-32s %2s %s") std::string result = Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str());
% type_str % func_str % oper_str % stream.str());
return result; return result;
} }
@ -156,13 +155,13 @@ void printTransport(const std::vector<ESM::Transport::Dest>& transport)
for (const ESM::Transport::Dest& dest : transport) for (const ESM::Transport::Dest& dest : transport)
{ {
std::cout << " Destination Position: " std::cout << " Destination Position: "
<< boost::format("%12.3f") % dest.mPos.pos[0] << "," << Misc::StringUtils::format("%12.3f", dest.mPos.pos[0]) << ","
<< boost::format("%12.3f") % dest.mPos.pos[1] << "," << Misc::StringUtils::format("%12.3f", dest.mPos.pos[1]) << ","
<< boost::format("%12.3f") % dest.mPos.pos[2] << ")" << std::endl; << Misc::StringUtils::format("%12.3f", dest.mPos.pos[2]) << ")" << std::endl;
std::cout << " Destination Rotation: " std::cout << " Destination Rotation: "
<< boost::format("%9.6f") % dest.mPos.rot[0] << "," << Misc::StringUtils::format("%9.6f", dest.mPos.rot[0]) << ","
<< boost::format("%9.6f") % dest.mPos.rot[1] << "," << Misc::StringUtils::format("%9.6f", dest.mPos.rot[1]) << ","
<< boost::format("%9.6f") % dest.mPos.rot[2] << ")" << std::endl; << Misc::StringUtils::format("%9.6f", dest.mPos.rot[2]) << ")" << std::endl;
if (!dest.mCellName.empty()) if (!dest.mCellName.empty())
std::cout << " Destination Cell: " << dest.mCellName << std::endl; std::cout << " Destination Cell: " << dest.mCellName << std::endl;
} }
@ -542,7 +541,7 @@ void Record<ESM::Cell>::print()
std::cout << " Water Level: " << mData.mWater << std::endl; std::cout << " Water Level: " << mData.mWater << std::endl;
} }
else else
std::cout << " Map Color: " << boost::format("0x%08X") % mData.mMapColor << std::endl; std::cout << " Map Color: " << Misc::StringUtils::format("0x%08X", mData.mMapColor) << std::endl;
std::cout << " Water Level Int: " << mData.mWaterInt << std::endl; std::cout << " Water Level Int: " << mData.mWaterInt << std::endl;
std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl; std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl; std::cout << " Deleted: " << mIsDeleted << std::endl;
@ -607,7 +606,7 @@ void Record<ESM::Container>::print()
std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl; std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl;
std::cout << " Weight: " << mData.mWeight << std::endl; std::cout << " Weight: " << mData.mWeight << std::endl;
for (const ESM::ContItem &item : mData.mInventory.mList) for (const ESM::ContItem &item : mData.mInventory.mList)
std::cout << " Inventory: Count: " << boost::format("%4d") % item.mCount std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount)
<< " Item: " << item.mItem.toString() << std::endl; << " Item: " << item.mItem.toString() << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl; std::cout << " Deleted: " << mIsDeleted << std::endl;
} }
@ -653,7 +652,7 @@ void Record<ESM::Creature>::print()
std::cout << " Gold: " << mData.mData.mGold << std::endl; std::cout << " Gold: " << mData.mData.mGold << std::endl;
for (const ESM::ContItem &item : mData.mInventory.mList) for (const ESM::ContItem &item : mData.mInventory.mList)
std::cout << " Inventory: Count: " << boost::format("%4d") % item.mCount std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount)
<< " Item: " << item.mItem.toString() << std::endl; << " Item: " << item.mItem.toString() << std::endl;
for (const std::string &spell : mData.mSpells.mList) for (const std::string &spell : mData.mSpells.mList)
@ -669,7 +668,7 @@ void Record<ESM::Creature>::print()
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl; std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl; std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl; std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl; std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
for (const ESM::AIPackage &package : mData.mAiPackage.mList) for (const ESM::AIPackage &package : mData.mAiPackage.mList)
printAIPackage(package); printAIPackage(package);
@ -1073,7 +1072,7 @@ void Record<ESM::NPC>::print()
} }
for (const ESM::ContItem &item : mData.mInventory.mList) for (const ESM::ContItem &item : mData.mInventory.mList)
std::cout << " Inventory: Count: " << boost::format("%4d") % item.mCount std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount)
<< " Item: " << item.mItem.toString() << std::endl; << " Item: " << item.mItem.toString() << std::endl;
for (const std::string &spell : mData.mSpells.mList) for (const std::string &spell : mData.mSpells.mList)
@ -1089,7 +1088,7 @@ void Record<ESM::NPC>::print()
std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl; std::cout << " AI U1:" << (int)mData.mAiData.mU1 << std::endl;
std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl; std::cout << " AI U2:" << (int)mData.mAiData.mU2 << std::endl;
std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl; std::cout << " AI U3:" << (int)mData.mAiData.mU3 << std::endl;
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl; std::cout << " AI Services:" << Misc::StringUtils::format("0x%08X", mData.mAiData.mServices) << std::endl;
for (const ESM::AIPackage &package : mData.mAiPackage.mList) for (const ESM::AIPackage &package : mData.mAiPackage.mList)
printAIPackage(package); printAIPackage(package);
@ -1212,7 +1211,7 @@ void Record<ESM::Script>::print()
std::cout << " ByteCode: "; std::cout << " ByteCode: ";
for (const unsigned char &byte : mData.mScriptData) for (const unsigned char &byte : mData.mScriptData)
std::cout << boost::format("%02X") % (int)(byte); std::cout << Misc::StringUtils::format("%02X", (int)(byte));
std::cout << std::endl; std::cout << std::endl;
if (mPrintPlain) if (mPrintPlain)

@ -39,10 +39,13 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config:
const QString encoding = mGameSettings.value("encoding", "win1252"); const QString encoding = mGameSettings.value("encoding", "win1252");
mSelector->setEncoding(encoding); mSelector->setEncoding(encoding);
mProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this); mNewProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
mCloneProfileDialog = new TextInputDialog(tr("Clone Content List"), tr("Content List name:"), this);
connect(mProfileDialog->lineEdit(), SIGNAL(textChanged(QString)), connect(mNewProfileDialog->lineEdit(), SIGNAL(textChanged(QString)),
this, SLOT(updateOkButton(QString))); this, SLOT(updateNewProfileOkButton(QString)));
connect(mCloneProfileDialog->lineEdit(), SIGNAL(textChanged(QString)),
this, SLOT(updateCloneProfileOkButton(QString)));
buildView(); buildView();
loadSettings(); loadSettings();
@ -61,6 +64,7 @@ void Launcher::DataFilesPage::buildView()
//tool buttons //tool buttons
ui.newProfileButton->setToolTip ("Create a new Content List"); ui.newProfileButton->setToolTip ("Create a new Content List");
ui.cloneProfileButton->setToolTip ("Clone the current Content List");
ui.deleteProfileButton->setToolTip ("Delete an existing Content List"); ui.deleteProfileButton->setToolTip ("Delete an existing Content List");
//combo box //combo box
@ -70,6 +74,7 @@ void Launcher::DataFilesPage::buildView()
// Add the actions to the toolbuttons // Add the actions to the toolbuttons
ui.newProfileButton->setDefaultAction (ui.newProfileAction); ui.newProfileButton->setDefaultAction (ui.newProfileAction);
ui.cloneProfileButton->setDefaultAction (ui.cloneProfileAction);
ui.deleteProfileButton->setDefaultAction (ui.deleteProfileAction); ui.deleteProfileButton->setDefaultAction (ui.deleteProfileAction);
//establish connections //establish connections
@ -246,10 +251,10 @@ void Launcher::DataFilesPage::slotProfileChanged(int index)
void Launcher::DataFilesPage::on_newProfileAction_triggered() void Launcher::DataFilesPage::on_newProfileAction_triggered()
{ {
if (mProfileDialog->exec() != QDialog::Accepted) if (mNewProfileDialog->exec() != QDialog::Accepted)
return; return;
QString profile = mProfileDialog->lineEdit()->text(); QString profile = mNewProfileDialog->lineEdit()->text();
if (profile.isEmpty()) if (profile.isEmpty())
return; return;
@ -273,6 +278,20 @@ void Launcher::DataFilesPage::addProfile (const QString &profile, bool setAsCurr
setProfile (ui.profilesComboBox->findText (profile), false); setProfile (ui.profilesComboBox->findText (profile), false);
} }
void Launcher::DataFilesPage::on_cloneProfileAction_triggered()
{
if (mCloneProfileDialog->exec() != QDialog::Accepted)
return;
QString profile = mCloneProfileDialog->lineEdit()->text();
if (profile.isEmpty())
return;
mLauncherSettings.setContentList(profile, selectedFilePaths());
addProfile(profile, true);
}
void Launcher::DataFilesPage::on_deleteProfileAction_triggered() void Launcher::DataFilesPage::on_deleteProfileAction_triggered()
{ {
QString profile = ui.profilesComboBox->currentText(); QString profile = ui.profilesComboBox->currentText();
@ -295,17 +314,16 @@ void Launcher::DataFilesPage::on_deleteProfileAction_triggered()
checkForDefaultProfile(); checkForDefaultProfile();
} }
void Launcher::DataFilesPage::updateOkButton(const QString &text) void Launcher::DataFilesPage::updateNewProfileOkButton(const QString &text)
{ {
// We do this here because we need the profiles combobox text // We do this here because we need the profiles combobox text
if (text.isEmpty()) { mNewProfileDialog->setOkButtonEnabled(!text.isEmpty() && ui.profilesComboBox->findText(text) == -1);
mProfileDialog->setOkButtonEnabled(false); }
return;
}
(ui.profilesComboBox->findText(text) == -1) void Launcher::DataFilesPage::updateCloneProfileOkButton(const QString &text)
? mProfileDialog->setOkButtonEnabled(true) {
: mProfileDialog->setOkButtonEnabled(false); // We do this here because we need the profiles combobox text
mCloneProfileDialog->setOkButtonEnabled(!text.isEmpty() && ui.profilesComboBox->findText(text) == -1);
} }
void Launcher::DataFilesPage::checkForDefaultProfile() void Launcher::DataFilesPage::checkForDefaultProfile()

@ -62,9 +62,11 @@ namespace Launcher
void slotProfileDeleted(const QString &item); void slotProfileDeleted(const QString &item);
void slotAddonDataChanged (); void slotAddonDataChanged ();
void updateOkButton(const QString &text); void updateNewProfileOkButton(const QString &text);
void updateCloneProfileOkButton(const QString &text);
void on_newProfileAction_triggered(); void on_newProfileAction_triggered();
void on_cloneProfileAction_triggered();
void on_deleteProfileAction_triggered(); void on_deleteProfileAction_triggered();
public: public:
@ -73,7 +75,8 @@ namespace Launcher
private: private:
TextInputDialog *mProfileDialog; TextInputDialog *mNewProfileDialog;
TextInputDialog *mCloneProfileDialog;
Files::ConfigurationManager &mCfgMgr; Files::ConfigurationManager &mCfgMgr;

@ -53,7 +53,7 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
// If object have creature soul trapped, check if that creature reference is valid // If object have creature soul trapped, check if that creature reference is valid
if (!cellRef.mSoul.empty()) if (!cellRef.mSoul.empty())
if (mObjects.searchId(cellRef.mSoul) == -1) if (mObjects.searchId(cellRef.mSoul) == -1)
messages.add(id, "Trapped soul object '" + cellRef.mOwner + "' does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Trapped soul object '" + cellRef.mSoul + "' does not exist", "", CSMDoc::Message::Severity_Error);
if (cellRef.mFaction.empty()) if (cellRef.mFaction.empty())
{ {

@ -62,7 +62,7 @@ add_openmw_dir (mwsound
add_openmw_dir (mwworld add_openmw_dir (mwworld
refdata worldimp scene globals class action nullaction actionteleport refdata worldimp scene globals class action nullaction actionteleport
containerstore actiontalk actiontake manualref player cellvisitors failedaction containerstore actiontalk actiontake manualref player cellvisitors failedaction
cells localscripts customdata inventorystore ptr actionopen actionread cells localscripts customdata inventorystore ptr actionopen actionread actionharvest
actionequip timestamp actionalchemy cellstore actionapply actioneat actionequip timestamp actionalchemy cellstore actionapply actioneat
store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager

@ -368,10 +368,10 @@ OMW::Engine::~Engine()
mWorkQueue = nullptr; mWorkQueue = nullptr;
mResourceSystem.reset();
mViewer = nullptr; mViewer = nullptr;
mResourceSystem.reset();
delete mEncoder; delete mEncoder;
mEncoder = nullptr; mEncoder = nullptr;
@ -404,7 +404,8 @@ void OMW::Engine::enableFSStrict(bool fsStrict)
void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs) void OMW::Engine::setDataDirs (const Files::PathContainer& dataDirs)
{ {
mDataDirs = dataDirs; mDataDirs = dataDirs;
mFileCollections = Files::Collections (dataDirs, !mFSStrict); mDataDirs.insert(mDataDirs.begin(), (mResDir / "vfs"));
mFileCollections = Files::Collections (mDataDirs, !mFSStrict);
} }
// Add BSA archive // Add BSA archive

@ -273,6 +273,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
cfgMgr.processPaths(dataDirs); cfgMgr.processPaths(dataDirs);
engine.setResourceDir(variables["resources"].as<Files::EscapeHashString>().toStdString());
engine.setDataDirs(dataDirs); engine.setDataDirs(dataDirs);
// fallback archives // fallback archives
@ -282,8 +283,6 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
engine.addArchive(*it); engine.addArchive(*it);
} }
engine.setResourceDir(variables["resources"].as<Files::EscapeHashString>().toStdString());
StringsVector content = variables["content"].as<Files::EscapeStringVector>().toStdStringVector(); StringsVector content = variables["content"].as<Files::EscapeStringVector>().toStdStringVector();
if (content.empty()) if (content.empty())
{ {

@ -375,9 +375,6 @@ namespace MWBase
virtual const Translation::Storage& getTranslationDataStorage() const = 0; virtual const Translation::Storage& getTranslationDataStorage() const = 0;
/// Warning: do not use MyGUI::InputManager::setKeyFocusWidget directly. Instead use this.
virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0;
virtual void loadUserFonts() = 0; virtual void loadUserFonts() = 0;
virtual Loading::Listener* getLoadingScreen() = 0; virtual Loading::Listener* getLoadingScreen() = 0;
@ -408,6 +405,7 @@ namespace MWBase
virtual void removeCurrentModal(MWGui::WindowModal* input) = 0; virtual void removeCurrentModal(MWGui::WindowModal* input) = 0;
virtual void pinWindow (MWGui::GuiWindow window) = 0; virtual void pinWindow (MWGui::GuiWindow window) = 0;
virtual void toggleMaximized(MWGui::Layout *layout) = 0;
/// Fade the screen in, over \a time seconds /// Fade the screen in, over \a time seconds
virtual void fadeScreenIn(const float time, bool clearQueue=true, float delay=0.f) = 0; virtual void fadeScreenIn(const float time, bool clearQueue=true, float delay=0.f) = 0;
@ -421,6 +419,7 @@ namespace MWBase
virtual void activateHitOverlay(bool interrupt=true) = 0; virtual void activateHitOverlay(bool interrupt=true) = 0;
virtual void setWerewolfOverlay(bool set) = 0; virtual void setWerewolfOverlay(bool set) = 0;
virtual void toggleConsole() = 0;
virtual void toggleDebugWindow() = 0; virtual void toggleDebugWindow() = 0;
/// Cycle to next or previous spell /// Cycle to next or previous spell
@ -436,6 +435,7 @@ namespace MWBase
virtual std::string correctTexturePath(const std::string& path) = 0; virtual std::string correctTexturePath(const std::string& path) = 0;
virtual bool textureExists(const std::string& path) = 0; virtual bool textureExists(const std::string& path) = 0;
virtual void addCell(MWWorld::CellStore* cell) = 0;
virtual void removeCell(MWWorld::CellStore* cell) = 0; virtual void removeCell(MWWorld::CellStore* cell) = 0;
virtual void writeFog(MWWorld::CellStore* cell) = 0; virtual void writeFog(MWWorld::CellStore* cell) = 0;

@ -187,7 +187,7 @@ namespace MWBase
///< Return a pointer to a liveCellRef with the given name. ///< Return a pointer to a liveCellRef with the given name.
/// \param activeOnly do non search inactive cells. /// \param activeOnly do non search inactive cells.
virtual MWWorld::Ptr searchPtr (const std::string& name, bool activeOnly) = 0; virtual MWWorld::Ptr searchPtr (const std::string& name, bool activeOnly, bool searchInContainers = true) = 0;
///< Return a pointer to a liveCellRef with the given name. ///< Return a pointer to a liveCellRef with the given name.
/// \param activeOnly do non search inactive cells. /// \param activeOnly do non search inactive cells.
@ -750,6 +750,7 @@ namespace MWBase
/// Return the distance between actor's weapon and target's collision box. /// Return the distance between actor's weapon and target's collision box.
virtual float getHitDistance(const MWWorld::ConstPtr& actor, const MWWorld::ConstPtr& target) = 0; virtual float getHitDistance(const MWWorld::ConstPtr& actor, const MWWorld::ConstPtr& target) = 0;
virtual void addContainerScripts(const MWWorld::Ptr& reference, MWWorld::CellStore* cell) = 0;
virtual void removeContainerScripts(const MWWorld::Ptr& reference) = 0; virtual void removeContainerScripts(const MWWorld::Ptr& reference) = 0;
virtual bool isPlayerInJail() const = 0; virtual bool isPlayerInJail() const = 0;

@ -27,6 +27,7 @@
#include "../mwworld/customdata.hpp" #include "../mwworld/customdata.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
#include "../mwworld/esmstore.hpp" #include "../mwworld/esmstore.hpp"
#include "../mwworld/actionharvest.hpp"
#include "../mwworld/actionopen.hpp" #include "../mwworld/actionopen.hpp"
#include "../mwworld/actiontrap.hpp" #include "../mwworld/actiontrap.hpp"
#include "../mwphysics/physicssystem.hpp" #include "../mwphysics/physicssystem.hpp"
@ -34,6 +35,7 @@
#include "../mwgui/tooltips.hpp" #include "../mwgui/tooltips.hpp"
#include "../mwrender/animation.hpp"
#include "../mwrender/objects.hpp" #include "../mwrender/objects.hpp"
#include "../mwrender/renderinginterface.hpp" #include "../mwrender/renderinginterface.hpp"
@ -52,6 +54,10 @@ namespace MWClass
{ {
return *this; return *this;
} }
virtual const ContainerCustomData& asContainerCustomData() const
{
return *this;
}
}; };
MWWorld::CustomData *ContainerCustomData::clone() const MWWorld::CustomData *ContainerCustomData::clone() const
@ -75,15 +81,30 @@ namespace MWClass
// store // store
ptr.getRefData().setCustomData (data.release()); ptr.getRefData().setCustomData (data.release());
MWBase::Environment::get().getWorld()->addContainerScripts(ptr, ptr.getCell());
} }
} }
bool canBeHarvested(const MWWorld::ConstPtr& ptr)
{
const MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);
if (animation == nullptr)
return false;
return animation->canBeHarvested();
}
void Container::respawn(const MWWorld::Ptr &ptr) const void Container::respawn(const MWWorld::Ptr &ptr) const
{ {
MWWorld::LiveCellRef<ESM::Container> *ref = MWWorld::LiveCellRef<ESM::Container> *ref =
ptr.get<ESM::Container>(); ptr.get<ESM::Container>();
if (ref->mBase->mFlags & ESM::Container::Respawn) if (ref->mBase->mFlags & ESM::Container::Respawn)
{ {
// Container was not touched, there is no need to modify its content.
if (ptr.getRefData().getCustomData() == nullptr)
return;
MWBase::Environment::get().getWorld()->removeContainerScripts(ptr); MWBase::Environment::get().getWorld()->removeContainerScripts(ptr);
ptr.getRefData().setCustomData(nullptr); ptr.getRefData().setCustomData(nullptr);
} }
@ -239,6 +260,12 @@ namespace MWClass
{ {
if(!isTrapped) if(!isTrapped)
{ {
if (canBeHarvested(ptr))
{
std::shared_ptr<MWWorld::Action> action (new MWWorld::ActionHarvest(ptr));
return action;
}
std::shared_ptr<MWWorld::Action> action (new MWWorld::ActionOpen(ptr)); std::shared_ptr<MWWorld::Action> action (new MWWorld::ActionOpen(ptr));
return action; return action;
} }
@ -289,9 +316,18 @@ namespace MWClass
bool Container::hasToolTip (const MWWorld::ConstPtr& ptr) const bool Container::hasToolTip (const MWWorld::ConstPtr& ptr) const
{ {
const MWWorld::LiveCellRef<ESM::Container> *ref = ptr.get<ESM::Container>(); if (getName(ptr).empty())
return false;
if (const MWWorld::CustomData* data = ptr.getRefData().getCustomData())
return !canBeHarvested(ptr) || data->asContainerCustomData().mContainerStore.hasVisibleItems();
return (ref->mBase->mName != ""); return true;
}
bool Container::canBeActivated(const MWWorld::Ptr& ptr) const
{
return hasToolTip(ptr);
} }
MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const

@ -73,6 +73,8 @@ namespace MWClass
const; const;
///< Write additional state from \a ptr into \a state. ///< Write additional state from \a ptr into \a state.
virtual bool canBeActivated(const MWWorld::Ptr& ptr) const;
static void registerSelf(); static void registerSelf();
virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void respawn (const MWWorld::Ptr& ptr) const;

@ -519,10 +519,10 @@ namespace MWClass
*/ */
} }
damage = std::max(1.f, damage);
if(ishealth) if(ishealth)
{ {
damage *= damage / (damage + getArmorRating(ptr));
damage = std::max(1.f, damage);
if (!attacker.isEmpty()) if (!attacker.isEmpty())
{ {
damage = scaleDamage(damage, attacker, ptr); damage = scaleDamage(damage, attacker, ptr);
@ -747,7 +747,7 @@ namespace MWClass
float Creature::getArmorRating (const MWWorld::Ptr& ptr) const float Creature::getArmorRating (const MWWorld::Ptr& ptr) const
{ {
// Note this is currently unused. Creatures do not use armor mitigation. // Equipment armor rating is deliberately ignored.
return getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).getMagnitude(); return getCreatureStats(ptr).getMagicEffects().get(ESM::MagicEffect::Shield).getMagnitude();
} }

@ -409,7 +409,7 @@ namespace MWClass
store.get<ESM::Region>().find(cell->mRegion); store.get<ESM::Region>().find(cell->mRegion);
//name as is, not a token //name as is, not a token
return region->mName; return MyGUI::TextIterator::toTagsString(region->mName);
} }
} }

@ -189,6 +189,7 @@ namespace MWClass
info.effects = list; info.effects = list;
info.text = text; info.text = text;
info.isIngredient = true;
return info; return info;
} }

@ -1601,6 +1601,19 @@ namespace MWClass
int Npc::getPrimaryFactionRank (const MWWorld::ConstPtr& ptr) const int Npc::getPrimaryFactionRank (const MWWorld::ConstPtr& ptr) const
{ {
std::string factionID = ptr.getClass().getPrimaryFaction(ptr);
if(factionID.empty())
return -1;
// Search in the NPC data first
if (const MWWorld::CustomData* data = ptr.getRefData().getCustomData())
{
int rank = data->asNpcCustomData().mNpcStats.getFactionRank(factionID);
if (rank >= 0)
return rank;
}
// Use base NPC record as a fallback
const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>(); const MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
return ref->mBase->getFactionRank(); return ref->mBase->getFactionRank();
} }

@ -4,6 +4,8 @@
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_EditBox.h> #include <MyGUI_EditBox.h>
#include <MyGUI_ControllerManager.h> #include <MyGUI_ControllerManager.h>
#include <MyGUI_ControllerRepeatClick.h>
#include <MyGUI_InputManager.h>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -26,9 +28,6 @@
namespace MWGui namespace MWGui
{ {
const float AlchemyWindow::sCountChangeInitialPause = 0.5f;
const float AlchemyWindow::sCountChangeInterval = 0.1f;
AlchemyWindow::AlchemyWindow() AlchemyWindow::AlchemyWindow()
: WindowBase("openmw_alchemy_window.layout") : WindowBase("openmw_alchemy_window.layout")
, mSortModel(nullptr) , mSortModel(nullptr)
@ -170,7 +169,7 @@ namespace MWGui
update(); update();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mNameEdit);
} }
void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender) void AlchemyWindow::onIngredientSelected(MyGUI::Widget* _sender)
@ -249,6 +248,7 @@ namespace MWGui
params.mAttribute = effectKey.mArg; params.mAttribute = effectKey.mArg;
params.mIsConstant = true; params.mIsConstant = true;
params.mNoTarget = true; params.mNoTarget = true;
params.mNoMagnitude = true;
params.mKnown = mAlchemy->knownEffect(effectIndex, MWBase::Environment::get().getWorld()->getPlayerPtr()); params.mKnown = mAlchemy->knownEffect(effectIndex, MWBase::Environment::get().getWorld()->getPlayerPtr());
@ -281,10 +281,9 @@ namespace MWGui
void AlchemyWindow::addRepeatController(MyGUI::Widget *widget) void AlchemyWindow::addRepeatController(MyGUI::Widget *widget)
{ {
MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(Controllers::ControllerRepeatEvent::getClassTypeName()); MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(MyGUI::ControllerRepeatClick::getClassTypeName());
Controllers::ControllerRepeatEvent* controller = item->castType<Controllers::ControllerRepeatEvent>(); MyGUI::ControllerRepeatClick* controller = static_cast<MyGUI::ControllerRepeatClick*>(item);
controller->eventRepeatClick += MyGUI::newDelegate(this, &AlchemyWindow::onRepeatClick); controller->eventRepeatClick += newDelegate(this, &AlchemyWindow::onRepeatClick);
controller->setRepeat(sCountChangeInitialPause, sCountChangeInterval);
MyGUI::ControllerManager::getInstance().addItem(widget, controller); MyGUI::ControllerManager::getInstance().addItem(widget, controller);
} }

@ -4,9 +4,10 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <MyGUI_ControllerItem.h>
#include <components/widgets/numericeditbox.hpp> #include <components/widgets/numericeditbox.hpp>
#include "controllers.hpp"
#include "windowbase.hpp" #include "windowbase.hpp"
namespace MWMechanics namespace MWMechanics

@ -4,6 +4,7 @@
#include <MyGUI_ImageBox.h> #include <MyGUI_ImageBox.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_ScrollView.h> #include <MyGUI_ScrollView.h>
#include <MyGUI_InputManager.h>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -71,7 +72,7 @@ namespace MWGui
WindowModal::onOpen(); WindowModal::onOpen();
updateBirths(); updateBirths();
updateSpells(); updateSpells();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mBirthList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mBirthList);
// Show the current birthsign by default // Show the current birthsign by default
const std::string &signId = const std::string &signId =

@ -101,7 +101,7 @@ namespace MWGui
setTakeButtonShow(showTakeButton); setTakeButtonShow(showTakeButton);
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
} }
void BookWindow::setTakeButtonShow(bool show) void BookWindow::setTakeButtonShow(bool show)
@ -161,9 +161,9 @@ namespace MWGui
mPrevPageButton->setVisible(prevPageVisible); mPrevPageButton->setVisible(prevPageVisible);
if (focus == mNextPageButton && !nextPageVisible && prevPageVisible) if (focus == mNextPageButton && !nextPageVisible && prevPageVisible)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mPrevPageButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mPrevPageButton);
else if (focus == mPrevPageButton && !prevPageVisible && nextPageVisible) else if (focus == mPrevPageButton && !prevPageVisible && nextPageVisible)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNextPageButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mNextPageButton);
if (mPages.empty()) if (mPages.empty())
return; return;

@ -3,6 +3,7 @@
#include <MyGUI_ImageBox.h> #include <MyGUI_ImageBox.h>
#include <MyGUI_ListBox.h> #include <MyGUI_ListBox.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_InputManager.h>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -135,7 +136,7 @@ namespace MWGui
WindowModal::onOpen (); WindowModal::onOpen ();
updateClasses(); updateClasses();
updateStats(); updateStats();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mClassList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mClassList);
// Show the current class by default // Show the current class by default
MWWorld::Ptr player = MWMechanics::getPlayer(); MWWorld::Ptr player = MWMechanics::getPlayer();
@ -436,7 +437,7 @@ namespace MWGui
getWidget(mEditName, "EditName"); getWidget(mEditName, "EditName");
// Make sure the edit box has focus // Make sure the edit box has focus
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mEditName); MyGUI::InputManager::getInstance().setKeyFocusWidget(mEditName);
MyGUI::Button* descriptionButton; MyGUI::Button* descriptionButton;
getWidget(descriptionButton, "DescriptionButton"); getWidget(descriptionButton, "DescriptionButton");
@ -902,7 +903,7 @@ namespace MWGui
okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sInputMenu1", "")); okButton->setCaption(MWBase::Environment::get().getWindowManager()->getGameSettingString("sInputMenu1", ""));
// Make sure the edit box has focus // Make sure the edit box has focus
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
DescriptionDialog::~DescriptionDialog() DescriptionDialog::~DescriptionDialog()

@ -2,6 +2,7 @@
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_EditBox.h> #include <MyGUI_EditBox.h>
#include <MyGUI_InputManager.h>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
@ -33,7 +34,7 @@ namespace MWGui
mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height + 24); mMessage->setSize(mMessage->getWidth(), mMessage->getTextSize().height + 24);
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mOkButton);
center(); center();
} }

@ -1,6 +1,8 @@
#include "console.hpp" #include "console.hpp"
#include <MyGUI_EditBox.h> #include <MyGUI_EditBox.h>
#include <MyGUI_InputManager.h>
#include <MyGUI_LayerManager.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
@ -150,8 +152,9 @@ namespace MWGui
void Console::onOpen() void Console::onOpen()
{ {
// Give keyboard focus to the combo box whenever the console is // Give keyboard focus to the combo box whenever the console is
// turned on // turned on and place it over other widgets
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCommandLine);
MyGUI::LayerManager::getInstance().upLayerItem(mMainWidget);
} }
void Console::print(const std::string &msg, const std::string& color) void Console::print(const std::string &msg, const std::string& color)
@ -471,7 +474,7 @@ namespace MWGui
mPtr = object; mPtr = object;
} }
// User clicked on an object. Restore focus to the console command line. // User clicked on an object. Restore focus to the console command line.
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCommandLine); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCommandLine);
} }
else else
{ {

@ -254,7 +254,7 @@ namespace MWGui
mItemView->setModel (mSortModel); mItemView->setModel (mSortModel);
mItemView->resetScrollBars(); mItemView->resetScrollBars();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
setTitle(container.getClass().getName(container)); setTitle(container.getClass().getName(container));
} }
@ -284,7 +284,8 @@ namespace MWGui
if (mModel) if (mModel)
mModel->onClose(); mModel->onClose();
MWBase::Environment::get().getMechanicsManager()->onClose(mPtr); if (!mPtr.isEmpty())
MWBase::Environment::get().getMechanicsManager()->onClose(mPtr);
} }
void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender) void ContainerWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
@ -297,7 +298,7 @@ namespace MWGui
if(mDragAndDrop != nullptr && mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop != nullptr && mDragAndDrop->mIsOnDragAndDrop)
return; return;
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
/* /*
Start of tes3mp addition Start of tes3mp addition
@ -377,7 +378,7 @@ namespace MWGui
{ {
if(mDragAndDrop == nullptr || !mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop == nullptr || !mDragAndDrop->mIsOnDragAndDrop)
{ {
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
onTakeAllButtonClicked(mTakeButton); onTakeAllButtonClicked(mTakeButton);

@ -7,54 +7,6 @@ namespace MWGui
{ {
namespace Controllers namespace Controllers
{ {
ControllerRepeatEvent::ControllerRepeatEvent() :
mInit(0.5f),
mStep(0.1f),
mEnabled(true),
mTimeLeft(0)
{
}
ControllerRepeatEvent::~ControllerRepeatEvent()
{
}
bool ControllerRepeatEvent::addTime(MyGUI::Widget* _widget, float _time)
{
if(mTimeLeft == 0)
mTimeLeft = mInit;
mTimeLeft -= _time;
while (mTimeLeft <= 0)
{
mTimeLeft += mStep;
eventRepeatClick(_widget, this);
}
return true;
}
void ControllerRepeatEvent::setRepeat(float init, float step)
{
mInit = init;
mStep = step;
}
void ControllerRepeatEvent::setEnabled(bool enable)
{
mEnabled = enable;
}
void ControllerRepeatEvent::setProperty(const std::string& _key, const std::string& _value)
{
}
void ControllerRepeatEvent::prepareItem(MyGUI::Widget* _widget)
{
}
// -------------------------------------------------------------
void ControllerFollowMouse::prepareItem(MyGUI::Widget *_widget) void ControllerFollowMouse::prepareItem(MyGUI::Widget *_widget)
{ {
} }

@ -13,39 +13,6 @@ namespace MWGui
{ {
namespace Controllers namespace Controllers
{ {
// Should be removed when upgrading to MyGUI 3.2.2 (current git), it has ControllerRepeatClick
class ControllerRepeatEvent :
public MyGUI::ControllerItem
{
MYGUI_RTTI_DERIVED( ControllerRepeatEvent )
public:
ControllerRepeatEvent();
virtual ~ControllerRepeatEvent();
void setRepeat(float init, float step);
void setEnabled(bool enable);
virtual void setProperty(const std::string& _key, const std::string& _value);
// Events
typedef MyGUI::delegates::CMultiDelegate2<MyGUI::Widget*, MyGUI::ControllerItem*> EventHandle_RepeatClickVoid;
/** Event : Repeat Click.\n
signature : void method(MyGUI::Widget* _sender, MyGUI::ControllerItem *_controller)\n
*/
EventHandle_RepeatClickVoid eventRepeatClick;
private:
bool addTime(MyGUI::Widget* _widget, float _time);
void prepareItem(MyGUI::Widget* _widget);
private:
float mInit;
float mStep;
bool mEnabled;
float mTimeLeft;
};
/// Automatically positions a widget below the mouse cursor. /// Automatically positions a widget below the mouse cursor.
class ControllerFollowMouse : class ControllerFollowMouse :
public MyGUI::ControllerItem public MyGUI::ControllerItem

@ -3,6 +3,7 @@
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_ScrollBar.h> #include <MyGUI_ScrollBar.h>
#include <MyGUI_RenderManager.h> #include <MyGUI_RenderManager.h>
#include <MyGUI_InputManager.h>
#include <components/widgets/numericeditbox.hpp> #include <components/widgets/numericeditbox.hpp>
@ -47,7 +48,7 @@ namespace MWGui
mMainWidget->getHeight()); mMainWidget->getHeight());
// by default, the text edit field has the focus of the keyboard // by default, the text edit field has the focus of the keyboard
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mItemEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mItemEdit);
mSlider->setScrollPosition(maxCount-1); mSlider->setScrollPosition(maxCount-1);

@ -5,6 +5,7 @@
#include <MyGUI_ProgressBar.h> #include <MyGUI_ProgressBar.h>
#include <MyGUI_ScrollBar.h> #include <MyGUI_ScrollBar.h>
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_InputManager.h>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/widgets/list.hpp> #include <components/widgets/list.hpp>
@ -380,7 +381,7 @@ namespace MWGui
{ {
onTopicActivated(topic); onTopicActivated(topic);
if (mGoodbyeButton->getEnabled()) if (mGoodbyeButton->getEnabled())
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mGoodbyeButton);
} }
else if (topic == sPersuasion) else if (topic == sPersuasion)
mPersuasionDialog.setVisible(true); mPersuasionDialog.setVisible(true);
@ -443,7 +444,7 @@ namespace MWGui
return; return;
} }
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mGoodbyeButton);
setTitle(mPtr.getClass().getName(mPtr)); setTitle(mPtr.getClass().getName(mPtr));
@ -622,7 +623,7 @@ namespace MWGui
bool goodbyeWasEnabled = mGoodbyeButton->getEnabled(); bool goodbyeWasEnabled = mGoodbyeButton->getEnabled();
mGoodbyeButton->setEnabled(goodbyeEnabled); mGoodbyeButton->setEnabled(goodbyeEnabled);
if (goodbyeEnabled && !goodbyeWasEnabled) if (goodbyeEnabled && !goodbyeWasEnabled)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mGoodbyeButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mGoodbyeButton);
bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye; bool topicsEnabled = !MWBase::Environment::get().getDialogueManager()->isInChoice() && !mGoodbye;
mTopicsList->setEnabled(topicsEnabled); mTopicsList->setEnabled(topicsEnabled);

@ -5,6 +5,7 @@
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_ScrollView.h> #include <MyGUI_ScrollView.h>
#include <MyGUI_EditBox.h> #include <MyGUI_EditBox.h>
#include <MyGUI_InputManager.h>
#include <components/widgets/list.hpp> #include <components/widgets/list.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -67,7 +68,7 @@ namespace MWGui
void EnchantingDialog::onOpen() void EnchantingDialog::onOpen()
{ {
center(); center();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mName); MyGUI::InputManager::getInstance().setKeyFocusWidget(mName);
} }
void EnchantingDialog::setSoulGem(const MWWorld::Ptr &gem) void EnchantingDialog::setSoulGem(const MWWorld::Ptr &gem)
@ -107,20 +108,11 @@ namespace MWGui
void EnchantingDialog::updateLabels() void EnchantingDialog::updateLabels()
{ {
std::stringstream enchantCost; mEnchantmentPoints->setCaption(std::to_string(static_cast<int>(mEnchanting.getEnchantPoints(false))) + " / " + std::to_string(mEnchanting.getMaxEnchantValue()));
enchantCost << std::setprecision(1) << std::fixed << mEnchanting.getEnchantPoints(); mCharge->setCaption(std::to_string(mEnchanting.getGemCharge()));
mEnchantmentPoints->setCaption(enchantCost.str() + " / " + MyGUI::utility::toString(mEnchanting.getMaxEnchantValue())); mSuccessChance->setCaption(std::to_string(std::max(0, std::min(100, mEnchanting.getEnchantChance()))));
mCastCost->setCaption(std::to_string(mEnchanting.getEffectiveCastCost()));
mCharge->setCaption(MyGUI::utility::toString(mEnchanting.getGemCharge())); mPrice->setCaption(std::to_string(mEnchanting.getEnchantPrice()));
int successChance = int(mEnchanting.getEnchantChance());
mSuccessChance->setCaption(MyGUI::utility::toString(std::max(0, successChance)));
std::stringstream castCost;
castCost << mEnchanting.getEffectiveCastCost();
mCastCost->setCaption(castCost.str());
mPrice->setCaption(MyGUI::utility::toString(mEnchanting.getEnchantPrice()));
switch(mEnchanting.getCastStyle()) switch(mEnchanting.getCastStyle())
{ {
@ -322,7 +314,7 @@ namespace MWGui
return; return;
} }
if (mEnchanting.getEnchantPoints() > mEnchanting.getMaxEnchantValue()) if (static_cast<int>(mEnchanting.getEnchantPoints(false)) > mEnchanting.getMaxEnchantValue())
{ {
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage29}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage29}");
return; return;
@ -348,7 +340,7 @@ namespace MWGui
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(item.getCellRef().getRefId(), mPtr)) if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(item.getCellRef().getRefId(), mPtr))
{ {
std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->mValue.getString(); std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->mValue.getString();
Misc::StringUtils::replace(msg, "%s", item.getClass().getName(item).c_str(), 2); msg = Misc::StringUtils::format(msg, item.getClass().getName(item));
MWBase::Environment::get().getWindowManager()->messageBox(msg); MWBase::Environment::get().getWindowManager()->messageBox(msg);
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, item, mPtr, 1); MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, item, mPtr, 1);
@ -366,13 +358,19 @@ namespace MWGui
{ {
MWBase::Environment::get().getWindowManager()->playSound("enchant success"); MWBase::Environment::get().getWindowManager()->playSound("enchant success");
MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu12}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sEnchantmentMenu12}");
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
} }
else else
{ {
MWBase::Environment::get().getWindowManager()->playSound("enchant fail"); MWBase::Environment::get().getWindowManager()->playSound("enchant fail");
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage34}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage34}");
if (!mEnchanting.getGem().isEmpty() && !mEnchanting.getGem().getRefData().getCount())
{
setSoulGem(MWWorld::Ptr());
mEnchanting.nextCastStyle();
updateLabels();
updateEffectsView();
}
} }
MWBase::Environment::get().getWindowManager()->removeGuiMode (GM_Enchanting);
} }
} }

@ -2,12 +2,12 @@
namespace MWGui namespace MWGui
{ {
MyGUI::VectorWidgetPtr ExposedWindow::getSkinWidgetsByName (const std::string &name) MyGUI::VectorWidgetPtr Window::getSkinWidgetsByName (const std::string &name)
{ {
return MyGUI::Widget::getSkinWidgetsByName (name); return MyGUI::Widget::getSkinWidgetsByName (name);
} }
MyGUI::Widget* ExposedWindow::getSkinWidget(const std::string & _name, bool _throw) MyGUI::Widget* Window::getSkinWidget(const std::string & _name, bool _throw)
{ {
MyGUI::VectorWidgetPtr widgets = getSkinWidgetsByName (_name); MyGUI::VectorWidgetPtr widgets = getSkinWidgetsByName (_name);

@ -9,9 +9,9 @@ namespace MWGui
/** /**
* @brief subclass to provide access to some Widget internals. * @brief subclass to provide access to some Widget internals.
*/ */
class ExposedWindow : public MyGUI::Window class Window : public MyGUI::Window
{ {
MYGUI_RTTI_DERIVED(ExposedWindow) MYGUI_RTTI_DERIVED(Window)
public: public:
MyGUI::VectorWidgetPtr getSkinWidgetsByName (const std::string &name); MyGUI::VectorWidgetPtr getSkinWidgetsByName (const std::string &name);

@ -274,6 +274,7 @@ namespace MWGui
if (!MWBase::Environment::get().getWindowManager ()->isGuiMode ()) if (!MWBase::Environment::get().getWindowManager ()->isGuiMode ())
return; return;
MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
if (mDragAndDrop->mIsOnDragAndDrop) if (mDragAndDrop->mIsOnDragAndDrop)
{ {
// drop item into the gameworld // drop item into the gameworld
@ -288,19 +289,19 @@ namespace MWGui
WorldItemModel drop (mouseX, mouseY); WorldItemModel drop (mouseX, mouseY);
mDragAndDrop->drop(&drop, nullptr); mDragAndDrop->drop(&drop, nullptr);
MWBase::Environment::get().getWindowManager()->changePointer("arrow"); winMgr->changePointer("arrow");
} }
else else
{ {
GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode(); GuiMode mode = winMgr->getMode();
if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) ) if (!winMgr->isConsoleMode() && (mode != GM_Container) && (mode != GM_Inventory))
return; return;
MWWorld::Ptr object = MWBase::Environment::get().getWorld()->getFacedObject(); MWWorld::Ptr object = MWBase::Environment::get().getWorld()->getFacedObject();
if (mode == GM_Console) if (winMgr->isConsoleMode())
MWBase::Environment::get().getWindowManager()->setConsoleSelectedObject(object); winMgr->setConsoleSelectedObject(object);
else //if ((mode == GM_Container) || (mode == GM_Inventory)) else //if ((mode == GM_Container) || (mode == GM_Inventory))
{ {
// pick up object // pick up object
@ -314,7 +315,7 @@ namespace MWGui
an item here, and expect the server's reply to our packet to cause the actual an item here, and expect the server's reply to our packet to cause the actual
picking up of items picking up of items
*/ */
//MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(object); //winMgr->getInventoryWindow()->pickUpObject(object);
{ {
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList(); mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset(); objectList->reset();

@ -176,28 +176,39 @@ namespace MWGui
mItemView->setModel(nullptr); mItemView->setModel(nullptr);
} }
void InventoryWindow::toggleMaximized()
{
std::string setting = getModeSetting();
bool maximized = !Settings::Manager::getBool(setting + " maximized", "Windows");
if (maximized)
setting += " maximized";
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
float x = Settings::Manager::getFloat(setting + " x", "Windows") * float(viewSize.width);
float y = Settings::Manager::getFloat(setting + " y", "Windows") * float(viewSize.height);
float w = Settings::Manager::getFloat(setting + " w", "Windows") * float(viewSize.width);
float h = Settings::Manager::getFloat(setting + " h", "Windows") * float(viewSize.height);
MyGUI::Window* window = mMainWidget->castType<MyGUI::Window>();
window->setCoord(x, y, w, h);
if (maximized)
Settings::Manager::setBool(setting, "Windows", maximized);
else
Settings::Manager::setBool(setting + " maximized", "Windows", maximized);
adjustPanes();
updatePreviewSize();
}
void InventoryWindow::setGuiMode(GuiMode mode) void InventoryWindow::setGuiMode(GuiMode mode)
{ {
std::string setting = "inventory";
mGuiMode = mode; mGuiMode = mode;
switch(mode) { std::string setting = getModeSetting();
case GM_Container: setPinButtonVisible(mode == GM_Inventory);
setPinButtonVisible(false);
setting += " container"; if (Settings::Manager::getBool(setting + " maximized", "Windows"))
break; setting += " maximized";
case GM_Companion:
setPinButtonVisible(false);
setting += " companion";
break;
case GM_Barter:
setPinButtonVisible(false);
setting += " barter";
break;
case GM_Inventory:
default:
setPinButtonVisible(true);
break;
}
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(setting + " x", "Windows") * viewSize.width), MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(setting + " x", "Windows") * viewSize.width),
@ -400,11 +411,11 @@ namespace MWGui
adjustPanes(); adjustPanes();
} }
void InventoryWindow::onWindowResize(MyGUI::Window* _sender) std::string InventoryWindow::getModeSetting() const
{ {
adjustPanes();
std::string setting = "inventory"; std::string setting = "inventory";
switch(mGuiMode) { switch(mGuiMode)
{
case GM_Container: case GM_Container:
setting += " container"; setting += " container";
break; break;
@ -418,6 +429,14 @@ namespace MWGui
break; break;
} }
return setting;
}
void InventoryWindow::onWindowResize(MyGUI::Window* _sender)
{
adjustPanes();
std::string setting = getModeSetting();
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
float x = _sender->getPosition().left / float(viewSize.width); float x = _sender->getPosition().left / float(viewSize.width);
float y = _sender->getPosition().top / float(viewSize.height); float y = _sender->getPosition().top / float(viewSize.height);
@ -427,6 +446,9 @@ namespace MWGui
Settings::Manager::setFloat(setting + " y", "Windows", y); Settings::Manager::setFloat(setting + " y", "Windows", y);
Settings::Manager::setFloat(setting + " w", "Windows", w); Settings::Manager::setFloat(setting + " w", "Windows", w);
Settings::Manager::setFloat(setting + " h", "Windows", h); Settings::Manager::setFloat(setting + " h", "Windows", h);
bool maximized = Settings::Manager::getBool(setting + " maximized", "Windows");
if (maximized)
Settings::Manager::setBool(setting + " maximized", "Windows", false);
if (mMainWidget->getSize().width != mLastXSize || mMainWidget->getSize().height != mLastYSize) if (mMainWidget->getSize().width != mLastXSize || mMainWidget->getSize().height != mLastYSize)
{ {
@ -490,7 +512,9 @@ namespace MWGui
void InventoryWindow::onTitleDoubleClicked() void InventoryWindow::onTitleDoubleClicked()
{ {
if (!mPinned) if (MyGUI::InputManager::getInstance().isShiftPressed())
toggleMaximized();
else if (!mPinned)
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Inventory);
} }

@ -65,6 +65,9 @@ namespace MWGui
/// Cycle to previous/next weapon /// Cycle to previous/next weapon
void cycle(bool next); void cycle(bool next);
protected:
virtual void onTitleDoubleClicked();
private: private:
DragAndDrop* mDragAndDrop; DragAndDrop* mDragAndDrop;
@ -104,11 +107,15 @@ namespace MWGui
float mScaleFactor; float mScaleFactor;
float mUpdateTimer; float mUpdateTimer;
void toggleMaximized();
void onItemSelected(int index); void onItemSelected(int index);
void onItemSelectedFromSourceModel(int index); void onItemSelectedFromSourceModel(int index);
void onBackgroundSelected(); void onBackgroundSelected();
std::string getModeSetting() const;
void sellItem(MyGUI::Widget* sender, int count); void sellItem(MyGUI::Widget* sender, int count);
void dragItem(MyGUI::Widget* sender, int count); void dragItem(MyGUI::Widget* sender, int count);
@ -116,7 +123,6 @@ namespace MWGui
void onFilterChanged(MyGUI::Widget* _sender); void onFilterChanged(MyGUI::Widget* _sender);
void onAvatarClicked(MyGUI::Widget* _sender); void onAvatarClicked(MyGUI::Widget* _sender);
void onPinToggled(); void onPinToggled();
void onTitleDoubleClicked();
void updateEncumbranceBar(); void updateEncumbranceBar();
void notifyContentChanged(); void notifyContentChanged();

@ -177,7 +177,7 @@ namespace MWGui
End of tes3mp addition End of tes3mp addition
*/ */
Misc::StringUtils::replace(message, "%d", std::to_string(mDays).c_str(), 2); message = Misc::StringUtils::format(message, mDays);
for (const int& skill : skills) for (const int& skill : skills)
{ {
@ -197,8 +197,7 @@ namespace MWGui
*/ */
skillMsg = gmst.find("sNotifyMessage39")->mValue.getString(); skillMsg = gmst.find("sNotifyMessage39")->mValue.getString();
Misc::StringUtils::replace(skillMsg, "%s", skillName.c_str(), 2); skillMsg = Misc::StringUtils::format(skillMsg, skillName, skillValue);
Misc::StringUtils::replace(skillMsg, "%d", std::to_string(skillValue).c_str(), 2);
message += "\n" + skillMsg; message += "\n" + skillMsg;
} }

@ -254,7 +254,7 @@ namespace
} }
updateShowingPages(); updateShowingPages();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(getWidget<MyGUI::Widget>(CloseBTN)); MyGUI::InputManager::getInstance().setKeyFocusWidget(getWidget<MyGUI::Widget>(CloseBTN));
} }
void onClose() void onClose()
@ -377,9 +377,9 @@ namespace
prevPageBtn->setVisible(prevPageVisible); prevPageBtn->setVisible(prevPageVisible);
if (focus == nextPageBtn && !nextPageVisible && prevPageVisible) if (focus == nextPageBtn && !nextPageVisible && prevPageVisible)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(prevPageBtn); MyGUI::InputManager::getInstance().setKeyFocusWidget(prevPageBtn);
else if (focus == prevPageBtn && !prevPageVisible && nextPageVisible) else if (focus == prevPageBtn && !prevPageVisible && nextPageVisible)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nextPageBtn); MyGUI::InputManager::getInstance().setKeyFocusWidget(nextPageBtn);
setVisible (PageOneNum, relPages > 0); setVisible (PageOneNum, relPages > 0);
setVisible (PageTwoNum, relPages > 1); setVisible (PageTwoNum, relPages > 1);

@ -83,7 +83,7 @@ void KeyboardNavigation::restoreFocus(int mode)
{ {
MyGUI::Widget* w = found->second; MyGUI::Widget* w = found->second;
if (w && w->getVisible() && w->getEnabled()) if (w && w->getVisible() && w->getEnabled())
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(found->second); MyGUI::InputManager::getInstance().setKeyFocusWidget(found->second);
} }
} }
@ -130,7 +130,7 @@ void KeyboardNavigation::onFrame()
// workaround incorrect key focus resets (fix in MyGUI TBD) // workaround incorrect key focus resets (fix in MyGUI TBD)
if (!shouldAcceptKeyFocus(focus) && shouldAcceptKeyFocus(mCurrentFocus) && (!mModalWindow || isRootParent(mCurrentFocus, mModalWindow))) if (!shouldAcceptKeyFocus(focus) && shouldAcceptKeyFocus(mCurrentFocus) && (!mModalWindow || isRootParent(mCurrentFocus, mModalWindow)))
{ {
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCurrentFocus); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCurrentFocus);
focus = mCurrentFocus; focus = mCurrentFocus;
} }
@ -154,12 +154,12 @@ void KeyboardNavigation::setDefaultFocus(MyGUI::Widget *window, MyGUI::Widget *d
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
if (!focus || !shouldAcceptKeyFocus(focus)) if (!focus || !shouldAcceptKeyFocus(focus))
{ {
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(defaultFocus); MyGUI::InputManager::getInstance().setKeyFocusWidget(defaultFocus);
} }
else else
{ {
if (!isRootParent(focus, window)) if (!isRootParent(focus, window))
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(defaultFocus); MyGUI::InputManager::getInstance().setKeyFocusWidget(defaultFocus);
} }
} }
@ -276,7 +276,7 @@ bool KeyboardNavigation::switchFocus(int direction, bool wrap)
else if (direction == D_Up && (vertdiff >= 0 || !isVertical)) else if (direction == D_Up && (vertdiff >= 0 || !isVertical))
return false; return false;
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[index]); MyGUI::InputManager::getInstance().setKeyFocusWidget(keyFocusList[index]);
return true; return true;
} }
@ -291,7 +291,7 @@ bool KeyboardNavigation::selectFirstWidget()
if (!keyFocusList.empty()) if (!keyFocusList.empty())
{ {
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(keyFocusList[0]); MyGUI::InputManager::getInstance().setKeyFocusWidget(keyFocusList[0]);
return true; return true;
} }
return false; return false;

@ -165,11 +165,6 @@ namespace MWGui
if (mMainWidget->getVisible()) if (mMainWidget->getVisible())
return; return;
if (mViewer->getIncrementalCompileOperation())
{
mViewer->getIncrementalCompileOperation()->setMaximumNumOfObjectsToCompilePerFrame(100);
}
// Assign dummy bounding sphere callback to avoid the bounding sphere of the entire scene being recomputed after each frame of loading // Assign dummy bounding sphere callback to avoid the bounding sphere of the entire scene being recomputed after each frame of loading
// We are already using node masks to avoid the scene from being updated/rendered, but node masks don't work for computeBound() // We are already using node masks to avoid the scene from being updated/rendered, but node masks don't work for computeBound()
mViewer->getSceneData()->setComputeBoundingSphereCallback(new DontComputeBoundCallback); mViewer->getSceneData()->setComputeBoundingSphereCallback(new DontComputeBoundCallback);

@ -3,6 +3,7 @@
#include <MyGUI_TextBox.h> #include <MyGUI_TextBox.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_RenderManager.h> #include <MyGUI_RenderManager.h>
#include <MyGUI_InputManager.h>
#include <components/widgets/imagebutton.hpp> #include <components/widgets/imagebutton.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -67,12 +68,12 @@ namespace MWGui
if (isMainMenu) if (isMainMenu)
{ {
if (mButtons["loadgame"]->getVisible()) if (mButtons["loadgame"]->getVisible())
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["loadgame"]); MyGUI::InputManager::getInstance().setKeyFocusWidget(mButtons["loadgame"]);
else else
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["newgame"]); MyGUI::InputManager::getInstance().setKeyFocusWidget(mButtons["newgame"]);
} }
else else
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mButtons["return"]); MyGUI::InputManager::getInstance().setKeyFocusWidget(mButtons["return"]);
} }
Layout::setVisible (visible); Layout::setVisible (visible);

@ -268,9 +268,6 @@ namespace MWGui
{ {
for (int my=0; my<mNumCells; ++my) for (int my=0; my<mNumCells; ++my)
{ {
int x = mCurX + (mx - mCellDistance);
int y = mCurY + (-1*(my - mCellDistance));
MapEntry& entry = mMaps[my + mNumCells*mx]; MapEntry& entry = mMaps[my + mNumCells*mx];
MyGUI::ImageBox* fog = entry.mFogWidget; MyGUI::ImageBox* fog = entry.mFogWidget;
@ -280,19 +277,6 @@ namespace MWGui
entry.mFogTexture.reset(); entry.mFogTexture.reset();
continue; continue;
} }
osg::ref_ptr<osg::Texture2D> tex = mLocalMapRender->getFogOfWarTexture(x, y);
if (tex)
{
entry.mFogTexture.reset(new osgMyGUI::OSGTexture(tex));
fog->setRenderItemTexture(entry.mFogTexture.get());
fog->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
}
else
{
fog->setImageTexture("black");
entry.mFogTexture.reset();
}
} }
} }
@ -425,31 +409,18 @@ namespace MWGui
mInterior = interior; mInterior = interior;
mChanged = false; mChanged = false;
applyFogOfWar();
// Update the map textures
for (int mx=0; mx<mNumCells; ++mx) for (int mx=0; mx<mNumCells; ++mx)
{ {
for (int my=0; my<mNumCells; ++my) for (int my=0; my<mNumCells; ++my)
{ {
int mapX = x + (mx - mCellDistance);
int mapY = y + (-1*(my - mCellDistance));
MapEntry& entry = mMaps[my + mNumCells*mx]; MapEntry& entry = mMaps[my + mNumCells*mx];
MyGUI::ImageBox* box = entry.mMapWidget; entry.mMapWidget->setRenderItemTexture(nullptr);
entry.mFogWidget->setRenderItemTexture(nullptr);
entry.mMapTexture.reset();
entry.mFogTexture.reset();
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(mapX, mapY); entry.mCellX = x + (mx - mCellDistance);
if (texture) entry.mCellY = y - (my - mCellDistance);
{
entry.mMapTexture.reset(new osgMyGUI::OSGTexture(texture));
box->setRenderItemTexture(entry.mMapTexture.get());
box->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
}
else
{
box->setRenderItemTexture(nullptr);
entry.mMapTexture.reset();
}
} }
} }
@ -463,22 +434,7 @@ namespace MWGui
void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell) void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell)
{ {
std::set<const MWWorld::CellStore*> cells; mLocalMapRender->requestMap(cell);
if (!cell->isExterior())
cells.insert(cell);
else
{
for (int dX=-mCellDistance; dX<=mCellDistance; ++dX)
{
for (int dY=-mCellDistance; dY<=mCellDistance; ++dY)
{
const MWWorld::CellStore* gridCell = MWBase::Environment::get().getWorld()->getExterior (cell->getCell()->getGridX()+dX, cell->getCell()->getGridY()+dY);
cells.insert(gridCell);
}
}
}
mLocalMapRender->requestMap(cells);
} }
void LocalMapBase::redraw() void LocalMapBase::redraw()
@ -581,6 +537,68 @@ namespace MWGui
mMarkerUpdateTimer = 0; mMarkerUpdateTimer = 0;
updateMagicMarkers(); updateMagicMarkers();
} }
updateRequiredMaps();
}
bool widgetCropped(MyGUI::Widget* widget, MyGUI::Widget* cropTo)
{
MyGUI::IntRect coord = widget->getAbsoluteRect();
MyGUI::IntRect croppedCoord = cropTo->getAbsoluteRect();
if (coord.left < croppedCoord.left && coord.right < croppedCoord.left)
return true;
if (coord.left > croppedCoord.right && coord.right > croppedCoord.right)
return true;
if (coord.top < croppedCoord.top && coord.bottom < croppedCoord.top)
return true;
if (coord.top > croppedCoord.bottom && coord.bottom > croppedCoord.bottom)
return true;
return false;
}
void LocalMapBase::updateRequiredMaps()
{
bool needRedraw = false;
for (MapEntry& entry : mMaps)
{
if (widgetCropped(entry.mMapWidget, mLocalMap))
continue;
if (!entry.mMapTexture)
{
if (!mInterior)
requestMapRender(MWBase::Environment::get().getWorld()->getExterior (entry.mCellX, entry.mCellY));
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(entry.mCellX, entry.mCellY);
if (texture)
{
entry.mMapTexture.reset(new osgMyGUI::OSGTexture(texture));
entry.mMapWidget->setRenderItemTexture(entry.mMapTexture.get());
entry.mMapWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
needRedraw = true;
}
else
entry.mMapTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
}
if (!entry.mFogTexture && mFogOfWarToggled && mFogOfWarEnabled)
{
osg::ref_ptr<osg::Texture2D> tex = mLocalMapRender->getFogOfWarTexture(entry.mCellX, entry.mCellY);
if (tex)
{
entry.mFogTexture.reset(new osgMyGUI::OSGTexture(tex));
entry.mFogWidget->setRenderItemTexture(entry.mFogTexture.get());
entry.mFogWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
}
else
{
entry.mFogWidget->setImageTexture("black");
entry.mFogTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
}
needRedraw = true;
}
}
if (needRedraw)
redraw();
} }
void LocalMapBase::updateDoorMarkers() void LocalMapBase::updateDoorMarkers()
@ -1004,7 +1022,9 @@ namespace MWGui
void MapWindow::onTitleDoubleClicked() void MapWindow::onTitleDoubleClicked()
{ {
if (!mPinned) if (MyGUI::InputManager::getInstance().isShiftPressed())
MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
else if (!mPinned)
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Map);
} }
@ -1176,7 +1196,7 @@ namespace MWGui
{ {
WindowModal::onOpen(); WindowModal::onOpen();
center(); center();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
void EditNoteDialog::onCancelButtonClicked(MyGUI::Widget *sender) void EditNoteDialog::onCancelButtonClicked(MyGUI::Widget *sender)

@ -151,12 +151,14 @@ namespace MWGui
struct MapEntry struct MapEntry
{ {
MapEntry(MyGUI::ImageBox* mapWidget, MyGUI::ImageBox* fogWidget) MapEntry(MyGUI::ImageBox* mapWidget, MyGUI::ImageBox* fogWidget)
: mMapWidget(mapWidget), mFogWidget(fogWidget) {} : mMapWidget(mapWidget), mFogWidget(fogWidget), mCellX(0), mCellY(0) {}
MyGUI::ImageBox* mMapWidget; MyGUI::ImageBox* mMapWidget;
MyGUI::ImageBox* mFogWidget; MyGUI::ImageBox* mFogWidget;
std::shared_ptr<MyGUI::ITexture> mMapTexture; std::shared_ptr<MyGUI::ITexture> mMapTexture;
std::shared_ptr<MyGUI::ITexture> mFogTexture; std::shared_ptr<MyGUI::ITexture> mFogTexture;
int mCellX;
int mCellY;
}; };
std::vector<MapEntry> mMaps; std::vector<MapEntry> mMaps;
@ -197,6 +199,8 @@ namespace MWGui
virtual void customMarkerCreated(MyGUI::Widget* marker) {} virtual void customMarkerCreated(MyGUI::Widget* marker) {}
virtual void doorMarkerCreated(MyGUI::Widget* marker) {} virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
void updateRequiredMaps();
void updateMagicMarkers(); void updateMagicMarkers();
void addDetectionMarkers(int type); void addDetectionMarkers(int type);

@ -12,7 +12,6 @@ namespace MWGui
GM_Companion, GM_Companion,
GM_MainMenu, // Main menu mode GM_MainMenu, // Main menu mode
GM_Console, // Console mode
GM_Journal, // Journal mode GM_Journal, // Journal mode
GM_Scroll, // Read scroll GM_Scroll, // Read scroll

@ -3,6 +3,7 @@
#include <MyGUI_ListBox.h> #include <MyGUI_ListBox.h>
#include <MyGUI_ImageBox.h> #include <MyGUI_ImageBox.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_InputManager.h>
#include <osg/Texture2D> #include <osg/Texture2D>
@ -176,7 +177,7 @@ namespace MWGui
mHeadRotate->setScrollPosition(initialPos); mHeadRotate->setScrollPosition(initialPos);
onHeadRotate(mHeadRotate, initialPos); onHeadRotate(mHeadRotate, initialPos);
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mRaceList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mRaceList);
} }
void RaceDialog::setRaceId(const std::string &raceId) void RaceDialog::setRaceId(const std::string &raceId)

@ -207,7 +207,7 @@ void Recharge::onItemClicked(MyGUI::Widget *sender, const MWWorld::Ptr& item)
if (gem.getRefData().getCount() == 0) if (gem.getRefData().getCount() == 0)
{ {
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage51")->mValue.getString(); std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage51")->mValue.getString();
Misc::StringUtils::replace(message, "%s", gem.getClass().getName(gem).c_str(), 2); message = Misc::StringUtils::format(message, gem.getClass().getName(gem));
MWBase::Environment::get().getWindowManager()->messageBox(message); MWBase::Environment::get().getWindowManager()->messageBox(message);

@ -94,7 +94,7 @@ namespace MWGui
MWBase::Environment::get().getStateManager()->deleteGame (mCurrentCharacter, mCurrentSlot); MWBase::Environment::get().getStateManager()->deleteGame (mCurrentCharacter, mCurrentSlot);
mSaveList->removeItemAt(mSaveList->getIndexSelected()); mSaveList->removeItemAt(mSaveList->getIndexSelected());
onSlotSelected(mSaveList, mSaveList->getIndexSelected()); onSlotSelected(mSaveList, mSaveList->getIndexSelected());
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList);
if (mSaveList->getItemCount() == 0) if (mSaveList->getItemCount() == 0)
{ {
@ -114,7 +114,7 @@ namespace MWGui
void SaveGameDialog::onDeleteSlotCancel() void SaveGameDialog::onDeleteSlotCancel()
{ {
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList);
} }
void SaveGameDialog::onSaveNameChanged(MyGUI::EditBox *sender) void SaveGameDialog::onSaveNameChanged(MyGUI::EditBox *sender)
@ -138,9 +138,9 @@ namespace MWGui
mSaveNameEdit->setCaption (""); mSaveNameEdit->setCaption ("");
if (mSaving) if (mSaving)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveNameEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveNameEdit);
else else
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList);
center(); center();
@ -244,14 +244,11 @@ namespace MWGui
void SaveGameDialog::onConfirmationCancel() void SaveGameDialog::onConfirmationCancel()
{ {
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList);
} }
void SaveGameDialog::accept(bool reallySure) void SaveGameDialog::accept(bool reallySure)
{ {
// Remove for MyGUI 3.2.2
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nullptr);
if (mSaving) if (mSaving)
{ {
// If overwriting an existing slot, ask for confirmation first // If overwriting an existing slot, ask for confirmation first
@ -334,7 +331,7 @@ namespace MWGui
void SaveGameDialog::onCharacterAccept(MyGUI::ComboBox* sender, size_t pos) void SaveGameDialog::onCharacterAccept(MyGUI::ComboBox* sender, size_t pos)
{ {
// Give key focus to save list so we can confirm the selection with Enter // Give key focus to save list so we can confirm the selection with Enter
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mSaveList); MyGUI::InputManager::getInstance().setKeyFocusWidget(mSaveList);
} }
void SaveGameDialog::fillSaveList() void SaveGameDialog::fillSaveList()

@ -1,6 +1,7 @@
#include "scrollwindow.hpp" #include "scrollwindow.hpp"
#include <MyGUI_ScrollView.h> #include <MyGUI_ScrollView.h>
#include <MyGUI_InputManager.h>
#include <components/esm/loadbook.hpp> #include <components/esm/loadbook.hpp>
#include <components/widgets/imagebutton.hpp> #include <components/widgets/imagebutton.hpp>
@ -66,7 +67,7 @@ namespace MWGui
setTakeButtonShow(showTakeButton); setTakeButtonShow(showTakeButton);
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mCloseButton);
} }
void ScrollWindow::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character) void ScrollWindow::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character)

@ -6,14 +6,18 @@
#include <MyGUI_ScrollView.h> #include <MyGUI_ScrollView.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_TabControl.h> #include <MyGUI_TabControl.h>
#include <MyGUI_InputManager.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <SDL_video.h> #include <SDL_video.h>
#include <iomanip>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/misc/gcd.hpp> #include <components/misc/gcd.hpp>
#include <components/misc/constants.hpp>
#include <components/widgets/sharedstatebutton.hpp> #include <components/widgets/sharedstatebutton.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -142,13 +146,22 @@ namespace MWGui
MyGUI::ScrollBar* scroll = current->castType<MyGUI::ScrollBar>(); MyGUI::ScrollBar* scroll = current->castType<MyGUI::ScrollBar>();
std::string valueStr; std::string valueStr;
std::string valueType = getSettingValueType(current); std::string valueType = getSettingValueType(current);
if (valueType == "Float" || valueType == "Integer") if (valueType == "Float" || valueType == "Integer" || valueType == "Cell")
{ {
// TODO: ScrollBar isn't meant for this. should probably use a dedicated FloatSlider widget // TODO: ScrollBar isn't meant for this. should probably use a dedicated FloatSlider widget
float min,max; float min,max;
getSettingMinMax(scroll, min, max); getSettingMinMax(scroll, min, max);
float value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current)); float value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current));
valueStr = MyGUI::utility::toString((int)value);
if (valueType == "Cell")
{
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << value/Constants::CellSizeInUnits;
valueStr = ss.str();
}
else
valueStr = MyGUI::utility::toString(int(value));
value = std::max(min, std::min(value, max)); value = std::max(min, std::min(value, max));
value = (value-min)/(max-min); value = (value-min)/(max-min);
@ -161,7 +174,8 @@ namespace MWGui
scroll->setScrollPosition(value); scroll->setScrollPosition(value);
} }
scroll->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); scroll->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition);
updateSliderLabel(scroll, valueStr); if (scroll->getVisible())
updateSliderLabel(scroll, valueStr);
} }
configureWidgets(current); configureWidgets(current);
@ -176,7 +190,7 @@ namespace MWGui
MyGUI::TextBox* textBox; MyGUI::TextBox* textBox;
getWidget(textBox, labelWidgetName); getWidget(textBox, labelWidgetName);
std::string labelCaption = scroller->getUserString("SettingLabelCaption"); std::string labelCaption = scroller->getUserString("SettingLabelCaption");
Misc::StringUtils::replaceAll(labelCaption, "%s", value.c_str(), 2); labelCaption = Misc::StringUtils::format(labelCaption, value);
textBox->setCaptionWithReplacing(labelCaption); textBox->setCaptionWithReplacing(labelCaption);
} }
} }
@ -185,6 +199,12 @@ namespace MWGui
WindowBase("openmw_settings_window.layout"), WindowBase("openmw_settings_window.layout"),
mKeyboardMode(true) mKeyboardMode(true)
{ {
bool terrain = Settings::Manager::getBool("distant terrain", "Terrain");
const std::string widgetName = terrain ? "RenderingDistanceSlider" : "LargeRenderingDistanceSlider";
MyGUI::Widget* unusedSlider;
getWidget(unusedSlider, widgetName);
unusedSlider->setVisible(false);
configureWidgets(mMainWidget); configureWidgets(mMainWidget);
setTitle("#{sOptions}"); setTitle("#{sOptions}");
@ -440,7 +460,7 @@ namespace MWGui
{ {
std::string valueStr; std::string valueStr;
std::string valueType = getSettingValueType(scroller); std::string valueType = getSettingValueType(scroller);
if (valueType == "Float" || valueType == "Integer") if (valueType == "Float" || valueType == "Integer" || valueType == "Cell")
{ {
float value = pos / float(scroller->getScrollRange()-1); float value = pos / float(scroller->getScrollRange()-1);
@ -451,7 +471,15 @@ namespace MWGui
Settings::Manager::setFloat(getSettingName(scroller), getSettingCategory(scroller), value); Settings::Manager::setFloat(getSettingName(scroller), getSettingCategory(scroller), value);
else else
Settings::Manager::setInt(getSettingName(scroller), getSettingCategory(scroller), (int)value); Settings::Manager::setInt(getSettingName(scroller), getSettingCategory(scroller), (int)value);
valueStr = MyGUI::utility::toString(int(value));
if (valueType == "Cell")
{
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << value/Constants::CellSizeInUnits;
valueStr = ss.str();
}
else
valueStr = MyGUI::utility::toString(int(value));
} }
else else
{ {
@ -466,12 +494,13 @@ namespace MWGui
void SettingsWindow::apply() void SettingsWindow::apply()
{ {
const Settings::CategorySettingVector changed = Settings::Manager::apply(); const Settings::CategorySettingVector changed = Settings::Manager::getPendingChanges();
MWBase::Environment::get().getWorld()->processChangedSettings(changed); MWBase::Environment::get().getWorld()->processChangedSettings(changed);
MWBase::Environment::get().getSoundManager()->processChangedSettings(changed); MWBase::Environment::get().getSoundManager()->processChangedSettings(changed);
MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); MWBase::Environment::get().getWindowManager()->processChangedSettings(changed);
MWBase::Environment::get().getInputManager()->processChangedSettings(changed); MWBase::Environment::get().getInputManager()->processChangedSettings(changed);
MWBase::Environment::get().getMechanicsManager()->processChangedSettings(changed); MWBase::Environment::get().getMechanicsManager()->processChangedSettings(changed);
Settings::Manager::resetPendingChanges();
} }
void SettingsWindow::onKeyboardSwitchClicked(MyGUI::Widget* _sender) void SettingsWindow::onKeyboardSwitchClicked(MyGUI::Widget* _sender)
@ -599,9 +628,10 @@ namespace MWGui
void SettingsWindow::onOpen() void SettingsWindow::onOpen()
{ {
highlightCurrentResolution();
updateControlsBox(); updateControlsBox();
resetScrollbars(); resetScrollbars();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mOkButton);
} }
void SettingsWindow::onWindowResize(MyGUI::Window *_sender) void SettingsWindow::onWindowResize(MyGUI::Window *_sender)

@ -2,6 +2,7 @@
#include <MyGUI_ImageBox.h> #include <MyGUI_ImageBox.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_InputManager.h>
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
#include <components/widgets/list.hpp> #include <components/widgets/list.hpp>
@ -457,7 +458,7 @@ namespace MWGui
void SpellCreationDialog::onOpen() void SpellCreationDialog::onOpen()
{ {
center(); center();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mNameEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mNameEdit);
} }
void SpellCreationDialog::onReferenceUnavailable () void SpellCreationDialog::onReferenceUnavailable ()

@ -148,6 +148,19 @@ namespace MWGui
return mSpells.size(); return mSpells.size();
} }
SpellModel::ModelIndex SpellModel::getSelectedIndex() const
{
ModelIndex selected = -1;
for (SpellModel::ModelIndex i = 0; i<int(getItemCount()); ++i)
{
if (getItem(i).mSelected) {
selected = i;
break;
}
}
return selected;
}
Spell SpellModel::getItem(ModelIndex index) const Spell SpellModel::getItem(ModelIndex index) const
{ {
if (index < 0 || index >= int(mSpells.size())) if (index < 0 || index >= int(mSpells.size()))

@ -48,6 +48,8 @@ namespace MWGui
///< throws for invalid index ///< throws for invalid index
size_t getItemCount() const; size_t getItemCount() const;
ModelIndex getSelectedIndex() const;
///< returns -1 if nothing is selected
private: private:
MWWorld::Ptr mActor; MWWorld::Ptr mActor;

@ -1,7 +1,9 @@
#include "spellwindow.hpp" #include "spellwindow.hpp"
#include <MyGUI_Button.h>
#include <MyGUI_EditBox.h> #include <MyGUI_EditBox.h>
#include <MyGUI_InputManager.h> #include <MyGUI_InputManager.h>
#include <MyGUI_Window.h>
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -47,6 +49,9 @@ namespace MWGui
{ {
mSpellIcons = new SpellIcons(); mSpellIcons = new SpellIcons();
MyGUI::Widget* deleteButton;
getWidget(deleteButton, "DeleteSpellButton");
getWidget(mSpellView, "SpellView"); getWidget(mSpellView, "SpellView");
getWidget(mEffectBox, "EffectsBox"); getWidget(mEffectBox, "EffectsBox");
getWidget(mFilterEdit, "FilterEdit"); getWidget(mFilterEdit, "FilterEdit");
@ -55,8 +60,13 @@ namespace MWGui
mSpellView->eventSpellClicked += MyGUI::newDelegate(this, &SpellWindow::onModelIndexSelected); mSpellView->eventSpellClicked += MyGUI::newDelegate(this, &SpellWindow::onModelIndexSelected);
mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &SpellWindow::onFilterChanged); mFilterEdit->eventEditTextChange += MyGUI::newDelegate(this, &SpellWindow::onFilterChanged);
deleteButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SpellWindow::onDeleteClicked);
setCoord(498, 300, 302, 300); setCoord(498, 300, 302, 300);
// Adjust the spell filtering widget size because of MyGUI limitations.
int filterWidth = mSpellView->getSize().width - deleteButton->getSize().width - 3;
mFilterEdit->setSize(filterWidth, mFilterEdit->getSize().height);
} }
SpellWindow::~SpellWindow() SpellWindow::~SpellWindow()
@ -73,7 +83,9 @@ namespace MWGui
void SpellWindow::onTitleDoubleClicked() void SpellWindow::onTitleDoubleClicked()
{ {
if (!mPinned) if (MyGUI::InputManager::getInstance().isShiftPressed())
MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
else if (!mPinned)
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Magic);
} }
@ -82,7 +94,7 @@ namespace MWGui
// Reset the filter focus when opening the window // Reset the filter focus when opening the window
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
if (focus == mFilterEdit) if (focus == mFilterEdit)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nullptr); MyGUI::InputManager::getInstance().resetKeyFocusWidget();
updateSpells(); updateSpells();
} }
@ -151,13 +163,17 @@ namespace MWGui
MWWorld::Ptr player = MWMechanics::getPlayer(); MWWorld::Ptr player = MWMechanics::getPlayer();
std::string raceId = player.get<ESM::NPC>()->mBase->mRace; std::string raceId = player.get<ESM::NPC>()->mBase->mRace;
const std::string& signId =
MWBase::Environment::get().getWorld()->getPlayer().getBirthSign();
const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(raceId); const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get<ESM::Race>().find(raceId);
const ESM::BirthSign* birthsign = MWBase::Environment::get().getWorld()->getStore().get<ESM::BirthSign>().find(signId); // can't delete racial spells, birthsign spells or powers
bool isInherent = race->mPowers.exists(spell->mId) || spell->mData.mType == ESM::Spell::ST_Power;
const std::string& signId = MWBase::Environment::get().getWorld()->getPlayer().getBirthSign();
if (!isInherent && !signId.empty())
{
const ESM::BirthSign* sign = MWBase::Environment::get().getWorld()->getStore().get<ESM::BirthSign>().find(signId);
isInherent = sign->mPowers.exists(spell->mId);
}
// can't delete racial spells, birthsign spells or powers if (isInherent)
if (race->mPowers.exists(spell->mId) || birthsign->mPowers.exists(spell->mId) || spell->mData.mType == ESM::Spell::ST_Power)
{ {
MWBase::Environment::get().getWindowManager()->messageBox("#{sDeleteSpellError}"); MWBase::Environment::get().getWindowManager()->messageBox("#{sDeleteSpellError}");
} }
@ -167,7 +183,7 @@ namespace MWGui
mSpellToDelete = spellId; mSpellToDelete = spellId;
ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog();
std::string question = MWBase::Environment::get().getWindowManager()->getGameSettingString("sQuestionDeleteSpell", "Delete %s?"); std::string question = MWBase::Environment::get().getWindowManager()->getGameSettingString("sQuestionDeleteSpell", "Delete %s?");
Misc::StringUtils::replace(question, "%s", spell->mName.c_str(), 2); question = Misc::StringUtils::format(question, spell->mName);
dialog->askForConfirmation(question); dialog->askForConfirmation(question);
dialog->eventOkClicked.clear(); dialog->eventOkClicked.clear();
dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept); dialog->eventOkClicked += MyGUI::newDelegate(this, &SpellWindow::onDeleteSpellAccept);
@ -196,6 +212,17 @@ namespace MWGui
mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), sender->getCaption())); mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), sender->getCaption()));
} }
void SpellWindow::onDeleteClicked(MyGUI::Widget *widget)
{
SpellModel::ModelIndex selected = mSpellView->getModel()->getSelectedIndex();
if (selected < 0)
return;
const Spell& spell = mSpellView->getModel()->getItem(selected);
if (spell.mType != Spell::Type_EnchantedItem)
askDeleteSpell(spell.mId);
}
void SpellWindow::onSpellSelected(const std::string& spellId) void SpellWindow::onSpellSelected(const std::string& spellId)
{ {
MWWorld::Ptr player = MWMechanics::getPlayer(); MWWorld::Ptr player = MWMechanics::getPlayer();
@ -253,12 +280,9 @@ namespace MWGui
mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), "")); mSpellView->setModel(new SpellModel(MWMechanics::getPlayer(), ""));
SpellModel::ModelIndex selected = 0; SpellModel::ModelIndex selected = mSpellView->getModel()->getSelectedIndex();
for (SpellModel::ModelIndex i = 0; i<int(mSpellView->getModel()->getItemCount()); ++i) if (selected < 0)
{ selected = 0;
if (mSpellView->getModel()->getItem(i).mSelected)
selected = i;
}
selected += next ? 1 : -1; selected += next ? 1 : -1;
int itemcount = mSpellView->getModel()->getItemCount(); int itemcount = mSpellView->getModel()->getItemCount();

@ -33,6 +33,7 @@ namespace MWGui
void onSpellSelected(const std::string& spellId); void onSpellSelected(const std::string& spellId);
void onModelIndexSelected(SpellModel::ModelIndex index); void onModelIndexSelected(SpellModel::ModelIndex index);
void onFilterChanged(MyGUI::EditBox *sender); void onFilterChanged(MyGUI::EditBox *sender);
void onDeleteClicked(MyGUI::Widget *widget);
void onDeleteSpellAccept(); void onDeleteSpellAccept();
void askDeleteSpell(const std::string& spellId); void askDeleteSpell(const std::string& spellId);

@ -4,6 +4,7 @@
#include <MyGUI_ScrollView.h> #include <MyGUI_ScrollView.h>
#include <MyGUI_ProgressBar.h> #include <MyGUI_ProgressBar.h>
#include <MyGUI_ImageBox.h> #include <MyGUI_ImageBox.h>
#include <MyGUI_InputManager.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
@ -652,7 +653,13 @@ namespace MWGui
void StatsWindow::onTitleDoubleClicked() void StatsWindow::onTitleDoubleClicked()
{ {
if (!mPinned) if (MyGUI::InputManager::getInstance().isShiftPressed())
{
MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
MyGUI::Window* t = mMainWidget->castType<MyGUI::Window>();
onWindowResize(t);
}
else if (!mPinned)
MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats); MWBase::Environment::get().getWindowManager()->toggleVisible(GW_Stats);
} }
} }

@ -5,6 +5,7 @@
#include <MyGUI_EditBox.h> #include <MyGUI_EditBox.h>
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_InputManager.h>
namespace MWGui namespace MWGui
{ {
@ -23,7 +24,7 @@ namespace MWGui
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked);
// Make sure the edit box has focus // Make sure the edit box has focus
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
void TextInputDialog::setNextButtonShow(bool shown) void TextInputDialog::setNextButtonShow(bool shown)
@ -46,7 +47,7 @@ namespace MWGui
{ {
WindowModal::onOpen(); WindowModal::onOpen();
// Make sure the edit box has focus // Make sure the edit box has focus
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
// widget controls // widget controls
@ -56,7 +57,7 @@ namespace MWGui
if (mTextEdit->getCaption() == "") if (mTextEdit->getCaption() == "")
{ {
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}");
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget (mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
else else
eventDone(this); eventDone(this);

@ -94,17 +94,19 @@ namespace MWGui
return; return;
} }
bool guiMode = MWBase::Environment::get().getWindowManager()->isGuiMode(); MWBase::WindowManager *winMgr = MWBase::Environment::get().getWindowManager();
bool guiMode = winMgr->isGuiMode();
if (guiMode) if (guiMode)
{ {
if (!MWBase::Environment::get().getWindowManager()->getCursorVisible()) if (!winMgr->getCursorVisible())
return; return;
const MyGUI::IntPoint& mousePos = MyGUI::InputManager::getInstance().getMousePosition(); const MyGUI::IntPoint& mousePos = MyGUI::InputManager::getInstance().getMousePosition();
if (MWBase::Environment::get().getWindowManager()->getWorldMouseOver() && ((MWBase::Environment::get().getWindowManager()->getMode() == GM_Console) if (winMgr->getWorldMouseOver() &&
|| (MWBase::Environment::get().getWindowManager()->getMode() == GM_Container) (winMgr->isConsoleMode() ||
|| (MWBase::Environment::get().getWindowManager()->getMode() == GM_Inventory))) (winMgr->getMode() == GM_Container) ||
(winMgr->getMode() == GM_Inventory)))
{ {
if (mFocusObject.isEmpty ()) if (mFocusObject.isEmpty ())
return; return;
@ -112,7 +114,7 @@ namespace MWGui
const MWWorld::Class& objectclass = mFocusObject.getClass(); const MWWorld::Class& objectclass = mFocusObject.getClass();
MyGUI::IntSize tooltipSize; MyGUI::IntSize tooltipSize;
if ((!objectclass.hasToolTip(mFocusObject))&&(MWBase::Environment::get().getWindowManager()->getMode() == GM_Console)) if (!objectclass.hasToolTip(mFocusObject) && winMgr->isConsoleMode())
{ {
setCoord(0, 0, 300, 300); setCoord(0, 0, 300, 300);
mDynamicToolTipBox->setVisible(true); mDynamicToolTipBox->setVisible(true);
@ -212,7 +214,7 @@ namespace MWGui
{ {
MyGUI::IntCoord avatarPos = focus->getAbsoluteCoord(); MyGUI::IntCoord avatarPos = focus->getAbsoluteCoord();
MyGUI::IntPoint relMousePos = MyGUI::InputManager::getInstance ().getMousePosition () - MyGUI::IntPoint(avatarPos.left, avatarPos.top); MyGUI::IntPoint relMousePos = MyGUI::InputManager::getInstance ().getMousePosition () - MyGUI::IntPoint(avatarPos.left, avatarPos.top);
MWWorld::Ptr item = MWBase::Environment::get().getWindowManager()->getInventoryWindow ()->getAvatarSelectedItem (relMousePos.left, relMousePos.top); MWWorld::Ptr item = winMgr->getInventoryWindow ()->getAvatarSelectedItem (relMousePos.left, relMousePos.top);
mFocusObject = item; mFocusObject = item;
if (!mFocusObject.isEmpty ()) if (!mFocusObject.isEmpty ())
@ -486,7 +488,9 @@ namespace MWGui
effectsWidget->setEffectList(info.effects); effectsWidget->setEffectList(info.effects);
std::vector<MyGUI::Widget*> effectItems; std::vector<MyGUI::Widget*> effectItems;
effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, info.isPotion ? Widgets::MWEffectList::EF_NoTarget : 0); int flag = info.isPotion ? Widgets::MWEffectList::EF_NoTarget : 0;
flag |= info.isIngredient ? Widgets::MWEffectList::EF_NoMagnitude : 0;
effectsWidget->createEffectWidgets(effectItems, effectArea, coord, true, flag);
totalSize.height += coord.top-6; totalSize.height += coord.top-6;
totalSize.width = std::max(totalSize.width, coord.width); totalSize.width = std::max(totalSize.width, coord.width);
} }

@ -22,6 +22,7 @@ namespace MWGui
: imageSize(32) : imageSize(32)
, remainingEnchantCharge(-1) , remainingEnchantCharge(-1)
, isPotion(false) , isPotion(false)
, isIngredient(false)
, wordWrap(true) , wordWrap(true)
{} {}
@ -41,6 +42,7 @@ namespace MWGui
std::vector<std::string> notes; std::vector<std::string> notes;
bool isPotion; // potions do not show target in the tooltip bool isPotion; // potions do not show target in the tooltip
bool isIngredient; // ingredients have no effect magnitude
bool wordWrap; bool wordWrap;
}; };

@ -3,6 +3,7 @@
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_InputManager.h> #include <MyGUI_InputManager.h>
#include <MyGUI_ControllerManager.h> #include <MyGUI_ControllerManager.h>
#include <MyGUI_ControllerRepeatClick.h>
#include <components/widgets/numericeditbox.hpp> #include <components/widgets/numericeditbox.hpp>
@ -44,9 +45,6 @@ namespace
namespace MWGui namespace MWGui
{ {
const float TradeWindow::sBalanceChangeInitialPause = 0.5f;
const float TradeWindow::sBalanceChangeInterval = 0.1f;
TradeWindow::TradeWindow() TradeWindow::TradeWindow()
: WindowBase("openmw_trade_window.layout") : WindowBase("openmw_trade_window.layout")
, mSortModel(nullptr) , mSortModel(nullptr)
@ -138,7 +136,7 @@ namespace MWGui
onFilterChanged(mFilterAll); onFilterChanged(mFilterAll);
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTotalBalance); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTotalBalance);
} }
void TradeWindow::onFrame(float dt) void TradeWindow::onFrame(float dt)
@ -311,7 +309,7 @@ namespace MWGui
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(itemStack.mBase.getCellRef().getRefId(), mPtr)) if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(itemStack.mBase.getCellRef().getRefId(), mPtr))
{ {
std::string msg = gmst.find("sNotifyMessage49")->mValue.getString(); std::string msg = gmst.find("sNotifyMessage49")->mValue.getString();
Misc::StringUtils::replace(msg, "%s", itemStack.mBase.getClass().getName(itemStack.mBase).c_str(), 2); msg = Misc::StringUtils::format(msg, itemStack.mBase.getClass().getName(itemStack.mBase));
MWBase::Environment::get().getWindowManager()->messageBox(msg); MWBase::Environment::get().getWindowManager()->messageBox(msg);
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, itemStack.mBase, mPtr, itemStack.mCount); MWBase::Environment::get().getMechanicsManager()->confiscateStolenItemToOwner(player, itemStack.mBase, mPtr, itemStack.mCount);
@ -382,10 +380,9 @@ namespace MWGui
void TradeWindow::addRepeatController(MyGUI::Widget *widget) void TradeWindow::addRepeatController(MyGUI::Widget *widget)
{ {
MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(Controllers::ControllerRepeatEvent::getClassTypeName()); MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(MyGUI::ControllerRepeatClick::getClassTypeName());
Controllers::ControllerRepeatEvent* controller = item->castType<Controllers::ControllerRepeatEvent>(); MyGUI::ControllerRepeatClick* controller = static_cast<MyGUI::ControllerRepeatClick*>(item);
controller->eventRepeatClick += MyGUI::newDelegate(this, &TradeWindow::onRepeatClick); controller->eventRepeatClick += newDelegate(this, &TradeWindow::onRepeatClick);
controller->setRepeat(sBalanceChangeInitialPause, sBalanceChangeInterval);
MyGUI::ControllerManager::getInstance().addItem(widget, controller); MyGUI::ControllerManager::getInstance().addItem(widget, controller);
} }
@ -468,16 +465,26 @@ namespace MWGui
int merchantOffer = 0; int merchantOffer = 0;
// The offered price must be capped at 75% of the base price to avoid exploits
// connected to buying and selling the same item.
// This value has been determined by researching the limitations of the vanilla formula
// and may not be sufficient if getBarterOffer behavior has been changed.
std::vector<ItemStack> playerBorrowed = playerTradeModel->getItemsBorrowedToUs(); std::vector<ItemStack> playerBorrowed = playerTradeModel->getItemsBorrowedToUs();
for (const ItemStack& itemStack : playerBorrowed) for (const ItemStack& itemStack : playerBorrowed)
{ {
merchantOffer -= MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(itemStack.mBase, itemStack.mCount), true); const int basePrice = getEffectiveValue(itemStack.mBase, itemStack.mCount);
const int cap = static_cast<int>(std::max(1.f, 0.75f * basePrice)); // Minimum buying price -- 75% of the base
const int buyingPrice = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, basePrice, true);
merchantOffer -= std::max(cap, buyingPrice);
} }
std::vector<ItemStack> merchantBorrowed = mTradeModel->getItemsBorrowedToUs(); std::vector<ItemStack> merchantBorrowed = mTradeModel->getItemsBorrowedToUs();
for (const ItemStack& itemStack : merchantBorrowed) for (const ItemStack& itemStack : merchantBorrowed)
{ {
merchantOffer += MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, getEffectiveValue(itemStack.mBase, itemStack.mCount), false); const int basePrice = getEffectiveValue(itemStack.mBase, itemStack.mCount);
const int cap = static_cast<int>(std::max(1.f, 0.75f * basePrice)); // Maximum selling price -- 75% of the base
const int sellingPrice = MWBase::Environment::get().getMechanicsManager()->getBarterOffer(mPtr, basePrice, false);
merchantOffer += mPtr.getClass().isNpc() ? std::min(cap, sellingPrice) : sellingPrice;
} }
int diff = merchantOffer - mCurrentMerchantOffer; int diff = merchantOffer - mCurrentMerchantOffer;

@ -91,22 +91,22 @@ namespace MWGui
mTimeAdvancer.eventInterrupted += MyGUI::newDelegate(this, &WaitDialog::onWaitingInterrupted); mTimeAdvancer.eventInterrupted += MyGUI::newDelegate(this, &WaitDialog::onWaitingInterrupted);
mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &WaitDialog::onWaitingFinished); mTimeAdvancer.eventFinished += MyGUI::newDelegate(this, &WaitDialog::onWaitingFinished);
} }
void WaitDialog::onReferenceUnavailable ()
{
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Rest);
resetReference();
}
void WaitDialog::setPtr(const MWWorld::Ptr &ptr) void WaitDialog::setPtr(const MWWorld::Ptr &ptr)
{ {
mPtr = ptr; setCanRest(!ptr.isEmpty() || MWBase::Environment::get().getWorld ()->canRest () == MWBase::World::Rest_Allowed);
setCanRest(!mPtr.isEmpty() || MWBase::Environment::get().getWorld ()->canRest () == MWBase::World::Rest_Allowed);
if (ptr.isEmpty() && MWBase::Environment::get().getWorld ()->canRest() == MWBase::World::Rest_PlayerIsInAir)
{
// Resting in air is not allowed unless you're using a bed
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage1}");
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Rest);
}
if (mUntilHealedButton->getVisible()) if (mUntilHealedButton->getVisible())
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mUntilHealedButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mUntilHealedButton);
else else
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mWaitButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mWaitButton);
} }
bool WaitDialog::exit() bool WaitDialog::exit()
@ -118,7 +118,6 @@ namespace MWGui
{ {
mSleeping = false; mSleeping = false;
mTimeAdvancer.stop(); mTimeAdvancer.stop();
resetReference();
} }
void WaitDialog::onOpen() void WaitDialog::onOpen()
@ -152,12 +151,6 @@ namespace MWGui
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage1}"); MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage1}");
MWBase::Environment::get().getWindowManager()->popGuiMode (); MWBase::Environment::get().getWindowManager()->popGuiMode ();
} }
else if (mPtr.isEmpty() && canRest == MWBase::World::Rest_PlayerIsInAir)
{
// Resting in air is not allowed either, unless you're using a bed
MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage1}");
MWBase::Environment::get().getWindowManager()->popGuiMode ();
}
/* /*
Start of tes3mp addition Start of tes3mp addition
@ -268,7 +261,7 @@ namespace MWGui
{ {
mHourText->setCaptionWithReplacing (MyGUI::utility::toString(position+1) + " #{sRestMenu2}"); mHourText->setCaptionWithReplacing (MyGUI::utility::toString(position+1) + " #{sRestMenu2}");
mManualHours = position+1; mManualHours = position+1;
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mWaitButton); MyGUI::InputManager::getInstance().setKeyFocusWidget(mWaitButton);
} }
void WaitDialog::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character) void WaitDialog::onKeyButtonPressed(MyGUI::Widget *sender, MyGUI::KeyCode key, MyGUI::Char character)
@ -351,8 +344,6 @@ namespace MWGui
void WaitDialog::onFrame(float dt) void WaitDialog::onFrame(float dt)
{ {
checkReferenceAvailable();
mTimeAdvancer.onFrame(dt); mTimeAdvancer.onFrame(dt);
if (mFadeTimeRemaining <= 0) if (mFadeTimeRemaining <= 0)

@ -4,7 +4,6 @@
#include "timeadvancer.hpp" #include "timeadvancer.hpp"
#include "windowbase.hpp" #include "windowbase.hpp"
#include "referenceinterface.hpp"
namespace MWGui namespace MWGui
{ {
@ -23,7 +22,7 @@ namespace MWGui
MyGUI::TextBox* mProgressText; MyGUI::TextBox* mProgressText;
}; };
class WaitDialog : public WindowBase, public ReferenceInterface class WaitDialog : public WindowBase
{ {
public: public:
WaitDialog(); WaitDialog();
@ -64,8 +63,6 @@ namespace MWGui
WaitDialogProgressBar mProgressBar; WaitDialogProgressBar mProgressBar;
virtual void onReferenceUnavailable();
void onUntilHealedButtonClicked(MyGUI::Widget* sender); void onUntilHealedButtonClicked(MyGUI::Widget* sender);
void onWaitButtonClicked(MyGUI::Widget* sender); void onWaitButtonClicked(MyGUI::Widget* sender);
void onCancelButtonClicked(MyGUI::Widget* sender); void onCancelButtonClicked(MyGUI::Widget* sender);

@ -235,6 +235,7 @@ namespace MWGui
params.mRange = effectInfo.mRange; params.mRange = effectInfo.mRange;
params.mIsConstant = (flags & MWEffectList::EF_Constant) != 0; params.mIsConstant = (flags & MWEffectList::EF_Constant) != 0;
params.mNoTarget = (flags & MWEffectList::EF_NoTarget); params.mNoTarget = (flags & MWEffectList::EF_NoTarget);
params.mNoMagnitude = (flags & MWEffectList::EF_NoMagnitude);
effect->setSpellEffect(params); effect->setSpellEffect(params);
effects.push_back(effect); effects.push_back(effect);
coord.top += effect->getHeight(); coord.top += effect->getHeight();
@ -293,6 +294,7 @@ namespace MWGui
effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default); effect = creator->createWidget<MWSpellEffect>("MW_EffectImage", coord, MyGUI::Align::Default);
effectInfo.mIsConstant = (flags & EF_Constant) || effectInfo.mIsConstant; effectInfo.mIsConstant = (flags & EF_Constant) || effectInfo.mIsConstant;
effectInfo.mNoTarget = (flags & EF_NoTarget) || effectInfo.mNoTarget; effectInfo.mNoTarget = (flags & EF_NoTarget) || effectInfo.mNoTarget;
effectInfo.mNoMagnitude = (flags & EF_NoMagnitude) || effectInfo.mNoMagnitude;
effect->setSpellEffect(effectInfo); effect->setSpellEffect(effectInfo);
effects.push_back(effect); effects.push_back(effect);
if (effect->getRequestedWidth() > maxwidth) if (effect->getRequestedWidth() > maxwidth)
@ -408,7 +410,7 @@ namespace MWGui
spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], ""); spellLine += " " + MWBase::Environment::get().getWindowManager()->getGameSettingString(ESM::Attribute::sGmstAttributeIds[mEffectParams.mAttribute], "");
} }
if (mEffectParams.mMagnMin >= 0 || mEffectParams.mMagnMax >= 0) { if (mEffectParams.mMagnMin || mEffectParams.mMagnMax) {
ESM::MagicEffect::MagnitudeDisplayType displayType = magicEffect->getMagnitudeDisplayType(); ESM::MagicEffect::MagnitudeDisplayType displayType = magicEffect->getMagnitudeDisplayType();
if ( displayType == ESM::MagicEffect::MDT_TimesInt ) { if ( displayType == ESM::MagicEffect::MDT_TimesInt ) {
std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", ""); std::string timesInt = MWBase::Environment::get().getWindowManager()->getGameSettingString("sXTimesINT", "");
@ -421,7 +423,7 @@ namespace MWGui
spellLine += formatter.str(); spellLine += formatter.str();
} }
else if ( displayType != ESM::MagicEffect::MDT_None ) { else if ( displayType != ESM::MagicEffect::MDT_None && !mEffectParams.mNoMagnitude) {
spellLine += " " + MyGUI::utility::toString(mEffectParams.mMagnMin); spellLine += " " + MyGUI::utility::toString(mEffectParams.mMagnMin);
if (mEffectParams.mMagnMin != mEffectParams.mMagnMax) if (mEffectParams.mMagnMin != mEffectParams.mMagnMax)
spellLine += to + MyGUI::utility::toString(mEffectParams.mMagnMax); spellLine += to + MyGUI::utility::toString(mEffectParams.mMagnMax);
@ -431,9 +433,9 @@ namespace MWGui
else if ( displayType == ESM::MagicEffect::MDT_Feet ) else if ( displayType == ESM::MagicEffect::MDT_Feet )
spellLine += " " + ft; spellLine += " " + ft;
else if ( displayType == ESM::MagicEffect::MDT_Level ) else if ( displayType == ESM::MagicEffect::MDT_Level )
spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? lvl : lvls ); spellLine += " " + ((mEffectParams.mMagnMin == mEffectParams.mMagnMax && std::abs(mEffectParams.mMagnMin) == 1) ? lvl : lvls );
else // ESM::MagicEffect::MDT_Points else // ESM::MagicEffect::MDT_Points
spellLine += " " + ((mEffectParams.mMagnMin == 1 && mEffectParams.mMagnMax == 1) ? pt : pts ); spellLine += " " + ((mEffectParams.mMagnMin == mEffectParams.mMagnMax && std::abs(mEffectParams.mMagnMin) == 1) ? pt : pts );
} }
} }
@ -528,99 +530,5 @@ namespace MWGui
assignWidget(mBarWidget, "Bar"); assignWidget(mBarWidget, "Bar");
assignWidget(mBarTextWidget, "BarText"); assignWidget(mBarTextWidget, "BarText");
} }
MWScrollBar::MWScrollBar()
: mEnableRepeat(true)
, mRepeatTriggerTime(0.5f)
, mRepeatStepTime(0.1f)
, mIsIncreasing(true)
{
ScrollBar::setRepeatEnabled(false);
}
MWScrollBar::~MWScrollBar()
{
}
void MWScrollBar::initialiseOverride()
{
ScrollBar::initialiseOverride();
if(mWidgetStart)
{
mWidgetStart->eventMouseButtonPressed += MyGUI::newDelegate(this, &MWScrollBar::onDecreaseButtonPressed);
mWidgetStart->eventMouseButtonReleased += MyGUI::newDelegate(this, &MWScrollBar::onDecreaseButtonReleased);
}
if(mWidgetEnd)
{
mWidgetEnd->eventMouseButtonPressed += MyGUI::newDelegate(this, &MWScrollBar::onIncreaseButtonPressed);
mWidgetEnd->eventMouseButtonReleased += MyGUI::newDelegate(this, &MWScrollBar::onIncreaseButtonReleased);
}
}
void MWScrollBar::setRepeat(float trigger, float step)
{
mRepeatTriggerTime = trigger;
mRepeatStepTime = step;
}
void MWScrollBar::repeatClick(MyGUI::Widget* _widget, MyGUI::ControllerItem* _controller)
{
int stepSize = mScrollPage;
if(mIsIncreasing && mScrollPosition < mScrollRange-1)
{
if(mScrollPosition + stepSize > mScrollRange-1)
mScrollPosition = mScrollRange-1;
else
mScrollPosition += stepSize;
eventScrollChangePosition(this, mScrollPosition);
updateTrack();
}
else if(!mIsIncreasing && mScrollPosition > 0)
{
int newPos = mScrollPosition - stepSize;
if(newPos < 0)
mScrollPosition = 0;
else
mScrollPosition -= stepSize;
eventScrollChangePosition(this, mScrollPosition);
updateTrack();
}
}
void MWScrollBar::onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
mIsIncreasing = false;
MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(MWGui::Controllers::ControllerRepeatEvent::getClassTypeName());
MWGui::Controllers::ControllerRepeatEvent* controller = item->castType<MWGui::Controllers::ControllerRepeatEvent>();
controller->eventRepeatClick += newDelegate(this, &MWScrollBar::repeatClick);
controller->setEnabled(mEnableRepeat);
controller->setRepeat(mRepeatTriggerTime, mRepeatStepTime);
MyGUI::ControllerManager::getInstance().addItem(this, controller);
}
void MWScrollBar::onDecreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
MyGUI::ControllerManager::getInstance().removeItem(this);
}
void MWScrollBar::onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
mIsIncreasing = true;
MyGUI::ControllerItem* item = MyGUI::ControllerManager::getInstance().createItem(MWGui::Controllers::ControllerRepeatEvent::getClassTypeName());
MWGui::Controllers::ControllerRepeatEvent* controller = item->castType<MWGui::Controllers::ControllerRepeatEvent>();
controller->eventRepeatClick += newDelegate(this, &MWScrollBar::repeatClick);
controller->setEnabled(mEnableRepeat);
controller->setRepeat(mRepeatTriggerTime, mRepeatStepTime);
MyGUI::ControllerManager::getInstance().addItem(this, controller);
}
void MWScrollBar::onIncreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
{
MyGUI::ControllerManager::getInstance().removeItem(this);
}
} }
} }

@ -38,6 +38,7 @@ namespace MWGui
SpellEffectParams() SpellEffectParams()
: mNoTarget(false) : mNoTarget(false)
, mIsConstant(false) , mIsConstant(false)
, mNoMagnitude(false)
, mKnown(true) , mKnown(true)
, mEffectID(-1) , mEffectID(-1)
, mSkill(-1) , mSkill(-1)
@ -52,6 +53,7 @@ namespace MWGui
bool mNoTarget; // potion effects for example have no target (target is always the player) bool mNoTarget; // potion effects for example have no target (target is always the player)
bool mIsConstant; // constant effect means that duration will not be displayed bool mIsConstant; // constant effect means that duration will not be displayed
bool mNoMagnitude; // effect magnitude will not be displayed (e.g ingredients)
bool mKnown; // is this effect known to the player? (If not, will display as a question mark instead) bool mKnown; // is this effect known to the player? (If not, will display as a question mark instead)
@ -218,7 +220,9 @@ namespace MWGui
enum EffectFlags enum EffectFlags
{ {
EF_NoTarget = 0x01, // potions have no target (target is always the player) EF_NoTarget = 0x01, // potions have no target (target is always the player)
EF_Constant = 0x02 // constant effect means that duration will not be displayed EF_Constant = 0x02, // constant effect means that duration will not be displayed
EF_NoMagnitude = 0x04 // ingredients have no magnitude
}; };
void setEffectList(const SpellEffectList& list); void setEffectList(const SpellEffectList& list);
@ -299,33 +303,6 @@ namespace MWGui
MyGUI::TextBox* mBarTextWidget; MyGUI::TextBox* mBarTextWidget;
}; };
typedef MWDynamicStat* MWDynamicStatPtr; typedef MWDynamicStat* MWDynamicStatPtr;
// Should be removed when upgrading to MyGUI 3.2.2 (current git), it has ScrollBar autorepeat support
class MWScrollBar : public MyGUI::ScrollBar
{
MYGUI_RTTI_DERIVED(MWScrollBar)
public:
MWScrollBar();
virtual ~MWScrollBar();
void setRepeat(float trigger, float step);
protected:
virtual void initialiseOverride();
void repeatClick(MyGUI::Widget* _widget, MyGUI::ControllerItem* _controller);
bool mEnableRepeat;
float mRepeatTriggerTime;
float mRepeatStepTime;
bool mIsIncreasing;
private:
void onDecreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onDecreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onIncreaseButtonPressed(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
void onIncreaseButtonReleased(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
};
} }
} }

@ -1,5 +1,6 @@
#include "windowbase.hpp" #include "windowbase.hpp"
#include <MyGUI_Button.h>
#include <MyGUI_InputManager.h> #include <MyGUI_InputManager.h>
#include <MyGUI_RenderManager.h> #include <MyGUI_RenderManager.h>
@ -9,6 +10,7 @@
#include <components/widgets/imagebutton.hpp> #include <components/widgets/imagebutton.hpp>
#include "draganddrop.hpp" #include "draganddrop.hpp"
#include "exposedwindow.hpp"
using namespace MWGui; using namespace MWGui;
@ -16,6 +18,32 @@ WindowBase::WindowBase(const std::string& parLayout)
: Layout(parLayout) : Layout(parLayout)
{ {
mMainWidget->setVisible(false); mMainWidget->setVisible(false);
Window* window = mMainWidget->castType<Window>(false);
if (!window)
return;
MyGUI::Button* button = nullptr;
MyGUI::VectorWidgetPtr widgets = window->getSkinWidgetsByName("Action");
for (MyGUI::Widget* widget : widgets)
{
if (widget->isUserString("SupportDoubleClick"))
button = widget->castType<MyGUI::Button>();
}
if (button)
button->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &WindowBase::onDoubleClick);
}
void WindowBase::onTitleDoubleClicked()
{
if (MyGUI::InputManager::getInstance().isShiftPressed())
MWBase::Environment::get().getWindowManager()->toggleMaximized(this);
}
void WindowBase::onDoubleClick(MyGUI::Widget *_sender)
{
onTitleDoubleClicked();
} }
void WindowBase::setVisible(bool visible) void WindowBase::setVisible(bool visible)
@ -27,18 +55,6 @@ void WindowBase::setVisible(bool visible)
onOpen(); onOpen();
else if (wasVisible) else if (wasVisible)
onClose(); onClose();
// This is needed as invisible widgets can retain key focus.
// Remove for MyGUI 3.2.2
if (!visible)
{
MyGUI::Widget* keyFocus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
while (keyFocus != mMainWidget && keyFocus != nullptr)
keyFocus = keyFocus->getParent();
if (keyFocus == mMainWidget)
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(nullptr);
}
} }
bool WindowBase::isVisible() bool WindowBase::isVisible()

@ -20,7 +20,7 @@ namespace MWGui
class WindowBase: public Layout class WindowBase: public Layout
{ {
public: public:
WindowBase(const std::string& parLayout); WindowBase(const std::string& parLayout);
virtual MyGUI::Widget* getDefaultKeyFocus() { return nullptr; } virtual MyGUI::Widget* getDefaultKeyFocus() { return nullptr; }
@ -52,8 +52,13 @@ namespace MWGui
/// Called when GUI viewport changes size /// Called when GUI viewport changes size
virtual void onResChange(int width, int height) {} virtual void onResChange(int width, int height) {}
};
protected:
virtual void onTitleDoubleClicked();
private:
void onDoubleClick(MyGUI::Widget* _sender);
};
/* /*
* "Modal" windows cause the rest of the interface to be inaccessible while they are visible * "Modal" windows cause the rest of the interface to be inaccessible while they are visible

@ -228,8 +228,7 @@ namespace MWGui
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::ExposedWindow>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Window>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWScrollBar>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<BackgroundImage>("Widget"); MyGUI::FactoryManager::getInstance().registerFactory<BackgroundImage>("Widget");
MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::AdditiveLayer>("Layer"); MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::AdditiveLayer>("Layer");
@ -248,7 +247,6 @@ namespace MWGui
MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource"); MyGUI::ResourceManager::getInstance().unregisterLoadXmlDelegate("Resource");
MyGUI::ResourceManager::getInstance().registerLoadXmlDelegate("Resource") = newDelegate(this, &WindowManager::loadFontDelegate); MyGUI::ResourceManager::getInstance().registerLoadXmlDelegate("Resource") = newDelegate(this, &WindowManager::loadFontDelegate);
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerRepeatEvent>("Controller");
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller"); MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer"); MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer");
@ -459,7 +457,6 @@ namespace MWGui
mConsole = new Console(w,h, mConsoleOnlyScripts); mConsole = new Console(w,h, mConsoleOnlyScripts);
mWindows.push_back(mConsole); mWindows.push_back(mConsole);
trackWindow(mConsole, "console"); trackWindow(mConsole, "console");
mGuiModeStates[GM_Console] = GuiModeState(mConsole);
bool questList = mResourceSystem->getVFS()->exists("textures/tx_menubook_options_over.dds"); bool questList = mResourceSystem->getVFS()->exists("textures/tx_menubook_options_over.dds");
JournalWindow* journal = JournalWindow::create(JournalViewModel::create (), questList, mEncoding); JournalWindow* journal = JournalWindow::create(JournalViewModel::create (), questList, mEncoding);
@ -721,7 +718,7 @@ namespace MWGui
setCursorVisible(!gameMode); setCursorVisible(!gameMode);
if (gameMode) if (gameMode)
setKeyFocusWidget (nullptr); MyGUI::InputManager::getInstance().resetKeyFocusWidget();
// Icons of forced hidden windows are displayed // Icons of forced hidden windows are displayed
setMinimapVisibility((mAllowed & GW_Map) && (!mMap->pinned() || (mForceHidden & GW_Map))); setMinimapVisibility((mAllowed & GW_Map) && (!mMap->pinned() || (mForceHidden & GW_Map)));
@ -734,10 +731,10 @@ namespace MWGui
// If in game mode (or interactive messagebox), show the pinned windows // If in game mode (or interactive messagebox), show the pinned windows
if (mGuiModes.empty()) if (mGuiModes.empty())
{ {
mMap->setVisible(mMap->pinned() && !(mForceHidden & GW_Map) && (mAllowed & GW_Map)); mMap->setVisible(mMap->pinned() && !isConsoleMode() && !(mForceHidden & GW_Map) && (mAllowed & GW_Map));
mStatsWindow->setVisible(mStatsWindow->pinned() && !(mForceHidden & GW_Stats) && (mAllowed & GW_Stats)); mStatsWindow->setVisible(mStatsWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Stats) && (mAllowed & GW_Stats));
mInventoryWindow->setVisible(mInventoryWindow->pinned() && !(mForceHidden & GW_Inventory) && (mAllowed & GW_Inventory)); mInventoryWindow->setVisible(mInventoryWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Inventory) && (mAllowed & GW_Inventory));
mSpellWindow->setVisible(mSpellWindow->pinned() && !(mForceHidden & GW_Magic) && (mAllowed & GW_Magic)); mSpellWindow->setVisible(mSpellWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Magic) && (mAllowed & GW_Magic));
return; return;
} }
else if (getMode() != GM_Inventory) else if (getMode() != GM_Inventory)
@ -1019,6 +1016,12 @@ namespace MWGui
void WindowManager::onFrame (float frameDuration) void WindowManager::onFrame (float frameDuration)
{ {
bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!=
MWBase::StateManager::State_NoGame;
if (gameRunning)
updateMap();
if (!mGuiModes.empty()) if (!mGuiModes.empty())
{ {
GuiModeState& state = mGuiModeStates[mGuiModes.back()]; GuiModeState& state = mGuiModeStates[mGuiModes.back()];
@ -1062,14 +1065,11 @@ namespace MWGui
if (mLocalMapRender) if (mLocalMapRender)
mLocalMapRender->cleanupCameras(); mLocalMapRender->cleanupCameras();
if (MWBase::Environment::get().getStateManager()->getState()== if (!gameRunning)
MWBase::StateManager::State_NoGame)
return; return;
mDragAndDrop->onFrame(); mDragAndDrop->onFrame();
updateMap();
mHud->onFrame(frameDuration); mHud->onFrame(frameDuration);
mDebugWindow->onFrame(frameDuration); mDebugWindow->onFrame(frameDuration);
@ -1254,6 +1254,7 @@ namespace MWGui
else if (tag.compare(0, tokenLength, tokenToFind) == 0) else if (tag.compare(0, tokenLength, tokenToFind) == 0)
{ {
_result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength)); _result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength));
_result = MyGUI::TextIterator::toTagsString(_result);
} }
else if (Gui::replaceTag(tag, _result)) else if (Gui::replaceTag(tag, _result))
{ {
@ -1306,10 +1307,14 @@ namespace MWGui
for (std::map<MyGUI::Window*, std::string>::iterator it = mTrackedWindows.begin(); it != mTrackedWindows.end(); ++it) for (std::map<MyGUI::Window*, std::string>::iterator it = mTrackedWindows.begin(); it != mTrackedWindows.end(); ++it)
{ {
MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(it->second + " x", "Windows") * x), std::string settingName = it->second;
static_cast<int>( Settings::Manager::getFloat(it->second+ " y", "Windows") * y)); if (Settings::Manager::getBool(settingName + " maximized", "Windows"))
MyGUI::IntSize size(static_cast<int>(Settings::Manager::getFloat(it->second + " w", "Windows") * x), settingName += " maximized";
static_cast<int>(Settings::Manager::getFloat(it->second + " h", "Windows") * y));
MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(settingName + " x", "Windows") * x),
static_cast<int>(Settings::Manager::getFloat(settingName + " y", "Windows") * y));
MyGUI::IntSize size(static_cast<int>(Settings::Manager::getFloat(settingName + " w", "Windows") * x),
static_cast<int>(Settings::Manager::getFloat(settingName + " h", "Windows") * y));
it->first->setPosition(pos); it->first->setPosition(pos);
it->first->setSize(size); it->first->setSize(size);
} }
@ -1386,6 +1391,10 @@ namespace MWGui
} }
updateVisible(); updateVisible();
// To make sure that console window get focus again
if (mConsole && mConsole->isVisible())
mConsole->onOpen();
} }
void WindowManager::removeGuiMode(GuiMode mode, bool noSound) void WindowManager::removeGuiMode(GuiMode mode, bool noSound)
@ -1619,14 +1628,15 @@ namespace MWGui
bool WindowManager::isGuiMode() const bool WindowManager::isGuiMode() const
{ {
return !mGuiModes.empty() || (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); return
!mGuiModes.empty() ||
isConsoleMode() ||
(mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox());
} }
bool WindowManager::isConsoleMode() const bool WindowManager::isConsoleMode() const
{ {
if (!mGuiModes.empty() && mGuiModes.back()==GM_Console) return mConsole && mConsole->isVisible();
return true;
return false;
} }
MWGui::GuiMode WindowManager::getMode() const MWGui::GuiMode WindowManager::getMode() const
@ -1794,16 +1804,6 @@ namespace MWGui
} }
} }
// Remove this method for MyGUI 3.2.2
void WindowManager::setKeyFocusWidget(MyGUI::Widget *widget)
{
if (widget == nullptr)
MyGUI::InputManager::getInstance().resetKeyFocusWidget();
else
MyGUI::InputManager::getInstance().setKeyFocusWidget(widget);
onKeyFocusChanged(widget);
}
void WindowManager::onKeyFocusChanged(MyGUI::Widget *widget) void WindowManager::onKeyFocusChanged(MyGUI::Widget *widget)
{ {
if (widget && widget->castType<MyGUI::EditBox>(false)) if (widget && widget->castType<MyGUI::EditBox>(false))
@ -1838,11 +1838,16 @@ namespace MWGui
void WindowManager::trackWindow(Layout *layout, const std::string &name) void WindowManager::trackWindow(Layout *layout, const std::string &name)
{ {
std::string settingName = name;
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(name + " x", "Windows") * viewSize.width), bool isMaximized = Settings::Manager::getBool(name + " maximized", "Windows");
static_cast<int>(Settings::Manager::getFloat(name + " y", "Windows") * viewSize.height)); if (isMaximized)
MyGUI::IntSize size (static_cast<int>(Settings::Manager::getFloat(name + " w", "Windows") * viewSize.width), settingName += " maximized";
static_cast<int>(Settings::Manager::getFloat(name + " h", "Windows") * viewSize.height));
MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(settingName + " x", "Windows") * viewSize.width),
static_cast<int>(Settings::Manager::getFloat(settingName + " y", "Windows") * viewSize.height));
MyGUI::IntSize size (static_cast<int>(Settings::Manager::getFloat(settingName + " w", "Windows") * viewSize.width),
static_cast<int>(Settings::Manager::getFloat(settingName + " h", "Windows") * viewSize.height));
layout->mMainWidget->setPosition(pos); layout->mMainWidget->setPosition(pos);
layout->mMainWidget->setSize(size); layout->mMainWidget->setSize(size);
@ -1851,6 +1856,26 @@ namespace MWGui
mTrackedWindows[window] = name; mTrackedWindows[window] = name;
} }
void WindowManager::toggleMaximized(Layout *layout)
{
MyGUI::Window* window = layout->mMainWidget->castType<MyGUI::Window>();
std::string setting = mTrackedWindows[window];
if (setting.empty())
return;
bool maximized = !Settings::Manager::getBool(setting + " maximized", "Windows");
if (maximized)
setting += " maximized";
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
float x = Settings::Manager::getFloat(setting + " x", "Windows") * float(viewSize.width);
float y = Settings::Manager::getFloat(setting + " y", "Windows") * float(viewSize.height);
float w = Settings::Manager::getFloat(setting + " w", "Windows") * float(viewSize.width);
float h = Settings::Manager::getFloat(setting + " h", "Windows") * float(viewSize.height);
window->setCoord(x, y, w, h);
Settings::Manager::setBool(mTrackedWindows[window] + " maximized", "Windows", maximized);
}
void WindowManager::onWindowChangeCoord(MyGUI::Window *_sender) void WindowManager::onWindowChangeCoord(MyGUI::Window *_sender)
{ {
std::string setting = mTrackedWindows[_sender]; std::string setting = mTrackedWindows[_sender];
@ -1863,6 +1888,9 @@ namespace MWGui
Settings::Manager::setFloat(setting + " y", "Windows", y); Settings::Manager::setFloat(setting + " y", "Windows", y);
Settings::Manager::setFloat(setting + " w", "Windows", w); Settings::Manager::setFloat(setting + " w", "Windows", w);
Settings::Manager::setFloat(setting + " h", "Windows", h); Settings::Manager::setFloat(setting + " h", "Windows", h);
bool maximized = Settings::Manager::getBool(setting + " maximized", "Windows");
if (maximized)
Settings::Manager::setBool(setting + " maximized", "Windows", false);
} }
void WindowManager::clear() void WindowManager::clear()
@ -1942,6 +1970,7 @@ namespace MWGui
bool WindowManager::isSavingAllowed() const bool WindowManager::isSavingAllowed() const
{ {
return !MyGUI::InputManager::getInstance().isModalAny() return !MyGUI::InputManager::getInstance().isModalAny()
&& !isConsoleMode()
// TODO: remove this, once we have properly serialized the state of open windows // TODO: remove this, once we have properly serialized the state of open windows
&& (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest))); && (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest)));
} }
@ -1968,7 +1997,7 @@ namespace MWGui
sizeVideo(screenSize.width, screenSize.height); sizeVideo(screenSize.width, screenSize.height);
MyGUI::Widget* oldKeyFocus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); MyGUI::Widget* oldKeyFocus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
setKeyFocusWidget(mVideoWidget); MyGUI::InputManager::getInstance().setKeyFocusWidget(mVideoWidget);
mVideoBackground->setVisible(true); mVideoBackground->setVisible(true);
@ -2006,7 +2035,7 @@ namespace MWGui
MWBase::Environment::get().getSoundManager()->resumeSounds(); MWBase::Environment::get().getSoundManager()->resumeSounds();
setKeyFocusWidget(oldKeyFocus); MyGUI::InputManager::getInstance().setKeyFocusWidget(oldKeyFocus);
setCursorVisible(cursorWasVisible); setCursorVisible(cursorWasVisible);
@ -2189,6 +2218,21 @@ namespace MWGui
SDL_free(text); SDL_free(text);
} }
void WindowManager::toggleConsole()
{
bool visible = mConsole->isVisible();
if (!visible && !mGuiModes.empty())
mKeyboardNavigation->saveFocus(mGuiModes.back());
mConsole->setVisible(!visible);
if (visible && !mGuiModes.empty())
mKeyboardNavigation->restoreFocus(mGuiModes.back());
updateVisible();
}
void WindowManager::toggleDebugWindow() void WindowManager::toggleDebugWindow()
{ {
mDebugWindow->setVisible(!mDebugWindow->isVisible()); mDebugWindow->setVisible(!mDebugWindow->isVisible());
@ -2358,6 +2402,11 @@ namespace MWGui
tex->unlock(); tex->unlock();
} }
void WindowManager::addCell(MWWorld::CellStore* cell)
{
mLocalMapRender->addCell(cell);
}
void WindowManager::removeCell(MWWorld::CellStore *cell) void WindowManager::removeCell(MWWorld::CellStore *cell)
{ {
mLocalMapRender->removeCell(cell); mLocalMapRender->removeCell(cell);

@ -147,9 +147,6 @@ namespace MWGui
/// (and will continually update the window while doing so) /// (and will continually update the window while doing so)
virtual void playVideo(const std::string& name, bool allowSkipping); virtual void playVideo(const std::string& name, bool allowSkipping);
/// Warning: do not use MyGUI::InputManager::setKeyFocusWidget directly. Instead use this.
virtual void setKeyFocusWidget (MyGUI::Widget* widget);
virtual void setNewGame(bool newgame); virtual void setNewGame(bool newgame);
virtual void pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg); virtual void pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg);
@ -436,6 +433,7 @@ namespace MWGui
virtual void removeCurrentModal(WindowModal* input); virtual void removeCurrentModal(WindowModal* input);
virtual void pinWindow (MWGui::GuiWindow window); virtual void pinWindow (MWGui::GuiWindow window);
virtual void toggleMaximized(Layout *layout);
/// Fade the screen in, over \a time seconds /// Fade the screen in, over \a time seconds
virtual void fadeScreenIn(const float time, bool clearQueue, float delay); virtual void fadeScreenIn(const float time, bool clearQueue, float delay);
@ -449,6 +447,7 @@ namespace MWGui
virtual void activateHitOverlay(bool interrupt); virtual void activateHitOverlay(bool interrupt);
virtual void setWerewolfOverlay(bool set); virtual void setWerewolfOverlay(bool set);
virtual void toggleConsole();
virtual void toggleDebugWindow(); virtual void toggleDebugWindow();
/// Cycle to next or previous spell /// Cycle to next or previous spell
@ -464,6 +463,7 @@ namespace MWGui
virtual std::string correctTexturePath(const std::string& path); virtual std::string correctTexturePath(const std::string& path);
virtual bool textureExists(const std::string& path); virtual bool textureExists(const std::string& path);
void addCell(MWWorld::CellStore* cell);
void removeCell(MWWorld::CellStore* cell); void removeCell(MWWorld::CellStore* cell);
void writeFog(MWWorld::CellStore* cell); void writeFog(MWWorld::CellStore* cell);

@ -1,7 +1,5 @@
#include "windowpinnablebase.hpp" #include "windowpinnablebase.hpp"
#include <MyGUI_Button.h>
#include "exposedwindow.hpp" #include "exposedwindow.hpp"
namespace MWGui namespace MWGui
@ -9,21 +7,10 @@ namespace MWGui
WindowPinnableBase::WindowPinnableBase(const std::string& parLayout) WindowPinnableBase::WindowPinnableBase(const std::string& parLayout)
: WindowBase(parLayout), mPinned(false) : WindowBase(parLayout), mPinned(false)
{ {
ExposedWindow* window = mMainWidget->castType<ExposedWindow>(); Window* window = mMainWidget->castType<Window>();
mPinButton = window->getSkinWidget ("Button"); mPinButton = window->getSkinWidget ("Button");
mPinButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonPressed); mPinButton->eventMouseButtonPressed += MyGUI::newDelegate(this, &WindowPinnableBase::onPinButtonPressed);
MyGUI::Button* button = nullptr;
MyGUI::VectorWidgetPtr widgets = window->getSkinWidgetsByName("Action");
for (MyGUI::Widget* widget : widgets)
{
if (widget->isUserString("HideWindowOnDoubleClick"))
button = widget->castType<MyGUI::Button>();
}
if (button)
button->eventMouseButtonDoubleClick += MyGUI::newDelegate(this, &WindowPinnableBase::onDoubleClick);
} }
void WindowPinnableBase::onPinButtonPressed(MyGUI::Widget* _sender, int left, int top, MyGUI::MouseButton id) void WindowPinnableBase::onPinButtonPressed(MyGUI::Widget* _sender, int left, int top, MyGUI::MouseButton id)
@ -41,11 +28,6 @@ namespace MWGui
onPinToggled(); onPinToggled();
} }
void WindowPinnableBase::onDoubleClick(MyGUI::Widget *_sender)
{
onTitleDoubleClicked();
}
void WindowPinnableBase::setPinned(bool pinned) void WindowPinnableBase::setPinned(bool pinned)
{ {
if (pinned != mPinned) if (pinned != mPinned)

@ -17,11 +17,9 @@ namespace MWGui
private: private:
void onPinButtonPressed(MyGUI::Widget* _sender, int left, int top, MyGUI::MouseButton id); void onPinButtonPressed(MyGUI::Widget* _sender, int left, int top, MyGUI::MouseButton id);
void onDoubleClick(MyGUI::Widget* _sender);
protected: protected:
virtual void onPinToggled() = 0; virtual void onPinToggled() = 0;
virtual void onTitleDoubleClicked() = 0;
MyGUI::Widget* mPinButton; MyGUI::Widget* mPinButton;
bool mPinned; bool mPinned;

@ -507,7 +507,7 @@ namespace MWInput
void InputManager::updateCursorMode() void InputManager::updateCursorMode()
{ {
bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)
&& MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console; && !MWBase::Environment::get().getWindowManager()->isConsoleMode();
bool was_relative = mInputManager->getMouseRelative(); bool was_relative = mInputManager->getMouseRelative();
bool is_relative = !MWBase::Environment::get().getWindowManager()->isGuiMode(); bool is_relative = !MWBase::Environment::get().getWindowManager()->isGuiMode();
@ -618,6 +618,7 @@ namespace MWInput
{ {
bool triedToMove = false; bool triedToMove = false;
bool isRunning = false; bool isRunning = false;
bool alwaysRunAllowed = false;
// joystick movement // joystick movement
float xAxis = mInputBinder->getChannel(A_MoveLeftRight)->getValue(); float xAxis = mInputBinder->getChannel(A_MoveLeftRight)->getValue();
@ -646,31 +647,23 @@ namespace MWInput
isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25; isRunning = xAxis > .75 || xAxis < .25 || yAxis > .75 || yAxis < .25;
if(triedToMove) resetIdleTime(); if(triedToMove) resetIdleTime();
if (actionIsActive(A_MoveLeft) && !actionIsActive(A_MoveRight)) if (actionIsActive(A_MoveLeft) != actionIsActive(A_MoveRight))
{ {
alwaysRunAllowed = true;
triedToMove = true; triedToMove = true;
mPlayer->setLeftRight (-1); mPlayer->setLeftRight (actionIsActive(A_MoveRight) ? 1 : -1);
}
else if (actionIsActive(A_MoveRight) && !actionIsActive(A_MoveLeft))
{
triedToMove = true;
mPlayer->setLeftRight (1);
} }
if (actionIsActive(A_MoveForward) && !actionIsActive(A_MoveBackward)) if (actionIsActive(A_MoveForward) != actionIsActive(A_MoveBackward))
{
triedToMove = true;
mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (1);
}
else if (actionIsActive(A_MoveBackward) && !actionIsActive(A_MoveForward))
{ {
alwaysRunAllowed = true;
triedToMove = true; triedToMove = true;
mPlayer->setAutoMove (false); mPlayer->setAutoMove (false);
mPlayer->setForwardBackward (-1); mPlayer->setForwardBackward (actionIsActive(A_MoveForward) ? 1 : -1);
} }
else if(mPlayer->getAutoMove()) else if(mPlayer->getAutoMove())
{ {
alwaysRunAllowed = true;
triedToMove = true; triedToMove = true;
mPlayer->setForwardBackward (1); mPlayer->setForwardBackward (1);
} }
@ -715,7 +708,7 @@ namespace MWInput
mOverencumberedMessageDelay = 0.f; mOverencumberedMessageDelay = 0.f;
} }
if (mAlwaysRunActive || isRunning) if ((mAlwaysRunActive && alwaysRunAllowed) || isRunning)
mPlayer->setRunState(!actionIsActive(A_Run)); mPlayer->setRunState(!actionIsActive(A_Run));
else else
mPlayer->setRunState(actionIsActive(A_Run)); mPlayer->setRunState(actionIsActive(A_Run));
@ -838,9 +831,6 @@ namespace MWInput
Settings::Manager::getInt("resolution y", "Video"), Settings::Manager::getInt("resolution y", "Video"),
Settings::Manager::getBool("fullscreen", "Video"), Settings::Manager::getBool("fullscreen", "Video"),
Settings::Manager::getBool("window border", "Video")); Settings::Manager::getBool("window border", "Video"));
// We should reload TrueType fonts to fit new resolution
MWBase::Environment::get().getWindowManager()->loadUserFonts();
} }
} }
@ -880,7 +870,7 @@ namespace MWInput
OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym);
if (mInputBinder->getKeyBinding(mInputBinder->getControl(A_Console), ICS::Control::INCREASE) if (mInputBinder->getKeyBinding(mInputBinder->getControl(A_Console), ICS::Control::INCREASE)
== arg.keysym.scancode == arg.keysym.scancode
&& MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console) && MWBase::Environment::get().getWindowManager()->isConsoleMode())
SDL_StopTextInput(); SDL_StopTextInput();
bool consumed = false; bool consumed = false;
@ -1142,10 +1132,17 @@ namespace MWInput
void InputManager::windowResized(int x, int y) void InputManager::windowResized(int x, int y)
{ {
// Note: this is a side effect of resolution change or window resize.
// There is no need to track these changes.
Settings::Manager::setInt("resolution x", "Video", x); Settings::Manager::setInt("resolution x", "Video", x);
Settings::Manager::setInt("resolution y", "Video", y); Settings::Manager::setInt("resolution y", "Video", y);
Settings::Manager::resetPendingChange("resolution x", "Video");
Settings::Manager::resetPendingChange("resolution y", "Video");
MWBase::Environment::get().getWindowManager()->windowResized(x, y); MWBase::Environment::get().getWindowManager()->windowResized(x, y);
// We should reload TrueType fonts to fit new resolution
MWBase::Environment::get().getWindowManager()->loadUserFonts();
} }
void InputManager::windowClosed() void InputManager::windowClosed()
@ -1161,6 +1158,9 @@ namespace MWInput
return; return;
} }
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
return;
bool inGame = MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_NoGame; bool inGame = MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_NoGame;
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode(); MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
@ -1179,6 +1179,9 @@ namespace MWInput
return; return;
} }
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
return;
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode(); MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
bool inGame = MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_NoGame; bool inGame = MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_NoGame;
@ -1327,7 +1330,7 @@ namespace MWInput
if (MyGUI::InputManager::getInstance ().isModalAny()) if (MyGUI::InputManager::getInstance ().isModalAny())
return; return;
/* /*
Start of tes3mp addition Start of tes3mp addition
@ -1339,6 +1342,9 @@ namespace MWInput
End of tes3mp addition End of tes3mp addition
*/ */
if (MWBase::Environment::get().getWindowManager()->isConsoleMode())
return;
// Toggle between game mode and inventory mode // Toggle between game mode and inventory mode
if(!MWBase::Environment::get().getWindowManager()->isGuiMode()) if(!MWBase::Environment::get().getWindowManager()->isGuiMode())
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Inventory); MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Inventory);
@ -1368,17 +1374,7 @@ namespace MWInput
if (MyGUI::InputManager::getInstance ().isModalAny()) if (MyGUI::InputManager::getInstance ().isModalAny())
return; return;
// Switch to console mode no matter what mode we are currently MWBase::Environment::get().getWindowManager()->toggleConsole();
// in, except of course if we are already in console mode
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console)
MWBase::Environment::get().getWindowManager()->popGuiMode();
else
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console);
}
else
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Console);
} }
void InputManager::toggleJournal() void InputManager::toggleJournal()
@ -1461,6 +1457,7 @@ namespace MWInput
void InputManager::toggleSneaking() void InputManager::toggleSneaking()
{ {
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return;
if (!mControlSwitch["playercontrols"]) return;
mSneaking = !mSneaking; mSneaking = !mSneaking;
mPlayer->setSneak(mSneaking); mPlayer->setSneak(mSneaking);
} }

@ -501,7 +501,7 @@ namespace MWMechanics
{ {
MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2); MWBase::Environment::get().getMechanicsManager()->startCombat(actor1, actor2);
// Also have actor1's allies start combat // Also have actor1's allies start combat
for (const MWWorld::Ptr ally1 : allies1) for (const MWWorld::Ptr& ally1 : allies1)
MWBase::Environment::get().getMechanicsManager()->startCombat(ally1, actor2); MWBase::Environment::get().getMechanicsManager()->startCombat(ally1, actor2);
return; return;
} }
@ -2328,7 +2328,7 @@ namespace MWMechanics
std::vector<MWWorld::Ptr> neighbors; std::vector<MWWorld::Ptr> neighbors;
osg::Vec3f position (actor.getRefData().getPosition().asVec3()); osg::Vec3f position (actor.getRefData().getPosition().asVec3());
getObjectsInRange(position, mActorsProcessingRange, neighbors); getObjectsInRange(position, mActorsProcessingRange, neighbors);
for(const MWWorld::Ptr neighbor : neighbors) for(const MWWorld::Ptr& neighbor : neighbors)
{ {
if (neighbor == actor) if (neighbor == actor)
continue; continue;

@ -3,6 +3,7 @@
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwworld/class.hpp"
#include "../mwworld/player.hpp" #include "../mwworld/player.hpp"
namespace MWMechanics namespace MWMechanics
@ -16,4 +17,10 @@ namespace MWMechanics
{ {
return MWBase::Environment::get().getWorld()->getPlayer().isInCombat(); return MWBase::Environment::get().getWorld()->getPlayer().isInCombat();
} }
bool canActorMoveByZAxis(const MWWorld::Ptr& actor)
{
MWBase::World* world = MWBase::Environment::get().getWorld();
return (actor.getClass().canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor);
}
} }

@ -10,6 +10,7 @@ namespace MWMechanics
{ {
MWWorld::Ptr getPlayer(); MWWorld::Ptr getPlayer();
bool isPlayerInCombat(); bool isPlayerInCombat();
bool canActorMoveByZAxis(const MWWorld::Ptr& actor);
} }
#endif #endif

@ -402,9 +402,3 @@ DetourNavigator::Flags MWMechanics::AiPackage::getNavigatorFlags(const MWWorld::
return result; return result;
} }
bool MWMechanics::AiPackage::canActorMoveByZAxis(const MWWorld::Ptr& actor) const
{
MWBase::World* world = MWBase::Environment::get().getWorld();
return (actor.getClass().canSwim(actor) && world->isSwimming(actor)) || world->isFlying(actor) || !world->isActorCollisionEnabled(actor);
}

@ -130,8 +130,6 @@ namespace MWMechanics
DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const; DetourNavigator::Flags getNavigatorFlags(const MWWorld::Ptr& actor) const;
bool canActorMoveByZAxis(const MWWorld::Ptr& actor) const;
// TODO: all this does not belong here, move into temporary storage // TODO: all this does not belong here, move into temporary storage
PathFinder mPathFinder; PathFinder mPathFinder;
ObstacleCheck mObstacleCheck; ObstacleCheck mObstacleCheck;

@ -215,11 +215,7 @@ namespace MWMechanics
getAllowedNodes(actor, currentCell->getCell(), storage); getAllowedNodes(actor, currentCell->getCell(), storage);
} }
bool actorCanMoveByZ = (actor.getClass().canSwim(actor) && MWBase::Environment::get().getWorld()->isSwimming(actor)) if (canActorMoveByZAxis(actor) && mDistance > 0) {
|| MWBase::Environment::get().getWorld()->isFlying(actor)
|| !MWBase::Environment::get().getWorld()->isActorCollisionEnabled(actor);
if(actorCanMoveByZ && mDistance > 0) {
// Typically want to idle for a short time before the next wander // Typically want to idle for a short time before the next wander
if (Misc::Rng::rollDice(100) >= 92 && storage.mState != AiWanderStorage::Wander_Walking) { if (Misc::Rng::rollDice(100) >= 92 && storage.mState != AiWanderStorage::Wander_Walking) {
wanderNearStart(actor, storage, mDistance); wanderNearStart(actor, storage, mDistance);

@ -565,8 +565,9 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
mCurrentMovement = movementAnimName; mCurrentMovement = movementAnimName;
if(!mCurrentMovement.empty()) if(!mCurrentMovement.empty())
{ {
bool isrunning = mPtr.getClass().getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) bool isflying = MWBase::Environment::get().getWorld()->isFlying(mPtr);
&& !MWBase::Environment::get().getWorld()->isFlying(mPtr); bool isrunning = mPtr.getClass().getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Run) && !isflying;
bool issneaking = mPtr.getClass().getCreatureStats(mPtr).getStance(MWMechanics::CreatureStats::Stance_Sneak) && !isflying;
// For non-flying creatures, MW uses the Walk animation to calculate the animation velocity // For non-flying creatures, MW uses the Walk animation to calculate the animation velocity
// even if we are running. This must be replicated, otherwise the observed speed would differ drastically. // even if we are running. This must be replicated, otherwise the observed speed would differ drastically.
@ -600,7 +601,7 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
// The first person anims don't have any velocity to calculate a speed multiplier from. // The first person anims don't have any velocity to calculate a speed multiplier from.
// We use the third person velocities instead. // We use the third person velocities instead.
// FIXME: should be pulled from the actual animation, but it is not presently loaded. // FIXME: should be pulled from the actual animation, but it is not presently loaded.
mMovementAnimSpeed = (isrunning ? 222.857f : 154.064f); mMovementAnimSpeed = (issneaking ? 33.5452f : (isrunning ? 222.857f : 154.064f));
mMovementAnimationControlled = false; mMovementAnimationControlled = false;
} }
} }
@ -1148,41 +1149,36 @@ void CharacterController::updatePtr(const MWWorld::Ptr &ptr)
void CharacterController::updateIdleStormState(bool inwater) void CharacterController::updateIdleStormState(bool inwater)
{ {
bool inStormDirection = false; if (!mAnimation->hasAnimation("idlestorm") || mUpperBodyState != UpperCharState_Nothing || inwater)
if (MWBase::Environment::get().getWorld()->isInStorm())
{ {
osg::Vec3f stormDirection = MWBase::Environment::get().getWorld()->getStormDirection(); mAnimation->disable("idlestorm");
osg::Vec3f characterDirection = mPtr.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0); return;
inStormDirection = std::acos(stormDirection * characterDirection / (stormDirection.length() * characterDirection.length()))
> osg::DegreesToRadians(120.f);
} }
if (inStormDirection && !inwater && mUpperBodyState == UpperCharState_Nothing && mAnimation->hasAnimation("idlestorm"))
{
float complete = 0;
mAnimation->getInfo("idlestorm", &complete);
if (complete == 0) if (MWBase::Environment::get().getWorld()->isInStorm())
mAnimation->play("idlestorm", Priority_Storm, MWRender::Animation::BlendMask_RightArm, false,
1.0f, "start", "loop start", 0.0f, 0);
else if (complete == 1)
mAnimation->play("idlestorm", Priority_Storm, MWRender::Animation::BlendMask_RightArm, false,
1.0f, "loop start", "loop stop", 0.0f, ~0ul);
}
else
{ {
if (mUpperBodyState == UpperCharState_Nothing) osg::Vec3f stormDirection = MWBase::Environment::get().getWorld()->getStormDirection();
osg::Vec3f characterDirection = mPtr.getRefData().getBaseNode()->getAttitude() * osg::Vec3f(0,1,0);
stormDirection.normalize();
characterDirection.normalize();
if (stormDirection * characterDirection < -0.5f)
{ {
if (mAnimation->isPlaying("idlestorm")) if (!mAnimation->isPlaying("idlestorm"))
{ {
if (mAnimation->getCurrentTime("idlestorm") < mAnimation->getTextKeyTime("idlestorm: loop stop")) mAnimation->play("idlestorm", Priority_Storm, MWRender::Animation::BlendMask_RightArm, true,
{ 1.0f, "start", "stop", 0.0f, ~0ul);
mAnimation->play("idlestorm", Priority_Storm, MWRender::Animation::BlendMask_RightArm, true,
1.0f, "loop stop", "stop", 0.0f, 0);
}
} }
else
{
mAnimation->setLoopingEnabled("idlestorm", true);
}
return;
} }
else }
mAnimation->disable("idlestorm");
if (mAnimation->isPlaying("idlestorm"))
{
mAnimation->setLoopingEnabled("idlestorm", false);
} }
} }
@ -2100,24 +2096,24 @@ void CharacterController::update(float duration, bool animationOnly)
osg::Vec3f rot = cls.getRotationVector(mPtr); osg::Vec3f rot = cls.getRotationVector(mPtr);
speed = cls.getSpeed(mPtr); speed = cls.getSpeed(mPtr);
float analogueMult = 1.f;
if(isPlayer) if(isPlayer)
{ {
// Joystick anologue movement. // Joystick analogue movement.
float xAxis = std::abs(cls.getMovementSettings(mPtr).mPosition[0]); float xAxis = std::abs(cls.getMovementSettings(mPtr).mPosition[0]);
float yAxis = std::abs(cls.getMovementSettings(mPtr).mPosition[1]); float yAxis = std::abs(cls.getMovementSettings(mPtr).mPosition[1]);
float analogueMovement = ((xAxis > yAxis) ? xAxis : yAxis); analogueMult = ((xAxis > yAxis) ? xAxis : yAxis);
// If Strafing, our max speed is slower so multiply by X axis instead. // If Strafing, our max speed is slower so multiply by X axis instead.
if(std::abs(vec.x()/2.0f) > std::abs(vec.y())) if(std::abs(vec.x()/2.0f) > std::abs(vec.y()))
analogueMovement = xAxis; analogueMult = xAxis;
// Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used. // Due to the half way split between walking/running, we multiply speed by 2 while walking, unless a keyboard was used.
if(!isrunning && !sneak && !flying && analogueMovement <= 0.5f) if(!isrunning && !sneak && !flying && analogueMult <= 0.5f)
speed *= 2; analogueMult *= 2.f;
speed *= (analogueMovement);
} }
speed *= analogueMult;
vec.x() *= speed; vec.x() *= speed;
vec.y() *= speed; vec.y() *= speed;
@ -2184,6 +2180,7 @@ void CharacterController::update(float duration, bool animationOnly)
} }
} }
fatigueLoss *= duration; fatigueLoss *= duration;
fatigueLoss *= analogueMult;
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue(); DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
if (!godmode) if (!godmode)

@ -590,6 +590,11 @@ namespace MWMechanics
{ {
osg::Vec3f pos1 (actor1.getRefData().getPosition().asVec3()); osg::Vec3f pos1 (actor1.getRefData().getPosition().asVec3());
osg::Vec3f pos2 (actor2.getRefData().getPosition().asVec3()); osg::Vec3f pos2 (actor2.getRefData().getPosition().asVec3());
if (canActorMoveByZAxis(actor2))
{
pos1.z() = 0.f;
pos2.z() = 0.f;
}
float d = (pos1 - pos2).length(); float d = (pos1 - pos2).length();

@ -61,7 +61,7 @@ namespace MWMechanics
std::string msg = "sMagicContractDisease"; std::string msg = "sMagicContractDisease";
msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->mValue.getString(); msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find(msg)->mValue.getString();
Misc::StringUtils::replace(msg, "%s", spell->mName.c_str(), 2); msg = Misc::StringUtils::format(msg, spell->mName);
MWBase::Environment::get().getWindowManager()->messageBox(msg); MWBase::Environment::get().getWindowManager()->messageBox(msg);
} }
} }

@ -193,46 +193,36 @@ namespace MWMechanics
* *
* Formula on UESPWiki is not entirely correct. * Formula on UESPWiki is not entirely correct.
*/ */
int Enchanting::getEnchantPoints() const float Enchanting::getEnchantPoints(bool precise) const
{ {
if (mEffectList.mList.empty()) if (mEffectList.mList.empty())
// No effects added, cost = 0 // No effects added, cost = 0
return 0; return 0;
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
std::vector<ESM::ENAMstruct> mEffects = mEffectList.mList; const float fEffectCostMult = store.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
const float fEnchantmentConstantDurationMult = store.get<ESM::GameSetting>().find("fEnchantmentConstantDurationMult")->mValue.getFloat();
int enchantmentCost = 0; float enchantmentCost = 0.f;
float cost = 0; float cost = 0.f;
for (std::vector<ESM::ENAMstruct>::const_iterator it = mEffects.begin(); it != mEffects.end(); ++it) for (const ESM::ENAMstruct& effect : mEffectList.mList)
{ {
float baseCost = (store.get<ESM::MagicEffect>().find(it->mEffectID))->mData.mBaseCost; float baseCost = (store.get<ESM::MagicEffect>().find(effect.mEffectID))->mData.mBaseCost;
int magMin = std::max(1, it->mMagnMin); int magMin = std::max(1, effect.mMagnMin);
int magMax = std::max(1, it->mMagnMax); int magMax = std::max(1, effect.mMagnMax);
int area = std::max(1, it->mArea); int area = std::max(1, effect.mArea);
float duration = static_cast<float>(effect.mDuration);
float magnitudeCost = (magMin + magMax) * baseCost * 0.05f;
if (mCastStyle == ESM::Enchantment::ConstantEffect) if (mCastStyle == ESM::Enchantment::ConstantEffect)
{ duration = fEnchantmentConstantDurationMult;
magnitudeCost *= store.get<ESM::GameSetting>().find("fEnchantmentConstantDurationMult")->mValue.getFloat();
}
else
{
magnitudeCost *= it->mDuration;
}
float areaCost = area * 0.05f * baseCost; cost += ((magMin + magMax) * duration + area) * baseCost * fEffectCostMult * 0.05f;
const float fEffectCostMult = store.get<ESM::GameSetting>().find("fEffectCostMult")->mValue.getFloat();
cost += (magnitudeCost + areaCost) * fEffectCostMult;
cost = std::max(1.f, cost); cost = std::max(1.f, cost);
if (it->mRange == ESM::RT_Target) if (effect.mRange == ESM::RT_Target)
cost *= 1.5; cost *= 1.5f;
enchantmentCost += static_cast<int>(cost); enchantmentCost += precise ? cost : std::floor(cost);
} }
return enchantmentCost; return enchantmentCost;
@ -244,7 +234,7 @@ namespace MWMechanics
if (mCastStyle == ESM::Enchantment::ConstantEffect) if (mCastStyle == ESM::Enchantment::ConstantEffect)
return 0; return 0;
return getEnchantPoints(); return static_cast<int>(getEnchantPoints(false));
} }
int Enchanting::getEffectiveCastCost() const int Enchanting::getEffectiveCastCost() const
@ -308,21 +298,21 @@ namespace MWMechanics
mEnchanter = enchanter; mEnchanter = enchanter;
} }
float Enchanting::getEnchantChance() const int Enchanting::getEnchantChance() const
{ {
const CreatureStats& stats = mEnchanter.getClass().getCreatureStats(mEnchanter); const CreatureStats& stats = mEnchanter.getClass().getCreatureStats(mEnchanter);
float chance1 = (mEnchanter.getClass().getSkill(mEnchanter, ESM::Skill::Enchant) +
(0.25f * stats.getAttribute (ESM::Attribute::Intelligence).getModified())
+ (0.125f * stats.getAttribute (ESM::Attribute::Luck).getModified()));
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>(); const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
const float a = static_cast<float>(mEnchanter.getClass().getSkill(mEnchanter, ESM::Skill::Enchant));
const float b = static_cast<float>(stats.getAttribute (ESM::Attribute::Intelligence).getModified());
const float c = static_cast<float>(stats.getAttribute (ESM::Attribute::Luck).getModified());
const float fEnchantmentChanceMult = gmst.find("fEnchantmentChanceMult")->mValue.getFloat();
const float fEnchantmentConstantChanceMult = gmst.find("fEnchantmentConstantChanceMult")->mValue.getFloat();
float chance2 = 7.5f / (gmst.find("fEnchantmentChanceMult")->mValue.getFloat() * ((mCastStyle == ESM::Enchantment::ConstantEffect) ? float x = (a - getEnchantPoints()*fEnchantmentChanceMult + 0.2f * b + 0.1f * c) * stats.getFatigueTerm();
gmst.find("fEnchantmentConstantChanceMult")->mValue.getFloat() : 1.0f )) if (mCastStyle == ESM::Enchantment::ConstantEffect)
* getEnchantPoints(); x *= fEnchantmentConstantChanceMult;
return (chance1-chance2); return static_cast<int>(x);
} }
void Enchanting::payForEnchantment() const void Enchanting::payForEnchantment() const

@ -37,13 +37,13 @@ namespace MWMechanics
bool create(); //Return true if created, false if failed. bool create(); //Return true if created, false if failed.
void nextCastStyle(); //Set enchant type to next possible type (for mOldItemPtr object) void nextCastStyle(); //Set enchant type to next possible type (for mOldItemPtr object)
int getCastStyle() const; int getCastStyle() const;
int getEnchantPoints() const; float getEnchantPoints(bool precise = true) const;
int getBaseCastCost() const; // To be saved in the enchantment's record int getBaseCastCost() const; // To be saved in the enchantment's record
int getEffectiveCastCost() const; // Effective cost taking player Enchant skill into account, used for preview purposes in the UI int getEffectiveCastCost() const; // Effective cost taking player Enchant skill into account, used for preview purposes in the UI
int getEnchantPrice() const; int getEnchantPrice() const;
int getMaxEnchantValue() const; int getMaxEnchantValue() const;
int getGemCharge() const; int getGemCharge() const;
float getEnchantChance() const; int getEnchantChance() const;
bool soulEmpty() const; //Return true if empty bool soulEmpty() const; //Return true if empty
bool itemEmpty() const; //Return true if empty bool itemEmpty() const; //Return true if empty
void payForEnchantment() const; void payForEnchantment() const;

@ -689,8 +689,8 @@ namespace MWMechanics
float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f); float f = std::min(0.2f * sellerStats.getAttribute(ESM::Attribute::Personality).getModified(), 10.f);
float pcTerm = (clampedDisposition - 50 + a + b + c) * playerStats.getFatigueTerm(); float pcTerm = (clampedDisposition - 50 + a + b + c) * playerStats.getFatigueTerm();
float npcTerm = (d + e + f) * sellerStats.getFatigueTerm(); float npcTerm = (d + e + f) * sellerStats.getFatigueTerm();
float buyTerm = 0.01f * std::max(75.f, (100 - 0.5f * (pcTerm - npcTerm))); float buyTerm = 0.01f * (100 - 0.5f * (pcTerm - npcTerm));
float sellTerm = 0.01f * std::min(75.f, (50 - 0.5f * (npcTerm - pcTerm))); float sellTerm = 0.01f * (50 - 0.5f * (npcTerm - pcTerm));
int offerPrice = int(basePrice * (buying ? buyTerm : sellTerm)); int offerPrice = int(basePrice * (buying ? buyTerm : sellTerm));
return std::max(1, offerPrice); return std::max(1, offerPrice);
} }
@ -1011,6 +1011,9 @@ namespace MWMechanics
return true; return true;
} }
if (!target.getClass().canBeActivated(target))
return true;
// TODO: implement a better check to check if target is owned bed // TODO: implement a better check to check if target is owned bed
if (target.getClass().isActivator() && target.getClass().getScript(target).compare(0, 3, "Bed") != 0) if (target.getClass().isActivator() && target.getClass().getScript(target).compare(0, 3, "Bed") != 0)
return true; return true;
@ -1053,7 +1056,7 @@ namespace MWMechanics
} }
if (!cellref.getOwner().empty()) if (!cellref.getOwner().empty())
victim = MWBase::Environment::get().getWorld()->searchPtr(cellref.getOwner(), true); victim = MWBase::Environment::get().getWorld()->searchPtr(cellref.getOwner(), true, false);
return (!isOwned && !isFactionOwned); return (!isOwned && !isFactionOwned);
} }

@ -66,6 +66,16 @@ const std::map<std::string, int>& MWMechanics::NpcStats::getFactionRanks() const
return mFactionRank; return mFactionRank;
} }
int MWMechanics::NpcStats::getFactionRank(const std::string &faction) const
{
const std::string lower = Misc::StringUtils::lowerCase(faction);
std::map<std::string, int>::const_iterator it = mFactionRank.find(lower);
if (it != mFactionRank.end())
return it->second;
return -1;
}
void MWMechanics::NpcStats::raiseRank(const std::string &faction) void MWMechanics::NpcStats::raiseRank(const std::string &faction)
{ {
const std::string lower = Misc::StringUtils::lowerCase(faction); const std::string lower = Misc::StringUtils::lowerCase(faction);
@ -85,7 +95,12 @@ void MWMechanics::NpcStats::lowerRank(const std::string &faction)
std::map<std::string, int>::iterator it = mFactionRank.find(lower); std::map<std::string, int>::iterator it = mFactionRank.find(lower);
if (it != mFactionRank.end()) if (it != mFactionRank.end())
{ {
it->second = std::max(0, it->second-1); it->second = it->second-1;
if (it->second < 0)
{
mFactionRank.erase(it);
mExpelled.erase(lower);
}
} }
} }
@ -250,8 +265,7 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
MWBase::Environment::get().getWindowManager()->playSound("skillraise"); MWBase::Environment::get().getWindowManager()->playSound("skillraise");
std::string message = MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""); std::string message = MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", "");
Misc::StringUtils::replace(message, "%s", ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}").c_str(), 2); message = Misc::StringUtils::format(message, ("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}"), base);
Misc::StringUtils::replace(message, "%d", std::to_string(base).c_str(), 2);
if (readBook) if (readBook)
message = "#{sBookSkillMessage}\n" + message; message = "#{sBookSkillMessage}\n" + message;

@ -49,7 +49,7 @@ namespace MWMechanics
// ----- used by the player only, maybe should be moved at some point ------- // ----- used by the player only, maybe should be moved at some point -------
int mBounty; int mBounty;
int mWerewolfKills; int mWerewolfKills;
/// Used for the player only; NPCs have maximum one faction defined in their NPC record /// Used only for the player and for NPC's with ranks, modified by scripts; other NPCs have maximum one faction defined in their NPC record
std::map<std::string, int> mFactionRank; std::map<std::string, int> mFactionRank;
std::set<std::string> mExpelled; std::set<std::string> mExpelled;
std::map<std::string, int> mFactionReputation; std::map<std::string, int> mFactionReputation;
@ -81,7 +81,9 @@ namespace MWMechanics
SkillValue& getSkill (int index); SkillValue& getSkill (int index);
void setSkill(int index, const SkillValue& value); void setSkill(int index, const SkillValue& value);
int getFactionRank(const std::string &faction) const;
const std::map<std::string, int>& getFactionRanks() const; const std::map<std::string, int>& getFactionRanks() const;
/// Increase the rank in this faction by 1, if such a rank exists. /// Increase the rank in this faction by 1, if such a rank exists.
void raiseRank(const std::string& faction); void raiseRank(const std::string& faction);
/// Lower the rank in this faction by 1, if such a rank exists. /// Lower the rank in this faction by 1, if such a rank exists.

@ -113,7 +113,7 @@ void Repair::repair(const MWWorld::Ptr &itemToRepair)
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>() std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("sNotifyMessage51")->mValue.getString(); .find("sNotifyMessage51")->mValue.getString();
Misc::StringUtils::replace(message, "%s", mTool.getClass().getName(mTool).c_str(), 2); message = Misc::StringUtils::format(message, mTool.getClass().getName(mTool));
MWBase::Environment::get().getWindowManager()->messageBox(message); MWBase::Environment::get().getWindowManager()->messageBox(message);

@ -1142,7 +1142,7 @@ namespace MWMechanics
{ {
// "X has no effect on you" // "X has no effect on you"
std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage50")->mValue.getString(); std::string message = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage50")->mValue.getString();
Misc::StringUtils::replace(message, "%s", ingredient->mName.c_str(), 2); message = Misc::StringUtils::format(message, ingredient->mName);
MWBase::Environment::get().getWindowManager()->messageBox(message); MWBase::Environment::get().getWindowManager()->messageBox(message);
return false; return false;
} }

@ -185,14 +185,16 @@ namespace MWMechanics
bool Spells::isSpellActive(const std::string &id) const bool Spells::isSpellActive(const std::string &id) const
{ {
TContainer::const_iterator found = mSpells.find(getSpell(id)); if (id.empty())
if (found != mSpells.end()) return false;
{
const ESM::Spell *spell = found->first;
return (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight || const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(id);
spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse); if (spell && hasSpell(spell))
{
auto type = spell->mData.mType;
return (type==ESM::Spell::ST_Ability || type==ESM::Spell::ST_Blight || type==ESM::Spell::ST_Disease || type==ESM::Spell::ST_Curse);
} }
return false; return false;
} }

@ -108,12 +108,6 @@ namespace MWMechanics
} }
} }
if (enemy.getClass().isNpc())
{
static const float fCombatArmorMinMult = gmst.find("fCombatArmorMinMult")->mValue.getFloat();
rating *= std::max(fCombatArmorMinMult, rating / (rating + enemy.getClass().getArmorRating(enemy)));
}
int value = 50.f; int value = 50.f;
if (actor.getClass().isNpc()) if (actor.getClass().isNpc())
{ {

@ -188,7 +188,7 @@ namespace mwmp
{ {
editState = state; editState = state;
mCommandLine->setVisible(editState); mCommandLine->setVisible(editState);
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(editState ? mCommandLine : nullptr); MyGUI::InputManager::getInstance().setKeyFocusWidget(editState ? mCommandLine : nullptr);
} }
void GUIChat::pressedSay() void GUIChat::pressedSay()

@ -9,6 +9,7 @@
#include <MyGUI_EditBox.h> #include <MyGUI_EditBox.h>
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_InputManager.h>
namespace mwmp namespace mwmp
{ {
@ -26,7 +27,7 @@ namespace mwmp
okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked); okButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TextInputDialog::onOkClicked);
// Make sure the edit box has focus // Make sure the edit box has focus
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
void TextInputDialog::setNextButtonShow(bool shown) void TextInputDialog::setNextButtonShow(bool shown)
@ -59,7 +60,7 @@ namespace mwmp
{ {
WindowModal::onOpen(); WindowModal::onOpen();
// Make sure the edit box has focus // Make sure the edit box has focus
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
bool TextInputDialog::exit() bool TextInputDialog::exit()
@ -74,7 +75,7 @@ namespace mwmp
if (mTextEdit->getCaption() == "") if (mTextEdit->getCaption() == "")
{ {
//MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}"); //MWBase::Environment::get().getWindowManager()->messageBox ("#{sNotifyMessage37}");
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mTextEdit); MyGUI::InputManager::getInstance().setKeyFocusWidget(mTextEdit);
} }
else else
eventDone(this); eventDone(this);
@ -94,4 +95,4 @@ namespace mwmp
{ {
mTextEdit->setCaption(text); mTextEdit->setCaption(text);
} }
} }

@ -27,7 +27,7 @@ namespace mwmp
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Console && !player->consoleAllowed) if (MWBase::Environment::get().getWindowManager()->isConsoleMode() && !player->consoleAllowed)
MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getWindowManager()->popGuiMode();
else if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Rest && else if (MWBase::Environment::get().getWindowManager()->getMode() == MWGui::GM_Rest &&
(!player->bedRestAllowed || !player->wildernessRestAllowed || !player->waitAllowed)) (!player->bedRestAllowed || !player->wildernessRestAllowed || !player->waitAllowed))

@ -1,4 +1,4 @@
#include "physicssystem.hpp" #include "physicssystem.hpp"
#include <osg/Group> #include <osg/Group>

@ -131,6 +131,25 @@ namespace
} }
}; };
class HarvestVisitor : public osg::NodeVisitor
{
public:
HarvestVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
{
}
virtual void apply(osg::Switch& node)
{
if (node.getName() == Constants::HerbalismLabel)
{
node.setSingleChildOn(1);
}
traverse(node);
}
};
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname) NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname)
{ {
NifOsg::TextKeyMap::const_iterator iter(keys.begin()); NifOsg::TextKeyMap::const_iterator iter(keys.begin());
@ -460,6 +479,46 @@ namespace
namespace MWRender namespace MWRender
{ {
class TransparencyUpdater : public SceneUtil::StateSetUpdater
{
public:
TransparencyUpdater(const float alpha)
: mAlpha(alpha)
{
}
void setAlpha(const float alpha)
{
mAlpha = alpha;
}
protected:
virtual void setDefaults(osg::StateSet* stateset)
{
osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
osg::BlendFunc* blendfunc (new osg::BlendFunc);
stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
// FIXME: overriding diffuse/ambient/emissive colors
material = new osg::Material;
material->setColorMode(osg::Material::OFF);
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,mAlpha));
material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* /*nv*/)
{
osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
material->setAlpha(osg::Material::FRONT_AND_BACK, mAlpha);
}
private:
float mAlpha;
};
class GlowUpdater : public SceneUtil::StateSetUpdater class GlowUpdater : public SceneUtil::StateSetUpdater
{ {
public: public:
@ -1772,32 +1831,21 @@ namespace MWRender
return; return;
mAlpha = alpha; mAlpha = alpha;
// TODO: we use it to fade actors away too, but it would be nice to have a dithering shader instead.
if (alpha != 1.f) if (alpha != 1.f)
{ {
// If we have an existing material for alpha transparency, just override alpha level if (mTransparencyUpdater == nullptr)
osg::StateSet* stateset = mObjectRoot->getOrCreateStateSet();
osg::Material* material = static_cast<osg::Material*>(stateset->getAttribute(osg::StateAttribute::MATERIAL));
if (material)
{ {
material->setAlpha(osg::Material::FRONT_AND_BACK, alpha); mTransparencyUpdater = new TransparencyUpdater(alpha);
mObjectRoot->addUpdateCallback(mTransparencyUpdater);
} }
else else
{ mTransparencyUpdater->setAlpha(alpha);
osg::BlendFunc* blendfunc (new osg::BlendFunc);
stateset->setAttributeAndModes(blendfunc, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
// FIXME: overriding diffuse/ambient/emissive colors
material = new osg::Material;
material->setColorMode(osg::Material::OFF);
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,alpha));
material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1,1,1,1));
stateset->setAttributeAndModes(material, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
stateset->addUniform(new osg::Uniform("colorMode", 0), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
mObjectRoot->setStateSet(stateset);
}
} }
else else
{ {
mObjectRoot->removeUpdateCallback(mTransparencyUpdater);
mTransparencyUpdater = nullptr;
mObjectRoot->setStateSet(nullptr); mObjectRoot->setStateSet(nullptr);
} }
@ -1970,6 +2018,28 @@ namespace MWRender
AddSwitchCallbacksVisitor visitor; AddSwitchCallbacksVisitor visitor;
mObjectRoot->accept(visitor); mObjectRoot->accept(visitor);
} }
if (ptr.getRefData().getCustomData() != nullptr && canBeHarvested())
{
const MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
if (!store.hasVisibleItems())
{
HarvestVisitor visitor;
mObjectRoot->accept(visitor);
}
}
}
bool ObjectAnimation::canBeHarvested() const
{
if (mPtr.getTypeName() != typeid(ESM::Container).name())
return false;
const MWWorld::LiveCellRef<ESM::Container>* ref = mPtr.get<ESM::Container>();
if (!(ref->mBase->mFlags & ESM::Container::Organic))
return false;
return SceneUtil::hasUserDescription(mObjectRoot, Constants::HerbalismLabel);
} }
Animation::AnimState::~AnimState() Animation::AnimState::~AnimState()

@ -35,6 +35,7 @@ namespace MWRender
class ResetAccumRootCallback; class ResetAccumRootCallback;
class RotateController; class RotateController;
class GlowUpdater; class GlowUpdater;
class TransparencyUpdater;
class EffectAnimationTime : public SceneUtil::ControllerSource class EffectAnimationTime : public SceneUtil::ControllerSource
{ {
@ -266,6 +267,7 @@ protected:
osg::ref_ptr<SceneUtil::LightSource> mGlowLight; osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
osg::ref_ptr<GlowUpdater> mGlowUpdater; osg::ref_ptr<GlowUpdater> mGlowUpdater;
osg::ref_ptr<TransparencyUpdater> mTransparencyUpdater;
float mAlpha; float mAlpha;
@ -475,6 +477,7 @@ public:
virtual float getHeadPitch() const; virtual float getHeadPitch() const;
virtual float getHeadYaw() const; virtual float getHeadYaw() const;
virtual void setAccurateAiming(bool enabled) {} virtual void setAccurateAiming(bool enabled) {}
virtual bool canBeHarvested() const { return false; }
private: private:
Animation(const Animation&); Animation(const Animation&);
@ -484,6 +487,8 @@ private:
class ObjectAnimation : public Animation { class ObjectAnimation : public Animation {
public: public:
ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem, bool animated, bool allowLight); ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem, bool animated, bool allowLight);
bool canBeHarvested() const;
}; };
class UpdateVfxCallback : public osg::NodeCallback class UpdateVfxCallback : public osg::NodeCallback

@ -256,36 +256,30 @@ bool needUpdate(std::set<std::pair<int, int> >& renderedGrid, std::set<std::pair
return false; return false;
} }
void LocalMap::requestMap(std::set<const MWWorld::CellStore*> cells) void LocalMap::requestMap(const MWWorld::CellStore* cell)
{ {
std::set<std::pair<int, int> > grid; if (cell->isExterior())
for (const MWWorld::CellStore* cell : cells)
{ {
if (cell->isExterior()) int cellX = cell->getCell()->getGridX();
grid.insert(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())); int cellY = cell->getCell()->getGridY();
}
for (const MWWorld::CellStore* cell : cells) MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
{ if (!needUpdate(segment.mGrid, mCurrentGrid, cellX, cellY))
if (cell->isExterior()) return;
else
{ {
int cellX = cell->getCell()->getGridX(); segment.mGrid = mCurrentGrid;
int cellY = cell->getCell()->getGridY(); requestExteriorMap(cell);
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
if (!needUpdate(segment.mGrid, grid, cellX, cellY))
{
continue;
}
else
{
segment.mGrid = grid;
requestExteriorMap(cell);
}
} }
else
requestInteriorMap(cell);
} }
else
requestInteriorMap(cell);
}
void LocalMap::addCell(MWWorld::CellStore *cell)
{
if (cell->isExterior())
mCurrentGrid.emplace(cell->getCell()->getGridX(), cell->getCell()->getGridY());
} }
void LocalMap::removeCell(MWWorld::CellStore *cell) void LocalMap::removeCell(MWWorld::CellStore *cell)
@ -293,7 +287,11 @@ void LocalMap::removeCell(MWWorld::CellStore *cell)
saveFogOfWar(cell); saveFogOfWar(cell);
if (cell->isExterior()) if (cell->isExterior())
mSegments.erase(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY())); {
std::pair<int, int> coords = std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY());
mSegments.erase(coords);
mCurrentGrid.erase(coords);
}
else else
mSegments.clear(); mSegments.clear();
} }

@ -45,13 +45,12 @@ namespace MWRender
void clear(); void clear();
/** /**
* Request a map render for the given cells. Render textures will be immediately created and can be retrieved with the getMapTexture function. * Request a map render for the given cell. Render textures will be immediately created and can be retrieved with the getMapTexture function.
*/ */
void requestMap (std::set<const MWWorld::CellStore*> cells); void requestMap (const MWWorld::CellStore* cell);
void addCell(MWWorld::CellStore* cell);
/**
* Remove map and fog textures for the given cell.
*/
void removeCell (MWWorld::CellStore* cell); void removeCell (MWWorld::CellStore* cell);
osg::ref_ptr<osg::Texture2D> getMapTexture (int x, int y); osg::ref_ptr<osg::Texture2D> getMapTexture (int x, int y);
@ -110,6 +109,9 @@ namespace MWRender
CameraVector mCamerasPendingRemoval; CameraVector mCamerasPendingRemoval;
typedef std::set<std::pair<int, int> > Grid;
Grid mCurrentGrid;
struct MapSegment struct MapSegment
{ {
MapSegment(); MapSegment();
@ -124,7 +126,7 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> mFogOfWarTexture; osg::ref_ptr<osg::Texture2D> mFogOfWarTexture;
osg::ref_ptr<osg::Image> mFogOfWarImage; osg::ref_ptr<osg::Image> mFogOfWarImage;
std::set<std::pair<int, int> > mGrid; // the grid that was active at the time of rendering this segment Grid mGrid; // the grid that was active at the time of rendering this segment
bool mHasFogState; bool mHasFogState;
}; };

@ -268,6 +268,7 @@ namespace MWRender
{ {
mViewer->setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation); mViewer->setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation);
mViewer->getIncrementalCompileOperation()->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells")); mViewer->getIncrementalCompileOperation()->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells"));
mViewer->getIncrementalCompileOperation()->setMaximumNumOfObjectsToCompilePerFrame(100);
} }
mResourceSystem->getSceneManager()->setIncrementalCompileOperation(mViewer->getIncrementalCompileOperation()); mResourceSystem->getSceneManager()->setIncrementalCompileOperation(mViewer->getIncrementalCompileOperation());

@ -68,8 +68,8 @@ namespace
osg::ref_ptr<osg::Material> mat (new osg::Material); osg::ref_ptr<osg::Material> mat (new osg::Material);
mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f)); mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f));
mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f)); mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f));
mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f)); mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f));
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f)); mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
mat->setColorMode(osg::Material::DIFFUSE); mat->setColorMode(osg::Material::DIFFUSE);
stateset->setAttributeAndModes(mat, osg::StateAttribute::ON); stateset->setAttributeAndModes(mat, osg::StateAttribute::ON);
@ -101,12 +101,15 @@ RippleSimulation::RippleSimulation(osg::Group *parent, Resource::ResourceSystem*
updater->addParticleSystem(mParticleSystem); updater->addParticleSystem(mParticleSystem);
mParticleNode = new osg::PositionAttitudeTransform; mParticleNode = new osg::PositionAttitudeTransform;
mParticleNode->setName("Ripple Root");
mParticleNode->addChild(updater); mParticleNode->addChild(updater);
mParticleNode->addChild(mParticleSystem); mParticleNode->addChild(mParticleSystem);
mParticleNode->setNodeMask(Mask_Effect); mParticleNode->setNodeMask(Mask_Water);
createWaterRippleStateSet(resourceSystem, mParticleNode); createWaterRippleStateSet(resourceSystem, mParticleNode);
resourceSystem->getSceneManager()->recreateShaders(mParticleNode);
mParent->addChild(mParticleNode); mParent->addChild(mParticleNode);
} }

@ -273,6 +273,7 @@ public:
attach(osg::Camera::COLOR_BUFFER, mRefractionTexture); attach(osg::Camera::COLOR_BUFFER, mRefractionTexture);
mRefractionDepthTexture = new osg::Texture2D; mRefractionDepthTexture = new osg::Texture2D;
mRefractionDepthTexture->setTextureSize(rttSize, rttSize);
mRefractionDepthTexture->setSourceFormat(GL_DEPTH_COMPONENT); mRefractionDepthTexture->setSourceFormat(GL_DEPTH_COMPONENT);
mRefractionDepthTexture->setInternalFormat(GL_DEPTH_COMPONENT24); mRefractionDepthTexture->setInternalFormat(GL_DEPTH_COMPONENT24);
mRefractionDepthTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); mRefractionDepthTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
@ -335,14 +336,7 @@ public:
setName("ReflectionCamera"); setName("ReflectionCamera");
setCullCallback(new InheritViewPointCallback); setCullCallback(new InheritViewPointCallback);
int reflectionDetail = Settings::Manager::getInt("reflection detail", "Water"); setInterior(isInterior);
reflectionDetail = std::min(4, std::max(isInterior ? 2 : 0, reflectionDetail));
unsigned int extraMask = 0;
if(reflectionDetail >= 1) extraMask |= Mask_Terrain;
if(reflectionDetail >= 2) extraMask |= Mask_Static;
if(reflectionDetail >= 3) extraMask |= Mask_Effect|Mask_ParticleSystem|Mask_Object;
if(reflectionDetail >= 4) extraMask |= Mask_Player|Mask_Actor;
setCullMask(Mask_Scene|Mask_Sky|Mask_Lighting|extraMask);
setNodeMask(Mask_RenderToTexture); setNodeMask(Mask_RenderToTexture);
unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water"); unsigned int rttSize = Settings::Manager::getInt("rtt size", "Water");
@ -353,6 +347,7 @@ public:
setUpdateCallback(new NoTraverseCallback); setUpdateCallback(new NoTraverseCallback);
mReflectionTexture = new osg::Texture2D; mReflectionTexture = new osg::Texture2D;
mReflectionTexture->setTextureSize(rttSize, rttSize);
mReflectionTexture->setInternalFormat(GL_RGB); mReflectionTexture->setInternalFormat(GL_RGB);
mReflectionTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); mReflectionTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
mReflectionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); mReflectionTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
@ -372,6 +367,18 @@ public:
SceneUtil::ShadowManager::disableShadowsForStateSet(getOrCreateStateSet()); SceneUtil::ShadowManager::disableShadowsForStateSet(getOrCreateStateSet());
} }
void setInterior(bool isInterior)
{
int reflectionDetail = Settings::Manager::getInt("reflection detail", "Water");
reflectionDetail = std::min(4, std::max(isInterior ? 2 : 0, reflectionDetail));
unsigned int extraMask = 0;
if(reflectionDetail >= 1) extraMask |= Mask_Terrain;
if(reflectionDetail >= 2) extraMask |= Mask_Static;
if(reflectionDetail >= 3) extraMask |= Mask_Effect|Mask_ParticleSystem|Mask_Object;
if(reflectionDetail >= 4) extraMask |= Mask_Player|Mask_Actor;
setCullMask(Mask_Scene|Mask_Sky|Mask_Lighting|extraMask);
}
void setWaterLevel(float waterLevel) void setWaterLevel(float waterLevel)
{ {
setViewMatrix(osg::Matrix::scale(1,1,-1) * osg::Matrix::translate(0,0,2 * waterLevel)); setViewMatrix(osg::Matrix::scale(1,1,-1) * osg::Matrix::translate(0,0,2 * waterLevel));
@ -430,15 +437,12 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
, mTop(0) , mTop(0)
, mInterior(false) , mInterior(false)
{ {
mSimulation.reset(new RippleSimulation(parent, resourceSystem)); mSimulation.reset(new RippleSimulation(mSceneRoot, resourceSystem));
mWaterGeom = SceneUtil::createWaterGeometry(Constants::CellSizeInUnits*150, 40, 900); mWaterGeom = SceneUtil::createWaterGeometry(Constants::CellSizeInUnits*150, 40, 900);
mWaterGeom->setDrawCallback(new DepthClampCallback); mWaterGeom->setDrawCallback(new DepthClampCallback);
mWaterGeom->setNodeMask(Mask_Water); mWaterGeom->setNodeMask(Mask_Water);
if (ico)
ico->add(mWaterGeom);
mWaterNode = new osg::PositionAttitudeTransform; mWaterNode = new osg::PositionAttitudeTransform;
mWaterNode->setName("Water Root"); mWaterNode->setName("Water Root");
mWaterNode->addChild(mWaterGeom); mWaterNode->addChild(mWaterGeom);
@ -457,6 +461,9 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0); mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0);
updateWaterMaterial(); updateWaterMaterial();
if (ico)
ico->add(mWaterNode);
} }
osg::Uniform *Water::getRainIntensityUniform() osg::Uniform *Water::getRainIntensityUniform()
@ -666,8 +673,8 @@ void Water::changeCell(const MWWorld::CellStore* store)
mWaterNode->setPosition(osg::Vec3f(0,0,mTop)); mWaterNode->setPosition(osg::Vec3f(0,0,mTop));
mInterior = true; mInterior = true;
} }
if(mInterior != wasInterior) if(mInterior != wasInterior && mReflection)
updateWaterMaterial(); mReflection->setInterior(mInterior);
// create a new StateSet to prevent threading issues // create a new StateSet to prevent threading issues
osg::ref_ptr<osg::StateSet> nodeStateSet (new osg::StateSet); osg::ref_ptr<osg::StateSet> nodeStateSet (new osg::StateSet);

@ -119,13 +119,13 @@ namespace MWScript
if (count == 1) if (count == 1)
{ {
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}"); msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage60}");
msgBox = ::Misc::StringUtils::format(msgBox, itemName);
} }
else else
{ {
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}"); msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage61}");
::Misc::StringUtils::replace(msgBox, "%d", std::to_string(count).c_str(), 2); msgBox = ::Misc::StringUtils::format(msgBox, count, itemName);
} }
::Misc::StringUtils::replace(msgBox, "%s", itemName.c_str(), 2);
MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only); MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only);
} }
/* /*
@ -254,13 +254,13 @@ namespace MWScript
if (numRemoved > 1) if (numRemoved > 1)
{ {
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}"); msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage63}");
::Misc::StringUtils::replace(msgBox, "%d", std::to_string(numRemoved).c_str(), 2); msgBox = ::Misc::StringUtils::format(msgBox, numRemoved, itemName);
} }
else else
{ {
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}"); msgBox = MyGUI::LanguageManager::getInstance().replaceTags("#{sNotifyMessage62}");
msgBox = ::Misc::StringUtils::format(msgBox, itemName);
} }
::Misc::StringUtils::replace(msgBox, "%s", itemName.c_str(), 2);
MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only); MWBase::Environment::get().getWindowManager()->messageBox(msgBox, MWGui::ShowInDialogueMode_Only);
} }
/* /*
@ -469,11 +469,27 @@ namespace MWScript
const MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr); const MWWorld::InventoryStore& invStore = ptr.getClass().getInventoryStore (ptr);
MWWorld::ConstContainerStoreIterator it = invStore.getSlot (MWWorld::InventoryStore::Slot_CarriedRight); MWWorld::ConstContainerStoreIterator it = invStore.getSlot (MWWorld::InventoryStore::Slot_CarriedRight);
if (it == invStore.end() || it->getTypeName () != typeid(ESM::Weapon).name()) if (it == invStore.end())
{ {
runtime.push(-1); runtime.push(-1);
return; return;
} }
else if (it->getTypeName() != typeid(ESM::Weapon).name())
{
if (it->getTypeName() == typeid(ESM::Lockpick).name())
{
runtime.push(-2);
}
else if (it->getTypeName() == typeid(ESM::Probe).name())
{
runtime.push(-3);
}
else
{
runtime.push(-1);
}
return;
}
runtime.push(it->get<ESM::Weapon>()->mBase->mData.mType); runtime.push(it->get<ESM::Weapon>()->mBase->mData.mType);
} }

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

Loading…
Cancel
Save