1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-30 13:15:32 +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

@ -680,7 +680,7 @@ if (WIN32)
# Warnings that aren't enabled normally and don't need to be enabled # Warnings that aren't enabled normally and don't need to be enabled
# They're unneeded and sometimes completely retarded warnings that /Wall enables # They're unneeded and sometimes completely retarded warnings that /Wall enables
# Not going to bother commenting them as they tend to warn on every standard library file # Not going to bother commenting them as they tend to warn on every standard library file
4061 4263 4264 4266 4350 4371 4435 4514 4548 4571 4610 4619 4623 4625 4061 4263 4264 4266 4350 4371 4435 4514 4548 4571 4610 4619 4623 4625
4626 4628 4640 4668 4710 4711 4768 4820 4826 4917 4946 5032 5039 5045 4626 4628 4640 4668 4710 4711 4768 4820 4826 4917 4946 5032 5039 5045
# Warnings that are thrown on standard libraries and not OpenMW # Warnings that are thrown on standard libraries and not OpenMW
@ -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