1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-30 21:15:33 +00:00

Add OpenMW commits up to 14 Sep 2018

# Conflicts:
#	apps/openmw/mwgui/container.cpp
#	apps/openmw/mwworld/worldimp.hpp
This commit is contained in:
David Cernat 2019-08-20 12:14:57 +03:00
commit 056591b957
84 changed files with 610 additions and 448 deletions

View file

@ -45,6 +45,7 @@
Bug #4230: AiTravel package issues break some Tribunal quests Bug #4230: AiTravel package issues break some Tribunal quests
Bug #4231: Infected rats from the "Crimson Plague" quest rendered unconscious by change in Drain Fatigue functionality Bug #4231: Infected rats from the "Crimson Plague" quest rendered unconscious by change in Drain Fatigue functionality
Bug #4251: Stationary NPCs do not return to their position after combat Bug #4251: Stationary NPCs do not return to their position after combat
Bug #4260: Keyboard navigation makes persuasion exploitable
Bug #4271: Scamp flickers when attacking Bug #4271: Scamp flickers when attacking
Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+ Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+
Bug #4286: Scripted animations can be interrupted Bug #4286: Scripted animations can be interrupted
@ -54,6 +55,7 @@
Bug #4307: World cleanup should remove dead bodies only if death animation is finished Bug #4307: World cleanup should remove dead bodies only if death animation is finished
Bug #4311: OpenMW does not handle RootCollisionNode correctly Bug #4311: OpenMW does not handle RootCollisionNode correctly
Bug #4327: Missing animations during spell/weapon stance switching Bug #4327: Missing animations during spell/weapon stance switching
Bug #4333: Keyboard navigation in containers is not intuitive
Bug #4358: Running animation is interrupted when magic mode is toggled Bug #4358: Running animation is interrupted when magic mode is toggled
Bug #4368: Settings window ok button doesn't have key focus by default Bug #4368: Settings window ok button doesn't have key focus by default
Bug #4378: On-self absorb spells restore stats Bug #4378: On-self absorb spells restore stats
@ -92,6 +94,7 @@
Bug #4519: Knockdown does not discard movement in the 1st-person mode Bug #4519: Knockdown does not discard movement in the 1st-person mode
Bug #4531: Movement does not reset idle animations Bug #4531: Movement does not reset idle animations
Bug #4539: Paper Doll is affected by GUI scaling Bug #4539: Paper Doll is affected by GUI scaling
Bug #4543: Picking cursed items through inventory (menumode) makes it disappear
Bug #4545: Creatures flee from werewolves Bug #4545: Creatures flee from werewolves
Bug #4551: Replace 0 sound range with default range separately Bug #4551: Replace 0 sound range with default range separately
Bug #4553: Forcegreeting on non-actor opens a dialogue window which cannot be closed Bug #4553: Forcegreeting on non-actor opens a dialogue window which cannot be closed
@ -109,10 +112,15 @@
Bug #4604: Picking up gold from the ground only makes 1 grabbed Bug #4604: Picking up gold from the ground only makes 1 grabbed
Bug #4607: Scaling for animated collision shapes is applied twice Bug #4607: Scaling for animated collision shapes is applied twice
Bug #4608: Falling damage is applied twice Bug #4608: Falling damage is applied twice
Bug #4611: Instant magic effects have 0 duration in custom spell cost calculations unlike vanilla
Bug #4614: Crash due to division by zero when FlipController has no textures
Bug #4615: Flicker effects for light sources are handled incorrectly Bug #4615: Flicker effects for light sources are handled incorrectly
Bug #4617: First person sneaking offset is not applied while the character is in air Bug #4617: First person sneaking offset is not applied while the character is in air
Bug #4618: Sneaking is possible while the character is flying Bug #4618: Sneaking is possible while the character is flying
Bug #4622: Recharging enchanted items with Soul Gems does not award experience if it fails Bug #4622: Recharging enchanted items with Soul Gems does not award experience if it fails
Bug #4628: NPC record reputation, disposition and faction rank should have unsigned char type
Bug #4633: Sneaking stance affects speed even if the actor is not able to crouch
Feature #912: Editor: Add missing icons to UniversalId tables
Feature #1645: Casting effects from objects Feature #1645: Casting effects from objects
Feature #2606: Editor: Implemented (optional) case sensitive global search Feature #2606: Editor: Implemented (optional) case sensitive global search
Feature #3083: Play animation when NPC is casting spell via script Feature #3083: Play animation when NPC is casting spell via script
@ -136,6 +144,11 @@
Feature #4550: Weapon priority: make ranged weapon bonus more sensible Feature #4550: Weapon priority: make ranged weapon bonus more sensible
Feature #4579: Add option for applying Strength into hand to hand damage Feature #4579: Add option for applying Strength into hand to hand damage
Feature #4581: Use proper logging system Feature #4581: Use proper logging system
Feature #4624: Spell priority: don't cast hit chance-affecting spells if the enemy is not in respective stance at the moment
Feature #4625: Weapon priority: use weighted mean for melee damage rating
Feature #4626: Weapon priority: account for weapon speed
Feature #4632: AI priority: utilize vanilla AI GMSTs for priority rating
Feature #4636: Use sTo GMST in spellmaking menu
Task #2490: Don't open command prompt window on Release-mode builds automatically Task #2490: Don't open command prompt window on Release-mode builds automatically
Task #4545: Enable is_pod string test Task #4545: Enable is_pod string test
Task #4605: Optimize skinning Task #4605: Optimize skinning

View file

@ -699,6 +699,7 @@ if (WIN32)
# caused by boost # caused by boost
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off) 4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
4643 # Forward declaring 'X' in namespace std is not permitted by the C++ Standard. (in *_std_fwd.h files)
# caused by MyGUI # caused by MyGUI
4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception' 4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception'

View file

@ -526,7 +526,10 @@ public:
class ConvertGAME : public Converter class ConvertGAME : public Converter
{ {
public: public:
ConvertGAME() : mHasGame(false) {} ConvertGAME()
: mHasGame(false)
{
}
virtual void read(ESM::ESMReader &esm) virtual void read(ESM::ESMReader &esm)
{ {

View file

@ -14,13 +14,13 @@ namespace ESSImport
{ {
struct GMDT struct GMDT
{ {
char mCellName[64]; char mCellName[64] {};
int mFogColour; int mFogColour {0};
float mFogDensity; float mFogDensity {0.f};
int mCurrentWeather, mNextWeather; int mCurrentWeather {0}, mNextWeather {0};
int mWeatherTransition; // 0-100 transition between weathers, top 3 bytes may be garbage int mWeatherTransition {0}; // 0-100 transition between weathers, top 3 bytes may be garbage
float mTimeOfNextTransition; // weather changes when gamehour == timeOfNextTransition float mTimeOfNextTransition {0.f}; // weather changes when gamehour == timeOfNextTransition
int mMasserPhase, mSecundaPhase; // top 3 bytes may be garbage int mMasserPhase {0}, mSecundaPhase {0}; // top 3 bytes may be garbage
}; };
GMDT mGMDT; GMDT mGMDT;

View file

@ -305,6 +305,7 @@ void CSMPrefs::State::declare()
declareShortcut ("document-assets-videos", "Open Video Asset List", QKeySequence()); declareShortcut ("document-assets-videos", "Open Video Asset List", QKeySequence());
declareShortcut ("document-debug-run", "Run Debug", QKeySequence()); declareShortcut ("document-debug-run", "Run Debug", QKeySequence());
declareShortcut ("document-debug-shutdown", "Stop Debug", QKeySequence()); declareShortcut ("document-debug-shutdown", "Stop Debug", QKeySequence());
declareShortcut ("document-debug-profiles", "Debug Profiles", QKeySequence());
declareShortcut ("document-debug-runlog", "Open Run Log", QKeySequence()); declareShortcut ("document-debug-runlog", "Open Run Log", QKeySequence());
declareSubcategory ("Table"); declareSubcategory ("Table");

View file

@ -109,7 +109,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
pathgrid.mPoints[i].mY == pathgrid.mPoints[j].mY && pathgrid.mPoints[i].mY == pathgrid.mPoints[j].mY &&
pathgrid.mPoints[i].mZ == pathgrid.mPoints[j].mZ) pathgrid.mPoints[i].mZ == pathgrid.mPoints[j].mZ)
{ {
std::vector<int>::const_iterator it = find(duplList.begin(), duplList.end(), i); std::vector<int>::const_iterator it = find(duplList.begin(), duplList.end(), static_cast<int>(i));
if (it == duplList.end()) if (it == duplList.end())
{ {
std::ostringstream ss; std::ostringstream ss;

View file

@ -18,47 +18,43 @@ namespace
static const TypeData sNoArg[] = static const TypeData sNoArg[] =
{ {
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", ":./global-variable.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":./gmst.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":./skill.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":./class.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":./faction.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":./race.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":./sound.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":./script.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":./region.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", ":./birthsign.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":./spell.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", ":./dialogue-topics.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", ":./journal-topics.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos", ":./dialogue-topic-infos.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos", ":./journal-topic-infos.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":./cell.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments", ":./enchantment.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", ":./body-part.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects", ":./object.png" },
"Objects", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances", ":./instance.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, { CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", ":./region-map.png" },
"Instances", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", ":./filter.png" },
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", ":./resources-mesh" },
"Region Map", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", ":./resources-icon" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files", ":./resources-music" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", ":resources-sound" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", ":./resources-texture" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", ":./resources-video" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles", ":./debug-profile.png" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", 0 }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":./run-log.png" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", ":./sound-generator.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", ":./magic-effect.png" },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", ":./land-heightmap.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "Land Textures", ":./land-texture.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", ":./pathgrid.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", ":./start-script.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "LandTextures", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata", ":./metadata.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Meta Data Table", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };
@ -81,7 +77,7 @@ namespace
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", ":./journal-topic-infos.png" }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", ":./journal-topic-infos.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", ":./object.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":./apparatus.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":./apparatus.png" },
@ -93,9 +89,9 @@ namespace
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":./door.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":./door.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":./ingredient.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":./ingredient.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList,
"Creature Levelled List", ":./leveled-creature.png" }, "Creature Levelled List", ":./levelled-creature.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList,
"Item Levelled List", ":./leveled-item.png" }, "Item Levelled List", ":./levelled-item.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous,
@ -105,35 +101,35 @@ namespace
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance", 0 }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance", ":./instance.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":./scene.png" },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", ":./record-preview.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", ":./enchantment.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", ":./enchantment.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":./body-part.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", ":./body-part.png" },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", ":resources-mesh"}, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", ":./resources-mesh"},
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", ":resources-icon"}, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", ":./resources-icon"},
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", ":resources-music" }, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", ":./resources-music" },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File", ":resources-sound" }, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File", ":./resources-sound" },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", ":resources-texture"}, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", ":./resources-texture" },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":resources-video"}, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", ":./resources-video" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", ":./debug-profile.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", ":./sound-generator.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", ":./sound-generator.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", ":./magic-effect.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", ":./magic-effect.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":./land-heightmap.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Land, "Land", ":./land-heightmap.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "LandTexture", ":./land-texture.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_LandTexture, "Land Texture", ":./land-texture.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":./pathgrid.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", ":./pathgrid.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", ":./start-script.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Meta Data", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":./metadata.png" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };
static const TypeData sIndexArg[] = static const TypeData sIndexArg[] =
{ {
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", ":./menu-verify.png" },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", ":./error-log.png" },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", 0 }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", ":./menu-search.png" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };
} }

View file

@ -47,58 +47,40 @@ void CSVDoc::View::setupFileMenu()
{ {
QMenu *file = menuBar()->addMenu (tr ("File")); QMenu *file = menuBar()->addMenu (tr ("File"));
QAction *newGame = new QAction (tr ("New Game"), this); QAction* newGame = createMenuEntry("New Game", ":./menu-new-game.png", file, "document-file-newgame");
connect (newGame, SIGNAL (triggered()), this, SIGNAL (newGameRequest())); connect (newGame, SIGNAL (triggered()), this, SIGNAL (newGameRequest()));
setupShortcut("document-file-newgame", newGame);
file->addAction (newGame);
QAction* newAddon = createMenuEntry("New Addon", ":./menu-new-addon.png", file, "document-file-newaddon");
QAction *newAddon = new QAction (tr ("New Addon"), this);
connect (newAddon, SIGNAL (triggered()), this, SIGNAL (newAddonRequest())); connect (newAddon, SIGNAL (triggered()), this, SIGNAL (newAddonRequest()));
setupShortcut("document-file-newaddon", newAddon);
file->addAction (newAddon);
QAction *open = new QAction (tr ("Open"), this); QAction* open = createMenuEntry("Open", ":./menu-open.png", file, "document-file-open");
connect (open, SIGNAL (triggered()), this, SIGNAL (loadDocumentRequest())); connect (open, SIGNAL (triggered()), this, SIGNAL (loadDocumentRequest()));
setupShortcut("document-file-open", open);
file->addAction (open);
mSave = new QAction (tr ("Save"), this); QAction* save = createMenuEntry("Save", ":./menu-save.png", file, "document-file-save");
connect (mSave, SIGNAL (triggered()), this, SLOT (save())); connect (save, SIGNAL (triggered()), this, SLOT (save()));
setupShortcut("document-file-save", mSave); mSave = save;
file->addAction (mSave);
mVerify = new QAction (tr ("Verify"), this); QAction* verify = createMenuEntry("Verify", ":./menu-verify.png", file, "document-file-verify");
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); connect (verify, SIGNAL (triggered()), this, SLOT (verify()));
setupShortcut("document-file-verify", mVerify); mVerify = verify;
file->addAction (mVerify);
mMerge = new QAction (tr ("Merge"), this); QAction* merge = createMenuEntry("Merge", ":./menu-merge.png", file, "document-file-merge");
connect (mMerge, SIGNAL (triggered()), this, SLOT (merge())); connect (merge, SIGNAL (triggered()), this, SLOT (merge()));
setupShortcut("document-file-merge", mMerge); mMerge = merge;
file->addAction (mMerge);
QAction *loadErrors = new QAction (tr ("Open Load Error Log"), this); QAction* loadErrors = createMenuEntry("Error Log", ":./error-log.png", file, "document-file-errorlog");
connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog())); connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog()));
setupShortcut("document-file-errorlog", loadErrors);
file->addAction (loadErrors);
QAction *meta = new QAction (tr ("Meta Data"), this); QAction* meta = createMenuEntry(CSMWorld::UniversalId::Type_MetaDatas, file, "document-file-metadata");
connect (meta, SIGNAL (triggered()), this, SLOT (addMetaDataSubView())); connect (meta, SIGNAL (triggered()), this, SLOT (addMetaDataSubView()));
setupShortcut("document-file-metadata", meta);
file->addAction (meta);
QAction *close = new QAction (tr ("Close Document"), this); QAction* close = createMenuEntry("Close", ":./menu-close.png", file, "document-file-close");
connect (close, SIGNAL (triggered()), this, SLOT (close())); connect (close, SIGNAL (triggered()), this, SLOT (close()));
setupShortcut("document-file-close", close);
file->addAction(close);
QAction *exit = new QAction (tr ("Exit Application"), this); QAction* exit = createMenuEntry("Exit", ":./menu-exit.png", file, "document-file-exit");
connect (exit, SIGNAL (triggered()), this, SLOT (exit())); connect (exit, SIGNAL (triggered()), this, SLOT (exit()));
connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
setupShortcut("document-file-exit", exit);
file->addAction(exit); connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
} }
namespace namespace
@ -130,251 +112,174 @@ void CSVDoc::View::setupEditMenu()
mUndo = mDocument->getUndoStack().createUndoAction (this, tr("Undo")); mUndo = mDocument->getUndoStack().createUndoAction (this, tr("Undo"));
setupShortcut("document-edit-undo", mUndo); setupShortcut("document-edit-undo", mUndo);
connect(mUndo, SIGNAL (changed ()), this, SLOT (undoActionChanged ())); connect(mUndo, SIGNAL (changed ()), this, SLOT (undoActionChanged ()));
mUndo->setIcon(QIcon(QString::fromStdString(":./menu-undo.png")));
edit->addAction (mUndo); edit->addAction (mUndo);
mRedo = mDocument->getUndoStack().createRedoAction (this, tr("Redo")); mRedo = mDocument->getUndoStack().createRedoAction (this, tr("Redo"));
connect(mRedo, SIGNAL (changed ()), this, SLOT (redoActionChanged ())); connect(mRedo, SIGNAL (changed ()), this, SLOT (redoActionChanged ()));
setupShortcut("document-edit-redo", mRedo); setupShortcut("document-edit-redo", mRedo);
mRedo->setIcon(QIcon(QString::fromStdString(":./menu-redo.png")));
edit->addAction (mRedo); edit->addAction (mRedo);
QAction *userSettings = new QAction (tr ("Preferences"), this); QAction* userSettings = createMenuEntry("Preferences", ":./menu-preferences.png", edit, "document-edit-preferences");
connect (userSettings, SIGNAL (triggered()), this, SIGNAL (editSettingsRequest())); connect (userSettings, SIGNAL (triggered()), this, SIGNAL (editSettingsRequest()));
setupShortcut("document-edit-preferences", userSettings);
edit->addAction (userSettings);
QAction *search = new QAction (tr ("Search"), this); QAction* search = createMenuEntry(CSMWorld::UniversalId::Type_Search, edit, "document-edit-search");
connect (search, SIGNAL (triggered()), this, SLOT (addSearchSubView())); connect (search, SIGNAL (triggered()), this, SLOT (addSearchSubView()));
setupShortcut("document-edit-search", search);
edit->addAction (search);
} }
void CSVDoc::View::setupViewMenu() void CSVDoc::View::setupViewMenu()
{ {
QMenu *view = menuBar()->addMenu (tr ("View")); QMenu *view = menuBar()->addMenu (tr ("View"));
QAction *newWindow = new QAction (tr ("New View"), this); QAction *newWindow = createMenuEntry("New View", ":./menu-new-window.png", view, "document-view-newview");
connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView()));
setupShortcut("document-view-newview", newWindow);
view->addAction (newWindow);
mShowStatusBar = new QAction (tr ("Toggle Status Bar"), this); mShowStatusBar = createMenuEntry("Toggle Status Bar", ":./menu-status-bar.png", view, "document-view-statusbar");
mShowStatusBar->setCheckable (true);
connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool))); connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool)));
setupShortcut("document-view-statusbar", mShowStatusBar); mShowStatusBar->setCheckable (true);
mShowStatusBar->setChecked (CSMPrefs::get()["Windows"]["show-statusbar"].isTrue()); mShowStatusBar->setChecked (CSMPrefs::get()["Windows"]["show-statusbar"].isTrue());
view->addAction (mShowStatusBar); view->addAction (mShowStatusBar);
QAction *filters = new QAction (tr ("Filters"), this); QAction *filters = createMenuEntry(CSMWorld::UniversalId::Type_Filters, view, "document-mechanics-filters");
connect (filters, SIGNAL (triggered()), this, SLOT (addFiltersSubView())); connect (filters, SIGNAL (triggered()), this, SLOT (addFiltersSubView()));
setupShortcut("document-view-filters", filters);
view->addAction (filters);
} }
void CSVDoc::View::setupWorldMenu() void CSVDoc::View::setupWorldMenu()
{ {
QMenu *world = menuBar()->addMenu (tr ("World")); QMenu *world = menuBar()->addMenu (tr ("World"));
QAction *regions = new QAction (tr ("Regions"), this); QAction* regions = createMenuEntry(CSMWorld::UniversalId::Type_Regions, world, "document-world-regions");
connect (regions, SIGNAL (triggered()), this, SLOT (addRegionsSubView())); connect (regions, SIGNAL (triggered()), this, SLOT (addRegionsSubView()));
setupShortcut("document-world-regions", regions);
world->addAction (regions);
QAction *cells = new QAction (tr ("Cells"), this); QAction* cells = createMenuEntry(CSMWorld::UniversalId::Type_Cells, world, "document-world-cells");
connect (cells, SIGNAL (triggered()), this, SLOT (addCellsSubView())); connect (cells, SIGNAL (triggered()), this, SLOT (addCellsSubView()));
setupShortcut("document-world-cells", cells);
world->addAction (cells);
QAction *referenceables = new QAction (tr ("Objects"), this); QAction* referenceables = createMenuEntry(CSMWorld::UniversalId::Type_Referenceables, world, "document-world-referencables");
connect (referenceables, SIGNAL (triggered()), this, SLOT (addReferenceablesSubView())); connect (referenceables, SIGNAL (triggered()), this, SLOT (addReferenceablesSubView()));
setupShortcut("document-world-referencables", referenceables);
world->addAction (referenceables);
QAction *references = new QAction (tr ("Instances"), this); QAction* references = createMenuEntry(CSMWorld::UniversalId::Type_References, world, "document-world-references");
connect (references, SIGNAL (triggered()), this, SLOT (addReferencesSubView())); connect (references, SIGNAL (triggered()), this, SLOT (addReferencesSubView()));
setupShortcut("document-world-references", references);
world->addAction (references);
QAction *lands = new QAction (tr ("Lands"), this); QAction *lands = createMenuEntry(CSMWorld::UniversalId::Type_Lands, world, "document-world-lands");
connect (lands, SIGNAL (triggered()), this, SLOT (addLandsSubView())); connect (lands, SIGNAL (triggered()), this, SLOT (addLandsSubView()));
setupShortcut("document-world-lands", lands);
world->addAction (lands);
QAction *landTextures = new QAction (tr ("Land Textures"), this); QAction *landTextures = createMenuEntry(CSMWorld::UniversalId::Type_LandTextures, world, "document-world-landtextures");
connect (landTextures, SIGNAL (triggered()), this, SLOT (addLandTexturesSubView())); connect (landTextures, SIGNAL (triggered()), this, SLOT (addLandTexturesSubView()));
setupShortcut("document-world-landtextures", landTextures);
world->addAction (landTextures);
QAction *grid = new QAction (tr ("Pathgrid"), this); QAction *grid = createMenuEntry(CSMWorld::UniversalId::Type_Pathgrids, world, "document-world-pathgrid");
connect (grid, SIGNAL (triggered()), this, SLOT (addPathgridSubView())); connect (grid, SIGNAL (triggered()), this, SLOT (addPathgridSubView()));
setupShortcut("document-world-pathgrid", grid);
world->addAction (grid);
world->addSeparator(); // items that don't represent single record lists follow here world->addSeparator(); // items that don't represent single record lists follow here
QAction *regionMap = new QAction (tr ("Region Map"), this); QAction *regionMap = createMenuEntry(CSMWorld::UniversalId::Type_RegionMap, world, "document-world-regionmap");
connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView())); connect (regionMap, SIGNAL (triggered()), this, SLOT (addRegionMapSubView()));
setupShortcut("document-world-regionmap", regionMap);
world->addAction (regionMap);
} }
void CSVDoc::View::setupMechanicsMenu() void CSVDoc::View::setupMechanicsMenu()
{ {
QMenu *mechanics = menuBar()->addMenu (tr ("Mechanics")); QMenu *mechanics = menuBar()->addMenu (tr ("Mechanics"));
QAction *globals = new QAction (tr ("Globals"), this); QAction* globals = createMenuEntry(CSMWorld::UniversalId::Type_Globals, mechanics, "document-mechanics-globals");
connect (globals, SIGNAL (triggered()), this, SLOT (addGlobalsSubView())); connect (globals, SIGNAL (triggered()), this, SLOT (addGlobalsSubView()));
setupShortcut("document-mechanics-globals", globals);
mechanics->addAction (globals);
QAction *gmsts = new QAction (tr ("Game Settings"), this); QAction* gmsts = createMenuEntry(CSMWorld::UniversalId::Type_Gmsts, mechanics, "document-mechanics-gamesettings");
connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView())); connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView()));
setupShortcut("document-mechanics-gamesettings", gmsts);
mechanics->addAction (gmsts);
QAction *scripts = new QAction (tr ("Scripts"), this); QAction* scripts = createMenuEntry(CSMWorld::UniversalId::Type_Scripts, mechanics, "document-mechanics-scripts");
connect (scripts, SIGNAL (triggered()), this, SLOT (addScriptsSubView())); connect (scripts, SIGNAL (triggered()), this, SLOT (addScriptsSubView()));
setupShortcut("document-mechanics-scripts", scripts);
mechanics->addAction (scripts);
QAction *spells = new QAction (tr ("Spells"), this); QAction* spells = createMenuEntry(CSMWorld::UniversalId::Type_Spells, mechanics, "document-mechanics-spells");
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView())); connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
setupShortcut("document-mechanics-spells", spells);
mechanics->addAction (spells);
QAction *enchantments = new QAction (tr ("Enchantments"), this); QAction* enchantments = createMenuEntry(CSMWorld::UniversalId::Type_Enchantments, mechanics, "document-mechanics-enchantments");
connect (enchantments, SIGNAL (triggered()), this, SLOT (addEnchantmentsSubView())); connect (enchantments, SIGNAL (triggered()), this, SLOT (addEnchantmentsSubView()));
setupShortcut("document-mechanics-enchantments", enchantments);
mechanics->addAction (enchantments);
QAction *effects = new QAction (tr ("Magic Effects"), this); QAction* magicEffects = createMenuEntry(CSMWorld::UniversalId::Type_MagicEffects, mechanics, "document-mechanics-magiceffects");
connect (effects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView())); connect (magicEffects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView()));
setupShortcut("document-mechanics-magiceffects", effects);
mechanics->addAction (effects);
QAction *startScripts = new QAction (tr ("Start Scripts"), this); QAction* startScripts = createMenuEntry(CSMWorld::UniversalId::Type_StartScripts, mechanics, "document-mechanics-startscripts");
connect (startScripts, SIGNAL (triggered()), this, SLOT (addStartScriptsSubView())); connect (startScripts, SIGNAL (triggered()), this, SLOT (addStartScriptsSubView()));
setupShortcut("document-mechanics-startscripts", startScripts);
mechanics->addAction (startScripts);
} }
void CSVDoc::View::setupCharacterMenu() void CSVDoc::View::setupCharacterMenu()
{ {
QMenu *characters = menuBar()->addMenu (tr ("Characters")); QMenu *characters = menuBar()->addMenu (tr ("Characters"));
QAction *skills = new QAction (tr ("Skills"), this); QAction* skills = createMenuEntry(CSMWorld::UniversalId::Type_Skills, characters, "document-character-skills");
connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView())); connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
setupShortcut("document-character-skills", skills);
characters->addAction (skills);
QAction *classes = new QAction (tr ("Classes"), this); QAction* classes = createMenuEntry(CSMWorld::UniversalId::Type_Classes, characters, "document-character-classes");
connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView())); connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView()));
setupShortcut("document-character-classes", classes);
characters->addAction (classes);
QAction *factions = new QAction (tr ("Factions"), this); QAction* factions = createMenuEntry(CSMWorld::UniversalId::Type_Faction, characters, "document-character-factions");
connect (factions, SIGNAL (triggered()), this, SLOT (addFactionsSubView())); connect (factions, SIGNAL (triggered()), this, SLOT (addFactionsSubView()));
setupShortcut("document-character-factions", factions);
characters->addAction (factions);
QAction *races = new QAction (tr ("Races"), this); QAction* races = createMenuEntry(CSMWorld::UniversalId::Type_Races, characters, "document-character-races");
connect (races, SIGNAL (triggered()), this, SLOT (addRacesSubView())); connect (races, SIGNAL (triggered()), this, SLOT (addRacesSubView()));
setupShortcut("document-character-races", races);
characters->addAction (races);
QAction *birthsigns = new QAction (tr ("Birthsigns"), this); QAction* birthsigns = createMenuEntry(CSMWorld::UniversalId::Type_Birthsigns, characters, "document-character-birthsigns");
connect (birthsigns, SIGNAL (triggered()), this, SLOT (addBirthsignsSubView())); connect (birthsigns, SIGNAL (triggered()), this, SLOT (addBirthsignsSubView()));
setupShortcut("document-character-birthsigns", birthsigns);
characters->addAction (birthsigns);
QAction *topics = new QAction (tr ("Topics"), this); QAction* topics = createMenuEntry(CSMWorld::UniversalId::Type_Topics, characters, "document-character-topics");
connect (topics, SIGNAL (triggered()), this, SLOT (addTopicsSubView())); connect (topics, SIGNAL (triggered()), this, SLOT (addTopicsSubView()));
setupShortcut("document-character-topics", topics);
characters->addAction (topics);
QAction *journals = new QAction (tr ("Journals"), this); QAction* journals = createMenuEntry(CSMWorld::UniversalId::Type_Journals, characters, "document-character-journals");
connect (journals, SIGNAL (triggered()), this, SLOT (addJournalsSubView())); connect (journals, SIGNAL (triggered()), this, SLOT (addJournalsSubView()));
setupShortcut("document-character-journals", journals);
characters->addAction (journals);
QAction *topicInfos = new QAction (tr ("Topic Infos"), this); QAction* topicInfos = createMenuEntry(CSMWorld::UniversalId::Type_TopicInfos, characters, "document-character-topicinfos");
connect (topicInfos, SIGNAL (triggered()), this, SLOT (addTopicInfosSubView())); connect (topicInfos, SIGNAL (triggered()), this, SLOT (addTopicInfosSubView()));
setupShortcut("document-character-topicinfos", topicInfos);
characters->addAction (topicInfos);
QAction *journalInfos = new QAction (tr ("Journal Infos"), this); QAction* journalInfos = createMenuEntry(CSMWorld::UniversalId::Type_JournalInfos, characters, "document-character-journalinfos");
connect (journalInfos, SIGNAL (triggered()), this, SLOT (addJournalInfosSubView())); connect (journalInfos, SIGNAL (triggered()), this, SLOT (addJournalInfosSubView()));
setupShortcut("document-character-journalinfos", journalInfos);
characters->addAction (journalInfos);
QAction *bodyParts = new QAction (tr ("Body Parts"), this); QAction* bodyParts = createMenuEntry(CSMWorld::UniversalId::Type_BodyParts, characters, "document-character-bodyparts");
connect (bodyParts, SIGNAL (triggered()), this, SLOT (addBodyPartsSubView())); connect (bodyParts, SIGNAL (triggered()), this, SLOT (addBodyPartsSubView()));
setupShortcut("document-character-bodyparts", bodyParts);
characters->addAction (bodyParts);
} }
void CSVDoc::View::setupAssetsMenu() void CSVDoc::View::setupAssetsMenu()
{ {
QMenu *assets = menuBar()->addMenu (tr ("Assets")); QMenu *assets = menuBar()->addMenu (tr ("Assets"));
QAction *reload = new QAction (tr ("Reload"), this); QAction* reload = createMenuEntry("Reload", ":./menu-reload.png", assets, "document-assets-reload");
connect (reload, SIGNAL (triggered()), &mDocument->getData(), SLOT (assetsChanged())); connect (reload, SIGNAL (triggered()), &mDocument->getData(), SLOT (assetsChanged()));
setupShortcut("document-assets-reload", reload);
assets->addAction (reload);
assets->addSeparator(); assets->addSeparator();
QAction *sounds = new QAction (tr ("Sounds"), this); QAction* sounds = createMenuEntry(CSMWorld::UniversalId::Type_Sounds, assets, "document-assets-sounds");
connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView())); connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView()));
setupShortcut("document-assets-sounds", sounds);
assets->addAction (sounds);
QAction *soundGens = new QAction (tr ("Sound Generators"), this); QAction* soundGens = createMenuEntry(CSMWorld::UniversalId::Type_SoundGens, assets, "document-assets-soundgens");
connect (soundGens, SIGNAL (triggered()), this, SLOT (addSoundGensSubView())); connect (soundGens, SIGNAL (triggered()), this, SLOT (addSoundGensSubView()));
setupShortcut("document-assets-soundgens", soundGens);
assets->addAction (soundGens);
assets->addSeparator(); // resources follow here assets->addSeparator(); // resources follow here
QAction *meshes = new QAction (tr ("Meshes"), this); QAction* meshes = createMenuEntry(CSMWorld::UniversalId::Type_Meshes, assets, "document-assets-meshes");
connect (meshes, SIGNAL (triggered()), this, SLOT (addMeshesSubView())); connect (meshes, SIGNAL (triggered()), this, SLOT (addMeshesSubView()));
setupShortcut("document-assets-meshes", meshes);
assets->addAction (meshes);
QAction *icons = new QAction (tr ("Icons"), this); QAction* icons = createMenuEntry(CSMWorld::UniversalId::Type_Icons, assets, "document-assets-icons");
connect (icons, SIGNAL (triggered()), this, SLOT (addIconsSubView())); connect (icons, SIGNAL (triggered()), this, SLOT (addIconsSubView()));
setupShortcut("document-assets-icons", icons);
assets->addAction (icons);
QAction *musics = new QAction (tr ("Music"), this); QAction* musics = createMenuEntry(CSMWorld::UniversalId::Type_Musics, assets, "document-assets-musics");
connect (musics, SIGNAL (triggered()), this, SLOT (addMusicsSubView())); connect (musics, SIGNAL (triggered()), this, SLOT (addMusicsSubView()));
setupShortcut("document-assets-music", musics);
assets->addAction (musics);
QAction *soundsRes = new QAction (tr ("Sound Files"), this); QAction* soundFiles = createMenuEntry(CSMWorld::UniversalId::Type_SoundsRes, assets, "document-assets-soundres");
connect (soundsRes, SIGNAL (triggered()), this, SLOT (addSoundsResSubView())); connect (soundFiles, SIGNAL (triggered()), this, SLOT (addSoundsResSubView()));
setupShortcut("document-assets-soundres", soundsRes);
assets->addAction (soundsRes);
QAction *textures = new QAction (tr ("Textures"), this); QAction* textures = createMenuEntry(CSMWorld::UniversalId::Type_Textures, assets, "document-assets-textures");
connect (textures, SIGNAL (triggered()), this, SLOT (addTexturesSubView())); connect (textures, SIGNAL (triggered()), this, SLOT (addTexturesSubView()));
setupShortcut("document-assets-textures", textures);
assets->addAction (textures);
QAction *videos = new QAction (tr ("Videos"), this); QAction* videos = createMenuEntry(CSMWorld::UniversalId::Type_Videos, assets, "document-assets-videos");
connect (videos, SIGNAL (triggered()), this, SLOT (addVideosSubView())); connect (videos, SIGNAL (triggered()), this, SLOT (addVideosSubView()));
setupShortcut("document-assets-videos", videos);
assets->addAction (videos);
} }
void CSVDoc::View::setupDebugMenu() void CSVDoc::View::setupDebugMenu()
{ {
QMenu *debug = menuBar()->addMenu (tr ("Debug")); QMenu *debug = menuBar()->addMenu (tr ("Debug"));
QAction *profiles = new QAction (tr ("Debug Profiles"), this); QAction* profiles = createMenuEntry(CSMWorld::UniversalId::Type_DebugProfiles, debug, "document-debug-profiles");
connect (profiles, SIGNAL (triggered()), this, SLOT (addDebugProfilesSubView())); connect (profiles, SIGNAL (triggered()), this, SLOT (addDebugProfilesSubView()));
debug->addAction (profiles);
debug->addSeparator(); debug->addSeparator();
@ -387,18 +292,41 @@ void CSVDoc::View::setupDebugMenu()
QAction *runDebug = debug->addMenu (mGlobalDebugProfileMenu); QAction *runDebug = debug->addMenu (mGlobalDebugProfileMenu);
runDebug->setText (tr ("Run OpenMW")); runDebug->setText (tr ("Run OpenMW"));
setupShortcut("document-debug-run", runDebug); setupShortcut("document-debug-run", runDebug);
runDebug->setIcon(QIcon(QString::fromStdString(":./run-openmw.png")));
mStopDebug = new QAction (tr ("Shutdown OpenMW"), this); QAction* stopDebug = createMenuEntry("Stop OpenMW", ":./stop-openmw.png", debug, "document-debug-shutdown");
connect (mStopDebug, SIGNAL (triggered()), this, SLOT (stop())); connect (stopDebug, SIGNAL (triggered()), this, SLOT (stop()));
setupShortcut("document-debug-shutdown", mStopDebug); mStopDebug = stopDebug;
debug->addAction (mStopDebug);
QAction *runLog = new QAction (tr ("Open Run Log"), this); QAction* runLog = createMenuEntry(CSMWorld::UniversalId::Type_RunLog, debug, "document-debug-runlog");
connect (runLog, SIGNAL (triggered()), this, SLOT (addRunLogSubView())); connect (runLog, SIGNAL (triggered()), this, SLOT (addRunLogSubView()));
setupShortcut("document-debug-runlog", runLog); }
debug->addAction (runLog);
QAction* CSVDoc::View::createMenuEntry(CSMWorld::UniversalId::Type type, QMenu* menu, const char* shortcutName)
{
const std::string title = CSMWorld::UniversalId (type).getTypeName();
QAction *entry = new QAction(QString::fromStdString(title), this);
setupShortcut(shortcutName, entry);
const std::string iconName = CSMWorld::UniversalId (type).getIcon();
if (!iconName.empty() && iconName != ":placeholder")
entry->setIcon(QIcon(QString::fromStdString(iconName)));
menu->addAction (entry);
return entry;
}
QAction* CSVDoc::View::createMenuEntry(const std::string& title, const std::string& iconName, QMenu* menu, const char* shortcutName)
{
QAction *entry = new QAction(QString::fromStdString(title), this);
setupShortcut(shortcutName, entry);
if (!iconName.empty() && iconName != ":placeholder")
entry->setIcon(QIcon(QString::fromStdString(iconName)));
menu->addAction (entry);
return entry;
} }
void CSVDoc::View::setupUi() void CSVDoc::View::setupUi()

View file

@ -66,6 +66,9 @@ namespace CSVDoc
void closeEvent (QCloseEvent *event); void closeEvent (QCloseEvent *event);
QAction* createMenuEntry(CSMWorld::UniversalId::Type type, QMenu* menu, const char* shortcutName);
QAction* createMenuEntry(const std::string& title, const std::string& iconName, QMenu* menu, const char* shortcutName);
void setupFileMenu(); void setupFileMenu();
void setupEditMenu(); void setupEditMenu();

View file

@ -436,7 +436,8 @@ namespace MWBase
virtual const MWGui::TextColours& getTextColours() = 0; virtual const MWGui::TextColours& getTextColours() = 0;
virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text) = 0; virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat) = 0;
virtual bool injectKeyRelease(MyGUI::KeyCode key) = 0;
}; };
} }

View file

@ -1123,8 +1123,8 @@ namespace MWClass
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
bool sneaking = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak); bool sneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr) && stats.getStance(MWMechanics::CreatureStats::Stance_Sneak);
bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run); bool running = MWBase::Environment::get().getMechanicsManager()->isRunning(ptr) && stats.getStance(MWMechanics::CreatureStats::Stance_Run);
float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()* float walkSpeed = gmst.fMinWalkSpeed->mValue.getFloat() + 0.01f*npcdata->mNpcStats.getAttribute(ESM::Attribute::Speed).getModified()*
(gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat()); (gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat());
@ -1149,7 +1149,7 @@ namespace MWClass
flySpeed = std::max(0.0f, flySpeed); flySpeed = std::max(0.0f, flySpeed);
moveSpeed = flySpeed; moveSpeed = flySpeed;
} }
else if(world->isSwimming(ptr)) else if (world->isSwimming(ptr))
{ {
float swimSpeed = walkSpeed; float swimSpeed = walkSpeed;
if(running) if(running)
@ -1159,7 +1159,7 @@ namespace MWClass
gmst.fSwimRunAthleticsMult->mValue.getFloat(); gmst.fSwimRunAthleticsMult->mValue.getFloat();
moveSpeed = swimSpeed; moveSpeed = swimSpeed;
} }
else if(running && !sneaking) else if (running)
moveSpeed = runSpeed; moveSpeed = runSpeed;
else else
moveSpeed = walkSpeed; moveSpeed = walkSpeed;

View file

@ -302,24 +302,27 @@ namespace MWClass
{ {
text += "\n#{sType} "; text += "\n#{sType} ";
std::map <int, std::pair <std::string, std::string> > mapping; static std::map <int, std::pair <std::string, std::string> > mapping;
mapping[ESM::Weapon::ShortBladeOneHand] = std::make_pair("sSkillShortblade", "sOneHanded"); if (mapping.empty())
mapping[ESM::Weapon::LongBladeOneHand] = std::make_pair("sSkillLongblade", "sOneHanded"); {
mapping[ESM::Weapon::LongBladeTwoHand] = std::make_pair("sSkillLongblade", "sTwoHanded"); mapping[ESM::Weapon::ShortBladeOneHand] = std::make_pair("sSkillShortblade", "sOneHanded");
mapping[ESM::Weapon::BluntOneHand] = std::make_pair("sSkillBluntweapon", "sOneHanded"); mapping[ESM::Weapon::LongBladeOneHand] = std::make_pair("sSkillLongblade", "sOneHanded");
mapping[ESM::Weapon::BluntTwoClose] = std::make_pair("sSkillBluntweapon", "sTwoHanded"); mapping[ESM::Weapon::LongBladeTwoHand] = std::make_pair("sSkillLongblade", "sTwoHanded");
mapping[ESM::Weapon::BluntTwoWide] = std::make_pair("sSkillBluntweapon", "sTwoHanded"); mapping[ESM::Weapon::BluntOneHand] = std::make_pair("sSkillBluntweapon", "sOneHanded");
mapping[ESM::Weapon::SpearTwoWide] = std::make_pair("sSkillSpear", "sTwoHanded"); mapping[ESM::Weapon::BluntTwoClose] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
mapping[ESM::Weapon::AxeOneHand] = std::make_pair("sSkillAxe", "sOneHanded"); mapping[ESM::Weapon::BluntTwoWide] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
mapping[ESM::Weapon::AxeTwoHand] = std::make_pair("sSkillAxe", "sTwoHanded"); mapping[ESM::Weapon::SpearTwoWide] = std::make_pair("sSkillSpear", "sTwoHanded");
mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::AxeOneHand] = std::make_pair("sSkillAxe", "sOneHanded");
mapping[ESM::Weapon::MarksmanCrossbow] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::AxeTwoHand] = std::make_pair("sSkillAxe", "sTwoHanded");
mapping[ESM::Weapon::MarksmanThrown] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::Arrow] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::MarksmanCrossbow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::Bolt] = std::make_pair("sSkillMarksman", ""); mapping[ESM::Weapon::MarksmanThrown] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::Arrow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::Bolt] = std::make_pair("sSkillMarksman", "");
}
std::string type = mapping[ref->mBase->mData.mType].first; const std::string type = mapping[ref->mBase->mData.mType].first;
std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second; const std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second;
text += store.get<ESM::GameSetting>().find(type)->mValue.getString() + text += store.get<ESM::GameSetting>().find(type)->mValue.getString() +
((oneOrTwoHanded != "") ? ", " + store.get<ESM::GameSetting>().find(oneOrTwoHanded)->mValue.getString() : ""); ((oneOrTwoHanded != "") ? ", " + store.get<ESM::GameSetting>().find(oneOrTwoHanded)->mValue.getString() : "");

View file

@ -65,6 +65,9 @@ namespace MWGui
void AlchemyWindow::onAccept(MyGUI::EditBox* sender) void AlchemyWindow::onAccept(MyGUI::EditBox* sender)
{ {
onCreateButtonClicked(sender); onCreateButtonClicked(sender);
// To do not spam onAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
} }
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender) void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)

View file

@ -297,6 +297,8 @@ namespace MWGui
if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop != NULL && mDragAndDrop->mIsOnDragAndDrop)
return; return;
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);
/* /*
Start of tes3mp addition Start of tes3mp addition
@ -375,6 +377,8 @@ namespace MWGui
{ {
if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop) if(mDragAndDrop == NULL || !mDragAndDrop->mIsOnDragAndDrop)
{ {
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);
onTakeAllButtonClicked(mTakeButton); onTakeAllButtonClicked(mTakeButton);
if (mPtr.getClass().isPersistent(mPtr)) if (mPtr.getClass().isPersistent(mPtr))

View file

@ -73,8 +73,10 @@ namespace MWGui
void CountDialog::onEnterKeyPressed(MyGUI::EditBox* _sender) void CountDialog::onEnterKeyPressed(MyGUI::EditBox* _sender)
{ {
eventOkClicked(NULL, mSlider->getScrollPosition()+1); eventOkClicked(NULL, mSlider->getScrollPosition()+1);
setVisible(false); setVisible(false);
// To do not spam onEnterKeyPressed() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
} }
void CountDialog::onEditValueChanged(int value) void CountDialog::onEditValueChanged(int value)

View file

@ -288,6 +288,9 @@ namespace MWGui
void EnchantingDialog::onAccept(MyGUI::EditBox *sender) void EnchantingDialog::onAccept(MyGUI::EditBox *sender)
{ {
onBuyButtonClicked(sender); onBuyButtonClicked(sender);
// To do not spam onAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
} }
void EnchantingDialog::onBuyButtonClicked(MyGUI::Widget* sender) void EnchantingDialog::onBuyButtonClicked(MyGUI::Widget* sender)

View file

@ -6,6 +6,8 @@
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_Window.h> #include <MyGUI_Window.h>
#include <components/debug/debuglog.hpp>
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
@ -49,7 +51,14 @@ KeyboardNavigation::KeyboardNavigation()
KeyboardNavigation::~KeyboardNavigation() KeyboardNavigation::~KeyboardNavigation()
{ {
MyGUI::WidgetManager::getInstance().unregisterUnlinker(this); try
{
MyGUI::WidgetManager::getInstance().unregisterUnlinker(this);
}
catch(const MyGUI::Exception& e)
{
Log(Debug::Error) << "Error in the destructor: " << e.what();
}
} }
void KeyboardNavigation::saveFocus(int mode) void KeyboardNavigation::saveFocus(int mode)
@ -172,7 +181,7 @@ enum Direction
D_Prev D_Prev
}; };
bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text) bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat)
{ {
if (!mEnabled) if (!mEnabled)
return false; return false;
@ -192,7 +201,14 @@ bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text)
case MyGUI::KeyCode::Return: case MyGUI::KeyCode::Return:
case MyGUI::KeyCode::NumpadEnter: case MyGUI::KeyCode::NumpadEnter:
case MyGUI::KeyCode::Space: case MyGUI::KeyCode::Space:
{
// We should disable repeating for activation keys
MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::None);
if (repeat)
return true;
return accept(); return accept();
}
default: default:
return false; return false;
} }

View file

@ -14,7 +14,7 @@ namespace MWGui
~KeyboardNavigation(); ~KeyboardNavigation();
/// @return Was the key handled by this class? /// @return Was the key handled by this class?
bool injectKeyPress(MyGUI::KeyCode key, unsigned int text); bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat);
void saveFocus(int mode); void saveFocus(int mode);
void restoreFocus(int mode); void restoreFocus(int mode);

View file

@ -5,6 +5,8 @@
#include <MyGUI_WidgetDefines.h> #include <MyGUI_WidgetDefines.h>
#include <MyGUI_Widget.h> #include <MyGUI_Widget.h>
#include <components/debug/debuglog.hpp>
namespace MWGui namespace MWGui
{ {
/** The Layout class is an utility class used to load MyGUI layouts /** The Layout class is an utility class used to load MyGUI layouts
@ -16,7 +18,17 @@ namespace MWGui
Layout(const std::string & _layout, MyGUI::Widget* _parent = nullptr) Layout(const std::string & _layout, MyGUI::Widget* _parent = nullptr)
: mMainWidget(nullptr) : mMainWidget(nullptr)
{ initialise(_layout, _parent); } { initialise(_layout, _parent); }
virtual ~Layout() { shutdown(); } virtual ~Layout()
{
try
{
shutdown();
}
catch(const MyGUI::Exception& e)
{
Log(Debug::Error) << "Error in the destructor: " << e.what();
}
}
MyGUI::Widget* getWidget(const std::string& _name); MyGUI::Widget* getWidget(const std::string& _name);

View file

@ -127,6 +127,9 @@ namespace MWGui
void SaveGameDialog::onEditSelectAccept(MyGUI::EditBox *sender) void SaveGameDialog::onEditSelectAccept(MyGUI::EditBox *sender)
{ {
accept(); accept();
// To do not spam onEditSelectAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
} }
void SaveGameDialog::onOpen() void SaveGameDialog::onOpen()

View file

@ -99,7 +99,14 @@ namespace MWGui
ScreenFader::~ScreenFader() ScreenFader::~ScreenFader()
{ {
MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &ScreenFader::onFrameStart); try
{
MyGUI::Gui::getInstance().eventFrameStart -= MyGUI::newDelegate(this, &ScreenFader::onFrameStart);
}
catch(const MyGUI::Exception& e)
{
Log(Debug::Error) << "Error in the destructor: " << e.what();
}
} }
void ScreenFader::onFrameStart(float dt) void ScreenFader::onFrameStart(float dt)

View file

@ -159,7 +159,9 @@ namespace MWGui
mDurationValue->setCaption("1"); mDurationValue->setCaption("1");
mMagnitudeMinValue->setCaption("1"); mMagnitudeMinValue->setCaption("1");
mMagnitudeMaxValue->setCaption("- 1"); const std::string to = MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "-");
mMagnitudeMaxValue->setCaption(to + " 1");
mAreaValue->setCaption("0"); mAreaValue->setCaption("0");
setVisible(true); setVisible(true);
@ -324,8 +326,9 @@ namespace MWGui
} }
mEffect.mMagnMax = pos+1; mEffect.mMagnMax = pos+1;
const std::string to = MWBase::Environment::get().getWindowManager()->getGameSettingString("sTo", "-");
mMagnitudeMaxValue->setCaption("- " + MyGUI::utility::toString(pos+1)); mMagnitudeMaxValue->setCaption(to + " " + MyGUI::utility::toString(pos+1));
eventEffectModified(mEffect); eventEffectModified(mEffect);
} }
@ -446,6 +449,9 @@ namespace MWGui
void SpellCreationDialog::onAccept(MyGUI::EditBox *sender) void SpellCreationDialog::onAccept(MyGUI::EditBox *sender)
{ {
onBuyButtonClicked(sender); onBuyButtonClicked(sender);
// To do not spam onAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
} }
void SpellCreationDialog::onOpen() void SpellCreationDialog::onOpen()

View file

@ -65,6 +65,9 @@ namespace MWGui
void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender) void TextInputDialog::onTextAccepted(MyGUI::Edit* _sender)
{ {
onOkClicked(_sender); onOkClicked(_sender);
// To do not spam onTextAccepted() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
} }
std::string TextInputDialog::getTextInput() const std::string TextInputDialog::getTextInput() const

View file

@ -367,6 +367,9 @@ namespace MWGui
void TradeWindow::onAccept(MyGUI::EditBox *sender) void TradeWindow::onAccept(MyGUI::EditBox *sender)
{ {
onOfferButtonClicked(sender); onOfferButtonClicked(sender);
// To do not spam onAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
} }
void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender) void TradeWindow::onCancelButtonClicked(MyGUI::Widget* _sender)

View file

@ -539,35 +539,42 @@ namespace MWGui
WindowManager::~WindowManager() WindowManager::~WindowManager()
{ {
mKeyboardNavigation.reset(); try
{
mKeyboardNavigation.reset();
MyGUI::LanguageManager::getInstance().eventRequestTag.clear(); MyGUI::LanguageManager::getInstance().eventRequestTag.clear();
MyGUI::PointerManager::getInstance().eventChangeMousePointer.clear(); MyGUI::PointerManager::getInstance().eventChangeMousePointer.clear();
MyGUI::InputManager::getInstance().eventChangeKeyFocus.clear(); MyGUI::InputManager::getInstance().eventChangeKeyFocus.clear();
MyGUI::ClipboardManager::getInstance().eventClipboardChanged.clear(); MyGUI::ClipboardManager::getInstance().eventClipboardChanged.clear();
MyGUI::ClipboardManager::getInstance().eventClipboardRequested.clear(); MyGUI::ClipboardManager::getInstance().eventClipboardRequested.clear();
for (WindowBase* window : mWindows) for (WindowBase* window : mWindows)
delete window; delete window;
mWindows.clear(); mWindows.clear();
delete mMessageBoxManager; delete mMessageBoxManager;
delete mLocalMapRender; delete mLocalMapRender;
delete mCharGen; delete mCharGen;
delete mDragAndDrop; delete mDragAndDrop;
delete mSoulgemDialog; delete mSoulgemDialog;
delete mCursorManager; delete mCursorManager;
delete mToolTips; delete mToolTips;
cleanupGarbage(); cleanupGarbage();
mFontLoader.reset(); mFontLoader.reset();
mGui->shutdown(); mGui->shutdown();
delete mGui; delete mGui;
mGuiPlatform->shutdown(); mGuiPlatform->shutdown();
delete mGuiPlatform; delete mGuiPlatform;
}
catch(const MyGUI::Exception& e)
{
Log(Debug::Error) << "Error in the destructor: " << e.what();
}
} }
void WindowManager::setStore(const MWWorld::ESMStore &store) void WindowManager::setStore(const MWWorld::ESMStore &store)
@ -2218,9 +2225,9 @@ namespace MWGui
return mTextColours; return mTextColours;
} }
bool WindowManager::injectKeyPress(MyGUI::KeyCode key, unsigned int text) bool WindowManager::injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat)
{ {
if (!mKeyboardNavigation->injectKeyPress(key, text)) if (!mKeyboardNavigation->injectKeyPress(key, text, repeat))
{ {
MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget();
bool widgetActive = MyGUI::InputManager::getInstance().injectKeyPress(key, text); bool widgetActive = MyGUI::InputManager::getInstance().injectKeyPress(key, text);
@ -2249,6 +2256,11 @@ namespace MWGui
return true; return true;
} }
bool WindowManager::injectKeyRelease(MyGUI::KeyCode key)
{
return MyGUI::InputManager::getInstance().injectKeyRelease(key);
}
void WindowManager::GuiModeState::update(bool visible) void WindowManager::GuiModeState::update(bool visible)
{ {
for (unsigned int i=0; i<mWindows.size(); ++i) for (unsigned int i=0; i<mWindows.size(); ++i)

View file

@ -465,7 +465,8 @@ namespace MWGui
virtual const MWGui::TextColours& getTextColours(); virtual const MWGui::TextColours& getTextColours();
virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text); virtual bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat=false);
virtual bool injectKeyRelease(MyGUI::KeyCode key);
private: private:
const MWWorld::ESMStore* mStore; const MWWorld::ESMStore* mStore;

View file

@ -226,7 +226,7 @@ namespace MWInput
break; break;
} }
MWBase::Environment::get().getWindowManager()->injectKeyPress(key, 0); MWBase::Environment::get().getWindowManager()->injectKeyPress(key, 0, false);
} }
void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue) void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue)
@ -733,7 +733,7 @@ namespace MWInput
bool consumed = false; bool consumed = false;
if (kc != OIS::KC_UNASSIGNED && !mInputBinder->detectingBindingState()) if (kc != OIS::KC_UNASSIGNED && !mInputBinder->detectingBindingState())
{ {
consumed = MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Enum(kc), 0); consumed = MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Enum(kc), 0, arg.repeat);
if (SDL_IsTextInputActive() && // Little trick to check if key is printable if (SDL_IsTextInputActive() && // Little trick to check if key is printable
( !(SDLK_SCANCODE_MASK & arg.keysym.sym) && std::isprint(arg.keysym.sym))) ( !(SDLK_SCANCODE_MASK & arg.keysym.sym) && std::isprint(arg.keysym.sym)))
consumed = true; consumed = true;
@ -1245,7 +1245,7 @@ namespace MWInput
if (MWBase::Environment::get().getWindowManager()->isGuiMode()) if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{ {
if (!SDL_IsTextInputActive() && !isLeftOrRightButton(A_Activate, mInputBinder, mFakeDeviceID, mJoystickLastUsed)) if (!SDL_IsTextInputActive() && !isLeftOrRightButton(A_Activate, mInputBinder, mFakeDeviceID, mJoystickLastUsed))
MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Return, 0); MWBase::Environment::get().getWindowManager()->injectKeyPress(MyGUI::KeyCode::Return, 0, false);
} }
else if (mControlSwitch["playercontrols"]) else if (mControlSwitch["playercontrols"])
mPlayer->activate(); mPlayer->activate();

View file

@ -259,7 +259,7 @@ std::string CharacterController::chooseRandomGroup (const std::string& prefix, i
return prefix + toString(roll); return prefix + toString(roll);
} }
void CharacterController::refreshHitRecoilAnims() void CharacterController::refreshHitRecoilAnims(CharacterState& idle)
{ {
bool recovery = mPtr.getClass().getCreatureStats(mPtr).getHitRecovery(); bool recovery = mPtr.getClass().getCreatureStats(mPtr).getHitRecovery();
bool knockdown = mPtr.getClass().getCreatureStats(mPtr).getKnockedDown(); bool knockdown = mPtr.getClass().getCreatureStats(mPtr).getKnockedDown();
@ -364,14 +364,16 @@ void CharacterController::refreshHitRecoilAnims()
mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::BlendMask_All, true, 1, "loop stop", "stop", 0.0f, 0); mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::BlendMask_All, true, 1, "loop stop", "stop", 0.0f, 0);
} }
if (mHitState != CharState_None) if (mHitState != CharState_None)
mIdleState = CharState_None; idle = CharState_None;
} }
void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, bool force) void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, bool force)
{ {
if(force || jump != mJumpState) if(force || jump != mJumpState)
{ {
mIdleState = CharState_None; if (jump != JumpState_None)
idle = CharState_None;
bool startAtLoop = (jump == mJumpState); bool startAtLoop = (jump == mJumpState);
mJumpState = jump; mJumpState = jump;
@ -388,6 +390,11 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
jumpmask = MWRender::Animation::BlendMask_LowerBody; jumpmask = MWRender::Animation::BlendMask_LowerBody;
jumpAnimName = "jump"; jumpAnimName = "jump";
// Since we apply movement only for lower body, do not reset idle animations.
// For upper body there will be idle animation.
if (idle == CharState_None)
idle = CharState_Idle;
// For crossbow animations use 1h ones as fallback // For crossbow animations use 1h ones as fallback
if (mWeaponType == WeapType_Crossbow) if (mWeaponType == WeapType_Crossbow)
jumpAnimName += "1h"; jumpAnimName += "1h";
@ -422,34 +429,48 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
} }
} }
void CharacterController::refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, bool force) void CharacterController::refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force)
{ {
if(force || movement != mMovementState) std::string movementAnimName;
MWRender::Animation::BlendMask movemask;
const StateInfo *movestate;
if(force || movement != mMovementState || idle != mIdleState)
{ {
mMovementState = movement; movemask = MWRender::Animation::BlendMask_All;
std::string movementAnimName; movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(movement));
MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All;
const StateInfo *movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(mMovementState));
if(movestate != sMovementListEnd) if(movestate != sMovementListEnd)
{ {
movementAnimName = movestate->groupname; movementAnimName = movestate->groupname;
if(weap != sWeaponTypeListEnd && movementAnimName.find("swim") == std::string::npos) if(weap != sWeaponTypeListEnd && movementAnimName.find("swim") == std::string::npos)
{ {
if (mWeaponType == WeapType_Spell && (mMovementState == CharState_TurnLeft || mMovementState == CharState_TurnRight)) // Spellcasting stance turning is a special case if (mWeaponType == WeapType_Spell && (movement == CharState_TurnLeft || movement == CharState_TurnRight)) // Spellcasting stance turning is a special case
movementAnimName = weap->shortgroup + movementAnimName; movementAnimName = weap->shortgroup + movementAnimName;
else else
movementAnimName += weap->shortgroup; movementAnimName += weap->shortgroup;
if(!mAnimation->hasAnimation(movementAnimName)) if(!mAnimation->hasAnimation(movementAnimName))
{ {
movemask = MWRender::Animation::BlendMask_LowerBody; movemask = MWRender::Animation::BlendMask_LowerBody;
movementAnimName = movestate->groupname; movementAnimName = movestate->groupname;
// Since we apply movement only for lower body, do not reset idle animations.
// For upper body there will be idle animation.
if (idle == CharState_None)
idle = CharState_Idle;
// For crossbow animations use 1h ones as fallback // For crossbow animations use 1h ones as fallback
if (mWeaponType == WeapType_Crossbow) if (mWeaponType == WeapType_Crossbow)
movementAnimName += "1h"; movementAnimName += "1h";
} }
} }
}
}
if(force || movement != mMovementState)
{
mMovementState = movement;
if(movestate != sMovementListEnd)
{
if(!mAnimation->hasAnimation(movementAnimName)) if(!mAnimation->hasAnimation(movementAnimName))
{ {
std::string::size_type swimpos = movementAnimName.find("swim"); std::string::size_type swimpos = movementAnimName.find("swim");
@ -467,6 +488,10 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
} }
else else
{ {
// For crossbow animations use 1h ones as fallback
if (mWeaponType == WeapType_Crossbow)
movementAnimName += "1h";
movementAnimName.erase(swimpos, 4); movementAnimName.erase(swimpos, 4);
if (weap != sWeaponTypeListEnd) if (weap != sWeaponTypeListEnd)
{ {
@ -543,7 +568,15 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force) void CharacterController::refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force)
{ {
if(force || idle != mIdleState || mIdleState == CharState_None || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty())) // FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update),
// the idle animation should be displayed
if (((mUpperBodyState != UpperCharState_Nothing && mUpperBodyState != UpperCharState_WeapEquiped)
|| (mMovementState != CharState_None && !isTurning())
|| mHitState != CharState_None)
&& !mPtr.getClass().isBipedal(mPtr))
idle = CharState_None;
if(force || idle != mIdleState || (!mAnimation->isPlaying(mCurrentIdle) && mAnimQueue.empty()))
{ {
mIdleState = idle; mIdleState = idle;
size_t numLoops = ~0ul; size_t numLoops = ~0ul;
@ -602,24 +635,16 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
return; return;
if (mPtr.getClass().isActor()) if (mPtr.getClass().isActor())
refreshHitRecoilAnims(); refreshHitRecoilAnims(idle);
const WeaponInfo *weap = std::find_if(sWeaponTypeList, sWeaponTypeListEnd, FindWeaponType(mWeaponType)); const WeaponInfo *weap = std::find_if(sWeaponTypeList, sWeaponTypeListEnd, FindWeaponType(mWeaponType));
if (!mPtr.getClass().hasInventoryStore(mPtr)) if (!mPtr.getClass().hasInventoryStore(mPtr))
weap = sWeaponTypeListEnd; weap = sWeaponTypeListEnd;
refreshJumpAnims(weap, jump, force); refreshJumpAnims(weap, jump, idle, force);
refreshMovementAnims(weap, movement, force); refreshMovementAnims(weap, movement, idle, force);
// idle handled last as it can depend on the other states // idle handled last as it can depend on the other states
// FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming update),
// the idle animation should be displayed
if (((mUpperBodyState != UpperCharState_Nothing && mUpperBodyState != UpperCharState_WeapEquiped)
|| (mMovementState != CharState_None && !isTurning())
|| mHitState != CharState_None)
&& !mPtr.getClass().isBipedal(mPtr))
idle = CharState_None;
refreshIdleAnims(weap, idle, force); refreshIdleAnims(weap, idle, force);
} }
@ -1255,7 +1280,7 @@ bool CharacterController::updateCarriedLeftVisible(WeaponType weaptype) const
} }
} }
bool CharacterController::updateWeaponState() bool CharacterController::updateWeaponState(CharacterState& idle)
{ {
const MWWorld::Class &cls = mPtr.getClass(); const MWWorld::Class &cls = mPtr.getClass();
CreatureStats &stats = cls.getCreatureStats(mPtr); CreatureStats &stats = cls.getCreatureStats(mPtr);
@ -1454,6 +1479,14 @@ bool CharacterController::updateWeaponState()
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr); MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
mAttackStrength = 0; mAttackStrength = 0;
// Randomize attacks for non-bipedal creatures with Weapon flag
if (mPtr.getClass().getTypeName() == typeid(ESM::Creature).name() &&
!mPtr.getClass().isBipedal(mPtr) &&
(!mAnimation->hasAnimation(mCurrentWeapon) || isRandomAttackAnimation(mCurrentWeapon)))
{
mCurrentWeapon = chooseRandomAttackAnimation();
}
if(mWeaponType == WeapType_Spell) if(mWeaponType == WeapType_Spell)
{ {
// Unset casting flag, otherwise pressing the mouse button down would // Unset casting flag, otherwise pressing the mouse button down would
@ -1646,11 +1679,11 @@ bool CharacterController::updateWeaponState()
// We should reset player's idle animation in the first-person mode. // We should reset player's idle animation in the first-person mode.
if (resetIdle && mPtr == player && MWBase::Environment::get().getWorld()->isFirstPerson()) if (resetIdle && mPtr == player && MWBase::Environment::get().getWorld()->isFirstPerson())
mIdleState = CharState_None; idle = CharState_None;
// In other cases we should not break swim and sneak animations // In other cases we should not break swim and sneak animations
if (resetIdle && mIdleState != CharState_IdleSneak && mIdleState != CharState_IdleSwim) if (resetIdle && mIdleState != CharState_IdleSneak && mIdleState != CharState_IdleSwim)
mIdleState = CharState_None; idle = CharState_None;
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete); animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
if(mUpperBodyState == UpperCharState_MinAttackToMaxAttack && !isKnockedDown()) if(mUpperBodyState == UpperCharState_MinAttackToMaxAttack && !isKnockedDown())
@ -2194,12 +2227,18 @@ void CharacterController::update(float duration)
: (sneak ? CharState_SneakBack : (sneak ? CharState_SneakBack
: (isrunning ? CharState_RunBack : CharState_WalkBack))); : (isrunning ? CharState_RunBack : CharState_WalkBack)));
} }
else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson())) else if(rot.z() != 0.0f)
{ {
if(rot.z() > rotationThreshold) // It seems only bipedal actors use turning animations.
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight; // Also do not use turning animations in the first-person view and when sneaking.
else if(rot.z() < -rotationThreshold) bool isFirstPlayer = mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson();
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft; if (!sneak && !isFirstPlayer && mPtr.getClass().isBipedal(mPtr))
{
if(rot.z() > rotationThreshold)
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
else if(rot.z() < -rotationThreshold)
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
}
} }
} }
@ -2217,16 +2256,21 @@ void CharacterController::update(float duration)
} }
else else
{ {
mTurnAnimationThreshold -= duration; if (mPtr.getClass().isBipedal(mPtr))
if (movestate == CharState_TurnRight || movestate == CharState_TurnLeft ||
movestate == CharState_SwimTurnRight || movestate == CharState_SwimTurnLeft)
{ {
mTurnAnimationThreshold = 0.05f; if (mTurnAnimationThreshold > 0)
} mTurnAnimationThreshold -= duration;
else if (movestate == CharState_None && isTurning()
&& mTurnAnimationThreshold > 0) if (movestate == CharState_TurnRight || movestate == CharState_TurnLeft ||
{ movestate == CharState_SwimTurnRight || movestate == CharState_SwimTurnLeft)
movestate = mMovementState; {
mTurnAnimationThreshold = 0.05f;
}
else if (movestate == CharState_None && isTurning()
&& mTurnAnimationThreshold > 0)
{
movestate = mMovementState;
}
} }
} }
@ -2235,13 +2279,12 @@ void CharacterController::update(float duration)
if(mAnimQueue.empty() || inwater || sneak) if(mAnimQueue.empty() || inwater || sneak)
{ {
// Note: turning animations should not interrupt idle ones. // Note: turning animations should not interrupt idle ones
// Also movement should not stop idle animation for spellcasting stance.
if (inwater) if (inwater)
idlestate = CharState_IdleSwim; idlestate = CharState_IdleSwim;
else if (sneak && !inJump) else if (sneak && !inJump)
idlestate = CharState_IdleSneak; idlestate = CharState_IdleSneak;
else if (movestate != CharState_None && !isTurning() && mWeaponType != WeapType_Spell) else if (movestate != CharState_None && !isTurning())
idlestate = CharState_None; idlestate = CharState_None;
else else
idlestate = CharState_Idle; idlestate = CharState_Idle;
@ -2253,7 +2296,7 @@ void CharacterController::update(float duration)
{ {
// bipedal means hand-to-hand could be used (which is handled in updateWeaponState). an existing InventoryStore means an actual weapon could be used. // bipedal means hand-to-hand could be used (which is handled in updateWeaponState). an existing InventoryStore means an actual weapon could be used.
if(cls.isBipedal(mPtr) || cls.hasInventoryStore(mPtr)) if(cls.isBipedal(mPtr) || cls.hasInventoryStore(mPtr))
forcestateupdate = updateWeaponState() || forcestateupdate; forcestateupdate = updateWeaponState(idlestate) || forcestateupdate;
else else
forcestateupdate = updateCreatureState() || forcestateupdate; forcestateupdate = updateCreatureState() || forcestateupdate;
@ -2268,9 +2311,11 @@ void CharacterController::update(float duration)
if (isTurning()) if (isTurning())
{ {
// Adjust animation speed from 1.0 to 1.5 multiplier // Adjust animation speed from 1.0 to 1.5 multiplier
float turnSpeed = std::min(1.5f, std::abs(rot.z()) / duration / static_cast<float>(osg::PI));
if (duration > 0) if (duration > 0)
{
float turnSpeed = std::min(1.5f, std::abs(rot.z()) / duration / static_cast<float>(osg::PI));
mAnimation->adjustSpeedMult(mCurrentMovement, std::max(turnSpeed, 1.0f)); mAnimation->adjustSpeedMult(mCurrentMovement, std::max(turnSpeed, 1.0f));
}
} }
else if (mMovementState != CharState_None && mAdjustMovementAnimSpeed) else if (mMovementState != CharState_None && mAdjustMovementAnimSpeed)
{ {

View file

@ -213,14 +213,14 @@ class CharacterController : public MWRender::Animation::TextKeyListener
void setAttackTypeBasedOnMovement(); void setAttackTypeBasedOnMovement();
void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false); void refreshCurrentAnims(CharacterState idle, CharacterState movement, JumpingState jump, bool force=false);
void refreshHitRecoilAnims(); void refreshHitRecoilAnims(CharacterState& idle);
void refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, bool force=false); void refreshJumpAnims(const WeaponInfo* weap, JumpingState jump, CharacterState& idle, bool force=false);
void refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, bool force=false); void refreshMovementAnims(const WeaponInfo* weap, CharacterState movement, CharacterState& idle, bool force=false);
void refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force=false); void refreshIdleAnims(const WeaponInfo* weap, CharacterState idle, bool force=false);
void clearAnimQueue(bool clearPersistAnims = false); void clearAnimQueue(bool clearPersistAnims = false);
bool updateWeaponState(); bool updateWeaponState(CharacterState& idle);
bool updateCreatureState(); bool updateCreatureState();
void updateIdleStormState(bool inwater); void updateIdleStormState(bool inwater);

View file

@ -82,7 +82,7 @@ namespace MWMechanics
maxMagn = effect.mMagnMax; maxMagn = effect.mMagnMax;
} }
int duration = 0; int duration = 1;
if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration)) if (!(magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration))
duration = effect.mDuration; duration = effect.mDuration;

View file

@ -232,20 +232,59 @@ namespace MWMechanics
case ESM::MagicEffect::CommandHumanoid: case ESM::MagicEffect::CommandHumanoid:
return 0.f; return 0.f;
case ESM::MagicEffect::Blind:
{
if (enemy.isEmpty())
return 0.f;
const CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
// Enemy can't attack
if (stats.isParalyzed() || stats.getKnockedDown())
return 0.f;
// Enemy doesn't attack
if (stats.getDrawState() != MWMechanics::DrawState_Weapon)
return 0.f;
break;
}
case ESM::MagicEffect::Sound: case ESM::MagicEffect::Sound:
{ {
if (enemy.isEmpty()) if (enemy.isEmpty())
return 0.f; return 0.f;
// there is no need to cast sound if enemy is not able to cast spells const CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
// Enemy can't cast spells
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude() > 0) if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude() > 0)
return 0.f; return 0.f;
if (stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0) if (stats.isParalyzed() || stats.getKnockedDown())
return 0.f; return 0.f;
// Enemy doesn't cast spells
if (stats.getDrawState() != MWMechanics::DrawState_Spell)
return 0.f;
break;
}
case ESM::MagicEffect::Silence:
{
if (enemy.isEmpty())
return 0.f;
const CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
// Enemy can't cast spells
if (stats.isParalyzed() || stats.getKnockedDown())
return 0.f;
// Enemy doesn't cast spells
if (stats.getDrawState() != MWMechanics::DrawState_Spell)
return 0.f;
break; break;
} }
@ -353,9 +392,10 @@ namespace MWMechanics
int priority = 1; int priority = 1;
if (effect.mEffectID == ESM::MagicEffect::RestoreHealth) if (effect.mEffectID == ESM::MagicEffect::RestoreHealth)
priority = 10; priority = 10;
const DynamicStat<float>& current = actor.getClass().getCreatureStats(actor). const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
getDynamic(effect.mEffectID - ESM::MagicEffect::RestoreHealth); const DynamicStat<float>& current = stats.getDynamic(effect.mEffectID - ESM::MagicEffect::RestoreHealth);
float toHeal = (effect.mMagnMin + effect.mMagnMax)/2.f * effect.mDuration; const float magnitude = (effect.mMagnMin + effect.mMagnMax)/2.f;
const float toHeal = magnitude * effect.mDuration;
// Effect doesn't heal more than we need, *or* we are below 1/2 health // Effect doesn't heal more than we need, *or* we are below 1/2 health
if (current.getModified() - current.getCurrent() > toHeal if (current.getModified() - current.getCurrent() > toHeal
|| current.getCurrent() < current.getModified()*0.5) || current.getCurrent() < current.getModified()*0.5)
@ -577,13 +617,19 @@ namespace MWMechanics
float rateEffects(const ESM::EffectList &list, const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy) float rateEffects(const ESM::EffectList &list, const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy)
{ {
// NOTE: enemy may be empty // NOTE: enemy may be empty
float rating = 0.f; float rating = 0.f;
float ratingMult = 1.f; // NB: this multiplier is applied to the effect rating, not the final rating
const MWWorld::Store<ESM::GameSetting>& gmst = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
static const float fAIMagicSpellMult = gmst.find("fAIMagicSpellMult")->mValue.getFloat();
static const float fAIRangeMagicSpellMult = gmst.find("fAIRangeMagicSpellMult")->mValue.getFloat();
for (std::vector<ESM::ENAMstruct>::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it) for (std::vector<ESM::ENAMstruct>::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it)
{ {
rating += rateEffect(*it, actor, enemy); ratingMult = (it->mRange == ESM::RT_Target) ? fAIRangeMagicSpellMult : fAIMagicSpellMult;
if (it->mRange == ESM::RT_Target) rating += rateEffect(*it, actor, enemy) * ratingMult;
rating *= 1.5f;
} }
return rating; return rating;
} }

View file

@ -21,7 +21,10 @@ namespace MWMechanics
float rateWeapon (const MWWorld::Ptr &item, const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy, int type, float rateWeapon (const MWWorld::Ptr &item, const MWWorld::Ptr& actor, const MWWorld::Ptr& enemy, int type,
float arrowRating, float boltRating) float arrowRating, float boltRating)
{ {
if (item.getTypeName() != typeid(ESM::Weapon).name()) if (enemy.isEmpty() || item.getTypeName() != typeid(ESM::Weapon).name())
return 0.f;
if (item.getClass().hasItemHealth(item) && item.getClass().getItemHealth(item) == 0)
return 0.f; return 0.f;
const ESM::Weapon* weapon = item.get<ESM::Weapon>()->mBase; const ESM::Weapon* weapon = item.get<ESM::Weapon>()->mBase;
@ -29,62 +32,46 @@ namespace MWMechanics
if (type != -1 && weapon->mData.mType != type) if (type != -1 && weapon->mData.mType != type)
return 0.f; return 0.f;
const MWBase::World* world = MWBase::Environment::get().getWorld();
const MWWorld::Store<ESM::GameSetting>& gmst = world->getStore().get<ESM::GameSetting>();
if (type == -1 && (weapon->mData.mType == ESM::Weapon::Arrow || weapon->mData.mType == ESM::Weapon::Bolt)) if (type == -1 && (weapon->mData.mType == ESM::Weapon::Arrow || weapon->mData.mType == ESM::Weapon::Bolt))
return 0.f; return 0.f;
float rating=0.f; float rating=0.f;
float rangedMult=1.f; static const float fAIMeleeWeaponMult = gmst.find("fAIMeleeWeaponMult")->mValue.getFloat();
float ratingMult = fAIMeleeWeaponMult;
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow && weapon->mData.mType <= ESM::Weapon::MarksmanThrown) if (weapon->mData.mType >= ESM::Weapon::MarksmanBow && weapon->mData.mType <= ESM::Weapon::MarksmanThrown)
{ {
// Range weapon is useless under water // Underwater ranged combat is impossible
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(actor), 0.75f)) if (world->isUnderwater(MWWorld::ConstPtr(actor), 0.75f)
return 0.f; || world->isUnderwater(MWWorld::ConstPtr(enemy), 0.75f))
if (enemy.isEmpty())
return 0.f;
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(enemy), 0.75f))
return 0.f; return 0.f;
// Use a higher rating multiplier if the actor is out of enemy's reach, use the normal mult otherwise
if (getDistanceMinusHalfExtents(actor, enemy) >= getMaxAttackDistance(enemy)) if (getDistanceMinusHalfExtents(actor, enemy) >= getMaxAttackDistance(enemy))
rangedMult = 1.5f; {
static const float fAIRangeMeleeWeaponMult = gmst.find("fAIRangeMeleeWeaponMult")->mValue.getFloat();
ratingMult = fAIRangeMeleeWeaponMult;
}
} }
const float chop = (weapon->mData.mChop[0] + weapon->mData.mChop[1]) / 2.f;
if (weapon->mData.mType >= ESM::Weapon::MarksmanBow) if (weapon->mData.mType >= ESM::Weapon::MarksmanBow)
{ rating = chop;
float rangedDamage = weapon->mData.mChop[0] + weapon->mData.mChop[1];
MWMechanics::adjustWeaponDamage(rangedDamage, item, actor);
rating = rangedDamage / 2.f;
if (weapon->mData.mType >= ESM::Weapon::MarksmanThrown)
MWMechanics::resistNormalWeapon(enemy, actor, item, rating);
}
else else
{ {
float meleeDamage = 0.f; const float slash = (weapon->mData.mSlash[0] + weapon->mData.mSlash[1]) / 2.f;
const float thrust = (weapon->mData.mThrust[0] + weapon->mData.mThrust[1]) / 2.f;
for (int i=0; i<2; ++i) rating = (slash * slash + thrust * thrust + chop * chop) / (slash + thrust + chop);
{
meleeDamage += weapon->mData.mSlash[i];
meleeDamage += weapon->mData.mThrust[i];
meleeDamage += weapon->mData.mChop[i];
}
MWMechanics::adjustWeaponDamage(meleeDamage, item, actor);
rating = meleeDamage / 6.f;
MWMechanics::resistNormalWeapon(enemy, actor, item, rating);
} }
if (item.getClass().hasItemHealth(item)) adjustWeaponDamage(rating, item, actor);
{
if (item.getClass().getItemHealth(item) == 0)
return 0.f;
}
if (weapon->mData.mType == ESM::Weapon::MarksmanBow) if (weapon->mData.mType != ESM::Weapon::MarksmanBow && weapon->mData.mType != ESM::Weapon::MarksmanCrossbow)
resistNormalWeapon(enemy, actor, item, rating);
else if (weapon->mData.mType == ESM::Weapon::MarksmanBow)
{ {
if (arrowRating <= 0.f) if (arrowRating <= 0.f)
rating = 0.f; rating = 0.f;
@ -101,7 +88,7 @@ namespace MWMechanics
if (!weapon->mEnchant.empty()) if (!weapon->mEnchant.empty())
{ {
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(weapon->mEnchant); const ESM::Enchantment* enchantment = world->getStore().get<ESM::Enchantment>().find(weapon->mEnchant);
if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes) if (enchantment->mData.mType == ESM::Enchantment::WhenStrikes)
{ {
int castCost = getEffectiveEnchantmentCastCost(static_cast<float>(enchantment->mData.mCost), actor); int castCost = getEffectiveEnchantmentCastCost(static_cast<float>(enchantment->mData.mCost), actor);
@ -111,22 +98,31 @@ 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;
if (actor.getClass().isNpc()) if (actor.getClass().isNpc())
{ {
int skill = item.getClass().getEquipmentSkill(item); int skill = item.getClass().getEquipmentSkill(item);
if (skill != -1) if (skill != -1)
{ value = actor.getClass().getSkill(actor, skill);
int value = actor.getClass().getSkill(actor, skill);
rating *= MWMechanics::getHitChance(actor, enemy, value) / 100.f;
}
} }
else else
{ {
MWWorld::LiveCellRef<ESM::Creature> *ref = actor.get<ESM::Creature>(); MWWorld::LiveCellRef<ESM::Creature> *ref = actor.get<ESM::Creature>();
rating *= MWMechanics::getHitChance(actor, enemy, ref->mBase->mData.mCombat) / 100.f; value = ref->mBase->mData.mCombat;
} }
return rating * rangedMult; rating *= getHitChance(actor, enemy, value) / 100.f;
if (weapon->mData.mType < ESM::Weapon::MarksmanBow)
rating *= weapon->mData.mSpeed;
return rating * ratingMult;
} }
float rateAmmo(const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy, MWWorld::Ptr &bestAmmo, ESM::Weapon::Type ammoType) float rateAmmo(const MWWorld::Ptr &actor, const MWWorld::Ptr &enemy, MWWorld::Ptr &bestAmmo, ESM::Weapon::Type ammoType)

View file

@ -219,6 +219,7 @@ namespace
RemoveFinishedCallbackVisitor(int effectId) RemoveFinishedCallbackVisitor(int effectId)
: RemoveVisitor() : RemoveVisitor()
, mHasMagicEffects(false)
, mEffectId(effectId) , mEffectId(effectId)
{ {
} }

View file

@ -1183,7 +1183,13 @@ namespace MWScript
runtime.pop(); runtime.pop();
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (spellId); const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find (spellId);
if (spell && spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power) if (!spell)
{
runtime.getContext().report("spellcasting failed: can not find spell \""+spellId+"\"");
return;
}
if (spell->mData.mType != ESM::Spell::ST_Spell && spell->mData.mType != ESM::Spell::ST_Power)
{ {
runtime.getContext().report("spellcasting failed: you can cast only spells and powers."); runtime.getContext().report("spellcasting failed: you can cast only spells and powers.");
return; return;

View file

@ -1483,7 +1483,8 @@ void OpenAL_Output::resumeSounds(int types)
OpenAL_Output::OpenAL_Output(SoundManager &mgr) OpenAL_Output::OpenAL_Output(SoundManager &mgr)
: Sound_Output(mgr), mDevice(0), mContext(0) : Sound_Output(mgr)
, mDevice(0), mContext(0)
, mListenerPos(0.0f, 0.0f, 0.0f), mListenerEnv(Env_Normal) , mListenerPos(0.0f, 0.0f, 0.0f), mListenerEnv(Env_Normal)
, mWaterFilter(0), mWaterEffect(0), mDefaultEffect(0), mEffectSlot(0) , mWaterFilter(0), mWaterEffect(0), mDefaultEffect(0), mEffectSlot(0)
, mStreamThread(new StreamThread) , mStreamThread(new StreamThread)

View file

@ -26,10 +26,10 @@ namespace MWSound
struct { struct {
bool EXT_EFX : 1; bool EXT_EFX : 1;
bool SOFT_HRTF : 1; bool SOFT_HRTF : 1;
} ALC; } ALC = {false, false};
struct { struct {
bool SOFT_source_spatialize : 1; bool SOFT_source_spatialize : 1;
} AL; } AL = {false};
typedef std::deque<ALuint> IDDq; typedef std::deque<ALuint> IDDq;
IDDq mFreeSources; IDDq mFreeSources;

View file

@ -17,6 +17,8 @@
#include "../mwbase/windowmanager.hpp" #include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwgui/inventorywindow.hpp"
#include "class.hpp" #include "class.hpp"
#include "containerstore.hpp" #include "containerstore.hpp"
@ -26,6 +28,17 @@ namespace MWWorld
void ActionTake::executeImp (const Ptr& actor) void ActionTake::executeImp (const Ptr& actor)
{ {
// When in GUI mode, we should use drag and drop
if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr())
{
MWGui::GuiMode mode = MWBase::Environment::get().getWindowManager()->getMode();
if (mode == MWGui::GM_Inventory || mode == MWGui::GM_Container)
{
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->pickUpObject(getTarget());
return;
}
}
MWBase::Environment::get().getMechanicsManager()->itemTaken( MWBase::Environment::get().getMechanicsManager()->itemTaken(
actor, getTarget(), MWWorld::Ptr(), getTarget().getRefData().getCount()); actor, getTarget(), MWWorld::Ptr(), getTarget().getRefData().getCount());
MWWorld::Ptr newitem = *actor.getClass().getContainerStore (actor).add (getTarget(), getTarget().getRefData().getCount(), actor); MWWorld::Ptr newitem = *actor.getClass().getContainerStore (actor).add (getTarget(), getTarget().getRefData().getCount(), actor);

View file

@ -1323,11 +1323,17 @@ namespace MWWorld
osg::Vec3f vec(x, y, z); osg::Vec3f vec(x, y, z);
CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL; // currCell == NULL should only happen for player, during initial startup CellStore *currCell = ptr.isInCell() ? ptr.getCell() : nullptr; // currCell == nullptr should only happen for player, during initial startup
bool isPlayer = ptr == mPlayer->getPlayer(); bool isPlayer = ptr == mPlayer->getPlayer();
bool haveToMove = isPlayer || (currCell && mWorldScene->isCellActive(*currCell)); bool haveToMove = isPlayer || (currCell && mWorldScene->isCellActive(*currCell));
MWWorld::Ptr newPtr = ptr; MWWorld::Ptr newPtr = ptr;
if (!isPlayer && !currCell)
throw std::runtime_error("Can not move actor \"" + ptr.getCellRef().getRefId() + "\" to another cell: current cell is nullptr");
if (!newCell)
throw std::runtime_error("Can not move actor \"" + ptr.getCellRef().getRefId() + "\" to another cell: new cell is nullptr");
if (currCell != newCell) if (currCell != newCell)
{ {
/* /*
@ -1371,10 +1377,10 @@ namespace MWWorld
addContainerScripts (getPlayerPtr(), newCell); addContainerScripts (getPlayerPtr(), newCell);
newPtr = getPlayerPtr(); newPtr = getPlayerPtr();
} }
else if (currCell) else
{ {
bool currCellActive = mWorldScene->isCellActive(*currCell); bool currCellActive = mWorldScene->isCellActive(*currCell);
bool newCellActive = newCell && mWorldScene->isCellActive(*newCell); bool newCellActive = mWorldScene->isCellActive(*newCell);
if (!currCellActive && newCellActive) if (!currCellActive && newCellActive)
{ {
newPtr = currCell->moveTo(ptr, newCell); newPtr = currCell->moveTo(ptr, newCell);

View file

@ -684,7 +684,7 @@ namespace MWWorld
End of tes3mp addition End of tes3mp addition
*/ */
void getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors); ///< get a list of actors standing on \a object void getActorsStandingOn (const MWWorld::ConstPtr& object, std::vector<MWWorld::Ptr> &actors) override; ///< get a list of actors standing on \a object
bool getPlayerStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if the player is standing on \a object bool getPlayerStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if the player is standing on \a object
bool getActorStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if any actor is standing on \a object bool getActorStandingOn (const MWWorld::ConstPtr& object) override; ///< @return true if any actor is standing on \a object
bool getPlayerCollidingWith(const MWWorld::ConstPtr& object) override; ///< @return true if the player is colliding with \a object bool getPlayerCollidingWith(const MWWorld::ConstPtr& object) override; ///< @return true if the player is colliding with \a object

View file

@ -38,7 +38,7 @@ namespace Compiler
{ {
case 'l': case 'l':
Generator::report (mCode, mLiterals, "%g"); Generator::report (mCode, mLiterals, "%d");
break; break;
case 'f': case 'f':

View file

@ -175,17 +175,18 @@ static void gdb_info(pid_t pid)
fflush(stdout); fflush(stdout);
/* Clean up */ /* Clean up */
remove(respfile); if (remove(respfile) != 0)
Log(Debug::Warning) << "Warning: can not remove file '" << respfile << "': " << std::strerror(errno);
} }
else else
{ {
/* Error creating temp file */ /* Error creating temp file */
if(fd >= 0) if(fd >= 0)
{ {
if (close(fd) == 0) if (close(fd) != 0)
remove(respfile); Log(Debug::Warning) << "Warning: can not close file '" << respfile << "': " << std::strerror(errno);
else else if (remove(respfile) != 0)
Log(Debug::Warning) << "Warning: can not close and remove file '" << respfile << "': " << std::strerror(errno); Log(Debug::Warning) << "Warning: can not remove file '" << respfile << "': " << std::strerror(errno);
} }
printf("!!! Could not create gdb command file\n"); printf("!!! Could not create gdb command file\n");
} }

View file

@ -41,8 +41,6 @@ namespace Debug
{ {
return size; return size;
} }
char mDebugLevel;
}; };
#if defined(_WIN32) && defined(_DEBUG) #if defined(_WIN32) && defined(_DEBUG)

View file

@ -43,14 +43,6 @@ public:
return *this; return *this;
} }
template<typename T>
Log& operator<<(const T& rhs)
{
if (mLevel <= Debug::CurrentDebugLevel)
std::cout << std::forward<const T&>(rhs);
return *this;
}
~Log() ~Log()
{ {

View file

@ -78,14 +78,14 @@ struct Cell
struct DATAstruct struct DATAstruct
{ {
int mFlags; int mFlags {0};
int mX, mY; int mX {0}, mY {0};
}; };
struct AMBIstruct struct AMBIstruct
{ {
Color mAmbient, mSunlight, mFog; Color mAmbient {0}, mSunlight {0}, mFog {0};
float mFogDensity; float mFogDensity {0.f};
}; };
Cell() : mName(""), Cell() : mName(""),

View file

@ -90,7 +90,7 @@ struct NPC
char mFactionID; char mFactionID;
unsigned short mHealth, mMana, mFatigue; unsigned short mHealth, mMana, mFatigue;
signed char mDisposition, mReputation, mRank; unsigned char mDisposition, mReputation, mRank;
char mUnknown; char mUnknown;
int mGold; int mGold;
}; // 52 bytes }; // 52 bytes
@ -101,7 +101,7 @@ struct NPC
{ {
short mLevel; short mLevel;
// see above // see above
signed char mDisposition, mReputation, mRank; unsigned char mDisposition, mReputation, mRank;
char mUnknown1, mUnknown2, mUnknown3; char mUnknown1, mUnknown2, mUnknown3;
int mGold; int mGold;
}; // 12 bytes }; // 12 bytes

View file

@ -103,21 +103,16 @@ namespace Files
}; };
ConstrainedFileStream::ConstrainedFileStream(const char *filename, size_t start, size_t length) ConstrainedFileStream::ConstrainedFileStream(std::unique_ptr<std::streambuf> buf)
: std::istream(new ConstrainedFileStreamBuf(filename, start, length)) : std::istream(buf.get())
, mBuf(std::move(buf))
{ {
} }
ConstrainedFileStream::~ConstrainedFileStream()
{
delete rdbuf();
}
IStreamPtr openConstrainedFileStream(const char *filename, IStreamPtr openConstrainedFileStream(const char *filename,
size_t start, size_t length) size_t start, size_t length)
{ {
return IStreamPtr(new ConstrainedFileStream(filename, start, length)); auto buf = std::unique_ptr<std::streambuf>(new ConstrainedFileStreamBuf(filename, start, length));
return IStreamPtr(new ConstrainedFileStream(std::move(buf)));
} }
} }

View file

@ -11,9 +11,11 @@ namespace Files
class ConstrainedFileStream : public std::istream class ConstrainedFileStream : public std::istream
{ {
public: public:
ConstrainedFileStream(const char *filename, ConstrainedFileStream(std::unique_ptr<std::streambuf> buf);
size_t start=0, size_t length=0xFFFFFFFF); virtual ~ConstrainedFileStream() {};
virtual ~ConstrainedFileStream();
private:
std::unique_ptr<std::streambuf> mBuf;
}; };
typedef std::shared_ptr<std::istream> IStreamPtr; typedef std::shared_ptr<std::istream> IStreamPtr;

View file

@ -161,7 +161,17 @@ namespace Gui
mTextures.clear(); mTextures.clear();
for (std::vector<MyGUI::ResourceManualFont*>::iterator it = mFonts.begin(); it != mFonts.end(); ++it) for (std::vector<MyGUI::ResourceManualFont*>::iterator it = mFonts.begin(); it != mFonts.end(); ++it)
MyGUI::ResourceManager::getInstance().removeByName((*it)->getResourceName()); {
try
{
MyGUI::ResourceManager::getInstance().removeByName((*it)->getResourceName());
}
catch(const MyGUI::Exception& e)
{
Log(Debug::Error) << "Error in the destructor: " << e.what();
}
}
mFonts.clear(); mFonts.clear();
} }

View file

@ -409,7 +409,7 @@ FlipController::FlipController(const FlipController &copy, const osg::CopyOp &co
void FlipController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv) void FlipController::apply(osg::StateSet* stateset, osg::NodeVisitor* nv)
{ {
if (hasInput() && mDelta != 0) if (hasInput() && mDelta != 0 && !mTextures.empty())
{ {
int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size(); int curTexture = int(getInputValue(nv) / mDelta) % mTextures.size();
stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]); stateset->setTextureAttribute(mTexSlot, mTextures[curTexture]);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

BIN
files/opencs/error-log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

View file

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
files/opencs/instance.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

View file

Before

Width:  |  Height:  |  Size: 521 B

After

Width:  |  Height:  |  Size: 521 B

View file

Before

Width:  |  Height:  |  Size: 516 B

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

After

Width:  |  Height:  |  Size: 356 B

BIN
files/opencs/menu-close.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

BIN
files/opencs/menu-exit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

BIN
files/opencs/menu-merge.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 B

BIN
files/opencs/menu-open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

BIN
files/opencs/menu-redo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

BIN
files/opencs/menu-save.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

BIN
files/opencs/menu-undo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

BIN
files/opencs/metadata.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

BIN
files/opencs/object.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
files/opencs/region-map.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

After

Width:  |  Height:  |  Size: 605 B

View file

@ -15,6 +15,7 @@
<file>clothing.png</file> <file>clothing.png</file>
<file>container.png</file> <file>container.png</file>
<file>creature.png</file> <file>creature.png</file>
<file>debug-profile.png</file>
<file>dialogue-info.png</file> <file>dialogue-info.png</file>
<file>dialogue-journal.png</file> <file>dialogue-journal.png</file>
<file>dialogue-regular.png</file> <file>dialogue-regular.png</file>
@ -27,34 +28,60 @@
<file>journal-topics.png</file> <file>journal-topics.png</file>
<file>door.png</file> <file>door.png</file>
<file>enchantment.png</file> <file>enchantment.png</file>
<file>error-log.png</file>
<file>faction.png</file> <file>faction.png</file>
<file>filter.png</file> <file>filter.png</file>
<file>global-variable.png</file> <file>global-variable.png</file>
<file>gmst.png</file> <file>gmst.png</file>
<file>Info.png</file> <file>info.png</file>
<file>ingredient.png</file> <file>ingredient.png</file>
<file>instance.png</file>
<file>land-heightmap.png</file> <file>land-heightmap.png</file>
<file>land-texture.png</file> <file>land-texture.png</file>
<file>leveled-creature.png</file> <file>levelled-creature.png</file>
<file>leveled-item.png</file> <file>levelled-item.png</file>
<file>light.png</file> <file>light.png</file>
<file>lockpick.png</file> <file>lockpick.png</file>
<file>magic-effect.png</file> <file>magic-effect.png</file>
<file>magicrabbit.png</file> <file>magicrabbit.png</file>
<file>map.png</file> <file>map.png</file>
<file>probe.png</file>
<file>menu-close.png</file>
<file>menu-exit.png</file>
<file>menu-new-addon.png</file>
<file>menu-new-game.png</file>
<file>menu-new-window.png</file>
<file>menu-merge.png</file>
<file>menu-open.png</file>
<file>menu-preferences.png</file>
<file>menu-reload.png</file>
<file>menu-redo.png</file>
<file>menu-save.png</file>
<file>menu-search.png</file>
<file>menu-status-bar.png</file>
<file>menu-undo.png</file>
<file>menu-verify.png</file>
<file>metadata.png</file>
<file>miscellaneous.png</file> <file>miscellaneous.png</file>
<file alias="list-modified">list-modified.png</file> <file alias="list-modified">list-modified.png</file>
<file>npc.png</file> <file>npc.png</file>
<file>object.png</file>
<file>pathgrid.png</file> <file>pathgrid.png</file>
<file>potion.png</file> <file>potion.png</file>
<file>probe.png</file>
<file>race.png</file> <file>race.png</file>
<file>random-item.png</file> <file>random-item.png</file>
<file>random.png</file> <file>random.png</file>
<file alias="list-removed">list-removed.png</file> <file alias="list-removed">list-removed.png</file>
<file>region.png</file>
<file>region-map.png</file>
<file>repair.png</file> <file>repair.png</file>
<file>run-log.png</file>
<file>run-openmw.png</file>
<file>scene.png</file>
<file>script.png</file> <file>script.png</file>
<file>skill.png</file> <file>skill.png</file>
<file>start-script.png</file>
<file>stop-openmw.png</file>
<file>sound-generator.png</file> <file>sound-generator.png</file>
<file>sound.png</file> <file>sound.png</file>
<file>spell.png</file> <file>spell.png</file>
@ -64,7 +91,6 @@
<file alias="record-next">record-next.png</file> <file alias="record-next">record-next.png</file>
<file alias="record-previous">record-previous.png</file> <file alias="record-previous">record-previous.png</file>
<file alias="edit-delete">record-delete.png</file> <file alias="edit-delete">record-delete.png</file>
<file alias="edit-undo">record-revert.png</file>
<file alias="edit-preview">record-preview.png</file> <file alias="edit-preview">record-preview.png</file>
<file alias="edit-clone">record-clone.png</file> <file alias="edit-clone">record-clone.png</file>
<file alias="edit-add">record-add.png</file> <file alias="edit-add">record-add.png</file>

BIN
files/opencs/run-log.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

BIN
files/opencs/run-openmw.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

BIN
files/opencs/scene.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B