1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-29 17: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 #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 #4260: Keyboard navigation makes persuasion exploitable
Bug #4271: Scamp flickers when attacking
Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+
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 #4311: OpenMW does not handle RootCollisionNode correctly
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 #4368: Settings window ok button doesn't have key focus by default
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 #4531: Movement does not reset idle animations
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 #4551: Replace 0 sound range with default range separately
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 #4607: Scaling for animated collision shapes 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 #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 #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 #2606: Editor: Implemented (optional) case sensitive global search
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 #4579: Add option for applying Strength into hand to hand damage
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 #4545: Enable is_pod string test
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
# 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
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
# Warnings that are thrown on standard libraries and not OpenMW
@ -699,6 +699,7 @@ if (WIN32)
# caused by boost
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
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
{
public:
ConvertGAME() : mHasGame(false) {}
ConvertGAME()
: mHasGame(false)
{
}
virtual void read(ESM::ESMReader &esm)
{

View file

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

View file

@ -305,6 +305,7 @@ void CSMPrefs::State::declare()
declareShortcut ("document-assets-videos", "Open Video Asset List", QKeySequence());
declareShortcut ("document-debug-run", "Run Debug", QKeySequence());
declareShortcut ("document-debug-shutdown", "Stop Debug", QKeySequence());
declareShortcut ("document-debug-profiles", "Debug Profiles", QKeySequence());
declareShortcut ("document-debug-runlog", "Open Run Log", QKeySequence());
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].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())
{
std::ostringstream ss;

View file

@ -18,47 +18,43 @@ namespace
static const TypeData sNoArg[] =
{
{ 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_Gmsts, "Game Settings", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
"Objects", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References,
"Instances", 0 },
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap,
"Region Map", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "LandTextures", 0 },
{ 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_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", ":./global-variable.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", ":./gmst.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", ":./skill.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", ":./class.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", ":./faction.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", ":./race.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", ":./sound.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", ":./script.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", ":./region.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", ":./birthsign.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", ":./spell.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Topics, "Topics", ":./dialogue-topics.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Journals, "Journals", ":./journal-topics.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_TopicInfos, "Topic Infos", ":./dialogue-topic-infos.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_JournalInfos, "Journal Infos", ":./journal-topic-infos.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", ":./cell.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Enchantments, "Enchantments", ":./enchantment.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_BodyParts, "Body Parts", ":./body-part.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, "Objects", ":./object.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, "Instances", ":./instance.png" },
{ CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", ":./region-map.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", ":./filter.png" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", ":./resources-mesh" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", ":./resources-icon" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files", ":./resources-music" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", ":resources-sound" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", ":./resources-texture" },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", ":./resources-video" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles", ":./debug-profile.png" },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":./run-log.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", ":./sound-generator.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", ":./magic-effect.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Lands, "Lands", ":./land-heightmap.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_LandTextures, "Land Textures", ":./land-texture.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", ":./pathgrid.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", ":./start-script.png" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Metadata", ":./metadata.png" },
{ 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_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_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_Potion, "Potion", ":./potion.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_Ingredient, "Ingredient", ":./ingredient.png" },
{ 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,
"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_Lockpick, "Lockpick", ":./lockpick.png" },
{ 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_Static, "Static", ":./static.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_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", ":./scene.png" },
{ 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_BodyPart, "Body Part", ":./body-part.png" },
{ 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_Music, "Music", ":resources-music" },
{ 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_Video, "Video", ":resources-video"},
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", 0 },
{ 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_Music, "Music", ":./resources-music" },
{ 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_Video, "Video", ":./resources-video" },
{ 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_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_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_StartScript, "Start Script", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Meta Data", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", ":./start-script.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Metadata", ":./metadata.png" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
};
static const TypeData sIndexArg[] =
{
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", 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", ":./error-log.png" },
{ 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
};
}

View file

@ -47,58 +47,40 @@ void CSVDoc::View::setupFileMenu()
{
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()));
setupShortcut("document-file-newgame", newGame);
file->addAction (newGame);
QAction *newAddon = new QAction (tr ("New Addon"), this);
QAction* newAddon = createMenuEntry("New Addon", ":./menu-new-addon.png", file, "document-file-newaddon");
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()));
setupShortcut("document-file-open", open);
file->addAction (open);
mSave = new QAction (tr ("Save"), this);
connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
setupShortcut("document-file-save", mSave);
file->addAction (mSave);
QAction* save = createMenuEntry("Save", ":./menu-save.png", file, "document-file-save");
connect (save, SIGNAL (triggered()), this, SLOT (save()));
mSave = save;
mVerify = new QAction (tr ("Verify"), this);
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
setupShortcut("document-file-verify", mVerify);
file->addAction (mVerify);
QAction* verify = createMenuEntry("Verify", ":./menu-verify.png", file, "document-file-verify");
connect (verify, SIGNAL (triggered()), this, SLOT (verify()));
mVerify = verify;
mMerge = new QAction (tr ("Merge"), this);
connect (mMerge, SIGNAL (triggered()), this, SLOT (merge()));
setupShortcut("document-file-merge", mMerge);
file->addAction (mMerge);
QAction* merge = createMenuEntry("Merge", ":./menu-merge.png", file, "document-file-merge");
connect (merge, SIGNAL (triggered()), this, SLOT (merge()));
mMerge = merge;
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()));
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()));
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()));
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 (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
@ -130,251 +112,174 @@ void CSVDoc::View::setupEditMenu()
mUndo = mDocument->getUndoStack().createUndoAction (this, tr("Undo"));
setupShortcut("document-edit-undo", mUndo);
connect(mUndo, SIGNAL (changed ()), this, SLOT (undoActionChanged ()));
mUndo->setIcon(QIcon(QString::fromStdString(":./menu-undo.png")));
edit->addAction (mUndo);
mRedo = mDocument->getUndoStack().createRedoAction (this, tr("Redo"));
connect(mRedo, SIGNAL (changed ()), this, SLOT (redoActionChanged ()));
setupShortcut("document-edit-redo", mRedo);
mRedo->setIcon(QIcon(QString::fromStdString(":./menu-redo.png")));
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()));
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()));
setupShortcut("document-edit-search", search);
edit->addAction (search);
}
void CSVDoc::View::setupViewMenu()
{
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()));
setupShortcut("document-view-newview", newWindow);
view->addAction (newWindow);
mShowStatusBar = new QAction (tr ("Toggle Status Bar"), this);
mShowStatusBar->setCheckable (true);
mShowStatusBar = createMenuEntry("Toggle Status Bar", ":./menu-status-bar.png", view, "document-view-statusbar");
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());
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()));
setupShortcut("document-view-filters", filters);
view->addAction (filters);
}
void CSVDoc::View::setupWorldMenu()
{
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()));
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()));
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()));
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()));
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()));
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()));
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()));
setupShortcut("document-world-pathgrid", grid);
world->addAction (grid);
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()));
setupShortcut("document-world-regionmap", regionMap);
world->addAction (regionMap);
}
void CSVDoc::View::setupMechanicsMenu()
{
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()));
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()));
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()));
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()));
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()));
setupShortcut("document-mechanics-enchantments", enchantments);
mechanics->addAction (enchantments);
QAction *effects = new QAction (tr ("Magic Effects"), this);
connect (effects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView()));
setupShortcut("document-mechanics-magiceffects", effects);
mechanics->addAction (effects);
QAction* magicEffects = createMenuEntry(CSMWorld::UniversalId::Type_MagicEffects, mechanics, "document-mechanics-magiceffects");
connect (magicEffects, SIGNAL (triggered()), this, SLOT (addMagicEffectsSubView()));
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()));
setupShortcut("document-mechanics-startscripts", startScripts);
mechanics->addAction (startScripts);
}
void CSVDoc::View::setupCharacterMenu()
{
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()));
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()));
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()));
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()));
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()));
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()));
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()));
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()));
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()));
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()));
setupShortcut("document-character-bodyparts", bodyParts);
characters->addAction (bodyParts);
}
void CSVDoc::View::setupAssetsMenu()
{
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()));
setupShortcut("document-assets-reload", reload);
assets->addAction (reload);
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()));
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()));
setupShortcut("document-assets-soundgens", soundGens);
assets->addAction (soundGens);
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()));
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()));
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()));
setupShortcut("document-assets-music", musics);
assets->addAction (musics);
QAction *soundsRes = new QAction (tr ("Sound Files"), this);
connect (soundsRes, SIGNAL (triggered()), this, SLOT (addSoundsResSubView()));
setupShortcut("document-assets-soundres", soundsRes);
assets->addAction (soundsRes);
QAction* soundFiles = createMenuEntry(CSMWorld::UniversalId::Type_SoundsRes, assets, "document-assets-soundres");
connect (soundFiles, SIGNAL (triggered()), this, SLOT (addSoundsResSubView()));
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()));
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()));
setupShortcut("document-assets-videos", videos);
assets->addAction (videos);
}
void CSVDoc::View::setupDebugMenu()
{
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()));
debug->addAction (profiles);
debug->addSeparator();
@ -387,18 +292,41 @@ void CSVDoc::View::setupDebugMenu()
QAction *runDebug = debug->addMenu (mGlobalDebugProfileMenu);
runDebug->setText (tr ("Run OpenMW"));
setupShortcut("document-debug-run", runDebug);
runDebug->setIcon(QIcon(QString::fromStdString(":./run-openmw.png")));
mStopDebug = new QAction (tr ("Shutdown OpenMW"), this);
connect (mStopDebug, SIGNAL (triggered()), this, SLOT (stop()));
setupShortcut("document-debug-shutdown", mStopDebug);
debug->addAction (mStopDebug);
QAction* stopDebug = createMenuEntry("Stop OpenMW", ":./stop-openmw.png", debug, "document-debug-shutdown");
connect (stopDebug, SIGNAL (triggered()), this, SLOT (stop()));
mStopDebug = stopDebug;
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()));
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()

View file

@ -66,6 +66,9 @@ namespace CSVDoc
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 setupEditMenu();

View file

@ -436,7 +436,8 @@ namespace MWBase
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);
bool sneaking = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak);
bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run);
bool sneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr) && stats.getStance(MWMechanics::CreatureStats::Stance_Sneak);
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()*
(gmst.fMaxWalkSpeed->mValue.getFloat() - gmst.fMinWalkSpeed->mValue.getFloat());
@ -1149,7 +1149,7 @@ namespace MWClass
flySpeed = std::max(0.0f, flySpeed);
moveSpeed = flySpeed;
}
else if(world->isSwimming(ptr))
else if (world->isSwimming(ptr))
{
float swimSpeed = walkSpeed;
if(running)
@ -1159,7 +1159,7 @@ namespace MWClass
gmst.fSwimRunAthleticsMult->mValue.getFloat();
moveSpeed = swimSpeed;
}
else if(running && !sneaking)
else if (running)
moveSpeed = runSpeed;
else
moveSpeed = walkSpeed;

View file

@ -302,24 +302,27 @@ namespace MWClass
{
text += "\n#{sType} ";
std::map <int, std::pair <std::string, std::string> > mapping;
mapping[ESM::Weapon::ShortBladeOneHand] = std::make_pair("sSkillShortblade", "sOneHanded");
mapping[ESM::Weapon::LongBladeOneHand] = std::make_pair("sSkillLongblade", "sOneHanded");
mapping[ESM::Weapon::LongBladeTwoHand] = std::make_pair("sSkillLongblade", "sTwoHanded");
mapping[ESM::Weapon::BluntOneHand] = std::make_pair("sSkillBluntweapon", "sOneHanded");
mapping[ESM::Weapon::BluntTwoClose] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
mapping[ESM::Weapon::BluntTwoWide] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
mapping[ESM::Weapon::SpearTwoWide] = std::make_pair("sSkillSpear", "sTwoHanded");
mapping[ESM::Weapon::AxeOneHand] = std::make_pair("sSkillAxe", "sOneHanded");
mapping[ESM::Weapon::AxeTwoHand] = std::make_pair("sSkillAxe", "sTwoHanded");
mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::MarksmanCrossbow] = 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", "");
static std::map <int, std::pair <std::string, std::string> > mapping;
if (mapping.empty())
{
mapping[ESM::Weapon::ShortBladeOneHand] = std::make_pair("sSkillShortblade", "sOneHanded");
mapping[ESM::Weapon::LongBladeOneHand] = std::make_pair("sSkillLongblade", "sOneHanded");
mapping[ESM::Weapon::LongBladeTwoHand] = std::make_pair("sSkillLongblade", "sTwoHanded");
mapping[ESM::Weapon::BluntOneHand] = std::make_pair("sSkillBluntweapon", "sOneHanded");
mapping[ESM::Weapon::BluntTwoClose] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
mapping[ESM::Weapon::BluntTwoWide] = std::make_pair("sSkillBluntweapon", "sTwoHanded");
mapping[ESM::Weapon::SpearTwoWide] = std::make_pair("sSkillSpear", "sTwoHanded");
mapping[ESM::Weapon::AxeOneHand] = std::make_pair("sSkillAxe", "sOneHanded");
mapping[ESM::Weapon::AxeTwoHand] = std::make_pair("sSkillAxe", "sTwoHanded");
mapping[ESM::Weapon::MarksmanBow] = std::make_pair("sSkillMarksman", "");
mapping[ESM::Weapon::MarksmanCrossbow] = 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;
std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second;
const std::string type = mapping[ref->mBase->mData.mType].first;
const std::string oneOrTwoHanded = mapping[ref->mBase->mData.mType].second;
text += store.get<ESM::GameSetting>().find(type)->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)
{
onCreateButtonClicked(sender);
// To do not spam onAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
}
void AlchemyWindow::onCancelButtonClicked(MyGUI::Widget* _sender)

View file

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

View file

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

View file

@ -288,6 +288,9 @@ namespace MWGui
void EnchantingDialog::onAccept(MyGUI::EditBox *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)

View file

@ -6,6 +6,8 @@
#include <MyGUI_Gui.h>
#include <MyGUI_Window.h>
#include <components/debug/debuglog.hpp>
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/environment.hpp"
@ -49,7 +51,14 @@ 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)
@ -172,7 +181,7 @@ enum Direction
D_Prev
};
bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text)
bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat)
{
if (!mEnabled)
return false;
@ -192,7 +201,14 @@ bool KeyboardNavigation::injectKeyPress(MyGUI::KeyCode key, unsigned int text)
case MyGUI::KeyCode::Return:
case MyGUI::KeyCode::NumpadEnter:
case MyGUI::KeyCode::Space:
{
// We should disable repeating for activation keys
MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::None);
if (repeat)
return true;
return accept();
}
default:
return false;
}

View file

@ -14,7 +14,7 @@ namespace MWGui
~KeyboardNavigation();
/// @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 restoreFocus(int mode);

View file

@ -5,6 +5,8 @@
#include <MyGUI_WidgetDefines.h>
#include <MyGUI_Widget.h>
#include <components/debug/debuglog.hpp>
namespace MWGui
{
/** 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)
: mMainWidget(nullptr)
{ 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);

View file

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

View file

@ -99,7 +99,14 @@ namespace MWGui
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)

View file

@ -159,7 +159,9 @@ namespace MWGui
mDurationValue->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");
setVisible(true);
@ -324,8 +326,9 @@ namespace MWGui
}
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);
}
@ -446,6 +449,9 @@ namespace MWGui
void SpellCreationDialog::onAccept(MyGUI::EditBox *sender)
{
onBuyButtonClicked(sender);
// To do not spam onAccept() again and again
MWBase::Environment::get().getWindowManager()->injectKeyRelease(MyGUI::KeyCode::None);
}
void SpellCreationDialog::onOpen()

View file

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

View file

@ -367,6 +367,9 @@ namespace MWGui
void TradeWindow::onAccept(MyGUI::EditBox *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)

View file

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

View file

@ -465,7 +465,8 @@ namespace MWGui
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:
const MWWorld::ESMStore* mStore;

View file

@ -226,7 +226,7 @@ namespace MWInput
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)
@ -733,7 +733,7 @@ namespace MWInput
bool consumed = false;
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
( !(SDLK_SCANCODE_MASK & arg.keysym.sym) && std::isprint(arg.keysym.sym)))
consumed = true;
@ -1245,7 +1245,7 @@ namespace MWInput
if (MWBase::Environment::get().getWindowManager()->isGuiMode())
{
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"])
mPlayer->activate();

View file

@ -259,7 +259,7 @@ std::string CharacterController::chooseRandomGroup (const std::string& prefix, i
return prefix + toString(roll);
}
void CharacterController::refreshHitRecoilAnims()
void CharacterController::refreshHitRecoilAnims(CharacterState& idle)
{
bool recovery = mPtr.getClass().getCreatureStats(mPtr).getHitRecovery();
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);
}
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)
{
mIdleState = CharState_None;
if (jump != JumpState_None)
idle = CharState_None;
bool startAtLoop = (jump == mJumpState);
mJumpState = jump;
@ -388,6 +390,11 @@ void CharacterController::refreshJumpAnims(const WeaponInfo* weap, JumpingState
jumpmask = MWRender::Animation::BlendMask_LowerBody;
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
if (mWeaponType == WeapType_Crossbow)
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;
std::string movementAnimName;
MWRender::Animation::BlendMask movemask = MWRender::Animation::BlendMask_All;
const StateInfo *movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(mMovementState));
movemask = MWRender::Animation::BlendMask_All;
movestate = std::find_if(sMovementList, sMovementListEnd, FindCharState(movement));
if(movestate != sMovementListEnd)
{
movementAnimName = movestate->groupname;
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;
else
movementAnimName += weap->shortgroup;
if(!mAnimation->hasAnimation(movementAnimName))
{
movemask = MWRender::Animation::BlendMask_LowerBody;
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
if (mWeaponType == WeapType_Crossbow)
movementAnimName += "1h";
}
}
}
}
if(force || movement != mMovementState)
{
mMovementState = movement;
if(movestate != sMovementListEnd)
{
if(!mAnimation->hasAnimation(movementAnimName))
{
std::string::size_type swimpos = movementAnimName.find("swim");
@ -467,6 +488,10 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
}
else
{
// For crossbow animations use 1h ones as fallback
if (mWeaponType == WeapType_Crossbow)
movementAnimName += "1h";
movementAnimName.erase(swimpos, 4);
if (weap != sWeaponTypeListEnd)
{
@ -543,7 +568,15 @@ void CharacterController::refreshMovementAnims(const WeaponInfo* weap, Character
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;
size_t numLoops = ~0ul;
@ -602,24 +635,16 @@ void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterStat
return;
if (mPtr.getClass().isActor())
refreshHitRecoilAnims();
refreshHitRecoilAnims(idle);
const WeaponInfo *weap = std::find_if(sWeaponTypeList, sWeaponTypeListEnd, FindWeaponType(mWeaponType));
if (!mPtr.getClass().hasInventoryStore(mPtr))
weap = sWeaponTypeListEnd;
refreshJumpAnims(weap, jump, force);
refreshMovementAnims(weap, movement, force);
refreshJumpAnims(weap, jump, idle, force);
refreshMovementAnims(weap, movement, idle, force);
// 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);
}
@ -1255,7 +1280,7 @@ bool CharacterController::updateCarriedLeftVisible(WeaponType weaptype) const
}
}
bool CharacterController::updateWeaponState()
bool CharacterController::updateWeaponState(CharacterState& idle)
{
const MWWorld::Class &cls = mPtr.getClass();
CreatureStats &stats = cls.getCreatureStats(mPtr);
@ -1454,6 +1479,14 @@ bool CharacterController::updateWeaponState()
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
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)
{
// 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.
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
if (resetIdle && mIdleState != CharState_IdleSneak && mIdleState != CharState_IdleSwim)
mIdleState = CharState_None;
idle = CharState_None;
animPlaying = mAnimation->getInfo(mCurrentWeapon, &complete);
if(mUpperBodyState == UpperCharState_MinAttackToMaxAttack && !isKnockedDown())
@ -2194,12 +2227,18 @@ void CharacterController::update(float duration)
: (sneak ? CharState_SneakBack
: (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)
movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight;
else if(rot.z() < -rotationThreshold)
movestate = inwater ? CharState_SwimTurnLeft : CharState_TurnLeft;
// It seems only bipedal actors use turning animations.
// Also do not use turning animations in the first-person view and when sneaking.
bool isFirstPlayer = mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson();
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
{
mTurnAnimationThreshold -= duration;
if (movestate == CharState_TurnRight || movestate == CharState_TurnLeft ||
movestate == CharState_SwimTurnRight || movestate == CharState_SwimTurnLeft)
if (mPtr.getClass().isBipedal(mPtr))
{
mTurnAnimationThreshold = 0.05f;
}
else if (movestate == CharState_None && isTurning()
&& mTurnAnimationThreshold > 0)
{
movestate = mMovementState;
if (mTurnAnimationThreshold > 0)
mTurnAnimationThreshold -= duration;
if (movestate == CharState_TurnRight || movestate == CharState_TurnLeft ||
movestate == CharState_SwimTurnRight || movestate == CharState_SwimTurnLeft)
{
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)
{
// Note: turning animations should not interrupt idle ones.
// Also movement should not stop idle animation for spellcasting stance.
// Note: turning animations should not interrupt idle ones
if (inwater)
idlestate = CharState_IdleSwim;
else if (sneak && !inJump)
idlestate = CharState_IdleSneak;
else if (movestate != CharState_None && !isTurning() && mWeaponType != WeapType_Spell)
else if (movestate != CharState_None && !isTurning())
idlestate = CharState_None;
else
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.
if(cls.isBipedal(mPtr) || cls.hasInventoryStore(mPtr))
forcestateupdate = updateWeaponState() || forcestateupdate;
forcestateupdate = updateWeaponState(idlestate) || forcestateupdate;
else
forcestateupdate = updateCreatureState() || forcestateupdate;
@ -2268,9 +2311,11 @@ void CharacterController::update(float duration)
if (isTurning())
{
// 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)
{
float turnSpeed = std::min(1.5f, std::abs(rot.z()) / duration / static_cast<float>(osg::PI));
mAnimation->adjustSpeedMult(mCurrentMovement, std::max(turnSpeed, 1.0f));
}
}
else if (mMovementState != CharState_None && mAdjustMovementAnimSpeed)
{

View file

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

View file

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

View file

@ -232,20 +232,59 @@ namespace MWMechanics
case ESM::MagicEffect::CommandHumanoid:
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:
{
if (enemy.isEmpty())
return 0.f;
// there is no need to cast sound if enemy is not able to cast spells
CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
const CreatureStats& stats = enemy.getClass().getCreatureStats(enemy);
// Enemy can't cast spells
if (stats.getMagicEffects().get(ESM::MagicEffect::Silence).getMagnitude() > 0)
return 0.f;
if (stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getMagnitude() > 0)
if (stats.isParalyzed() || stats.getKnockedDown())
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;
}
@ -353,9 +392,10 @@ namespace MWMechanics
int priority = 1;
if (effect.mEffectID == ESM::MagicEffect::RestoreHealth)
priority = 10;
const DynamicStat<float>& current = actor.getClass().getCreatureStats(actor).
getDynamic(effect.mEffectID - ESM::MagicEffect::RestoreHealth);
float toHeal = (effect.mMagnMin + effect.mMagnMax)/2.f * effect.mDuration;
const MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
const DynamicStat<float>& current = stats.getDynamic(effect.mEffectID - ESM::MagicEffect::RestoreHealth);
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
if (current.getModified() - current.getCurrent() > toHeal
|| 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)
{
// NOTE: enemy may be empty
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)
{
rating += rateEffect(*it, actor, enemy);
ratingMult = (it->mRange == ESM::RT_Target) ? fAIRangeMagicSpellMult : fAIMagicSpellMult;
if (it->mRange == ESM::RT_Target)
rating *= 1.5f;
rating += rateEffect(*it, actor, enemy) * ratingMult;
}
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 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;
const ESM::Weapon* weapon = item.get<ESM::Weapon>()->mBase;
@ -29,62 +32,46 @@ namespace MWMechanics
if (type != -1 && weapon->mData.mType != type)
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))
return 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)
{
// Range weapon is useless under water
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(actor), 0.75f))
return 0.f;
if (enemy.isEmpty())
return 0.f;
if (MWBase::Environment::get().getWorld()->isUnderwater(MWWorld::ConstPtr(enemy), 0.75f))
// Underwater ranged combat is impossible
if (world->isUnderwater(MWWorld::ConstPtr(actor), 0.75f)
|| world->isUnderwater(MWWorld::ConstPtr(enemy), 0.75f))
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))
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)
{
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);
}
rating = chop;
else
{
float meleeDamage = 0.f;
for (int i=0; i<2; ++i)
{
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);
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;
rating = (slash * slash + thrust * thrust + chop * chop) / (slash + thrust + chop);
}
if (item.getClass().hasItemHealth(item))
{
if (item.getClass().getItemHealth(item) == 0)
return 0.f;
}
adjustWeaponDamage(rating, item, actor);
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)
rating = 0.f;
@ -101,7 +88,7 @@ namespace MWMechanics
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)
{
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())
{
int skill = item.getClass().getEquipmentSkill(item);
if (skill != -1)
{
int value = actor.getClass().getSkill(actor, skill);
rating *= MWMechanics::getHitChance(actor, enemy, value) / 100.f;
}
value = actor.getClass().getSkill(actor, skill);
}
else
{
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)

View file

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

View file

@ -1183,7 +1183,13 @@ namespace MWScript
runtime.pop();
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.");
return;

View file

@ -1483,7 +1483,8 @@ void OpenAL_Output::resumeSounds(int types)
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)
, mWaterFilter(0), mWaterEffect(0), mDefaultEffect(0), mEffectSlot(0)
, mStreamThread(new StreamThread)

View file

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

View file

@ -17,6 +17,8 @@
#include "../mwbase/windowmanager.hpp"
#include "../mwbase/mechanicsmanager.hpp"
#include "../mwgui/inventorywindow.hpp"
#include "class.hpp"
#include "containerstore.hpp"
@ -26,6 +28,17 @@ namespace MWWorld
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(
actor, getTarget(), MWWorld::Ptr(), getTarget().getRefData().getCount());
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);
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 haveToMove = isPlayer || (currCell && mWorldScene->isCellActive(*currCell));
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)
{
/*
@ -1371,10 +1377,10 @@ namespace MWWorld
addContainerScripts (getPlayerPtr(), newCell);
newPtr = getPlayerPtr();
}
else if (currCell)
else
{
bool currCellActive = mWorldScene->isCellActive(*currCell);
bool newCellActive = newCell && mWorldScene->isCellActive(*newCell);
bool newCellActive = mWorldScene->isCellActive(*newCell);
if (!currCellActive && newCellActive)
{
newPtr = currCell->moveTo(ptr, newCell);

View file

@ -684,7 +684,7 @@ namespace MWWorld
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 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -103,21 +103,16 @@ namespace Files
};
ConstrainedFileStream::ConstrainedFileStream(const char *filename, size_t start, size_t length)
: std::istream(new ConstrainedFileStreamBuf(filename, start, length))
ConstrainedFileStream::ConstrainedFileStream(std::unique_ptr<std::streambuf> buf)
: std::istream(buf.get())
, mBuf(std::move(buf))
{
}
ConstrainedFileStream::~ConstrainedFileStream()
{
delete rdbuf();
}
IStreamPtr openConstrainedFileStream(const char *filename,
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
{
public:
ConstrainedFileStream(const char *filename,
size_t start=0, size_t length=0xFFFFFFFF);
virtual ~ConstrainedFileStream();
ConstrainedFileStream(std::unique_ptr<std::streambuf> buf);
virtual ~ConstrainedFileStream() {};
private:
std::unique_ptr<std::streambuf> mBuf;
};
typedef std::shared_ptr<std::istream> IStreamPtr;

View file

@ -161,7 +161,17 @@ namespace Gui
mTextures.clear();
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();
}

View file

@ -409,7 +409,7 @@ FlipController::FlipController(const FlipController &copy, const osg::CopyOp &co
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();
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>container.png</file>
<file>creature.png</file>
<file>debug-profile.png</file>
<file>dialogue-info.png</file>
<file>dialogue-journal.png</file>
<file>dialogue-regular.png</file>
@ -27,34 +28,60 @@
<file>journal-topics.png</file>
<file>door.png</file>
<file>enchantment.png</file>
<file>error-log.png</file>
<file>faction.png</file>
<file>filter.png</file>
<file>global-variable.png</file>
<file>gmst.png</file>
<file>Info.png</file>
<file>info.png</file>
<file>ingredient.png</file>
<file>instance.png</file>
<file>land-heightmap.png</file>
<file>land-texture.png</file>
<file>leveled-creature.png</file>
<file>leveled-item.png</file>
<file>levelled-creature.png</file>
<file>levelled-item.png</file>
<file>light.png</file>
<file>lockpick.png</file>
<file>magic-effect.png</file>
<file>magicrabbit.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 alias="list-modified">list-modified.png</file>
<file>npc.png</file>
<file>object.png</file>
<file>pathgrid.png</file>
<file>potion.png</file>
<file>probe.png</file>
<file>race.png</file>
<file>random-item.png</file>
<file>random.png</file>
<file alias="list-removed">list-removed.png</file>
<file>region.png</file>
<file>region-map.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>skill.png</file>
<file>start-script.png</file>
<file>stop-openmw.png</file>
<file>sound-generator.png</file>
<file>sound.png</file>
<file>spell.png</file>
@ -64,7 +91,6 @@
<file alias="record-next">record-next.png</file>
<file alias="record-previous">record-previous.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-clone">record-clone.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