From dd8964da99a2d2ace31fb0ed4f68b689d495c8b2 Mon Sep 17 00:00:00 2001 From: Bodillium Date: Wed, 22 Oct 2014 21:54:37 +1100 Subject: [PATCH 001/142] Begin reworking files and directories section First attempt at LaTeX and Git! --- manual/opencs/files_and_directories.tex | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/manual/opencs/files_and_directories.tex b/manual/opencs/files_and_directories.tex index fc9ae878ae..39d918b46a 100644 --- a/manual/opencs/files_and_directories.tex +++ b/manual/opencs/files_and_directories.tex @@ -1,22 +1,23 @@ \section{Files and Directories} \subsection{Introduction} -This section of the manual covers usage of files and directories by the OpenCS. Files and directories are file system concepts, -and you are probably already familiar with it. We won't try to explain this concepts, we will just focus on \OCS. +This section of the manual describes the directories and file types used by OpenCS. A file is a resource for storing data, identified by its +filename extension (e.g. .exe, .jpg, .txt), whereas a directory is a folder or file system structure in which these files are stored. You +are most likely already familiar with these concepts. \subsection{Used terms} %TODO \subsection{Basics} \paragraph{Directories} -OpenMW and \OCS{} uses multiple directories on file systems. First of, there is a \textbf{user directory} that holds configuration -files and few different folders. The location of the user directory is hard coded for each supported operating system. +OpenMW and \OCS{} store their files in multiple directories. Firstly, there is the \textbf{user directory} that holds configuration +files and several other folders. The location of the user directory is hard coded for each supported operating system. %TODO list paths. -In addition to this single hard coded directory, both \OMW{} and \OCS{} need a~place to seek for actual data files of the game: -textures, models, sounds and files that store records of objects in game; dialogues and so one -- so called content files. We support -multiple such paths (we call it \textbf{data paths}) as specified in the configuration. Usually one data path points to the directory -where original \MW{} is either installed or unpacked. You are free to specify as many data paths as you would like, -however, there is one special data path that, as described later, is used to store newly created content files. +In addition to the user directory, both \OMW{} and \OCS{} need a place to store the game’s actual data files: for example, the +textures, models, sounds and records of in-game objects. We support multiple paths to these files (termed \textbf{data paths}), +as specified in the configuration. Usually, one data path points to the directory where \MW{} is installed, however, you are +free to specify as many data paths as you would like. In addition, one particular data path, as described below, is used to store +newly created content files. \paragraph{Content files} \BS{} \MW{} engine is using two types of files: ESM (master) and ESP (plugin). The distinction between those From f70ddb5e980b543e146d4d95662a0d09f0bff400 Mon Sep 17 00:00:00 2001 From: Bodillium Date: Thu, 23 Oct 2014 15:46:43 +1100 Subject: [PATCH 002/142] Finish reworking files and directories section --- manual/opencs/files_and_directories.tex | 135 ++++++++++++------------ 1 file changed, 65 insertions(+), 70 deletions(-) diff --git a/manual/opencs/files_and_directories.tex b/manual/opencs/files_and_directories.tex index 39d918b46a..21774093e1 100644 --- a/manual/opencs/files_and_directories.tex +++ b/manual/opencs/files_and_directories.tex @@ -13,109 +13,104 @@ OpenMW and \OCS{} store their files in multiple directories. Firstly, there is t files and several other folders. The location of the user directory is hard coded for each supported operating system. %TODO list paths. -In addition to the user directory, both \OMW{} and \OCS{} need a place to store the game’s actual data files: for example, the -textures, models, sounds and records of in-game objects. We support multiple paths to these files (termed \textbf{data paths}), -as specified in the configuration. Usually, one data path points to the directory where \MW{} is installed, however, you are -free to specify as many data paths as you would like. In addition, one particular data path, as described below, is used to store +In addition to the user directory, both \OMW{} and \OCS{} need a place to store the game’s actual data files: for example, the +textures, models, sounds and records of in-game objects. We support multiple paths to these files (termed \textbf{data paths}), +as specified in the configuration. Usually, one data path points to the directory where \MW{} is installed, however, you are +free to specify as many data paths as you would like. In addition, one particular data path, as described below, is used to store newly created content files. \paragraph{Content files} -\BS{} \MW{} engine is using two types of files: ESM (master) and ESP (plugin). The distinction between those -is not clear, and often confusing. You would expect the ESM (master) file is used to specify one master, that is modified by the ESPs plugins, -and indeed: this is the basic idea. However, original expansions also were made as ESM files, even though they essentially could be -described as a really large plugins, and therefore rather use ESP files. There were technical reasons behind this decision -- somewhat valid -in the case of original engine, but clearly it's better to create a system that can be used is more sensible way. \OMW{} achieves -this with our own content file types. +\BS{} \MW{} engine uses two file types: ESM (master) and ESP (plugin). The distinction between the two is often confusing. +You would expect that the ESM (master) file is used to specify a single master which is modified by the ESP files (plugins), and indeed: +this is the basic idea. However, the original expansions are also ESM files, even though they can be described as a really large plugins. +There were technical reasons behind this decision -- somewhat valid in the case of original engine, but a more logical file system is +much preferable. \OMW{} achieves this through the creation of our own types of content file. -We support both ESM and ESP files, but in order to make use of new features of OpenMW one should consider using new file types designed -with our engine in mind: game files and addon files together called ``content files``. +We support both ESM and ESP files, but, in order to make use of \OMW{}'s new features, one should consider using new file types designed +with our engine in mind: game files and addon files, collectively termed \textbf{content files}. \subparagraph{OpenMW content files} -Game and Addon files are concept somewhat similar to the old ESM/ESP, only in the way it should be from the very beginning. Nothing easier -to describe. If you want to make new game using \OMW{} as engine (so called ``total conversion'') you should create a game file. -If you want to create a addon for existing game file -- simply create addon file. Nothing else matters: The only distinction you should -consider is if your project is about changing other game, or creating a new one. Simple as that. +The distinction between game and addon files is similar to that between ESM and ESP, however their relationship to each other is +strictly defined -– the former are always master files, and the latter are always plugins. If you want to make a new game using the \OMW{} +engine (i.e. a ``total conversion''), you should create a game file. If you want to create an addon for an existing game file, simply +create an addon file. Nothing else matters: the only distinction you should consider is whether your project involves changing another game, +or creating a new one. Simple as that. -Other simple thing about content files are extensions. We are using .omwaddon for addon files and .omwgame for game files. +Furthermore, our content files’ extensions are .omwaddon for addon files and .omwgame for game files. %TODO describe what content files contains. and what not. \subparagraph{\MW{} content files} -Using our content files is recommended solution for projects that are intended to used with \OMW{} engine. However some players -wish to use original \MW{} engine, even with it large flaws and lacking features\footnote{If this is actually wrong, we are very -successful project. Yay!}. Also, since 2002 thousands of ESP/ESM files were created, some with really outstanding content. -Because of this \OCS{} simply has no other choice but support ESP/ESM files. However, if you decided to choose ESP/ESM file instead -using our own content file types you are most likely aim at the original engine compatibility. This subject is covered in the very -last section of this manual. %not finished TODO add the said section. Most likely when more features are present. +Using our content files is the recommended solution for projects that employ the \OMW{} engine. However, some players will wish to use +the original \MW{} engine, despite its large flaws and lacking features\footnote{If this is wrong, we are a very successful project. Yay!}. +In addition, since 2002 thousands of ESP/ESM files have been created, some with truly outstanding content. Because of this, \OCS{} is +committed to supporting ESP/ESM files. If you do decide to use ESP/ESM files rather than our own content files, you are most likely aiming +for original engine compatibility. This subject is covered in the very last section of the manual. +%not finished TODO add the said section. Most likely when more features are present. -The actual creation of new files is described in the next chapter. Here we are gonna focus only on details that you need to know -in order to create your first \OCS{} file while full understanding your needs. For now let's jut remember that content files -are created inside the user directory, in the the \textbf{data} subfolder (that is the one special data directory mentioned earlier). +The actual creation of new files is described in the next chapter. Here we are going to focus only on the essential information needed +to create your first \OCS{} file. For now, let's jut remember that content files are stored in the user directory, in the \textbf{data} subfolder (the particular data directory mentioned above). \subparagraph{Dependencies} -Since addon is supposed to change the game it is logical that it also depends on the said game. It simply can not work otherwise. -Just think about it: your modification is changing prize of the iron sword. But what if there is no iron sword in game? That is right: -we get nonsense. What you want to do is to tie your addon to the files you are changing. Those can be either game files (expansion island -for a game) or other addon files (house on the said island). It is a good idea to be dependent only on files that are really changed -in your addon obviously, but sadly there is no other way to achieve this than knowing what you want to do. Again, please remember that -this section of the manual does not cover creating the content files -- it is only theoretical introduction to the subject. For now just -keep in mind that dependencies exist, and is up to you what to decide if your content file should depend on other content file. +Since addons aim to modify an existing game, it is logical that they also depend on the said game: otherwise they will not function. +For example, your modification changes the price of iron swords. But what if there are no iron swords in the game? That is right: +it is nonsense. Therefore, it is necessary to make your addon a dependency of other content files. These can be either game files +(e.g. an entirely new island), or other addon files (e.g. a house on the island). It is a good idea for addons to depend only on the +content files they modify, but this is up to the end user to determine. -Game files are not intend to have any dependencies for a very simple reasons: player is using only one game file (excluding original -and dirty {ESP/ESM} system) at the time and therefore no game file can depend on other game file, and since game file makes the base -for addon files -- it can not depend on addon files. +Game files do not depend on any other content files, as they act as master files. A player can only use one game file at a time +(although this does not apply to the original and dirty ESP/ESM system). %\subparagraph{Loading order} %TODO \paragraph{Project files} -Project files act as containers for data not used by the \OMW{} game engine itself, but still useful for OpenCS. The shining example -of this data category are without doubt record filters (described in the later section of the manual you are reading currently). -As a mod author you probably do not need and/or want to distribute project files at all, they are meant to be used only by you. +Project files contain data not used by the \OMW{} game engine but which are still needed by OpenCS. Good examples of this data type +are the record filters (described below). As a mod author, you probably do not need and/or want to distribute project files at all, +as they are meant to be used only by you. -As you would imagine, project file makes sense only in combination with actual content files. In fact, each time you start to work -on new content file and project file was not found, it will be created. -Project files extension is, to not surprise ``.project''. The whole name of the project file is the whole name of the content file -with appended extensions. For instance swords.omwaddon file is associated with swords.omwaddon.project file. +Since project files govern how content files are used in OpenCS, they are always used in conjunction with your specific project. +In fact, each time work commences on a new content file without a corresponding project file, a new project file will be created. + +Project file extension is ``.project''. The name of the project file is the whole name of the content file with appended extensions. +For instance, a content file named swords.omwaddon is associated with the project file swords.omwaddon.project. %TODO where are they stored. -Project files are stored inside the user directory, in the \textbf{projects} subfolder. This is the path location for both freshly -created project files, and a place where \OCS{} looks for already existing files. +Project files are stored inside the user directory, in the \textbf{projects} subfolder. This is both the location of newly created +project files, and the place where \OCS{} looks for already existing files. -\paragraph{Resources files} +\paragraph{Resource files} %textures, sounds, whatever -Unless we are talking about the fully text based game, like Zork or Rogue, you are expecting that a video game is using some media files: -models with textures, pictures acting as icons, sounds and everything else. Since content files, no matter if it is ESP, ESM or new \OMW{} -file type do not contain any of those, it is clear that they have to be deliver with a different file. It is also clear that this, -let's call it ``resources file``, have to be supported by the engine. Without code handling those files, it is nothing more than -a mathematical abstraction -- something, that lacks meaning for human beings\footnote{Unless we call programmers a human beings.}. -Therefore this section must cover ways to add resources files to your content file, and point out what is supported. We are going -to do just that. Later, you will learn how to make use of those files in your content. +The vast majority of modern video games use what we shall term \textbf{resource files}: models, textures, icons, sounds and so on. +ESPs, ESMs and \OMW{} content files do not contain these files, merely instructions on how they are used. It follows that the \OMW{} +engine must be capable of supporting these resource files in order for them to function. Therefore this section cover ways to add +resource files to your content file, and outlines which formats are supported. Later, you will learn how to make use of these files +in your content. \subparagraph{Audio} -OpenMW is using {FFmpeg} for audio playback, and so we support every audio type that is supported by this library. This makes a huge list. -Below is only small portion of supported file types. +OpenMW utilises {FFmpeg} for audio playback, so we support every audio type supported by this library. This is a huge list. +Below is only a small sample of supported file types. \begin{description} - \item mp3 ({MPEG}-1 {Part 3 Layer 3}) popular audio file format and \textit{de facto} standard for storing audio. Used by the \MW{} game. - \item ogg open source, multimedia container file using high quality vorbis audio codec. Recommended. + \item mp3 ({MPEG}-1 {Part 3 Layer 3}) A popular audio file format and the \textit{de facto} standard for storing audio. Used by + the \MW{} game. + \item ogg Open source, multimedia container file which uses the high quality vorbis audio codec. Recommended. \end{description} \subparagraph{Video} -As in the case of audio files, we are using {FFmepg} to decode video files. The list of supported files is long, we will cover -only the most significant. +As in the case of audio files, we use {FFmpeg} to decode video files. The list of supported files is long -– only the most +significant will be covered. \begin{description} - \item bik videos used by original \MW{} game. - \item mp4 multimedia container which use more advanced codecs ({MPEG-4 Parts 2,3,10}) with a better audio and video compression rate, - but also requiring more {CPU} intensive decoding -- this makes it probably less suited for storing sounds in computer games, but good for videos. - \item webm is a new, shiny and open source video format with excellent compression. It needs quite a lot of processing power to be decoded, + \item bik Format used by the original \MW{} game. + \item mp4 Multimedia container which use more advanced codecs ({MPEG-4 Parts 2,3,10}) with a better audio and video compression rate, + but which require more {CPU} intensive decoding -- this probably makes it less suited for storing sounds in computer games, but good for videos. + \item webm A new, shiny and open source video format with excellent compression. It needs quite a lot of processing power to be decoded, but since game logic is not running during cut scenes we can recommend it for use with \OMW. - \item ogv alternative, open source container using theora codec for video and vorbis for audio. + \item ogv An alternative, open source container using theora codec for video and vorbis for audio. \end{description} \subparagraph{Textures and images} -Original \MW{} game uses {DDS} and {TGA} files for all kind of two dimensional images and textures alike. In addition, engine supported BMP -files for some reason ({BMP} is a terrible format for a video game). We also support extended set of image files -- including {JPEG} and {PNG}. -JPEG and PNG files can be useful in some cases, for instance JPEG file is a valid option for skybox texture and PNG can useful for masks. -However please, keep in mind that JPEG can grow into large sizes quickly and are not the best option with {DirectX} rendering backend. You probabbly still want -to use {DDS} files for textures. - +\MW{} uses {DDS} and {TGA} files for all kinds of two dimensional images and textures. In addition, the original engine supported BMP +files (although {BMP} is a terrible format for a video game). We also support an extended set of image files -- including {JPEG} and {PNG}. +JPEG and PNG files can be useful in some cases. For instance, a JPEG file is a valid option for a skybox texture and PNG can useful for masks. +However, keep in mind that a JPEG can grow large quickly and so are not the best option with a {DirectX} rendering backend. DDS files +are therefore recommended for textures. %\subparagraph{Meshes} %TODO once we will support something more than just nifs \ No newline at end of file From 20aa89e785a5e61f80057584b3aebddcee11f187 Mon Sep 17 00:00:00 2001 From: Bodillium Date: Thu, 23 Oct 2014 23:32:24 +1100 Subject: [PATCH 003/142] Minor tweaks to files and directories --- manual/opencs/files_and_directories.tex | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/manual/opencs/files_and_directories.tex b/manual/opencs/files_and_directories.tex index 21774093e1..1b07fe267a 100644 --- a/manual/opencs/files_and_directories.tex +++ b/manual/opencs/files_and_directories.tex @@ -22,8 +22,8 @@ newly created content files. \paragraph{Content files} \BS{} \MW{} engine uses two file types: ESM (master) and ESP (plugin). The distinction between the two is often confusing. You would expect that the ESM (master) file is used to specify a single master which is modified by the ESP files (plugins), and indeed: -this is the basic idea. However, the original expansions are also ESM files, even though they can be described as a really large plugins. -There were technical reasons behind this decision -- somewhat valid in the case of original engine, but a more logical file system is +this is the basic idea. However, the original expansions are also ESM files, even though they can be described as very large plugins. +There were technical reasons behind this decision -- somewhat valid in the case of the original engine, but a more logical file system is much preferable. \OMW{} achieves this through the creation of our own types of content file. We support both ESM and ESP files, but, in order to make use of \OMW{}'s new features, one should consider using new file types designed @@ -48,7 +48,8 @@ for original engine compatibility. This subject is covered in the very last sect %not finished TODO add the said section. Most likely when more features are present. The actual creation of new files is described in the next chapter. Here we are going to focus only on the essential information needed -to create your first \OCS{} file. For now, let's jut remember that content files are stored in the user directory, in the \textbf{data} subfolder (the particular data directory mentioned above). +to create your first \OCS{} file. For now, let's jut remember that content files are stored in the user directory, in the \textbf{data} +subfolder (the particular data directory mentioned above). \subparagraph{Dependencies} Since addons aim to modify an existing game, it is logical that they also depend on the said game: otherwise they will not function. @@ -67,9 +68,9 @@ are the record filters (described below). As a mod author, you probably do not n as they are meant to be used only by you. Since project files govern how content files are used in OpenCS, they are always used in conjunction with your specific project. -In fact, each time work commences on a new content file without a corresponding project file, a new project file will be created. +In fact, each time work commences on a content file that does not have a corresponding project file, a new project file will be created. -Project file extension is ``.project''. The name of the project file is the whole name of the content file with appended extensions. +The project file extension is ``.project''. The name of the project file is the whole name of the content file with appended extensions. For instance, a content file named swords.omwaddon is associated with the project file swords.omwaddon.project. %TODO where are they stored. @@ -80,7 +81,7 @@ project files, and the place where \OCS{} looks for already existing files. %textures, sounds, whatever The vast majority of modern video games use what we shall term \textbf{resource files}: models, textures, icons, sounds and so on. ESPs, ESMs and \OMW{} content files do not contain these files, merely instructions on how they are used. It follows that the \OMW{} -engine must be capable of supporting these resource files in order for them to function. Therefore this section cover ways to add +engine must be capable of supporting these resource files in order for them to function. Therefore this section covers ways to add resource files to your content file, and outlines which formats are supported. Later, you will learn how to make use of these files in your content. @@ -101,7 +102,8 @@ significant will be covered. \begin{description} \item bik Format used by the original \MW{} game. \item mp4 Multimedia container which use more advanced codecs ({MPEG-4 Parts 2,3,10}) with a better audio and video compression rate, - but which require more {CPU} intensive decoding -- this probably makes it less suited for storing sounds in computer games, but good for videos. + but which require more {CPU} intensive decoding -- this probably makes it less suited for storing sounds in computer games, but + good for videos. \item webm A new, shiny and open source video format with excellent compression. It needs quite a lot of processing power to be decoded, but since game logic is not running during cut scenes we can recommend it for use with \OMW. \item ogv An alternative, open source container using theora codec for video and vorbis for audio. From 3b534326ff0c01de98deb9a3220e74c2049073ad Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 5 Jan 2015 15:04:11 +0100 Subject: [PATCH 004/142] forbid manual editing of the cell field in reference records --- apps/opencs/model/world/columnimp.hpp | 10 ++++++++-- apps/opencs/model/world/data.cpp | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index eba73cf0b0..95023f49d6 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -870,7 +870,13 @@ namespace CSMWorld template struct CellColumn : public Column { - CellColumn() : Column (Columns::ColumnId_Cell, ColumnBase::Display_Cell) {} + bool mBlocked; + + /// \param blocked Do not allow user-modification + CellColumn (bool blocked = false) + : Column (Columns::ColumnId_Cell, ColumnBase::Display_Cell), + mBlocked (blocked) + {} virtual QVariant get (const Record& record) const { @@ -893,7 +899,7 @@ namespace CSMWorld virtual bool isUserEditable() const { - return true; + return !mBlocked; } }; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 67f6822c7c..b925a66b3a 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -257,7 +257,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mRefs.addColumn (new StringIdColumn (true)); mRefs.addColumn (new RecordStateColumn); mRefs.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Reference)); - mRefs.addColumn (new CellColumn); + mRefs.addColumn (new CellColumn (true)); mRefs.addColumn (new IdColumn); mRefs.addColumn (new PosColumn (&CellRef::mPos, 0, false)); mRefs.addColumn (new PosColumn (&CellRef::mPos, 1, false)); From ba7b74217b9b821f2d354f5ee131b90bc333fd50 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 5 Jan 2015 15:20:47 +0100 Subject: [PATCH 005/142] added original cell column to reference table --- apps/opencs/model/world/columnimp.hpp | 32 +++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 1 + apps/opencs/model/world/columns.hpp | 1 + apps/opencs/model/world/data.cpp | 1 + apps/opencs/model/world/ref.hpp | 1 + apps/opencs/model/world/refcollection.cpp | 1 + 6 files changed, 37 insertions(+) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 95023f49d6..ed2cfc310a 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -903,6 +903,38 @@ namespace CSMWorld } }; + template + struct OriginalCellColumn : public Column + { + OriginalCellColumn() + : Column (Columns::ColumnId_OriginalCell, ColumnBase::Display_Cell) + {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mOriginalCell.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mOriginalCell = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + + virtual bool isUserEditable() const + { + return false; + } + }; + template struct IdColumn : public Column { diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 8349eb515b..d85125bd58 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -201,6 +201,7 @@ namespace CSMWorld { ColumnId_HitSound, "Hit Sound" }, { ColumnId_AreaSound, "Area Sound" }, { ColumnId_BoltSound, "Bolt Sound" }, + { ColumnId_OriginalCell, "Original Cell" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index ca03266557..d3476f7b21 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -194,6 +194,7 @@ namespace CSMWorld ColumnId_HitSound = 178, ColumnId_AreaSound = 179, ColumnId_BoltSound = 180, + ColumnId_OriginalCell = 181, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b925a66b3a..e8905b9252 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -258,6 +258,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mRefs.addColumn (new RecordStateColumn); mRefs.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Reference)); mRefs.addColumn (new CellColumn (true)); + mRefs.addColumn (new OriginalCellColumn); mRefs.addColumn (new IdColumn); mRefs.addColumn (new PosColumn (&CellRef::mPos, 0, false)); mRefs.addColumn (new PosColumn (&CellRef::mPos, 1, false)); diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index eb62434cf2..4110246918 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -12,6 +12,7 @@ namespace CSMWorld { std::string mId; std::string mCell; + std::string mOriginalCell; CellRef(); }; diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 47f0276c6c..1a0dd1e5bf 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -23,6 +23,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool while (ESM::Cell::getNextRef (reader, ref, deleted)) { + ref.mOriginalCell = cell2.mId; ref.mCell = cell2.mId; /// \todo handle moved references From e32402a0402be2bb36754fe2b718aa384df54726 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 9 Jan 2015 12:05:16 +0100 Subject: [PATCH 006/142] handle moved references on load --- apps/opencs/model/world/ref.cpp | 10 ++++++++++ apps/opencs/model/world/ref.hpp | 5 +++++ apps/opencs/model/world/refcollection.cpp | 14 ++++++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/ref.cpp b/apps/opencs/model/world/ref.cpp index f3c1b0b73f..63594acc8f 100644 --- a/apps/opencs/model/world/ref.cpp +++ b/apps/opencs/model/world/ref.cpp @@ -1,8 +1,18 @@ #include "ref.hpp" +#include + CSMWorld::CellRef::CellRef() { mRefNum.mIndex = 0; mRefNum.mContentFile = 0; +} + +std::pair CSMWorld::CellRef::getCellIndex() const +{ + const int cellSize = 8192; + + return std::make_pair ( + std::floor (mPos.pos[0]/cellSize), std::floor (mPos.pos[1]/cellSize)); } \ No newline at end of file diff --git a/apps/opencs/model/world/ref.hpp b/apps/opencs/model/world/ref.hpp index 4110246918..dae9488f05 100644 --- a/apps/opencs/model/world/ref.hpp +++ b/apps/opencs/model/world/ref.hpp @@ -1,6 +1,8 @@ #ifndef CSM_WOLRD_REF_H #define CSM_WOLRD_REF_H +#include + #include namespace CSMWorld @@ -15,6 +17,9 @@ namespace CSMWorld std::string mOriginalCell; CellRef(); + + /// Calculate cell index based on coordinates (x and y) + std::pair getCellIndex() const; }; } diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 1a0dd1e5bf..19dfae57dd 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -24,9 +24,19 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool while (ESM::Cell::getNextRef (reader, ref, deleted)) { ref.mOriginalCell = cell2.mId; - ref.mCell = cell2.mId; - /// \todo handle moved references + if (cell.get().isExterior()) + { + // ignoring moved references sub-record; instead calculate cell from coordinates + std::pair index = ref.getCellIndex(); + + std::ostringstream stream; + stream << "#" << index.first << " " << index.second; + + ref.mCell = stream.str(); + } + else + ref.mCell = cell2.mId; std::map::iterator iter = cache.find (ref.mRefNum); From 320b994aef7ed7f0df3987c4ffc909aa287e9059 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 10 Jan 2015 12:35:59 +0100 Subject: [PATCH 007/142] keep original cell field empty, if reference is in modified --- apps/opencs/model/world/refcollection.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 19dfae57dd..dcb295626a 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -23,10 +23,13 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool while (ESM::Cell::getNextRef (reader, ref, deleted)) { - ref.mOriginalCell = cell2.mId; + // Keep mOriginalCell empty when in modified (as an indicator that the + // original cell will always be equal the current cell). + ref.mOriginalCell = base ? cell2.mId : ""; if (cell.get().isExterior()) { + // ignoring moved references sub-record; instead calculate cell from coordinates std::pair index = ref.getCellIndex(); From 7615cbafcee43007b60da8de8f7e1a5795b1471b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 15 Jan 2015 14:24:33 +0100 Subject: [PATCH 008/142] create modify commands through command dispatcher --- apps/opencs/model/world/commanddispatcher.cpp | 8 ++++++++ apps/opencs/model/world/commanddispatcher.hpp | 9 +++++++++ apps/opencs/view/tools/reporttable.cpp | 4 ++-- apps/opencs/view/world/datadisplaydelegate.cpp | 7 ++++--- apps/opencs/view/world/datadisplaydelegate.hpp | 11 ++++------- apps/opencs/view/world/dialoguesubview.cpp | 14 +++++++------- apps/opencs/view/world/dialoguesubview.hpp | 10 ++++++---- apps/opencs/view/world/enumdelegate.cpp | 8 ++++---- apps/opencs/view/world/enumdelegate.hpp | 4 ++-- apps/opencs/view/world/idtypedelegate.cpp | 8 ++++---- apps/opencs/view/world/idtypedelegate.hpp | 4 ++-- .../opencs/view/world/recordstatusdelegate.cpp | 8 ++++---- .../opencs/view/world/recordstatusdelegate.hpp | 8 ++++---- apps/opencs/view/world/table.cpp | 2 +- apps/opencs/view/world/util.cpp | 18 ++++++++++++------ apps/opencs/view/world/util.hpp | 14 ++++++++++---- apps/opencs/view/world/vartypedelegate.cpp | 8 ++++---- apps/opencs/view/world/vartypedelegate.hpp | 5 +++-- 18 files changed, 90 insertions(+), 60 deletions(-) diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 4e146d87c0..a0b7a9fa06 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -131,6 +131,14 @@ std::vector CSMWorld::CommandDispatcher::getExtendedTypes return tables; } +void CSMWorld::CommandDispatcher::executeModify (QAbstractItemModel *model, const QModelIndex& index, const QVariant& new_) +{ + if (mLocked) + return; + + mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, new_)); +} + void CSMWorld::CommandDispatcher::executeDelete() { if (mLocked) diff --git a/apps/opencs/model/world/commanddispatcher.hpp b/apps/opencs/model/world/commanddispatcher.hpp index 50085b1a1e..1d29e48c19 100644 --- a/apps/opencs/model/world/commanddispatcher.hpp +++ b/apps/opencs/model/world/commanddispatcher.hpp @@ -7,6 +7,9 @@ #include "universalid.hpp" +class QModelIndex; +class QAbstractItemModel; + namespace CSMDoc { class Document; @@ -53,6 +56,12 @@ namespace CSMWorld /// the extended mode, the returned vector will be empty instead. std::vector getExtendedTypes() const; + /// Add a modify command to the undo stack. + /// + /// \attention model must either be a model for the table operated on by this + /// dispatcher or a proxy of it. + void executeModify (QAbstractItemModel *model, const QModelIndex& index, const QVariant& new_); + public slots: void executeDelete(); diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index 4cd11925e0..6ab470a02c 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -79,8 +79,8 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, setModel (mModel); setColumnHidden (2, true); - mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate ( - document, this); + mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate (0, + mDocument, this); setItemDelegateForColumn (0, mIdTypeDelegate); diff --git a/apps/opencs/view/world/datadisplaydelegate.cpp b/apps/opencs/view/world/datadisplaydelegate.cpp index 46ca17a292..b9df52bf7e 100644 --- a/apps/opencs/view/world/datadisplaydelegate.cpp +++ b/apps/opencs/view/world/datadisplaydelegate.cpp @@ -6,11 +6,12 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, const IconList &icons, + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, const QString &pageName, const QString &settingName, QObject *parent) - : EnumDelegate (values, document, parent), mDisplayMode (Mode_TextOnly), + : EnumDelegate (values, dispatcher, document, parent), mDisplayMode (Mode_TextOnly), mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) { @@ -136,9 +137,9 @@ void CSVWorld::DataDisplayDelegateFactory::add (int enumValue, QString enumName, } CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate ( - CSMDoc::Document& document, QObject *parent) const + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const { - return new DataDisplayDelegate (mValues, mIcons, document, "", "", parent); + return new DataDisplayDelegate (mValues, mIcons, dispatcher, document, "", "", parent); } diff --git a/apps/opencs/view/world/datadisplaydelegate.hpp b/apps/opencs/view/world/datadisplaydelegate.hpp index 73790e3c65..f6e4c26887 100755 --- a/apps/opencs/view/world/datadisplaydelegate.hpp +++ b/apps/opencs/view/world/datadisplaydelegate.hpp @@ -38,12 +38,9 @@ namespace CSVWorld QString mSettingKey; public: - explicit DataDisplayDelegate (const ValueList & values, - const IconList & icons, - CSMDoc::Document& document, - const QString &pageName, - const QString &settingName, - QObject *parent); + DataDisplayDelegate (const ValueList & values, const IconList & icons, + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, + const QString &pageName, const QString &settingName, QObject *parent); ~DataDisplayDelegate(); @@ -82,7 +79,7 @@ namespace CSVWorld public: - virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const; + virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. protected: diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 8790601ea3..497ce7acdc 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -167,10 +167,10 @@ void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std:: ==============================DialogueDelegateDispatcher========================================== */ -CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMDoc::Document& document) : +CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document) : mParent(parent), mTable(table), -mDocument (document), +mCommandDispatcher (commandDispatcher), mDocument (document), mNotEditableDelegate(table, parent) { } @@ -182,7 +182,7 @@ CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CS if (delegateIt == mDelegates.end()) { delegate = CommandDelegateFactoryCollection::get().makeDelegate ( - display, mDocument, mParent); + display, &mCommandDispatcher, mDocument, mParent); mDelegates.insert(std::make_pair(display, delegate)); } else { @@ -309,12 +309,12 @@ CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher() =============================================================EditWidget===================================================== */ -CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMDoc::Document& document, bool createAndDelete) : -mDispatcher(this, table, document), +CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, bool createAndDelete) : +mDispatcher(this, table, commandDispatcher, document), QScrollArea(parent), mWidgetMapper(NULL), mMainWidget(NULL), -mDocument (document), +mCommandDispatcher (commandDispatcher), mTable(table) { remake (row); @@ -471,7 +471,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout = new QVBoxLayout(mainWidget); - mEditWidget = new EditWidget(mainWidget, mRow, mTable, document, false); + mEditWidget = new EditWidget(mainWidget, mRow, mTable, mCommandDispatcher, document, false); connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 4c260170f3..f45ed40c44 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -101,14 +101,16 @@ namespace CSVWorld CSMWorld::IdTable* mTable; - CSMDoc::Document& mDocument; + CSMWorld::CommandDispatcher& mCommandDispatcher; + CSMDoc::Document& mDocument; NotEditableSubDelegate mNotEditableDelegate; std::vector mProxys; //once we move to the C++11 we should use unique_ptr public: - DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMDoc::Document& document); + DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, + CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document); ~DialogueDelegateDispatcher(); @@ -145,11 +147,11 @@ namespace CSVWorld DialogueDelegateDispatcher mDispatcher; QWidget* mMainWidget; CSMWorld::IdTable* mTable; - CSMDoc::Document& mDocument; + CSMWorld::CommandDispatcher& mCommandDispatcher; public: - EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, CSMDoc::Document& document, bool createAndDelete = false); + EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, bool createAndDelete = false); void remake(int row); diff --git a/apps/opencs/view/world/enumdelegate.cpp b/apps/opencs/view/world/enumdelegate.cpp index 168e5cb0a3..95b120e9af 100644 --- a/apps/opencs/view/world/enumdelegate.cpp +++ b/apps/opencs/view/world/enumdelegate.cpp @@ -35,8 +35,8 @@ void CSVWorld::EnumDelegate::addCommands (QAbstractItemModel *model, CSVWorld::EnumDelegate::EnumDelegate (const std::vector >& values, - CSMDoc::Document& document, QObject *parent) -: CommandDelegate (document, parent), mValues (values) + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) +: CommandDelegate (dispatcher, document, parent), mValues (values) { } @@ -141,9 +141,9 @@ CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector >& values, - CSMDoc::Document& document, QObject *parent); + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent); virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem& option, @@ -64,7 +64,7 @@ namespace CSVWorld EnumDelegateFactory (const std::vector& names, bool allowNone = false); /// \param allowNone Use value of -1 for "none selected" (empty string) - virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const; + virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. void add (int value, const QString& name); diff --git a/apps/opencs/view/world/idtypedelegate.cpp b/apps/opencs/view/world/idtypedelegate.cpp index 3b440ff714..34c8d12cd7 100755 --- a/apps/opencs/view/world/idtypedelegate.cpp +++ b/apps/opencs/view/world/idtypedelegate.cpp @@ -3,8 +3,8 @@ #include "../../model/world/universalid.hpp" CSVWorld::IdTypeDelegate::IdTypeDelegate - (const ValueList &values, const IconList &icons, CSMDoc::Document& document, QObject *parent) - : DataDisplayDelegate (values, icons, document, + (const ValueList &values, const IconList &icons, CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) + : DataDisplayDelegate (values, icons, dispatcher, document, "records", "type-format", parent) {} @@ -21,7 +21,7 @@ CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory() } CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate ( - CSMDoc::Document& document, QObject *parent) const + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const { - return new IdTypeDelegate (mValues, mIcons, document, parent); + return new IdTypeDelegate (mValues, mIcons, dispatcher, document, parent); } diff --git a/apps/opencs/view/world/idtypedelegate.hpp b/apps/opencs/view/world/idtypedelegate.hpp index e9a0af68c5..d0ed6997b4 100755 --- a/apps/opencs/view/world/idtypedelegate.hpp +++ b/apps/opencs/view/world/idtypedelegate.hpp @@ -11,7 +11,7 @@ namespace CSVWorld class IdTypeDelegate : public DataDisplayDelegate { public: - IdTypeDelegate (const ValueList &mValues, const IconList &icons, CSMDoc::Document& document, QObject *parent); + IdTypeDelegate (const ValueList &mValues, const IconList &icons, CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent); }; class IdTypeDelegateFactory : public DataDisplayDelegateFactory @@ -20,7 +20,7 @@ namespace CSVWorld IdTypeDelegateFactory(); - virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const; + virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. }; } diff --git a/apps/opencs/view/world/recordstatusdelegate.cpp b/apps/opencs/view/world/recordstatusdelegate.cpp index 708a780155..58a5c01774 100644 --- a/apps/opencs/view/world/recordstatusdelegate.cpp +++ b/apps/opencs/view/world/recordstatusdelegate.cpp @@ -9,16 +9,16 @@ CSVWorld::RecordStatusDelegate::RecordStatusDelegate(const ValueList& values, const IconList & icons, - CSMDoc::Document& document, QObject *parent) - : DataDisplayDelegate (values, icons, document, + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) + : DataDisplayDelegate (values, icons, dispatcher, document, "records", "status-format", parent) {} CSVWorld::CommandDelegate *CSVWorld::RecordStatusDelegateFactory::makeDelegate ( - CSMDoc::Document& document, QObject *parent) const + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const { - return new RecordStatusDelegate (mValues, mIcons, document, parent); + return new RecordStatusDelegate (mValues, mIcons, dispatcher, document, parent); } CSVWorld::RecordStatusDelegateFactory::RecordStatusDelegateFactory() diff --git a/apps/opencs/view/world/recordstatusdelegate.hpp b/apps/opencs/view/world/recordstatusdelegate.hpp index fbdaed538b..acaf872a63 100644 --- a/apps/opencs/view/world/recordstatusdelegate.hpp +++ b/apps/opencs/view/world/recordstatusdelegate.hpp @@ -17,9 +17,9 @@ namespace CSVWorld { public: - explicit RecordStatusDelegate(const ValueList& values, - const IconList& icons, - CSMDoc::Document& document, QObject *parent = 0); + RecordStatusDelegate (const ValueList& values, const IconList& icons, + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, + QObject *parent = 0); }; class RecordStatusDelegateFactory : public DataDisplayDelegateFactory @@ -28,7 +28,7 @@ namespace CSVWorld RecordStatusDelegateFactory(); - virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const; + virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. }; diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index e864e4ed26..794510f42f 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -281,7 +281,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, mModel->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); CommandDelegate *delegate = CommandDelegateFactoryCollection::get().makeDelegate (display, - mDocument, this); + mDispatcher, document, this); mDelegates.push_back (delegate); setItemDelegateForColumn (i, delegate); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index c65e12c609..8039034a21 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -18,6 +18,7 @@ #include "../../model/world/commands.hpp" #include "../../model/world/tablemimedata.hpp" +#include "../../model/world/commanddispatcher.hpp" #include "scriptedit.hpp" @@ -82,15 +83,15 @@ void CSVWorld::CommandDelegateFactoryCollection::add (CSMWorld::ColumnBase::Disp } CSVWorld::CommandDelegate *CSVWorld::CommandDelegateFactoryCollection::makeDelegate ( - CSMWorld::ColumnBase::Display display, CSMDoc::Document& document, QObject *parent) const + CSMWorld::ColumnBase::Display display, CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const { std::map::const_iterator iter = mFactories.find (display); if (iter!=mFactories.end()) - return iter->second->makeDelegate (document, parent); + return iter->second->makeDelegate (dispatcher, document, parent); - return new CommandDelegate (document, parent); + return new CommandDelegate (dispatcher, document, parent); } const CSVWorld::CommandDelegateFactoryCollection& CSVWorld::CommandDelegateFactoryCollection::get() @@ -115,17 +116,22 @@ CSMDoc::Document& CSVWorld::CommandDelegate::getDocument() const void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const { + if (!mCommandDispatcher) + return; + NastyTableModelHack hack (*model); QStyledItemDelegate::setModelData (editor, &hack, index); QVariant new_ = hack.getData(); if (model->data (index)!=new_) - getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, new_)); + mCommandDispatcher->executeModify (model, index, new_); } -CSVWorld::CommandDelegate::CommandDelegate (CSMDoc::Document& document, QObject *parent) -: QStyledItemDelegate (parent), mDocument (document), mEditLock (false) +CSVWorld::CommandDelegate::CommandDelegate (CSMWorld::CommandDispatcher *commandDispatcher, + CSMDoc::Document& document, QObject *parent) +: QStyledItemDelegate (parent), mEditLock (false), + mCommandDispatcher (commandDispatcher), mDocument (document) {} void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index b4d972bf3f..df9d61dadd 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -16,6 +16,7 @@ namespace CSMWorld { class TableMimeData; class UniversalId; + class CommandDispatcher; } namespace CSVWorld @@ -51,7 +52,8 @@ namespace CSVWorld virtual ~CommandDelegateFactory(); - virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) + virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, QObject *parent) const = 0; ///< The ownership of the returned CommandDelegate is transferred to the caller. }; @@ -78,7 +80,8 @@ namespace CSVWorld /// /// This function must not be called more than once per value of \a display. - CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, CSMDoc::Document& document, + CommandDelegate *makeDelegate (CSMWorld::ColumnBase::Display display, + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. /// @@ -111,8 +114,9 @@ namespace CSVWorld { Q_OBJECT - CSMDoc::Document& mDocument; bool mEditLock; + CSMWorld::CommandDispatcher *mCommandDispatcher; + CSMDoc::Document& mDocument; protected: @@ -125,7 +129,9 @@ namespace CSVWorld public: - CommandDelegate (CSMDoc::Document& document, QObject *parent); + /// \param commandDispatcher If CommandDelegate will be only be used on read-only + /// cells, a 0-pointer can be passed here. + CommandDelegate (CSMWorld::CommandDispatcher *commandDispatcher, CSMDoc::Document& document, QObject *parent); virtual void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; diff --git a/apps/opencs/view/world/vartypedelegate.cpp b/apps/opencs/view/world/vartypedelegate.cpp index c3c98b800c..90a686a67e 100644 --- a/apps/opencs/view/world/vartypedelegate.cpp +++ b/apps/opencs/view/world/vartypedelegate.cpp @@ -47,8 +47,8 @@ void CSVWorld::VarTypeDelegate::addCommands (QAbstractItemModel *model, const QM } CSVWorld::VarTypeDelegate::VarTypeDelegate (const std::vector >& values, - CSMDoc::Document& document, QObject *parent) -: EnumDelegate (values, document, parent) + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) +: EnumDelegate (values, dispatcher, document, parent) {} @@ -69,9 +69,9 @@ CSVWorld::VarTypeDelegateFactory::VarTypeDelegateFactory (ESM::VarType type0, } CSVWorld::CommandDelegate *CSVWorld::VarTypeDelegateFactory::makeDelegate ( - CSMDoc::Document& document, QObject *parent) const + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) const { - return new VarTypeDelegate (mValues, document, parent); + return new VarTypeDelegate (mValues, dispatcher, document, parent); } void CSVWorld::VarTypeDelegateFactory::add (ESM::VarType type) diff --git a/apps/opencs/view/world/vartypedelegate.hpp b/apps/opencs/view/world/vartypedelegate.hpp index c86b936f63..a8f39c318d 100644 --- a/apps/opencs/view/world/vartypedelegate.hpp +++ b/apps/opencs/view/world/vartypedelegate.hpp @@ -17,7 +17,7 @@ namespace CSVWorld public: VarTypeDelegate (const std::vector >& values, - CSMDoc::Document& document, QObject *parent); + CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent); }; class VarTypeDelegateFactory : public CommandDelegateFactory @@ -30,7 +30,8 @@ namespace CSVWorld ESM::VarType type1 = ESM::VT_Unknown, ESM::VarType type2 = ESM::VT_Unknown, ESM::VarType type3 = ESM::VT_Unknown); - virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const; + virtual CommandDelegate *makeDelegate (CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, QObject *parent) const; ///< The ownership of the returned CommandDelegate is transferred to the caller. void add (ESM::VarType type); From 561ddfa0c59bdea8cb717658b56f6b4701c4cef7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 16 Jan 2015 11:27:17 +0100 Subject: [PATCH 009/142] make column type accessable via the regular table model --- apps/opencs/model/world/columnbase.hpp | 3 ++- apps/opencs/model/world/idtable.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index db9b8b3c64..03e3739043 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -15,7 +15,8 @@ namespace CSMWorld enum Roles { Role_Flags = Qt::UserRole, - Role_Display = Qt::UserRole+1 + Role_Display = Qt::UserRole+1, + Role_ColumnId = Qt::UserRole+1 }; enum Flags diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index c68b717896..7733264904 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -27,9 +27,15 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const return mIdCollection->getColumns(); } -QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const +QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const { - if ((role!=Qt::DisplayRole && role!=Qt::EditRole) || index.row() < 0 || index.column() < 0) + if (index.row() < 0 || index.column() < 0) + return QVariant(); + + if (role==ColumnBase::Role_ColumnId) + return QVariant (getColumnId (index.column())); + + if ((role!=Qt::DisplayRole && role!=Qt::EditRole)) return QVariant(); if (role==Qt::EditRole && !mIdCollection->getColumn (index.column()).isEditable()) @@ -52,6 +58,9 @@ QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation if (role==ColumnBase::Role_Display) return mIdCollection->getColumn (section).mDisplayType; + if (role==ColumnBase::Role_ColumnId) + return getColumnId (section); + return QVariant(); } From 9670e0881dd74c83e2ce40d7b5495d99bc525603 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 16 Jan 2015 15:17:52 +0100 Subject: [PATCH 010/142] update reference's current cell when x/y-coordinates are modified --- apps/opencs/model/world/commanddispatcher.cpp | 44 ++++++++++++++++- apps/opencs/model/world/commands.cpp | 47 ++++++++++++++++++- apps/opencs/model/world/commands.hpp | 23 ++++++++- 3 files changed, 111 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index a0b7a9fa06..cda4f3a748 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -2,6 +2,7 @@ #include "commanddispatcher.hpp" #include +#include #include @@ -10,6 +11,7 @@ #include "idtable.hpp" #include "record.hpp" #include "commands.hpp" +#include "idtableproxymodel.hpp" std::vector CSMWorld::CommandDispatcher::getDeletableRecords() const { @@ -136,7 +138,47 @@ void CSMWorld::CommandDispatcher::executeModify (QAbstractItemModel *model, cons if (mLocked) return; - mDocument.getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, new_)); + std::auto_ptr modifyCell; + + int columnId = model->data (index, ColumnBase::Role_ColumnId).toInt(); + + if (columnId==Columns::ColumnId_PositionXPos || columnId==Columns::ColumnId_PositionYPos) + { + IdTableProxyModel *proxy = dynamic_cast (model); + + int row = proxy ? proxy->mapToSource (index).row() : index.row(); + + // This is not guaranteed to be the same as \a model, since a proxy could be used. + IdTable& model2 = dynamic_cast (*mDocument.getData().getTableModel (mId)); + + int cellColumn = model2.searchColumnIndex (Columns::ColumnId_Cell); + + if (cellColumn!=-1) + { + QModelIndex cellIndex = model2.index (row, cellColumn); + + std::string cellId = model2.data (cellIndex).toString().toUtf8().data(); + + if (cellId.find ('#')!=std::string::npos) + { + // Need to recalculate the cell + modifyCell.reset (new UpdateCellCommand (model2, row)); + } + } + } + + std::auto_ptr modifyData ( + new CSMWorld::ModifyCommand (*model, index, new_)); + + if (modifyCell.get()) + { + mDocument.getUndoStack().beginMacro (modifyData->text()); + mDocument.getUndoStack().push (modifyData.release()); + mDocument.getUndoStack().push (modifyCell.release()); + mDocument.getUndoStack().endMacro(); + } + else + mDocument.getUndoStack().push (modifyData.release()); } void CSMWorld::CommandDispatcher::executeDelete() diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index de0e9a4e53..bd667e40b9 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -1,11 +1,16 @@ #include "commands.hpp" +#include + +#include + #include -#include "idtable.hpp" #include +#include "idtable.hpp" + CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand* parent) : QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) @@ -170,4 +175,44 @@ void CSMWorld::CloneCommand::redo() void CSMWorld::CloneCommand::undo() { mModel.removeRow (mModel.getModelIndex (mId, 0).row()); +} + + +CSMWorld::UpdateCellCommand::UpdateCellCommand (IdTable& model, int row, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mRow (row) +{ + setText ("Update cell ID"); +} + +void CSMWorld::UpdateCellCommand::redo() +{ + if (!mNew.isValid()) + { + int cellColumn = mModel.searchColumnIndex (Columns::ColumnId_Cell); + mIndex = mModel.index (mRow, cellColumn); + + const int cellSize = 8192; + + QModelIndex xIndex = mModel.index ( + mRow, mModel.findColumnIndex (Columns::ColumnId_PositionXPos)); + + QModelIndex yIndex = mModel.index ( + mRow, mModel.findColumnIndex (Columns::ColumnId_PositionYPos)); + + int x = std::floor (mModel.data (xIndex).toFloat() / cellSize); + int y = std::floor (mModel.data (yIndex).toFloat() / cellSize); + + std::ostringstream stream; + + stream << "#" << x << " " << y; + + mNew = QString::fromUtf8 (stream.str().c_str()); + } + + mModel.setData (mIndex, mNew); +} + +void CSMWorld::UpdateCellCommand::undo() +{ + mModel.setData (mIndex, mOld); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index a15c071a8b..26e1da828f 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -18,7 +18,6 @@ class QAbstractItemModel; namespace CSMWorld { - class IdTable; class IdTable; class RecordBase; @@ -139,6 +138,28 @@ namespace CSMWorld virtual void undo(); }; + + /// \brief Update cell ID according to x/y-coordinates + /// + /// \note The new value will be calculated in the first call to redo instead of the + /// constructor to accommodate multiple coordinate-affecting commands being executed + /// in a macro. + class UpdateCellCommand : public QUndoCommand + { + IdTable& mModel; + int mRow; + QModelIndex mIndex; + QVariant mNew; // invalid, if new cell ID has not been calculated yet + QVariant mOld; + + public: + + UpdateCellCommand (IdTable& model, int row, QUndoCommand *parent = 0); + + virtual void redo(); + + virtual void undo(); + }; } #endif \ No newline at end of file From 764c155cece395e7e05de885dd26a0ad62b5c6f4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Jan 2015 13:33:23 +0100 Subject: [PATCH 011/142] moved code for writing/reading ref nums into RefNum struct --- components/esm/cellref.cpp | 27 +++++++++++++++++++-------- components/esm/cellref.hpp | 4 ++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 29d26d013f..a14f977d64 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -4,6 +4,23 @@ #include "esmreader.hpp" #include "esmwriter.hpp" +void ESM::RefNum::load (ESMReader& esm, bool wide) +{ + if (wide) + esm.getHNT (*this, "FRMR", 8); + else + esm.getHNT (mIndex, "FRMR"); +} + +void ESM::RefNum::save (ESMWriter &esm, bool wide) const +{ + if (wide) + esm.writeHNT ("FRMR", *this, 8); + else + esm.writeHNT ("FRMR", mIndex, 4); +} + + void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) { // According to Hrnchamd, this does not belong to the actual ref. Instead, it is a marker indicating that @@ -13,10 +30,7 @@ void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) if (esm.isNextSub ("NAM0")) esm.skipHSub(); - if (wideRefNum) - esm.getHNT (mRefNum, "FRMR", 8); - else - esm.getHNT (mRefNum.mIndex, "FRMR"); + mRefNum.load (esm, wideRefNum); mRefID = esm.getHNString ("NAME"); @@ -74,10 +88,7 @@ void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) const { - if (wideRefNum) - esm.writeHNT ("FRMR", mRefNum, 8); - else - esm.writeHNT ("FRMR", mRefNum.mIndex, 4); + mRefNum.save (esm, wideRefNum); esm.writeHNCString("NAME", mRefID); diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 9c57061b00..505f676b18 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -15,6 +15,10 @@ namespace ESM { int mIndex; int mContentFile; // -1 no content file + + void load (ESMReader& esm, bool wide = false); + + void save (ESMWriter &esm, bool wide = false) const; }; /* Cell reference. This represents ONE object (of many) inside the From a97f599e6529ebdf87188c110839baa40f0c6f7c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Jan 2015 13:41:09 +0100 Subject: [PATCH 012/142] fixed ref num saving in non-wide format --- apps/opencs/model/doc/savingstages.cpp | 36 +++++++++++++++++++++++--- apps/opencs/model/doc/savingstate.cpp | 2 +- apps/opencs/model/doc/savingstate.hpp | 5 ++-- components/esm/cellref.cpp | 6 ++++- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 08f8c9eaa8..6b8750b446 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -231,8 +231,18 @@ void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages) record.mState==CSMWorld::RecordBase::State_Modified || record.mState==CSMWorld::RecordBase::State_ModifiedOnly) { - mState.getSubRecords()[Misc::StringUtils::lowerCase (record.get().mCell)] - .push_back (i); + std::string cellId = record.get().mOriginalCell.empty() ? + record.get().mCell : record.get().mOriginalCell; + + std::deque& indices = + mState.getSubRecords()[Misc::StringUtils::lowerCase (cellId)]; + + // collect moved references at the end of the container + if (!record.get().mOriginalCell.empty() && + record.get().mOriginalCell!=record.get().mCell) + indices.push_back (i); + else + indices.push_front (i); } } } @@ -253,7 +263,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) const CSMWorld::Record& cell = mDocument.getData().getCells().getRecord (stage); - std::map >::const_iterator references = + std::map >::const_iterator references = mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId)); if (cell.mState==CSMWorld::RecordBase::State_Modified || @@ -284,7 +294,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) // write references if (references!=mState.getSubRecords().end()) { - for (std::vector::const_iterator iter (references->second.begin()); + for (std::deque::const_iterator iter (references->second.begin()); iter!=references->second.end(); ++iter) { const CSMWorld::Record& ref = @@ -293,6 +303,24 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) if (ref.mState==CSMWorld::RecordBase::State_Modified || ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) { + if (!ref.get().mOriginalCell.empty() && + ref.get().mOriginalCell!=ref.get().mCell) + { + ESM::MovedCellRef moved; + moved.mRefNum = ref.get().mRefNum; + + std::istringstream stream (ref.get().mCell.c_str()); + + char ignore; + stream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; + + mState.getWriter().startSubRecord ("MVRF"); + + mState.getWriter().endRecord ("MVRF"); + mState.getWriter().writeHNT ("FRMR", moved.mRefNum.mIndex, 4); + mState.getWriter().writeHNT ("CNDT", moved.mTarget, 8); + } + ref.get().save (mState.getWriter()); } else if (ref.mState==CSMWorld::RecordBase::State_Deleted) diff --git a/apps/opencs/model/doc/savingstate.cpp b/apps/opencs/model/doc/savingstate.cpp index 84bca1e95c..e7ad551b27 100644 --- a/apps/opencs/model/doc/savingstate.cpp +++ b/apps/opencs/model/doc/savingstate.cpp @@ -64,7 +64,7 @@ bool CSMDoc::SavingState::isProjectFile() const return mProjectFile; } -std::map >& CSMDoc::SavingState::getSubRecords() +std::map >& CSMDoc::SavingState::getSubRecords() { return mSubRecords; } diff --git a/apps/opencs/model/doc/savingstate.hpp b/apps/opencs/model/doc/savingstate.hpp index 577fc734d6..e6c8c545a7 100644 --- a/apps/opencs/model/doc/savingstate.hpp +++ b/apps/opencs/model/doc/savingstate.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -26,7 +27,7 @@ namespace CSMDoc ESM::ESMWriter mWriter; boost::filesystem::path mProjectPath; bool mProjectFile; - std::map > mSubRecords; // record ID, list of subrecords + std::map > mSubRecords; // record ID, list of subrecords public: @@ -49,7 +50,7 @@ namespace CSMDoc bool isProjectFile() const; ///< Currently saving project file? (instead of content file) - std::map >& getSubRecords(); + std::map >& getSubRecords(); }; diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index a14f977d64..0e258571f6 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -17,7 +17,11 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide) const if (wide) esm.writeHNT ("FRMR", *this, 8); else - esm.writeHNT ("FRMR", mIndex, 4); + { + int refNum = (mIndex & 0xffffff) | ((mContentFile==-1 ? 0xff : mContentFile)<<24); + + esm.writeHNT ("FRMR", refNum, 4); + } } From 89998a6a036fa22cbb81b9113f534571eb3c7a1e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Jan 2015 14:22:29 +0100 Subject: [PATCH 013/142] save MVRF subrecords --- apps/opencs/model/doc/savingstages.cpp | 5 +---- components/esm/cellref.cpp | 6 +++--- components/esm/cellref.hpp | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 6b8750b446..4354a03130 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -314,10 +314,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) char ignore; stream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; - mState.getWriter().startSubRecord ("MVRF"); - - mState.getWriter().endRecord ("MVRF"); - mState.getWriter().writeHNT ("FRMR", moved.mRefNum.mIndex, 4); + ref.get().mRefNum.save (mState.getWriter(), false, "MVRF"); mState.getWriter().writeHNT ("CNDT", moved.mTarget, 8); } diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 0e258571f6..546151e276 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -12,15 +12,15 @@ void ESM::RefNum::load (ESMReader& esm, bool wide) esm.getHNT (mIndex, "FRMR"); } -void ESM::RefNum::save (ESMWriter &esm, bool wide) const +void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const { if (wide) - esm.writeHNT ("FRMR", *this, 8); + esm.writeHNT (tag, *this, 8); else { int refNum = (mIndex & 0xffffff) | ((mContentFile==-1 ? 0xff : mContentFile)<<24); - esm.writeHNT ("FRMR", refNum, 4); + esm.writeHNT (tag, refNum, 4); } } diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 505f676b18..d4e63d6e89 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -18,7 +18,7 @@ namespace ESM void load (ESMReader& esm, bool wide = false); - void save (ESMWriter &esm, bool wide = false) const; + void save (ESMWriter &esm, bool wide = false, const std::string& tag = "FRMR") const; }; /* Cell reference. This represents ONE object (of many) inside the From 7f905470fae10ac8d5665b19adbc995a92cb720d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Jan 2015 15:01:38 +0100 Subject: [PATCH 014/142] fixed moved reference loading --- apps/opencs/model/world/refcollection.cpp | 3 +-- components/esm/cellref.cpp | 5 +++-- components/esm/loadcell.cpp | 20 +++++++++++++++----- components/esm/loadcell.hpp | 3 ++- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index dcb295626a..39f85da708 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -21,7 +21,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool bool deleted = false; - while (ESM::Cell::getNextRef (reader, ref, deleted)) + while (ESM::Cell::getNextRef (reader, ref, deleted, true)) { // Keep mOriginalCell empty when in modified (as an indicator that the // original cell will always be equal the current cell). @@ -29,7 +29,6 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool if (cell.get().isExterior()) { - // ignoring moved references sub-record; instead calculate cell from coordinates std::pair index = ref.getCellIndex(); diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index 546151e276..8579d891f0 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -25,7 +25,7 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const } -void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) +void ESM::CellRef::load (ESMReader& esm, bool wideRefNum, bool ignoreRefNum) { // According to Hrnchamd, this does not belong to the actual ref. Instead, it is a marker indicating that // the following refs are part of a "temp refs" section. A temp ref is not being tracked by the moved references system. @@ -34,7 +34,8 @@ void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) if (esm.isNextSub ("NAM0")) esm.skipHSub(); - mRefNum.load (esm, wideRefNum); + if (!ignoreRefNum) + mRefNum.load (esm, wideRefNum); mRefID = esm.getHNString ("NAME"); diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index e4f847dec2..d836ec9cfd 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -168,7 +168,7 @@ std::string Cell::getDescription() const } } -bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted) +bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMoves) { // TODO: Try and document reference numbering, I don't think this has been done anywhere else. if (!esm.hasMoreSubs()) @@ -176,10 +176,20 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted) // NOTE: We should not need this check. It is a safety check until we have checked // more plugins, and how they treat these moved references. - if (esm.isNextSub("MVRF")) { - // skip rest of cell record (moved references), they are handled elsewhere - esm.skipRecord(); // skip MVRF, CNDT - return false; + if (esm.isNextSub("MVRF")) + { + if (ignoreMoves) + { + MovedCellRef mref; + esm.getHT (mref.mRefNum.mIndex); + esm.getHNOT (mref.mTarget, "CNDT"); + } + else + { + // skip rest of cell record (moved references), they are handled elsewhere + esm.skipRecord(); // skip MVRF, CNDT + return false; + } } ref.load (esm); diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index e1a6eee1ab..8eeecd8931 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -156,7 +156,8 @@ struct Cell All fields of the CellRef struct are overwritten. You can safely reuse one memory location without blanking it between calls. */ - static bool getNextRef(ESMReader &esm, CellRef &ref, bool& deleted); + /// \param ignoreMoves ignore MVRF record and read reference like a regular CellRef. + static bool getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMoves = false); /* This fetches an MVRF record, which is used to track moved references. * Since they are comparably rare, we use a separate method for this. From 7bc0d41bb060f59e5356244119ca2f32406dbf9d Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 19 Mar 2015 15:51:45 +0100 Subject: [PATCH 015/142] Marker collision fix (Fixes #2461) --- components/nifbullet/bulletnifloader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index cdc06f985b..93c9797b25 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -274,9 +274,9 @@ void ManualBulletShapeLoader::handleNode(const Nif::Node *node, int flags, // No collision. Use an internal flag setting to mark this. flags |= 0x800; } - else if (sd->string == "MRK" && !mShowMarkers && raycasting) + else if (sd->string == "MRK" && !mShowMarkers && (raycasting || mShape->mAutogenerated)) { - // Marker objects should be invisible, but still have collision. + // Marker objects should be invisible, but can still have collision if the model explicitely specifies it via a RootCollisionNode. // Except in the editor, the marker objects are visible. return; } From 5cb61fa01cc8cbaacec8f348f473bff7d3781619 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 22 Mar 2015 17:25:23 +0100 Subject: [PATCH 016/142] Don't mark gold as stolen, adjust stolen tooltip (Fixes #2465) --- apps/openmw/mwgui/tooltips.cpp | 5 ++++- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 4e03b788a4..4e83c25db3 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -593,7 +593,10 @@ namespace MWGui for (std::vector >::const_iterator it = itemOwners.begin(); it != itemOwners.end(); ++it) { - ret += std::string("\nStolen from ") + it->first; + if (it->second == std::numeric_limits::max()) + ret += std::string("\nStolen from ") + it->first; // for legacy (ESS) savegames + else + ret += std::string("\nStolen ") + MyGUI::utility::toString(it->second) + " from " + it->first; } ret += getMiscString(cellref.getGlobalVariable(), "Global"); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 0d4518f875..617f38daf2 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1030,7 +1030,9 @@ namespace MWMechanics owner.second = true; } Misc::StringUtils::toLower(owner.first); - mStolenItems[Misc::StringUtils::lowerCase(item.getClass().getId(item))][owner] += count; + + if (!Misc::StringUtils::ciEqual(item.getCellRef().getRefId(), MWWorld::ContainerStore::sGoldId)) + mStolenItems[Misc::StringUtils::lowerCase(item.getClass().getId(item))][owner] += count; commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count); } From 20af2b67a838dbda3fe1e622b0a25d058e813427 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 17 Apr 2015 18:54:14 +0200 Subject: [PATCH 017/142] Change the triangle pattern used for terrain (Fixes #2459) --- components/terrain/buffercache.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/components/terrain/buffercache.cpp b/components/terrain/buffercache.cpp index 01032bcdae..1b000fabb1 100644 --- a/components/terrain/buffercache.cpp +++ b/components/terrain/buffercache.cpp @@ -59,13 +59,27 @@ Ogre::HardwareIndexBufferSharedPtr createIndexBuffer(unsigned int flags, unsigne { for (size_t col = colStart; col < colEnd; col += increment) { - indices.push_back(verts*col+row); - indices.push_back(verts*(col+increment)+row+increment); - indices.push_back(verts*col+row+increment); + // diamond pattern + if ((row + col%2) % 2 == 1) + { + indices.push_back(verts*(col+increment)+row); + indices.push_back(verts*(col+increment)+row+increment); + indices.push_back(verts*col+row+increment); - indices.push_back(verts*col+row); - indices.push_back(verts*(col+increment)+row); - indices.push_back(verts*(col+increment)+row+increment); + indices.push_back(verts*col+row); + indices.push_back(verts*(col+increment)+row); + indices.push_back(verts*(col)+row+increment); + } + else + { + indices.push_back(verts*col+row); + indices.push_back(verts*(col+increment)+row+increment); + indices.push_back(verts*col+row+increment); + + indices.push_back(verts*col+row); + indices.push_back(verts*(col+increment)+row); + indices.push_back(verts*(col+increment)+row+increment); + } } } From b80f8afab8cd3a99e643ac64623e2624645b7e51 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 22 Apr 2015 00:04:46 +0200 Subject: [PATCH 018/142] Readme: Make status badges consistent again --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa5af0e6d7..811eb87632 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ OpenMW ====== -[![Build Status](https://img.shields.io/travis/OpenMW/openmw.svg?style=plastic)](https://travis-ci.org/OpenMW/openmw) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740) +[![Build Status](https://img.shields.io/travis/OpenMW/openmw.svg)](https://travis-ci.org/OpenMW/openmw) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740) OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. From e49b8fe690fa899b72b74844415be46c79e87716 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 22 Apr 2015 01:17:01 +0200 Subject: [PATCH 019/142] Fix persuasion mechanics using player stats instead of NPC's (Fixes #2475) --- .../mwmechanics/mechanicsmanagerimp.cpp | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 617f38daf2..da8d49db0f 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -52,6 +52,31 @@ namespace return ((50.f - disposition) * fFightDispMult); } + void getPersuasionRatings(const MWMechanics::NpcStats& stats, float& rating1, float& rating2, float& rating3, bool player) + { + const MWWorld::Store &gmst = + MWBase::Environment::get().getWorld()->getStore().get(); + + float persTerm = stats.getAttribute(ESM::Attribute::Personality).getModified() / gmst.find("fPersonalityMod")->getFloat(); + float luckTerm = stats.getAttribute(ESM::Attribute::Luck).getModified() / gmst.find("fLuckMod")->getFloat(); + float repTerm = stats.getReputation() * gmst.find("fReputationMod")->getFloat(); + float fatigueTerm = stats.getFatigueTerm(); + float levelTerm = stats.getLevel() * gmst.find("fLevelMod")->getFloat(); + + rating1 = (repTerm + luckTerm + persTerm + stats.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; + + if (player) + { + rating2 = rating1 + levelTerm; + rating3 = (stats.getSkill(ESM::Skill::Mercantile).getModified() + luckTerm + persTerm) * fatigueTerm; + } + else + { + rating2 = (levelTerm + repTerm + luckTerm + persTerm + stats.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; + rating3 = (stats.getSkill(ESM::Skill::Mercantile).getModified() + repTerm + luckTerm + persTerm) * fatigueTerm; + } + } + } namespace MWMechanics @@ -685,24 +710,11 @@ namespace MWMechanics MWWorld::Ptr playerPtr = MWBase::Environment::get().getWorld()->getPlayerPtr(); const MWMechanics::NpcStats &playerStats = playerPtr.getClass().getNpcStats(playerPtr); - float persTerm = playerStats.getAttribute(ESM::Attribute::Personality).getModified() - / gmst.find("fPersonalityMod")->getFloat(); + float npcRating1, npcRating2, npcRating3; + getPersuasionRatings(npcStats, npcRating1, npcRating2, npcRating3, false); - float luckTerm = playerStats.getAttribute(ESM::Attribute::Luck).getModified() - / gmst.find("fLuckMod")->getFloat(); - - float repTerm = playerStats.getReputation() * gmst.find("fReputationMod")->getFloat(); - float levelTerm = playerStats.getLevel() * gmst.find("fLevelMod")->getFloat(); - - float fatigueTerm = playerStats.getFatigueTerm(); - - float playerRating1 = (repTerm + luckTerm + persTerm + playerStats.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; - float playerRating2 = playerRating1 + levelTerm; - float playerRating3 = (playerStats.getSkill(ESM::Skill::Mercantile).getModified() + luckTerm + persTerm) * fatigueTerm; - - float npcRating1 = (repTerm + luckTerm + persTerm + playerStats.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; - float npcRating2 = (levelTerm + repTerm + luckTerm + persTerm + npcStats.getSkill(ESM::Skill::Speechcraft).getModified()) * fatigueTerm; - float npcRating3 = (playerStats.getSkill(ESM::Skill::Mercantile).getModified() + repTerm + luckTerm + persTerm) * fatigueTerm; + float playerRating1, playerRating2, playerRating3; + getPersuasionRatings(playerStats, playerRating1, playerRating2, playerRating3, true); int currentDisposition = std::min(100, std::max(0, int(getDerivedDisposition(npc) + currentTemporaryDispositionDelta))); From a6925683c69817aad02305356e02e881d9a03c3e Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Apr 2015 06:04:39 +1000 Subject: [PATCH 020/142] Off by one error - can't delete the last element of a refid collection. --- apps/opencs/model/world/refiddata.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refiddata.hpp b/apps/opencs/model/world/refiddata.hpp index eaa7b115d3..85d16a6eb2 100644 --- a/apps/opencs/model/world/refiddata.hpp +++ b/apps/opencs/model/world/refiddata.hpp @@ -130,7 +130,7 @@ namespace CSMWorld template void RefIdDataContainer::erase (int index, int count) { - if (index<0 || index+count>=getSize()) + if (index<0 || index+count>getSize()) throw std::runtime_error ("invalid RefIdDataContainer index"); mContainer.erase (mContainer.begin()+index, mContainer.begin()+index+count); From 8aaa74a9838aeb92710c601369534b3b82433e9a Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Apr 2015 06:06:11 +1000 Subject: [PATCH 021/142] Undo for delete operation in referenceables table. Implemented by saving UniversalId::Type in DeleteCommand. --- apps/opencs/model/world/commanddispatcher.cpp | 24 ++++++++++++++++--- apps/opencs/model/world/commands.cpp | 7 +++--- apps/opencs/model/world/commands.hpp | 4 +++- apps/opencs/model/world/idtable.cpp | 4 ++-- apps/opencs/model/world/idtable.hpp | 3 ++- apps/opencs/model/world/idtree.cpp | 7 ++++++ apps/opencs/model/world/idtree.hpp | 2 ++ 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index ca6faafbc0..d94033d9cf 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -8,6 +8,7 @@ #include "../doc/document.hpp" #include "idtable.hpp" +#include "idtree.hpp" #include "record.hpp" #include "commands.hpp" @@ -153,7 +154,15 @@ void CSMWorld::CommandDispatcher::executeDelete() std::string id = model.data (model.getModelIndex (*iter, columnIndex)). toString().toUtf8().constData(); - mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id)); + if (mId.getType() == UniversalId::Type_Referenceables) + { + IdTree& tree = dynamic_cast (*mDocument.getData().getTableModel (mId)); + std::pair localIndex = tree.searchId (id); + + mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id, localIndex.second)); + } + else + mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id)); } if (rows.size()>1) @@ -219,8 +228,17 @@ void CSMWorld::CommandDispatcher::executeExtendedDelete() Misc::StringUtils::lowerCase (record.get().mCell))) continue; - mDocument.getUndoStack().push ( - new CSMWorld::DeleteCommand (model, record.get().mId)); + if (mId.getType() == UniversalId::Type_Referenceables) + { + IdTree& tree = dynamic_cast (*mDocument.getData().getTableModel (mId)); + std::pair localIndex = tree.searchId (record.get().mId); + + mDocument.getUndoStack().push ( + new CSMWorld::DeleteCommand (model, record.get().mId, localIndex.second)); + } + else + mDocument.getUndoStack().push ( + new CSMWorld::DeleteCommand (model, record.get().mId)); } } } diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index ce82e07bfa..5a3190846d 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -103,8 +103,9 @@ void CSMWorld::RevertCommand::undo() mModel.setRecord (mId, *mOld); } -CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, const std::string& id, QUndoCommand* parent) -: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, + const std::string& id, CSMWorld::UniversalId::Type type, QUndoCommand* parent) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0), mType(type) { setText (("Delete record " + id).c_str()); @@ -135,7 +136,7 @@ void CSMWorld::DeleteCommand::redo() void CSMWorld::DeleteCommand::undo() { - mModel.setRecord (mId, *mOld); + mModel.setRecord (mId, *mOld, mType); } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 2bd47ae916..89ca5d1ffd 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -111,6 +111,7 @@ namespace CSMWorld IdTable& mModel; std::string mId; RecordBase *mOld; + UniversalId::Type mType; // not implemented DeleteCommand (const DeleteCommand&); @@ -118,7 +119,8 @@ namespace CSMWorld public: - DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); + DeleteCommand (IdTable& model, const std::string& id, + UniversalId::Type type = UniversalId::Type_None, QUndoCommand *parent = 0); virtual ~DeleteCommand(); diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 28742c8f2c..2f0164c2d3 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -145,7 +145,7 @@ QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) return index(mIdCollection->getIndex (id), column); } -void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record) +void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record, CSMWorld::UniversalId::Type type) { int index = mIdCollection->searchId (id); @@ -155,7 +155,7 @@ void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& reco beginInsertRows (QModelIndex(), index, index); - mIdCollection->appendRecord (record); + mIdCollection->appendRecord (record, type); endInsertRows(); } diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 559a43cb73..9ecba02142 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -59,7 +59,8 @@ namespace CSMWorld virtual QModelIndex getModelIndex (const std::string& id, int column) const; - void setRecord (const std::string& id, const RecordBase& record); + void setRecord (const std::string& id, const RecordBase& record, + UniversalId::Type type = UniversalId::Type_None); ///< Add record or overwrite existing recrod. const RecordBase& getRecord (const std::string& id) const; diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp index 06db09a0fc..564e4ec2f4 100644 --- a/apps/opencs/model/world/idtree.cpp +++ b/apps/opencs/model/world/idtree.cpp @@ -4,6 +4,7 @@ #include "collectionbase.hpp" #include "nestedcollection.hpp" +#include "refidcollection.hpp" // HACK: for searchId() only #include "columnbase.hpp" // NOTE: parent class still needs idCollection @@ -257,3 +258,9 @@ CSMWorld::NestedTableWrapperBase* CSMWorld::IdTree::nestedTable(const QModelInde return mNestedCollection->nestedTable(index.row(), index.column()); } + +// HACK: to get the UniversalId::Type associated with a particular record +std::pair CSMWorld::IdTree::searchId (const std::string& id) const +{ + return dynamic_cast(idCollection())->getDataSet().searchId(id); +} diff --git a/apps/opencs/model/world/idtree.hpp b/apps/opencs/model/world/idtree.hpp index 5337ed82b8..73cc9bdfd8 100644 --- a/apps/opencs/model/world/idtree.hpp +++ b/apps/opencs/model/world/idtree.hpp @@ -73,6 +73,8 @@ namespace CSMWorld virtual bool hasChildren (const QModelIndex& index) const; + std::pair searchId (const std::string& id) const; + signals: void resetStart(const QString& id); From acb800b8f980f5cdb52974f6ec43def7a6ac7480 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Apr 2015 09:39:37 +1000 Subject: [PATCH 022/142] Resolve merge issues and fix typos. --- apps/opencs/model/world/columnbase.hpp | 2 +- apps/opencs/model/world/ref.cpp | 3 -- apps/opencs/view/world/dialoguesubview.cpp | 42 ++++++++++------------ apps/opencs/view/world/dialoguesubview.hpp | 17 ++------- apps/opencs/view/world/nestedtable.cpp | 4 +++ apps/opencs/view/world/nestedtable.hpp | 3 ++ apps/opencs/view/world/util.cpp | 8 ++--- components/esm/cellref.cpp | 6 ++-- components/esm/cellref.hpp | 13 +++---- 9 files changed, 38 insertions(+), 60 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 257b67d723..71c22a9f07 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -18,7 +18,7 @@ namespace CSMWorld { Role_Flags = Qt::UserRole, Role_Display = Qt::UserRole+1, - Role_ColumnId = Qt::UserRole+1 + Role_ColumnId = Qt::UserRole+2 }; enum Flags diff --git a/apps/opencs/model/world/ref.cpp b/apps/opencs/model/world/ref.cpp index 6612349f7b..13706c950c 100644 --- a/apps/opencs/model/world/ref.cpp +++ b/apps/opencs/model/world/ref.cpp @@ -8,7 +8,6 @@ CSMWorld::CellRef::CellRef() mRefNum.mIndex = 0; mRefNum.mContentFile = 0; } -<<<<<<< HEAD std::pair CSMWorld::CellRef::getCellIndex() const { @@ -17,5 +16,3 @@ std::pair CSMWorld::CellRef::getCellIndex() const return std::make_pair ( std::floor (mPos.pos[0]/cellSize), std::floor (mPos.pos[1]/cellSize)); } -======= ->>>>>>> master diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 12b4c86f67..cf3653c1b2 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -176,18 +176,12 @@ void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std:: ==============================DialogueDelegateDispatcher========================================== */ -<<<<<<< HEAD -CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document) : -mParent(parent), -mTable(table), -mCommandDispatcher (commandDispatcher), mDocument (document), -======= CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, - CSMWorld::IdTable* table, CSMDoc::Document& document, QAbstractItemModel *model) : + CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, + CSMDoc::Document& document, QAbstractItemModel *model) : mParent(parent), mTable(model ? model : table), -mDocument (document), ->>>>>>> master +mCommandDispatcher (commandDispatcher), mDocument (document), mNotEditableDelegate(table, parent) { } @@ -350,10 +344,6 @@ CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher() =============================================================EditWidget===================================================== */ -<<<<<<< HEAD -CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, bool createAndDelete) : -mDispatcher(this, table, commandDispatcher, document), -======= CSVWorld::EditWidget::~EditWidget() { for (unsigned i = 0; i < mNestedModels.size(); ++i) @@ -363,15 +353,17 @@ CSVWorld::EditWidget::~EditWidget() delete mNestedTableDispatcher; } -CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMDoc::Document& document, bool createAndDelete) : -mDispatcher(this, table, document), +CSVWorld::EditWidget::EditWidget(QWidget *parent, + int row, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, + CSMDoc::Document& document, bool createAndDelete) : +mDispatcher(this, table, commandDispatcher, document), mNestedTableDispatcher(NULL), ->>>>>>> master QScrollArea(parent), mWidgetMapper(NULL), mNestedTableMapper(NULL), mMainWidget(NULL), mCommandDispatcher (commandDispatcher), +mDocument (document), mTable(table) { remake (row); @@ -454,7 +446,14 @@ void CSVWorld::EditWidget::remake(int row) { mNestedModels.push_back(new CSMWorld::NestedTableProxyModel (mTable->index(row, i), display, dynamic_cast(mTable))); - NestedTable* table = new NestedTable(mDocument, mNestedModels.back(), this); + int idColumn = mTable->findColumnIndex (CSMWorld::Columns::ColumnId_Id); + int typeColumn = mTable->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType); + + CSMWorld::UniversalId id = CSMWorld::UniversalId( + static_cast (mTable->data (mTable->index (row, typeColumn)).toInt()), + mTable->data (mTable->index (row, idColumn)).toString().toUtf8().constData()); + + NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this); // FIXME: does not work well when enum delegates are used //table->resizeColumnsToContents(); table->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::CurrentChanged); @@ -511,7 +510,7 @@ void CSVWorld::EditWidget::remake(int row) mNestedTableMapper->setModel(mNestedModels.back()); // FIXME: lack MIME support? mNestedTableDispatcher = - new DialogueDelegateDispatcher (this, mTable, mDocument, mNestedModels.back()); + new DialogueDelegateDispatcher (this, mTable, mCommandDispatcher, mDocument, mNestedModels.back()); mNestedTableMapper->setItemDelegate(mNestedTableDispatcher); int columnCount = @@ -638,11 +637,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout = new QVBoxLayout(mainWidget); -<<<<<<< HEAD - mEditWidget = new EditWidget(mainWidget, mRow, mTable, mCommandDispatcher, document, false); -======= - mEditWidget = new EditWidget(mainWidget, mTable->getModelIndex(mCurrentId, 0).row(), mTable, document, false); ->>>>>>> master + mEditWidget = new EditWidget(mainWidget, + mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false); connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 4d463246aa..b5a44d266f 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -109,10 +109,7 @@ namespace CSVWorld QAbstractItemModel* mTable; -<<<<<<< HEAD CSMWorld::CommandDispatcher& mCommandDispatcher; -======= ->>>>>>> master CSMDoc::Document& mDocument; NotEditableSubDelegate mNotEditableDelegate; @@ -121,15 +118,11 @@ namespace CSVWorld //once we move to the C++11 we should use unique_ptr public: -<<<<<<< HEAD - DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, - CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document); -======= DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, + CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, QAbstractItemModel* model = 0); ->>>>>>> master ~DialogueDelegateDispatcher(); @@ -176,23 +169,17 @@ namespace CSVWorld DialogueDelegateDispatcher *mNestedTableDispatcher; QWidget* mMainWidget; CSMWorld::IdTable* mTable; -<<<<<<< HEAD CSMWorld::CommandDispatcher& mCommandDispatcher; - - public: - - EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, bool createAndDelete = false); -======= CSMDoc::Document& mDocument; std::vector mNestedModels; //Plain, raw C pointers, deleted in the dtor public: EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, + CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, bool createAndDelete = false); virtual ~EditWidget(); ->>>>>>> master void remake(int row); diff --git a/apps/opencs/view/world/nestedtable.cpp b/apps/opencs/view/world/nestedtable.cpp index 1597c81a35..5c8762020f 100644 --- a/apps/opencs/view/world/nestedtable.cpp +++ b/apps/opencs/view/world/nestedtable.cpp @@ -2,6 +2,7 @@ #include "../../model/world/nestedtableproxymodel.hpp" #include "../../model/world/universalid.hpp" #include "../../model/world/commands.hpp" +#include "../../model/world/commanddispatcher.hpp" #include "util.hpp" #include @@ -10,12 +11,14 @@ #include CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, + CSMWorld::UniversalId id, CSMWorld::NestedTableProxyModel* model, QWidget* parent) : QTableView(parent), mUndoStack(document.getUndoStack()), mModel(model) { + mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); setSelectionBehavior (QAbstractItemView::SelectRows); setSelectionMode (QAbstractItemView::ExtendedSelection); @@ -31,6 +34,7 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, model->headerData (i, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); CommandDelegate *delegate = CommandDelegateFactoryCollection::get().makeDelegate(display, + mDispatcher, document, this); diff --git a/apps/opencs/view/world/nestedtable.hpp b/apps/opencs/view/world/nestedtable.hpp index f41ba43452..b8e91844c2 100644 --- a/apps/opencs/view/world/nestedtable.hpp +++ b/apps/opencs/view/world/nestedtable.hpp @@ -12,6 +12,7 @@ namespace CSMWorld { class NestedTableProxyModel; class UniversalId; + class CommandDispatcher; } namespace CSMDoc @@ -29,9 +30,11 @@ namespace CSVWorld QAction *mRemoveRowAction; QUndoStack& mUndoStack; CSMWorld::NestedTableProxyModel* mModel; + CSMWorld::CommandDispatcher *mDispatcher; public: NestedTable(CSMDoc::Document& document, + CSMWorld::UniversalId id, CSMWorld::NestedTableProxyModel* model, QWidget* parent = NULL); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index fbcfc5215d..8b4bfeaacc 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -124,13 +124,9 @@ void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemM QVariant new_ = hack.getData(); -<<<<<<< HEAD - if (model->data (index)!=new_) - mCommandDispatcher->executeModify (model, index, new_); -======= if ((model->data (index)!=new_) && (model->flags(index) & Qt::ItemIsEditable)) - getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, new_)); ->>>>>>> master + //getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, new_)); // FIXME + mCommandDispatcher->executeModify (model, index, new_); } CSVWorld::CommandDelegate::CommandDelegate (CSMWorld::CommandDispatcher *commandDispatcher, diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index f78cc0c85a..f9f5e161a3 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -18,7 +18,7 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const esm.writeHNT (tag, *this, 8); else { - int refNum = (mIndex & 0xffffff) | ((mContentFile==-1 ? 0xff : mContentFile)<<24); + int refNum = (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile<<24 : 0xff)); esm.writeHNT (tag, refNum, 4); } @@ -27,11 +27,11 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const void ESM::CellRef::load (ESMReader& esm, bool wideRefNum, bool ignoreRefNum) { - loadId(esm, wideRefNum); + loadId(esm, wideRefNum, ignoreRefNum); loadData(esm); } -void ESM::CellRef::loadId(ESMReader &esm, bool wideRefNum) +void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum, bool ignoreRefNum) { // According to Hrnchamd, this does not belong to the actual ref. Instead, it is a marker indicating that // the following refs are part of a "temp refs" section. A temp ref is not being tracked by the moved references system. diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index f98b407c65..0fb449e161 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -13,21 +13,16 @@ namespace ESM struct RefNum { -<<<<<<< HEAD - int mIndex; - int mContentFile; // -1 no content file + unsigned int mIndex; + int mContentFile; void load (ESMReader& esm, bool wide = false); void save (ESMWriter &esm, bool wide = false, const std::string& tag = "FRMR") const; -======= - unsigned int mIndex; - int mContentFile; enum { RefNum_NoContentFile = -1 }; inline bool hasContentFile() const { return mContentFile != RefNum_NoContentFile; } inline void unset() { mIndex = 0; mContentFile = RefNum_NoContentFile; } ->>>>>>> master }; /* Cell reference. This represents ONE object (of many) inside the @@ -105,9 +100,9 @@ namespace ESM Position mPos; /// Calls loadId and loadData - void load (ESMReader& esm, bool wideRefNum = false); + void load (ESMReader& esm, bool wideRefNum = false, bool ignoreRefNum = false); - void loadId (ESMReader& esm, bool wideRefNum = false); + void loadId (ESMReader& esm, bool wideRefNum = false, bool ignoreRefNum = false); /// Implicitly called by load void loadData (ESMReader& esm); From 932f1f9fbd02b50770a7831d1862bdfde954fdfd Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Apr 2015 15:26:32 +1000 Subject: [PATCH 023/142] Alternative way of finding UniversalId without bloating IdTree. --- apps/opencs/model/world/commanddispatcher.cpp | 22 +++++-------------- apps/opencs/model/world/idtree.cpp | 7 ------ apps/opencs/model/world/idtree.hpp | 2 -- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index d94033d9cf..199f91e29c 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -8,7 +8,6 @@ #include "../doc/document.hpp" #include "idtable.hpp" -#include "idtree.hpp" #include "record.hpp" #include "commands.hpp" @@ -156,10 +155,10 @@ void CSMWorld::CommandDispatcher::executeDelete() if (mId.getType() == UniversalId::Type_Referenceables) { - IdTree& tree = dynamic_cast (*mDocument.getData().getTableModel (mId)); - std::pair localIndex = tree.searchId (id); - - mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id, localIndex.second)); + mDocument.getUndoStack().push ( new CSMWorld::DeleteCommand (model, id, + static_cast(model.data (model.index ( + model.getModelIndex (id, columnIndex).row(), + model.findColumnIndex (CSMWorld::Columns::ColumnId_RecordType))).toInt()))); } else mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id)); @@ -228,17 +227,8 @@ void CSMWorld::CommandDispatcher::executeExtendedDelete() Misc::StringUtils::lowerCase (record.get().mCell))) continue; - if (mId.getType() == UniversalId::Type_Referenceables) - { - IdTree& tree = dynamic_cast (*mDocument.getData().getTableModel (mId)); - std::pair localIndex = tree.searchId (record.get().mId); - - mDocument.getUndoStack().push ( - new CSMWorld::DeleteCommand (model, record.get().mId, localIndex.second)); - } - else - mDocument.getUndoStack().push ( - new CSMWorld::DeleteCommand (model, record.get().mId)); + mDocument.getUndoStack().push ( + new CSMWorld::DeleteCommand (model, record.get().mId)); } } } diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp index 564e4ec2f4..06db09a0fc 100644 --- a/apps/opencs/model/world/idtree.cpp +++ b/apps/opencs/model/world/idtree.cpp @@ -4,7 +4,6 @@ #include "collectionbase.hpp" #include "nestedcollection.hpp" -#include "refidcollection.hpp" // HACK: for searchId() only #include "columnbase.hpp" // NOTE: parent class still needs idCollection @@ -258,9 +257,3 @@ CSMWorld::NestedTableWrapperBase* CSMWorld::IdTree::nestedTable(const QModelInde return mNestedCollection->nestedTable(index.row(), index.column()); } - -// HACK: to get the UniversalId::Type associated with a particular record -std::pair CSMWorld::IdTree::searchId (const std::string& id) const -{ - return dynamic_cast(idCollection())->getDataSet().searchId(id); -} diff --git a/apps/opencs/model/world/idtree.hpp b/apps/opencs/model/world/idtree.hpp index 73cc9bdfd8..5337ed82b8 100644 --- a/apps/opencs/model/world/idtree.hpp +++ b/apps/opencs/model/world/idtree.hpp @@ -73,8 +73,6 @@ namespace CSMWorld virtual bool hasChildren (const QModelIndex& index) const; - std::pair searchId (const std::string& id) const; - signals: void resetStart(const QString& id); From dcce59f76cb5915216dfaffface63a8592eba85b Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Apr 2015 17:20:02 +1000 Subject: [PATCH 024/142] Pass MovedCellRef info to RefCollection. Still has debugging code. --- apps/opencs/model/world/refcollection.cpp | 21 ++++++++++++++++-- components/esm/loadcell.cpp | 26 +++++++++++++++++++---- components/esm/loadcell.hpp | 3 ++- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 39f85da708..bd4e69d6b2 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -2,8 +2,10 @@ #include "refcollection.hpp" #include +#include // FIXME: debug only #include +#include #include "ref.hpp" #include "cell.hpp" @@ -20,20 +22,35 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool CellRef ref; bool deleted = false; + ESM::MovedCellRef mref; - while (ESM::Cell::getNextRef (reader, ref, deleted, true)) + // hack to initialise mindex + while (!(mref.mRefNum.mIndex = 0) && ESM::Cell::getNextRef (reader, ref, deleted, true, &mref)) { // Keep mOriginalCell empty when in modified (as an indicator that the // original cell will always be equal the current cell). ref.mOriginalCell = base ? cell2.mId : ""; + if (mref.mRefNum.mIndex != 0 && + ((int)std::floor(ref.mPos.pos[0]/8192) != mref.mTarget[0] || + (int)std::floor(ref.mPos.pos[1]/8192) != mref.mTarget[1])) + { + //std::cout <<"refcollection #" << mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; + } + if (cell.get().isExterior()) { // ignoring moved references sub-record; instead calculate cell from coordinates std::pair index = ref.getCellIndex(); std::ostringstream stream; - stream << "#" << index.first << " " << index.second; + if (mref.mRefNum.mIndex) + { + stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1]; + //std::cout <<"refcollection " + stream.str() << std::endl; + } + else + stream << "#" << index.first << " " << index.second; ref.mCell = stream.str(); } diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index d836ec9cfd..aed56f415b 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -3,6 +3,7 @@ #include #include #include +#include // FIXME: debugging only #include @@ -168,11 +169,12 @@ std::string Cell::getDescription() const } } -bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMoves) +bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMoves, MovedCellRef *mref) { // TODO: Try and document reference numbering, I don't think this has been done anywhere else. if (!esm.hasMoreSubs()) return false; + //bool print = false; // FIXME: debugging only // NOTE: We should not need this check. It is a safety check until we have checked // more plugins, and how they treat these moved references. @@ -180,9 +182,12 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMo { if (ignoreMoves) { - MovedCellRef mref; - esm.getHT (mref.mRefNum.mIndex); - esm.getHNOT (mref.mTarget, "CNDT"); + esm.getHT (mref->mRefNum.mIndex); + esm.getHNOT (mref->mTarget, "CNDT"); + //std::cout << "index " + std::to_string(mref->mRefNum.mIndex) + " target " << + //std::to_string(mref->mTarget[0]) + ", " + std::to_string(mref->mTarget[1]) << std::endl; + //print = true; // FIXME: debugging only + adjustRefNum (mref->mRefNum, esm); } else { @@ -194,6 +199,19 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMo ref.load (esm); +#if 0 + // FIXME: debugging only + if (print && + ((int)std::floor(ref.mPos.pos[0]/8192) != mref->mTarget[0] || + (int)std::floor(ref.mPos.pos[1]/8192) != mref->mTarget[1])) + { + std::cout << ref.mRefID << + ", " + std::to_string((int)std::floor(ref.mPos.pos[0]/8192)) << + ", " + std::to_string((int)std::floor(ref.mPos.pos[1]/8192)) << + ", Z: " +std::to_string(ref.mPos.pos[2]) << std::endl; + } +#endif + // Identify references belonging to a parent file and adapt the ID accordingly. adjustRefNum (ref.mRefNum, esm); diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index 554fa39674..b78d4075a7 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -157,7 +157,8 @@ struct Cell reuse one memory location without blanking it between calls. */ /// \param ignoreMoves ignore MVRF record and read reference like a regular CellRef. - static bool getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMoves = false); + static bool getNextRef(ESMReader &esm, + CellRef &ref, bool& deleted, bool ignoreMoves = false, MovedCellRef *mref = 0); /* This fetches an MVRF record, which is used to track moved references. * Since they are comparably rare, we use a separate method for this. From 2e2d6e04feb8e5cf80b04219b0c1730fe90b26e1 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Apr 2015 17:43:29 +1000 Subject: [PATCH 025/142] gcc friendly version. --- apps/opencs/model/world/refcollection.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index bd4e69d6b2..14d4a1db57 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -31,12 +31,14 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool // original cell will always be equal the current cell). ref.mOriginalCell = base ? cell2.mId : ""; +#if 0 if (mref.mRefNum.mIndex != 0 && ((int)std::floor(ref.mPos.pos[0]/8192) != mref.mTarget[0] || (int)std::floor(ref.mPos.pos[1]/8192) != mref.mTarget[1])) { - //std::cout <<"refcollection #" << mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; + std::cout <<"refcollection #" << mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; } +#endif if (cell.get().isExterior()) { From e668b35b02ee40236a7291cd14f7df3b5fb27b49 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 25 Apr 2015 17:51:31 +1000 Subject: [PATCH 026/142] Fix typo. --- components/esm/cellref.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index f9f5e161a3..ef33f495f1 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -18,7 +18,7 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const esm.writeHNT (tag, *this, 8); else { - int refNum = (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile<<24 : 0xff)); + int refNum = (mIndex & 0xffffff) | ((hasContentFile() ? mContentFile : 0xff)<<24); esm.writeHNT (tag, refNum, 4); } From 74b98f7178584a04d32f9e1b1bc7cd3ab1b1b1ba Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Apr 2015 11:35:46 +1000 Subject: [PATCH 027/142] Fixed initial loading of moved refs. --- apps/opencs/model/world/data.cpp | 13 ++++-- apps/opencs/model/world/idcollection.hpp | 9 ++++ apps/opencs/model/world/refcollection.cpp | 57 ++++++++++++++++------- 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index b25d84829a..91fa556ab7 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -861,9 +862,15 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) case ESM::REC_CELL: { - mCells.load (*mReader, mBase); - std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (mCells.getSize()-1)); - mRefs.load (*mReader, mCells.getSize()-1, mBase, mRefLoadCache[cellId], messages); + int index = mCells.load (*mReader, mBase); + if (index < 0 || index >= mCells.getSize()) + { + // log an error and continue loading the refs to the last loaded cell + std::cerr << "Logic error: cell index out of bounds" << std::endl; + index = mCells.getSize()-1; + } + std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index)); + mRefs.load (*mReader, index, mBase, mRefLoadCache[cellId], messages); break; } diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index f00ea447aa..4eafc59bd5 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -74,6 +74,15 @@ namespace CSMWorld { ESXRecordT record; + // Sometimes id (i.e. NAME of the cell) may be different to the id we stored + // earlier. e.g. NAME == "Vivec, Arena" but id == "#-4 11". Sometime NAME is + // missing altogether for scripts or cells. + // + // In such cases the returned index will be -1. We then try updating the + // IdAccessor's id manually (e.g. set mId of the record to "Vivec, Arena") + // and try getting the index once more after loading the record. The mId of the + // record would have changed to "#-4 11" after the load, and searchId() should find + // it (if this is a modify) int index = this->searchId (id); if (index==-1) diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 14d4a1db57..bd4cf918cf 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -2,7 +2,6 @@ #include "refcollection.hpp" #include -#include // FIXME: debug only #include #include @@ -25,36 +24,58 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool ESM::MovedCellRef mref; // hack to initialise mindex - while (!(mref.mRefNum.mIndex = 0) && ESM::Cell::getNextRef (reader, ref, deleted, true, &mref)) + while (!(mref.mRefNum.mIndex = 0) && ESM::Cell::getNextRef(reader, ref, deleted, true, &mref)) { // Keep mOriginalCell empty when in modified (as an indicator that the // original cell will always be equal the current cell). ref.mOriginalCell = base ? cell2.mId : ""; -#if 0 - if (mref.mRefNum.mIndex != 0 && - ((int)std::floor(ref.mPos.pos[0]/8192) != mref.mTarget[0] || - (int)std::floor(ref.mPos.pos[1]/8192) != mref.mTarget[1])) - { - std::cout <<"refcollection #" << mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; - } -#endif - if (cell.get().isExterior()) { // ignoring moved references sub-record; instead calculate cell from coordinates std::pair index = ref.getCellIndex(); std::ostringstream stream; - if (mref.mRefNum.mIndex) - { - stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1]; - //std::cout <<"refcollection " + stream.str() << std::endl; - } - else - stream << "#" << index.first << " " << index.second; + stream << "#" << index.first << " " << index.second; ref.mCell = stream.str(); + + // It is not always possibe to ignore moved references sub-record and calculate from + // coordinates. Some mods may place the ref in positions outside normal bounds, + // resulting in non sensical cell id's. + // + // Use the target cell from the MVRF tag but if different output an error message + if (!base && // don't try to update base records + mref.mRefNum.mIndex != 0) // MVRF tag found + { + std::ostringstream stream; + stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1]; + ref.mCell = stream.str(); // overwrite + + ref.mOriginalCell = cell2.mId; + + if (deleted) + { + // FIXME: how to mark the record deleted? + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell, + mCells.getId (cellIndex)); + + messages.add (id, "Moved reference "+ref.mRefID+" is in DELE state"); + + continue; + } + else + { + if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1]) + { + std::cerr << "The Position of moved ref " + << ref.mRefID << " does not match the target cell" << std::endl; + std::cerr << "Position: #" << index.first << " " << index.second + <<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; + } + // FIXME: need to transfer the ref to the new cell + } + } } else ref.mCell = cell2.mId; From 7673be6d0fb9a2083d63d421a0e30c886270a372 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Apr 2015 12:18:23 +1000 Subject: [PATCH 028/142] Loading of moved refs complete. --- apps/opencs/model/world/data.cpp | 6 +++--- apps/opencs/model/world/refcollection.cpp | 19 ++++++++++++------- apps/opencs/model/world/refcollection.hpp | 2 +- components/esm/loadcell.cpp | 18 ------------------ 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 91fa556ab7..f4ae78ae72 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -3,7 +3,6 @@ #include #include -#include #include @@ -866,11 +865,12 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) if (index < 0 || index >= mCells.getSize()) { // log an error and continue loading the refs to the last loaded cell - std::cerr << "Logic error: cell index out of bounds" << std::endl; + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_None); + messages.add (id, "Logic error: cell index out of bounds"); index = mCells.getSize()-1; } std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index)); - mRefs.load (*mReader, index, mBase, mRefLoadCache[cellId], messages); + mRefs.load (*mReader, index, mBase, mRefLoadCache, cellId, messages); break; } diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index bd4cf918cf..c94ec1dc41 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -2,6 +2,7 @@ #include "refcollection.hpp" #include +#include #include #include @@ -12,8 +13,10 @@ #include "record.hpp" void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map& cache, CSMDoc::Messages& messages) + std::map >& cache, const std::string& origCellId, + CSMDoc::Messages& messages) { + std::string cellid = origCellId; Record cell = mCells.getRecord (cellIndex); Cell& cell2 = base ? cell.mBase : cell.mModified; @@ -73,18 +76,20 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool std::cerr << "Position: #" << index.first << " " << index.second <<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; } - // FIXME: need to transfer the ref to the new cell + + // transfer the ref to the new cell + cellid = ref.mCell; } } } else ref.mCell = cell2.mId; - std::map::iterator iter = cache.find (ref.mRefNum); + std::map::iterator iter = cache[cellid].find (ref.mRefNum); if (deleted) { - if (iter==cache.end()) + if (iter==cache[cellid].end()) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell, mCells.getId (cellIndex)); @@ -101,7 +106,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool if (record.mState==RecordBase::State_BaseOnly) { removeRows (index, 1); - cache.erase (iter); + cache[cellid].erase (iter); } else { @@ -112,7 +117,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool continue; } - if (iter==cache.end()) + if (iter==cache[cellid].end()) { // new reference ref.mId = getNewId(); @@ -123,7 +128,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool appendRecord (record); - cache.insert (std::make_pair (ref.mRefNum, ref.mId)); + cache[cellid].insert (std::make_pair (ref.mRefNum, ref.mId)); } else { diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 46572752e3..82ec2f390d 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -27,7 +27,7 @@ namespace CSMWorld {} void load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map& cache, + std::map >& cache, const std::string& cellid, CSMDoc::Messages& messages); ///< Load a sequence of references. diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index aed56f415b..0f8897c488 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -3,7 +3,6 @@ #include #include #include -#include // FIXME: debugging only #include @@ -174,7 +173,6 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMo // TODO: Try and document reference numbering, I don't think this has been done anywhere else. if (!esm.hasMoreSubs()) return false; - //bool print = false; // FIXME: debugging only // NOTE: We should not need this check. It is a safety check until we have checked // more plugins, and how they treat these moved references. @@ -184,9 +182,6 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMo { esm.getHT (mref->mRefNum.mIndex); esm.getHNOT (mref->mTarget, "CNDT"); - //std::cout << "index " + std::to_string(mref->mRefNum.mIndex) + " target " << - //std::to_string(mref->mTarget[0]) + ", " + std::to_string(mref->mTarget[1]) << std::endl; - //print = true; // FIXME: debugging only adjustRefNum (mref->mRefNum, esm); } else @@ -199,19 +194,6 @@ bool Cell::getNextRef(ESMReader &esm, CellRef &ref, bool& deleted, bool ignoreMo ref.load (esm); -#if 0 - // FIXME: debugging only - if (print && - ((int)std::floor(ref.mPos.pos[0]/8192) != mref->mTarget[0] || - (int)std::floor(ref.mPos.pos[1]/8192) != mref->mTarget[1])) - { - std::cout << ref.mRefID << - ", " + std::to_string((int)std::floor(ref.mPos.pos[0]/8192)) << - ", " + std::to_string((int)std::floor(ref.mPos.pos[1]/8192)) << - ", Z: " +std::to_string(ref.mPos.pos[2]) << std::endl; - } -#endif - // Identify references belonging to a parent file and adapt the ID accordingly. adjustRefNum (ref.mRefNum, esm); From e0d061c37b9fc0f37c729bc8cf54abe8a06f11d1 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Apr 2015 12:32:07 +1000 Subject: [PATCH 029/142] Implemented a workaround for saving moved refs. --- apps/opencs/model/doc/savingstages.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index e5595ccf69..5a45691d56 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -303,13 +303,34 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) if (ref.mState==CSMWorld::RecordBase::State_Modified || ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) { + // To get an MVRF tag, the ref's mOriginalCell needs to be non-empty (empty + // is meant to indicate that it is the same as the current cell) and + // different to mCell (its current cell) TODO: the second check seems redundant? + // + // To have mOriginalCell be non-empty, it needs to be loaded as 'base' in + // RefCollection::load() + // + // recalculate the ref's cell location + std::ostringstream stream; + if (!interior) + { + std::pair index = ref.get().getCellIndex(); + stream << "#" << index.first << " " << index.second; + } + if (!ref.get().mOriginalCell.empty() && - ref.get().mOriginalCell!=ref.get().mCell) + ref.get().mOriginalCell!=stream.str()) { ESM::MovedCellRef moved; moved.mRefNum = ref.get().mRefNum; - std::istringstream stream (ref.get().mCell.c_str()); + // Need to fill mTarget with the ref's new position. + // + // For this to work the view tht modified this ref needed to have the + // ref's mCell updted properly. + // + // For now use the temporary solution calculated above + std::istringstream stream (stream.str().c_str()); char ignore; stream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; From b54e5714c968b29ed3d87ca13bfa376ba28bc192 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Apr 2015 14:55:40 +1000 Subject: [PATCH 030/142] Revert rebasing the moved refs to the new cell, because the original ref may still be referred by a mod. --- apps/opencs/model/doc/savingstages.cpp | 13 ++---- apps/opencs/model/world/data.cpp | 2 +- apps/opencs/model/world/refcollection.cpp | 55 +++++++++++------------ apps/opencs/model/world/refcollection.hpp | 3 +- 4 files changed, 33 insertions(+), 40 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 5a45691d56..1f6da2580d 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -303,13 +303,6 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) if (ref.mState==CSMWorld::RecordBase::State_Modified || ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) { - // To get an MVRF tag, the ref's mOriginalCell needs to be non-empty (empty - // is meant to indicate that it is the same as the current cell) and - // different to mCell (its current cell) TODO: the second check seems redundant? - // - // To have mOriginalCell be non-empty, it needs to be loaded as 'base' in - // RefCollection::load() - // // recalculate the ref's cell location std::ostringstream stream; if (!interior) @@ -318,8 +311,10 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) stream << "#" << index.first << " " << index.second; } - if (!ref.get().mOriginalCell.empty() && - ref.get().mOriginalCell!=stream.str()) + // An empty mOriginalCell is meant to indicate that it is the same as + // the current cell. It is possible that a moved ref is moved again. + if ((ref.get().mOriginalCell.empty() ? ref.get().mCell : ref.get().mOriginalCell) + != stream.str()) { ESM::MovedCellRef moved; moved.mRefNum = ref.get().mRefNum; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index f4ae78ae72..97b34551de 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -870,7 +870,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) index = mCells.getSize()-1; } std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index)); - mRefs.load (*mReader, index, mBase, mRefLoadCache, cellId, messages); + mRefs.load (*mReader, index, mBase, mRefLoadCache[cellId], messages); break; } diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index c94ec1dc41..8f12b6844b 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -13,10 +13,8 @@ #include "record.hpp" void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map >& cache, const std::string& origCellId, - CSMDoc::Messages& messages) + std::map& cache, CSMDoc::Messages& messages) { - std::string cellid = origCellId; Record cell = mCells.getRecord (cellIndex); Cell& cell2 = base ? cell.mBase : cell.mModified; @@ -43,18 +41,13 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool ref.mCell = stream.str(); - // It is not always possibe to ignore moved references sub-record and calculate from - // coordinates. Some mods may place the ref in positions outside normal bounds, - // resulting in non sensical cell id's. - // - // Use the target cell from the MVRF tag but if different output an error message if (!base && // don't try to update base records mref.mRefNum.mIndex != 0) // MVRF tag found { - std::ostringstream stream; - stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1]; - ref.mCell = stream.str(); // overwrite - + // there is a requirement for a placeholder where the original object was + // + // see the forum discussions here for more details: + // https://forum.openmw.org/viewtopic.php?f=6&t=577&start=30 ref.mOriginalCell = cell2.mId; if (deleted) @@ -67,29 +60,35 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool continue; } - else - { - if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1]) - { - std::cerr << "The Position of moved ref " - << ref.mRefID << " does not match the target cell" << std::endl; - std::cerr << "Position: #" << index.first << " " << index.second - <<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; - } - // transfer the ref to the new cell - cellid = ref.mCell; + // It is not always possibe to ignore moved references sub-record and + // calculate from coordinates. Some mods may place the ref in positions + // outside normal bounds, resulting in non sensical cell id's. This often + // happens if the moved ref was deleted. + // + // Use the target cell from the MVRF tag but if different output an error + // message + if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1]) + { + std::cerr << "The Position of moved ref " + << ref.mRefID << " does not match the target cell" << std::endl; + std::cerr << "Position: #" << index.first << " " << index.second + <<", Target #"<< mref.mTarget[0] << " " << mref.mTarget[1] << std::endl; + + std::ostringstream stream; + stream << "#" << mref.mTarget[0] << " " << mref.mTarget[1]; + ref.mCell = stream.str(); // overwrite } } } else ref.mCell = cell2.mId; - std::map::iterator iter = cache[cellid].find (ref.mRefNum); + std::map::iterator iter = cache.find (ref.mRefNum); if (deleted) { - if (iter==cache[cellid].end()) + if (iter==cache.end()) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell, mCells.getId (cellIndex)); @@ -106,7 +105,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool if (record.mState==RecordBase::State_BaseOnly) { removeRows (index, 1); - cache[cellid].erase (iter); + cache.erase (iter); } else { @@ -117,7 +116,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool continue; } - if (iter==cache[cellid].end()) + if (iter==cache.end()) { // new reference ref.mId = getNewId(); @@ -128,7 +127,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool appendRecord (record); - cache[cellid].insert (std::make_pair (ref.mRefNum, ref.mId)); + cache.insert (std::make_pair (ref.mRefNum, ref.mId)); } else { diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index 82ec2f390d..d031398d3f 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -27,8 +27,7 @@ namespace CSMWorld {} void load (ESM::ESMReader& reader, int cellIndex, bool base, - std::map >& cache, const std::string& cellid, - CSMDoc::Messages& messages); + std::map& cache, CSMDoc::Messages& messages); ///< Load a sequence of references. std::string getNewId(); From 889749a4933b4b641320363cad2b007cfef17658 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Apr 2015 15:44:40 +1000 Subject: [PATCH 031/142] Allow non-empty mOriginalCell (case where a moved ref is moved again) --- apps/opencs/model/doc/savingstages.cpp | 17 ++++++++++++++--- apps/opencs/model/world/commands.cpp | 7 +------ apps/opencs/model/world/commands.hpp | 1 - 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 1f6da2580d..7363f999e5 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -238,8 +238,19 @@ void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages) mState.getSubRecords()[Misc::StringUtils::lowerCase (cellId)]; // collect moved references at the end of the container - if (!record.get().mOriginalCell.empty() && - record.get().mOriginalCell!=record.get().mCell) + bool interior = cellId.substr (0, 1)!="#"; + std::ostringstream stream; + if (!interior) + { + // recalculate the ref's cell location + std::pair index = record.get().getCellIndex(); + stream << "#" << index.first << " " << index.second; + } + + // An empty mOriginalCell is meant to indicate that it is the same as + // the current cell. It is possible that a moved ref is moved again. + if ((record.get().mOriginalCell.empty() ? + record.get().mCell : record.get().mOriginalCell) != stream.str() && !interior) indices.push_back (i); else indices.push_front (i); @@ -314,7 +325,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) // An empty mOriginalCell is meant to indicate that it is the same as // the current cell. It is possible that a moved ref is moved again. if ((ref.get().mOriginalCell.empty() ? ref.get().mCell : ref.get().mOriginalCell) - != stream.str()) + != stream.str() && !interior) { ESM::MovedCellRef moved; moved.mRefNum = ref.get().mRefNum; diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index afc4fcb962..4fe9651486 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -8,11 +8,10 @@ #include #include +#include "idtable.hpp" #include "idtree.hpp" #include "nestedtablewrapper.hpp" -#include "idtable.hpp" - CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand* parent) : QUndoCommand (parent), mModel (&model), mIndex (index), mNew (new_) @@ -227,10 +226,6 @@ void CSMWorld::UpdateCellCommand::undo() } - - - - CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTree& model, const std::string& id, int nestedRow, diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index ca7c13fea4..f3d2b852ac 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -20,7 +20,6 @@ class QAbstractItemModel; namespace CSMWorld { class IdTable; - class RecordBase; class IdTree; struct RecordBase; struct NestedTableWrapperBase; From 2ef8103cc77c18c46113ebb6d4decc565cdd72ea Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 26 Apr 2015 12:36:05 +0200 Subject: [PATCH 032/142] fixed ReportModel::RemoveRows view updates --- apps/opencs/model/tools/reportmodel.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index 5648ace549..1248e202bf 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -120,7 +120,14 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p if (parent.isValid()) return false; - mRows.erase (mRows.begin()+row, mRows.begin()+row+count); + if (count>0) + { + beginRemoveRows (parent, row, row+count-1); + + mRows.erase (mRows.begin()+row, mRows.begin()+row+count); + + endRemoveRows(); + } return true; } From 33a8cd245a37cec85dfc7bf1bbb8e32f1f247fa9 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 26 Apr 2015 21:02:50 +1000 Subject: [PATCH 033/142] Fix crash with gcc/linux. --- apps/opencs/model/doc/savingstages.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 7363f999e5..d6258da6ae 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -331,15 +331,10 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) moved.mRefNum = ref.get().mRefNum; // Need to fill mTarget with the ref's new position. - // - // For this to work the view tht modified this ref needed to have the - // ref's mCell updted properly. - // - // For now use the temporary solution calculated above - std::istringstream stream (stream.str().c_str()); + std::istringstream istream (stream.str().c_str()); char ignore; - stream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; + istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1]; ref.get().mRefNum.save (mState.getWriter(), false, "MVRF"); mState.getWriter().writeHNT ("CNDT", moved.mTarget, 8); From dab650a3d54f2ff903716ffe0b0b0f829e3c8aa7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 26 Apr 2015 13:26:20 +0200 Subject: [PATCH 034/142] remove rows from result table after a successful replace (configurable via user settings) --- apps/opencs/model/settings/usersettings.cpp | 5 ++++- apps/opencs/view/tools/searchsubview.cpp | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 7a975c99c4..6e240c9987 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -220,7 +220,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "Characters after search string"); after->setDefaultValue (10); after->setRange (0, 1000); - after->setToolTip ("Maximum number of character to display in search result after the searched text"); + after->setToolTip ("Maximum number of character to display in search result after the searched text"); + + Setting *autoDelete = createSetting (Type_CheckBox, "auto-delete", "Delete row from result table after a successful replace"); + autoDelete->setDefaultValue ("true"); } { diff --git a/apps/opencs/view/tools/searchsubview.cpp b/apps/opencs/view/tools/searchsubview.cpp index 5743ad7614..9a654c802f 100644 --- a/apps/opencs/view/tools/searchsubview.cpp +++ b/apps/opencs/view/tools/searchsubview.cpp @@ -7,6 +7,7 @@ #include "../../model/tools/search.hpp" #include "../../model/tools/reportmodel.hpp" #include "../../model/world/idtablebase.hpp" +#include "../../model/settings/usersettings.hpp" #include "reporttable.hpp" #include "searchbox.hpp" @@ -22,7 +23,10 @@ void CSVTools::SearchSubView::replace (bool selection) const CSMTools::ReportModel& model = dynamic_cast (*mTable->model()); - + + bool autoDelete = CSMSettings::UserSettings::instance().setting ( + "search/auto-delete", QString ("true"))=="true"; + // We are running through the indices in reverse order to avoid messing up multiple results // in a single string. for (std::vector::const_reverse_iterator iter (indices.rbegin()); iter!=indices.rend(); ++iter) @@ -38,6 +42,9 @@ void CSVTools::SearchSubView::replace (bool selection) mSearch.replace (mDocument, table, id, hint, replace); mTable->flagAsReplaced (*iter); + + if (autoDelete) + mTable->model()->removeRows (*iter, 1); } } From 6fac4c5dd981d0f11f409fb9099e04e01e826e93 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 26 Apr 2015 13:31:35 +0200 Subject: [PATCH 035/142] made user settings handling in search sub view more consistent --- apps/opencs/view/tools/searchsubview.cpp | 18 +++++++----------- apps/opencs/view/tools/searchsubview.hpp | 2 -- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/tools/searchsubview.cpp b/apps/opencs/view/tools/searchsubview.cpp index 9a654c802f..2038612a26 100644 --- a/apps/opencs/view/tools/searchsubview.cpp +++ b/apps/opencs/view/tools/searchsubview.cpp @@ -49,8 +49,7 @@ void CSVTools::SearchSubView::replace (bool selection) } CSVTools::SearchSubView::SearchSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: CSVDoc::SubView (id), mDocument (document), mPaddingBefore (10), mPaddingAfter (10), - mLocked (false) +: CSVDoc::SubView (id), mDocument (document), mLocked (false) { QVBoxLayout *layout = new QVBoxLayout; @@ -91,14 +90,6 @@ void CSVTools::SearchSubView::setEditLock (bool locked) void CSVTools::SearchSubView::updateUserSetting (const QString &name, const QStringList &list) { mTable->updateUserSetting (name, list); - - if (!list.empty()) - { - if (name=="search/char-before") - mPaddingBefore = list.at (0).toInt(); - else if (name=="search/char-after") - mPaddingAfter = list.at (0).toInt(); - } } void CSVTools::SearchSubView::stateChanged (int state, CSMDoc::Document *document) @@ -108,8 +99,13 @@ void CSVTools::SearchSubView::stateChanged (int state, CSMDoc::Document *documen void CSVTools::SearchSubView::startSearch (const CSMTools::Search& search) { + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + + int paddingBefore = userSettings.setting ("search/char-before", QString ("5")).toInt(); + int paddingAfter = userSettings.setting ("search/char-after", QString ("5")).toInt(); + mSearch = search; - mSearch.setPadding (mPaddingBefore, mPaddingAfter); + mSearch.setPadding (paddingBefore, paddingAfter); mTable->clear(); mDocument.runSearch (getUniversalId(), mSearch); diff --git a/apps/opencs/view/tools/searchsubview.hpp b/apps/opencs/view/tools/searchsubview.hpp index eeefa9afbf..6dedd6ef2b 100644 --- a/apps/opencs/view/tools/searchsubview.hpp +++ b/apps/opencs/view/tools/searchsubview.hpp @@ -26,8 +26,6 @@ namespace CSVTools ReportTable *mTable; SearchBox mSearchBox; CSMDoc::Document& mDocument; - int mPaddingBefore; - int mPaddingAfter; CSMTools::Search mSearch; bool mLocked; From ae5de0cb2b1ad90ded17fc227a513979dd8118e9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 27 Apr 2015 22:43:09 +0200 Subject: [PATCH 036/142] implemented additional check before performing replace (make sure data hasn't been changed since the search) --- apps/opencs/model/tools/search.cpp | 17 ++++++++++++++++ apps/opencs/model/tools/search.hpp | 4 ++++ apps/opencs/view/tools/searchsubview.cpp | 26 +++++++++++++++++------- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/tools/search.cpp b/apps/opencs/model/tools/search.cpp index cb88507547..7eb531161e 100644 --- a/apps/opencs/model/tools/search.cpp +++ b/apps/opencs/model/tools/search.cpp @@ -276,4 +276,21 @@ void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBas new CSMWorld::ModifyCommand (*model, index, QString::fromUtf8 (newText.c_str()))); } } + +bool CSMTools::Search::verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model, + const CSMWorld::UniversalId& id, const std::string& messageHint) const +{ + CSMDoc::Messages messages; + + int row = model->getModelIndex (id.getId(), + model->findColumnIndex (CSMWorld::Columns::ColumnId_Id)).row(); + + searchRow (model, row, messages); + + for (CSMDoc::Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter) + if (iter->mHint==messageHint) + return true; + + return false; +} diff --git a/apps/opencs/model/tools/search.hpp b/apps/opencs/model/tools/search.hpp index c9dfc4c446..69b98bbdb2 100644 --- a/apps/opencs/model/tools/search.hpp +++ b/apps/opencs/model/tools/search.hpp @@ -88,6 +88,10 @@ namespace CSMTools void replace (CSMDoc::Document& document, CSMWorld::IdTableBase *model, const CSMWorld::UniversalId& id, const std::string& messageHint, const std::string& replaceText) const; + + // Check if model still matches search results. + bool verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model, + const CSMWorld::UniversalId& id, const std::string& messageHint) const; }; } diff --git a/apps/opencs/view/tools/searchsubview.cpp b/apps/opencs/view/tools/searchsubview.cpp index 2038612a26..32c26ee969 100644 --- a/apps/opencs/view/tools/searchsubview.cpp +++ b/apps/opencs/view/tools/searchsubview.cpp @@ -26,6 +26,9 @@ void CSVTools::SearchSubView::replace (bool selection) bool autoDelete = CSMSettings::UserSettings::instance().setting ( "search/auto-delete", QString ("true"))=="true"; + + CSMTools::Search search (mSearch); + CSMWorld::IdTableBase *currentTable = 0; // We are running through the indices in reverse order to avoid messing up multiple results // in a single string. @@ -37,14 +40,23 @@ void CSVTools::SearchSubView::replace (bool selection) CSMWorld::IdTableBase *table = &dynamic_cast ( *mDocument.getData().getTableModel (type)); - - std::string hint = model.getHint (*iter); - - mSearch.replace (mDocument, table, id, hint, replace); - mTable->flagAsReplaced (*iter); - if (autoDelete) - mTable->model()->removeRows (*iter, 1); + if (table!=currentTable) + { + search.configure (table); + currentTable = table; + } + + std::string hint = model.getHint (*iter); + + if (search.verify (mDocument, table, id, hint)) + { + search.replace (mDocument, table, id, hint, replace); + mTable->flagAsReplaced (*iter); + + if (autoDelete) + mTable->model()->removeRows (*iter, 1); + } } } From 49884f54f7f00e1d4413b77eae3d6091043aa016 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 28 Apr 2015 08:07:01 +1000 Subject: [PATCH 037/142] Fix loading moved references. --- apps/opencs/model/world/data.cpp | 4 ++-- apps/opencs/model/world/refcollection.cpp | 8 +++++++- apps/opencs/view/world/util.cpp | 1 - 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 97b34551de..fc4532fb0e 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -458,6 +458,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc UniversalId::Type_Texture); addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)), UniversalId::Type_Video); + + mRefLoadCache.clear(); // clear here rather than startLoading() and continueLoading() for multiple content files } CSMWorld::Data::~Data() @@ -779,7 +781,6 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base mReader = 0; mDialogue = 0; - mRefLoadCache.clear(); mReader = new ESM::ESMReader; mReader->setEncoder (&mEncoder); @@ -816,7 +817,6 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) mReader = 0; mDialogue = 0; - mRefLoadCache.clear(); return true; } diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 8f12b6844b..ff30dafae6 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -84,7 +84,13 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool else ref.mCell = cell2.mId; - std::map::iterator iter = cache.find (ref.mRefNum); + // ignore content file number + std::map::iterator iter = cache.begin(); + for (; iter != cache.end(); ++iter) + { + if (ref.mRefNum.mIndex == iter->first.mIndex) + break; + } if (deleted) { diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 8b4bfeaacc..a11b5bdded 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -125,7 +125,6 @@ void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemM QVariant new_ = hack.getData(); if ((model->data (index)!=new_) && (model->flags(index) & Qt::ItemIsEditable)) - //getUndoStack().push (new CSMWorld::ModifyCommand (*model, index, new_)); // FIXME mCommandDispatcher->executeModify (model, index, new_); } From e69687b0f290a6ea519d167d467530ddc0a0de6e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 28 Apr 2015 14:06:52 +0200 Subject: [PATCH 038/142] silenced a warning (potentially unintialised variable) --- components/nif/nifkey.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index cb81427201..b36b1d8cb1 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -18,6 +18,8 @@ struct KeyT { float mTension; // Only for TBC interpolation float mBias; // Only for TBC interpolation float mContinuity; // Only for TBC interpolation + + KeyT() : mTension (0), mBias (0), mContinuity (0) {} }; typedef KeyT FloatKey; typedef KeyT Vector3Key; From 28048c0bf36e267320f6e4ca43d2998829be20d8 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 28 Apr 2015 23:07:42 +1000 Subject: [PATCH 039/142] Simple line numbering and fixed-width fonts for the script dialogue. Based on Qt examples. Should resolve Bugs #2505 and #2512. --- apps/opencs/view/world/scriptedit.cpp | 122 ++++++++++++++++++++++++++ apps/opencs/view/world/scriptedit.hpp | 29 +++++- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index 271b0316d3..991e58ae77 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include "../../model/doc/document.hpp" @@ -72,6 +74,20 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli connect (&mUpdateTimer, SIGNAL (timeout()), this, SLOT (updateHighlighting())); mUpdateTimer.setSingleShot (true); + + // FIXME: make this configurable or provide a font selector dialogue + // FIXME: save QFontInfo somewhere before switching to a new one + QFont font("Monospace"); + font.setStyleHint(QFont::TypeWriter); + setFont(font); + + // FIXME: make this configurable + lineNumberArea = new LineNumberArea(this); + + connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); + connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); + + updateLineNumberAreaWidth(0); } bool CSVWorld::ScriptEdit::isChangeLocked() const @@ -157,3 +173,109 @@ void CSVWorld::ScriptEdit::updateHighlighting() mHighlighter->rehighlight(); } + +int CSVWorld::ScriptEdit::lineNumberAreaWidth() +{ + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) + { + max /= 10; + ++digits; + } + + int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits; + + return space; +} + +void CSVWorld::ScriptEdit::updateLineNumberAreaWidth(int /* newBlockCount */) +{ + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + +void CSVWorld::ScriptEdit::updateLineNumberArea(const QRect &rect, int dy) +{ + if (dy) + lineNumberArea->scroll(0, dy); + else + lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + + if (rect.contains(viewport()->rect())) + updateLineNumberAreaWidth(0); +} + +void CSVWorld::ScriptEdit::resizeEvent(QResizeEvent *e) +{ + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); +} + +void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent *event) +{ + QPainter painter(lineNumberArea); + + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top(); + int bottom = top + (int) blockBoundingRect(block).height(); + + int startBlock = textCursor().blockNumber(); + int endBlock = textCursor().blockNumber(); + if(textCursor().hasSelection()) + { + QString str = textCursor().selection().toPlainText(); + int selectedLines = str.count("\n")+1; + if(textCursor().position() < textCursor().anchor()) + endBlock += selectedLines; + else + startBlock -= selectedLines; + } + painter.setBackgroundMode(Qt::OpaqueMode); + QFont font = painter.font(); + QBrush background = painter.background(); + + while (block.isValid() && top <= event->rect().bottom()) + { + if (block.isVisible() && bottom >= event->rect().top()) + { + QFont newFont = painter.font(); + QString number = QString::number(blockNumber + 1); + if(blockNumber >= startBlock && blockNumber <= endBlock) + { + painter.setBackground(Qt::cyan); + painter.setPen(Qt::darkMagenta); + newFont.setBold(true); + } + else + { + painter.setBackground(background); + painter.setPen(Qt::black); + } + painter.setFont(newFont); + painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), + Qt::AlignRight, number); + painter.setFont(font); + } + + block = block.next(); + top = bottom; + bottom = top + (int) blockBoundingRect(block).height(); + ++blockNumber; + } +} + +CSVWorld::LineNumberArea::LineNumberArea(ScriptEdit *editor) : QWidget(editor), mScriptEdit(editor) +{} + +QSize CSVWorld::LineNumberArea::sizeHint() const +{ + return QSize(mScriptEdit->lineNumberAreaWidth(), 0); +} + +void CSVWorld::LineNumberArea::paintEvent(QPaintEvent *event) +{ + mScriptEdit->lineNumberAreaPaintEvent(event); +} diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index 0192bc5503..90fe2917e5 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -2,6 +2,7 @@ #define SCRIPTEDIT_H #include +#include #include #include @@ -9,7 +10,6 @@ #include "scripthighlighter.hpp" -class QWidget; class QRegExp; namespace CSMDoc @@ -19,6 +19,8 @@ namespace CSMDoc namespace CSVWorld { + class LineNumberArea; + class ScriptEdit : public QPlainTextEdit { Q_OBJECT @@ -45,6 +47,7 @@ namespace CSVWorld int mChangeLocked; ScriptHighlighter *mHighlighter; QTimer mUpdateTimer; + QWidget *lineNumberArea; public: @@ -56,6 +59,13 @@ namespace CSVWorld /// \note This mechanism is used to avoid infinite update recursions bool isChangeLocked() const; + void lineNumberAreaPaintEvent(QPaintEvent *event); + int lineNumberAreaWidth(); + + protected: + + virtual void resizeEvent(QResizeEvent *e); + private: QVector mAllowedTypes; const CSMDoc::Document& mDocument; @@ -74,6 +84,23 @@ namespace CSVWorld void idListChanged(); void updateHighlighting(); + + void updateLineNumberAreaWidth(int newBlockCount); + void updateLineNumberArea(const QRect &, int); + }; + + class LineNumberArea : public QWidget + { + ScriptEdit *mScriptEdit; + + public: + + LineNumberArea(ScriptEdit *editor); + QSize sizeHint() const; + + protected: + + void paintEvent(QPaintEvent *event); }; } #endif // SCRIPTEDIT_H From 997347b01eb2f0ab8e0c73f7839613ce21b350a8 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Sat, 25 Apr 2015 13:37:42 -0500 Subject: [PATCH 040/142] Silence -Wreorder warnings. --- apps/launcher/datafilespage.cpp | 4 ++-- apps/launcher/maindialog.cpp | 2 +- apps/opencs/view/settings/rangeview.cpp | 2 +- apps/opencs/view/settings/textview.cpp | 2 +- apps/openmw/engine.cpp | 14 ++++++------- apps/openmw/mwgui/hud.cpp | 12 +++++------ apps/openmw/mwgui/mainmenu.cpp | 4 ++-- apps/openmw/mwgui/spellicons.hpp | 4 ++-- apps/openmw/mwgui/spellmodel.hpp | 4 ++-- apps/openmw/mwgui/spellview.cpp | 4 ++-- apps/openmw/mwgui/tooltips.hpp | 6 +++--- apps/openmw/mwgui/tradewindow.cpp | 6 +++--- apps/openmw/mwgui/widgets.hpp | 14 ++++++------- apps/openmw/mwgui/windowmanagerimp.cpp | 6 +++--- apps/openmw/mwinput/inputmanagerimp.cpp | 24 +++++++++++----------- apps/openmw/mwmechanics/aicombataction.hpp | 2 +- apps/openmw/mwrender/animation.cpp | 2 +- apps/openmw/mwrender/characterpreview.cpp | 14 ++++++------- apps/openmw/mwrender/debugging.cpp | 6 +++--- apps/openmw/mwrender/localmap.cpp | 4 ++-- apps/openmw/mwrender/npcanimation.cpp | 10 ++++----- apps/openmw/mwrender/renderingmanager.cpp | 8 ++++---- apps/openmw/mwrender/sky.cpp | 24 +++++++++++----------- apps/openmw/mwrender/water.hpp | 6 +++--- apps/wizard/mainwizard.cpp | 4 ++-- components/esm/esmreader.cpp | 4 ++-- components/esm/esmwriter.cpp | 4 ++-- components/esm/loadcell.hpp | 4 ++-- components/esm/loadland.cpp | 2 +- components/files/fixedpath.hpp | 2 +- components/nif/nifstream.hpp | 2 +- components/nifbullet/bulletnifloader.hpp | 2 +- components/nifogre/ogrenifloader.hpp | 2 +- components/terrain/defaultworld.cpp | 14 ++++++------- components/terrain/quadtreenode.cpp | 4 ++-- components/terrain/world.cpp | 12 +++++------ components/widgets/list.cpp | 4 ++-- libs/openengine/bullet/physic.cpp | 14 ++++++------- libs/openengine/gui/manager.cpp | 2 +- 39 files changed, 129 insertions(+), 131 deletions(-) diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index 7861894b08..ec2e1246ef 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -24,10 +24,10 @@ const char *Launcher::DataFilesPage::mDefaultContentListName = "Default"; Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings, Config::LauncherSettings &launcherSettings, QWidget *parent) - : mCfgMgr(cfg) + : QWidget(parent) + , mCfgMgr(cfg) , mGameSettings(gameSettings) , mLauncherSettings(launcherSettings) - , QWidget(parent) { ui.setupUi (this); setObjectName ("DataFilesPage"); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 4c142231d5..00e6a9aa29 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -25,7 +25,7 @@ using namespace Process; Launcher::MainDialog::MainDialog(QWidget *parent) - : mGameSettings(mCfgMgr), QMainWindow (parent) + : QMainWindow(parent), mGameSettings (mCfgMgr) { setupUi(this); diff --git a/apps/opencs/view/settings/rangeview.cpp b/apps/opencs/view/settings/rangeview.cpp index 246f7ece25..5893c5d0da 100644 --- a/apps/opencs/view/settings/rangeview.cpp +++ b/apps/opencs/view/settings/rangeview.cpp @@ -12,7 +12,7 @@ CSVSettings::RangeView::RangeView (CSMSettings::Setting *setting, Page *parent) - : mRangeWidget (0), mRangeType (setting->type()), View (setting, parent) + : View (setting, parent), mRangeWidget (0), mRangeType (setting->type()) { mRangeWidget = 0; diff --git a/apps/opencs/view/settings/textview.cpp b/apps/opencs/view/settings/textview.cpp index 6886732dbe..a6ab657fe2 100644 --- a/apps/opencs/view/settings/textview.cpp +++ b/apps/opencs/view/settings/textview.cpp @@ -5,7 +5,7 @@ #include "../../model/settings/setting.hpp" CSVSettings::TextView::TextView(CSMSettings::Setting *setting, Page *parent) - : mDelimiter (setting->delimiter()), View (setting, parent) + : View (setting, parent), mDelimiter (setting->delimiter()) { if (setting->isMultiLine()) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a4bb8c5380..4496490d42 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -174,24 +174,24 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) } OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) - : mOgre (0) + : mEncoding(ToUTF8::WINDOWS_1252) + , mEncoder(NULL) + , mOgre (0) , mVerboseScripts (false) , mSkipMenu (false) , mUseSound (true) , mCompileAll (false) , mCompileAllDialogue (false) , mWarningsMode (1) - , mScriptContext (0) - , mFSStrict (false) , mScriptConsoleMode (false) - , mCfgMgr(configurationManager) - , mEncoding(ToUTF8::WINDOWS_1252) - , mEncoder(NULL) , mActivationDistanceOverride(-1) , mGrab(true) - , mScriptBlacklistUse (true) , mExportFonts(false) + , mScriptContext (0) + , mFSStrict (false) + , mScriptBlacklistUse (true) , mNewGame (false) + , mCfgMgr(configurationManager) { OEngine::Misc::Rng::init(); std::srand ( static_cast(std::time(NULL)) ); diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index eb458be500..1f24b58d82 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -77,8 +77,6 @@ namespace MWGui , mMagicka(NULL) , mStamina(NULL) , mDrowning(NULL) - , mDrowningFrame(NULL) - , mDrowningFlash(NULL) , mWeapImage(NULL) , mSpellImage(NULL) , mWeapStatus(NULL) @@ -87,6 +85,9 @@ namespace MWGui , mMinimap(NULL) , mCompass(NULL) , mCrosshair(NULL) + , mCellNameBox(NULL) + , mDrowningFrame(NULL) + , mDrowningFlash(NULL) , mFpsBox(NULL) , mFpsCounter(NULL) , mTriangleCounter(NULL) @@ -94,19 +95,18 @@ namespace MWGui , mHealthManaStaminaBaseLeft(0) , mWeapBoxBaseLeft(0) , mSpellBoxBaseLeft(0) - , mEffectBoxBaseRight(0) , mMinimapBoxBaseRight(0) + , mEffectBoxBaseRight(0) , mDragAndDrop(dragAndDrop) , mCellNameTimer(0.0f) - , mCellNameBox(NULL) + , mWeaponSpellTimer(0.f) , mMapVisible(true) , mWeaponVisible(true) , mSpellVisible(true) , mWorldMouseOver(false) - , mEnemyHealthTimer(-1) , mEnemyActorId(-1) + , mEnemyHealthTimer(-1) , mIsDrowning(false) - , mWeaponSpellTimer(0.f) , mDrowningFlashTheta(0.f) { mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize()); diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 6ad4da3bfb..9a737af64c 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -31,11 +31,11 @@ namespace MWGui MainMenu::MainMenu(int w, int h) : OEngine::GUI::Layout("openmw_mainmenu.layout") - , mButtonBox(0), mWidth (w), mHeight (h) - , mSaveGameDialog(NULL) + , mWidth (w), mHeight (h), mButtonBox(0) , mBackground(NULL) , mVideoBackground(NULL) , mVideo(NULL) + , mSaveGameDialog(NULL) { getWidget(mVersionText, "VersionText"); std::stringstream sstream; diff --git a/apps/openmw/mwgui/spellicons.hpp b/apps/openmw/mwgui/spellicons.hpp index 5099fc4d63..26761f2fc8 100644 --- a/apps/openmw/mwgui/spellicons.hpp +++ b/apps/openmw/mwgui/spellicons.hpp @@ -24,10 +24,10 @@ namespace MWGui struct MagicEffectInfo { MagicEffectInfo() - : mPermanent(false) - , mMagnitude(0) + : mMagnitude(0) , mRemainingTime(0.f) , mTotalTime(0.f) + , mPermanent(false) {} std::string mSource; // display name for effect source (e.g. potion name) MWMechanics::EffectKey mKey; diff --git a/apps/openmw/mwgui/spellmodel.hpp b/apps/openmw/mwgui/spellmodel.hpp index 7859c8a7b6..21fbc9a6e2 100644 --- a/apps/openmw/mwgui/spellmodel.hpp +++ b/apps/openmw/mwgui/spellmodel.hpp @@ -24,9 +24,9 @@ namespace MWGui bool mActive; // (Items only) is the item equipped? Spell() - : mSelected(false) + : mType(Type_Spell) + , mSelected(false) , mActive(false) - , mType(Type_Spell) { } }; diff --git a/apps/openmw/mwgui/spellview.cpp b/apps/openmw/mwgui/spellview.cpp index a7c1d781bd..6d86b4a23a 100644 --- a/apps/openmw/mwgui/spellview.cpp +++ b/apps/openmw/mwgui/spellview.cpp @@ -21,9 +21,9 @@ namespace MWGui } SpellView::SpellView() - : mShowCostColumn(true) + : mScrollView(NULL) + , mShowCostColumn(true) , mHighlightSelected(true) - , mScrollView(NULL) { } diff --git a/apps/openmw/mwgui/tooltips.hpp b/apps/openmw/mwgui/tooltips.hpp index 71b4a560f5..c50d47ef57 100644 --- a/apps/openmw/mwgui/tooltips.hpp +++ b/apps/openmw/mwgui/tooltips.hpp @@ -20,10 +20,10 @@ namespace MWGui { public: ToolTipInfo() - : isPotion(false) - , imageSize(32) - , wordWrap(true) + : imageSize(32) , remainingEnchantCharge(-1) + , isPotion(false) + , wordWrap(true) {} std::string caption; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 42491a5e87..aecfce98d0 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -54,10 +54,10 @@ namespace MWGui TradeWindow::TradeWindow() : WindowBase("openmw_trade_window.layout") - , mCurrentBalance(0) - , mItemToSell(-1) - , mTradeModel(NULL) , mSortModel(NULL) + , mTradeModel(NULL) + , mItemToSell(-1) + , mCurrentBalance(0) , mCurrentMerchantOffer(0) { getWidget(mFilterAll, "AllButton"); diff --git a/apps/openmw/mwgui/widgets.hpp b/apps/openmw/mwgui/widgets.hpp index 09a3c11acf..6d9c0a580c 100644 --- a/apps/openmw/mwgui/widgets.hpp +++ b/apps/openmw/mwgui/widgets.hpp @@ -36,17 +36,17 @@ namespace MWGui struct SpellEffectParams { SpellEffectParams() - : mMagnMin(-1) + : mNoTarget(false) + , mIsConstant(false) + , mKnown(true) + , mEffectID(-1) + , mSkill(-1) + , mAttribute(-1) + , mMagnMin(-1) , mMagnMax(-1) , mRange(-1) , mDuration(-1) - , mSkill(-1) , mArea(0) - , mAttribute(-1) - , mEffectID(-1) - , mNoTarget(false) - , mIsConstant(false) - , mKnown(true) { } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 279c2f22ea..015af00432 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -102,6 +102,7 @@ namespace MWGui const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding, bool exportFonts, const std::map& fallbackMap) : mConsoleOnlyScripts(consoleOnlyScripts) + , mCurrentModals() , mGuiManager(NULL) , mRendering(ogre) , mHud(NULL) @@ -135,8 +136,8 @@ namespace MWGui , mTrainingWindow(NULL) , mMerchantRepair(NULL) , mSoulgemDialog(NULL) - , mRecharge(NULL) , mRepair(NULL) + , mRecharge(NULL) , mCompanionWindow(NULL) , mVideoBackground(NULL) , mVideoWidget(NULL) @@ -159,8 +160,8 @@ namespace MWGui , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() - , mPlayerMinorSkills() , mPlayerMajorSkills() + , mPlayerMinorSkills() , mPlayerSkillValues() , mGui(NULL) , mGuiModes() @@ -173,7 +174,6 @@ namespace MWGui , mFPS(0.0f) , mTriangleCount(0) , mBatchCount(0) - , mCurrentModals() , mFallbackMap(fallbackMap) { // Set up the GUI system diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 88d891a028..2e82faa6dc 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -102,32 +102,32 @@ namespace MWInput OMW::Engine& engine, const std::string& userFile, bool userFileExists, const std::string& controllerBindingsFile, bool grab) - : mOgre(ogre) + : mJoystickLastUsed(false) + , mOgre(ogre) , mPlayer(NULL) , mEngine(engine) - , mMouseLookEnabled(false) - , mMouseX(ogre.getWindow()->getWidth ()/2.f) - , mMouseY(ogre.getWindow()->getHeight ()/2.f) - , mMouseWheel(0) - , mDragDrop(false) - , mGuiCursorEnabled(true) , mUserFile(userFile) - , mUserFileExists(userFileExists) + , mDragDrop(false) + , mGrabCursor (Settings::Manager::getBool("grab cursor", "Input")) , mInvertY (Settings::Manager::getBool("invert y axis", "Input")) + , mControlsDisabled(false) , mCameraSensitivity (Settings::Manager::getFloat("camera sensitivity", "Input")) , mUISensitivity (Settings::Manager::getFloat("ui sensitivity", "Input")) , mCameraYMultiplier (Settings::Manager::getFloat("camera y multiplier", "Input")) - , mGrabCursor (Settings::Manager::getBool("grab cursor", "Input")) , mPreviewPOVDelay(0.f) , mTimeIdle(0.f) + , mMouseLookEnabled(false) + , mGuiCursorEnabled(true) + , mDetectingKeyboard(false) , mOverencumberedMessageDelay(0.f) + , mMouseX(ogre.getWindow()->getWidth ()/2.f) + , mMouseY(ogre.getWindow()->getHeight ()/2.f) + , mMouseWheel(0) + , mUserFileExists(userFileExists) , mAlwaysRunActive(Settings::Manager::getBool("always run", "Input")) , mSneakToggles(Settings::Manager::getBool("toggle sneak", "Input")) , mSneaking(false) , mAttemptJump(false) - , mControlsDisabled(false) - , mJoystickLastUsed(false) - , mDetectingKeyboard(false) , mFakeDeviceID(1) { diff --git a/apps/openmw/mwmechanics/aicombataction.hpp b/apps/openmw/mwmechanics/aicombataction.hpp index 1c7451c32b..a4a398d05f 100644 --- a/apps/openmw/mwmechanics/aicombataction.hpp +++ b/apps/openmw/mwmechanics/aicombataction.hpp @@ -66,7 +66,7 @@ namespace MWMechanics public: /// \a weapon may be empty for hand-to-hand combat ActionWeapon(const MWWorld::Ptr& weapon, const MWWorld::Ptr& ammo = MWWorld::Ptr()) - : mWeapon(weapon), mAmmunition(ammo) {} + : mAmmunition(ammo), mWeapon(weapon) {} /// Equips the given weapon. virtual void prepare(const MWWorld::Ptr& actor); virtual void getCombatRange (float& rangeAttack, float& rangeFollow); diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 871561bdcf..6dcd92b154 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -65,6 +65,7 @@ void Animation::EffectAnimationTime::setValue(Ogre::Real) Animation::Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node) : mPtr(ptr) + , mGlowLight(NULL) , mInsert(node) , mSkelBase(NULL) , mAccumRoot(NULL) @@ -72,7 +73,6 @@ Animation::Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node) , mNonAccumCtrl(NULL) , mAccumulate(0.0f) , mNullAnimationTimePtr(OGRE_NEW NullAnimationTime) - , mGlowLight(NULL) { for(size_t i = 0;i < sNumGroups;i++) mAnimationTimePtr[i].bind(OGRE_NEW AnimationTime(this)); diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 8071dd5fda..7d61e3b6c1 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -25,7 +25,12 @@ namespace MWRender CharacterPreview::CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name, Ogre::Vector3 position, Ogre::Vector3 lookAt) - : mSceneMgr (0) + : mRecover(false) + , mRenderTarget(NULL) + , mViewport(NULL) + , mCamera(NULL) + , mSceneMgr (0) + , mNode(NULL) , mPosition(position) , mLookAt(lookAt) , mCharacter(character) @@ -33,11 +38,6 @@ namespace MWRender , mName(name) , mSizeX(sizeX) , mSizeY(sizeY) - , mRenderTarget(NULL) - , mViewport(NULL) - , mCamera(NULL) - , mNode(NULL) - , mRecover(false) { mCharacter.mCell = NULL; } @@ -161,9 +161,9 @@ namespace MWRender InventoryPreview::InventoryPreview(MWWorld::Ptr character) : CharacterPreview(character, 512, 1024, "CharacterPreview", Ogre::Vector3(0, 71, -700), Ogre::Vector3(0,71,0)) - , mSelectionBuffer(NULL) , mSizeX(0) , mSizeY(0) + , mSelectionBuffer(NULL) { } diff --git a/apps/openmw/mwrender/debugging.cpp b/apps/openmw/mwrender/debugging.cpp index 79eeff2d04..49e65490d5 100644 --- a/apps/openmw/mwrender/debugging.cpp +++ b/apps/openmw/mwrender/debugging.cpp @@ -155,10 +155,10 @@ ManualObject *Debugging::createPathgridPoints(const ESM::Pathgrid *pathgrid) } Debugging::Debugging(SceneNode *root, OEngine::Physic::PhysicEngine *engine) : - mRootNode(root), mEngine(engine), - mSceneMgr(root->getCreator()), + mEngine(engine), mSceneMgr(root->getCreator()), mPathgridEnabled(false), - mInteriorPathgridNode(NULL), mPathGridRoot(NULL), + mRootNode(root), + mPathGridRoot(NULL), mInteriorPathgridNode(NULL), mGridMatsCreated(false) { ResourceGroupManager::getSingleton().createResourceGroup(DEBUGGING_GROUP); diff --git a/apps/openmw/mwrender/localmap.cpp b/apps/openmw/mwrender/localmap.cpp index 0299dc493c..b692226642 100644 --- a/apps/openmw/mwrender/localmap.cpp +++ b/apps/openmw/mwrender/localmap.cpp @@ -25,9 +25,9 @@ using namespace MWRender; using namespace Ogre; LocalMap::LocalMap(OEngine::Render::OgreRenderer* rend, MWRender::RenderingManager* rendering) - : mInterior(false) + : mMapResolution(Settings::Manager::getInt("local map resolution", "Map")) , mAngle(0.f) - , mMapResolution(Settings::Manager::getInt("local map resolution", "Map")) + , mInterior(false) { mRendering = rend; mRenderingManager = rendering; diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index a724644a70..6a6d52e262 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -91,7 +91,7 @@ namespace MWRender { HeadAnimationTime::HeadAnimationTime(MWWorld::Ptr reference) - : mReference(reference), mTalkStart(0), mTalkStop(0), mBlinkStart(0), mBlinkStop(0), mValue(0), mEnabled(true) + : mReference(reference), mTalkStart(0), mTalkStop(0), mBlinkStart(0), mBlinkStop(0), mEnabled(true), mValue(0) { resetBlinkTimer(); } @@ -203,17 +203,17 @@ NpcAnimation::~NpcAnimation() NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener, bool disableSounds, ViewMode viewMode) : Animation(ptr, node), - mVisibilityFlags(visibilityFlags), mListenerDisabled(disableListener), mViewMode(viewMode), mShowWeapons(false), mShowCarriedLeft(true), + mNpcType(Type_Normal), + mVisibilityFlags(visibilityFlags), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), - mNpcType(Type_Normal), mSoundsDisabled(disableSounds), - mHeadPitch(0.f), - mHeadYaw(0.f) + mHeadYaw(0.f), + mHeadPitch(0.f) { mNpc = mPtr.get()->mBase; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 8fb1ee53c5..f00ebb3039 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -56,14 +56,14 @@ namespace MWRender { RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine, MWWorld::Fallback* fallback) - : mRendering(_rend) + : mSunEnabled(0) , mFallback(fallback) + , mTerrain(NULL) + , mRendering(_rend) + , mEffectManager(NULL) , mPlayerAnimation(NULL) , mAmbientMode(0) - , mSunEnabled(0) , mPhysicsEngine(engine) - , mTerrain(NULL) - , mEffectManager(NULL) , mRenderWorld(true) { mActors = new MWRender::Actors(mRendering, this); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index d591cca2ea..fd439050c5 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -247,9 +247,13 @@ unsigned int Moon::getPhaseInt() const } SkyManager::SkyManager(Ogre::SceneNode *root, Ogre::Camera *pCamera) - : mHour(0.0f) + : mCreated(false) + , mMoonRed(false) + , mIsStorm(false) + , mHour(0.0f) , mDay(0) , mMonth(0) + , mCloudAnimationTimer(0.f) , mSun(NULL) , mSunGlare(NULL) , mMasser(NULL) @@ -260,6 +264,9 @@ SkyManager::SkyManager(Ogre::SceneNode *root, Ogre::Camera *pCamera) , mAtmosphereDay(NULL) , mAtmosphereNight(NULL) , mCloudNode(NULL) + , mParticleNode(NULL) + , mRainTimer(0) + , mStormDirection(0,-1,0) , mClouds() , mNextClouds() , mCloudBlendFactor(0.0f) @@ -268,22 +275,15 @@ SkyManager::SkyManager(Ogre::SceneNode *root, Ogre::Camera *pCamera) , mStarsOpacity(0.0f) , mLightning(NULL) , mRemainingTransitionTime(0.0f) - , mGlareFade(0.0f) , mGlare(0.0f) + , mGlareFade(0.0f) + , mRainEnabled(false) + , mRainSpeed(0) + , mRainFrequency(1) , mEnabled(true) , mSunEnabled(true) , mMasserEnabled(true) , mSecundaEnabled(true) - , mCreated(false) - , mCloudAnimationTimer(0.f) - , mMoonRed(false) - , mParticleNode(NULL) - , mRainEnabled(false) - , mRainTimer(0) - , mRainSpeed(0) - , mRainFrequency(1) - , mStormDirection(0,-1,0) - , mIsStorm(false) { mSceneMgr = root->getCreator(); mRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 775950431e..53d54cdc92 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -46,10 +46,10 @@ namespace MWRender { { public: Reflection(Ogre::SceneManager* sceneManager) - : mSceneMgr(sceneManager) - , mIsUnderwater(false) - , mCamera(NULL) + : mCamera(NULL) , mParentCamera(NULL) + , mSceneMgr(sceneManager) + , mIsUnderwater(false) {} virtual ~Reflection() {} diff --git a/apps/wizard/mainwizard.cpp b/apps/wizard/mainwizard.cpp index a61daa5a4c..7538511fe9 100644 --- a/apps/wizard/mainwizard.cpp +++ b/apps/wizard/mainwizard.cpp @@ -25,10 +25,10 @@ using namespace Process; Wizard::MainWizard::MainWizard(QWidget *parent) : - mGameSettings(mCfgMgr), QWizard(parent), + mInstallations(), mError(false), - mInstallations() + mGameSettings(mCfgMgr) { #ifndef Q_OS_MAC setWizardStyle(QWizard::ModernStyle); diff --git a/components/esm/esmreader.cpp b/components/esm/esmreader.cpp index bbe475ff74..2804f89d41 100644 --- a/components/esm/esmreader.cpp +++ b/components/esm/esmreader.cpp @@ -21,9 +21,9 @@ ESM_Context ESMReader::getContext() } ESMReader::ESMReader() - : mBuffer(50*1024) + : mIdx(0) , mRecordFlags(0) - , mIdx(0) + , mBuffer(50*1024) , mGlobalReaderList(NULL) , mEncoder(NULL) { diff --git a/components/esm/esmwriter.cpp b/components/esm/esmwriter.cpp index 14951608d2..c64678e702 100644 --- a/components/esm/esmwriter.cpp +++ b/components/esm/esmwriter.cpp @@ -9,10 +9,10 @@ namespace ESM { ESMWriter::ESMWriter() - : mEncoder (0) + : mStream(NULL) + , mEncoder (0) , mRecordCount (0) , mCounting (true) - , mStream(NULL) {} unsigned int ESMWriter::getVersion() const diff --git a/components/esm/loadcell.hpp b/components/esm/loadcell.hpp index b78d4075a7..1aef97d9f5 100644 --- a/components/esm/loadcell.hpp +++ b/components/esm/loadcell.hpp @@ -78,9 +78,9 @@ struct Cell float mFogDensity; }; - Cell() : mWater(0), - mName(""), + Cell() : mName(""), mRegion(""), + mWater(0), mWaterInt(false), mMapColor(0), mRefNumCounter(0) diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index b1c01fcba6..b0897ec67d 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -67,11 +67,11 @@ Land::Land() : mFlags(0) , mX(0) , mY(0) + , mPlugin(0) , mEsm(NULL) , mDataTypes(0) , mDataLoaded(false) , mLandData(NULL) - , mPlugin(0) { } diff --git a/components/files/fixedpath.hpp b/components/files/fixedpath.hpp index 9fb36d9845..5e0ea6c867 100644 --- a/components/files/fixedpath.hpp +++ b/components/files/fixedpath.hpp @@ -57,8 +57,8 @@ struct FixedPath , mGlobalConfigPath(mPath.getGlobalConfigPath()) , mLocalPath(mPath.getLocalPath()) , mGlobalDataPath(mPath.getGlobalDataPath()) - , mInstallPath(mPath.getInstallPath()) , mCachePath(mPath.getCachePath()) + , mInstallPath(mPath.getInstallPath()) { } diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 6c5e83eebd..aee16f2804 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -35,7 +35,7 @@ public: NIFFile * const file; - NIFStream (NIFFile * file, Ogre::DataStreamPtr inp): file (file), inp (inp) {} + NIFStream (NIFFile * file, Ogre::DataStreamPtr inp): inp (inp), file (file) {} void skip(size_t size) { inp->skip(size); } diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index 0d81d84b6b..f4126b7a73 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -69,8 +69,8 @@ class ManualBulletShapeLoader : public OEngine::Physic::BulletShapeLoader public: ManualBulletShapeLoader(bool showMarkers=false) : mShape(NULL) - , mStaticMesh(NULL) , mCompoundShape(NULL) + , mStaticMesh(NULL) , mBoundingBox(NULL) , mShowMarkers(showMarkers) { diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp index c135326448..b583429dd1 100644 --- a/components/nifogre/ogrenifloader.hpp +++ b/components/nifogre/ogrenifloader.hpp @@ -75,7 +75,7 @@ struct ObjectScene { std::vector > mControllers; - ObjectScene(Ogre::SceneManager* sceneMgr) : mSkelBase(0), mMaxControllerLength(0), mSceneMgr(sceneMgr) + ObjectScene(Ogre::SceneManager* sceneMgr) : mSkelBase(0), mSceneMgr(sceneMgr), mMaxControllerLength(0) { } ~ObjectScene(); diff --git a/components/terrain/defaultworld.cpp b/components/terrain/defaultworld.cpp index c6f0f7136c..7bc73ddda8 100644 --- a/components/terrain/defaultworld.cpp +++ b/components/terrain/defaultworld.cpp @@ -78,15 +78,15 @@ namespace Terrain DefaultWorld::DefaultWorld(Ogre::SceneManager* sceneMgr, Storage* storage, int visibilityFlags, bool shaders, Alignment align, float minBatchSize, float maxBatchSize) : World(sceneMgr, storage, visibilityFlags, shaders, align) + , mWorkQueueChannel(0) + , mVisible(true) + , mChunksLoading(0) + , mMinX(0) + , mMaxX(0) + , mMinY(0) + , mMaxY(0) , mMinBatchSize(minBatchSize) , mMaxBatchSize(maxBatchSize) - , mVisible(true) - , mMaxX(0) - , mMinX(0) - , mMaxY(0) - , mMinY(0) - , mChunksLoading(0) - , mWorkQueueChannel(0) , mLayerLoadPending(true) { #if TERRAIN_USE_SHADER == 0 diff --git a/components/terrain/quadtreenode.cpp b/components/terrain/quadtreenode.cpp index 6a99642132..89e5e34a36 100644 --- a/components/terrain/quadtreenode.cpp +++ b/components/terrain/quadtreenode.cpp @@ -133,6 +133,7 @@ namespace QuadTreeNode::QuadTreeNode(DefaultWorld* terrain, ChildDirection dir, float size, const Ogre::Vector2 ¢er, QuadTreeNode* parent) : mMaterialGenerator(NULL) + , mLoadState(LS_Unloaded) , mIsDummy(false) , mSize(size) , mLodLevel(Log2(static_cast(mSize))) @@ -142,9 +143,8 @@ QuadTreeNode::QuadTreeNode(DefaultWorld* terrain, ChildDirection dir, float size , mCenter(center) , mSceneNode(NULL) , mParent(parent) - , mTerrain(terrain) , mChunk(NULL) - , mLoadState(LS_Unloaded) + , mTerrain(terrain) { mBounds.setNull(); for (int i=0; i<4; ++i) diff --git a/components/terrain/world.cpp b/components/terrain/world.cpp index 5cc2647c67..3baaaed44e 100644 --- a/components/terrain/world.cpp +++ b/components/terrain/world.cpp @@ -30,14 +30,14 @@ namespace Terrain World::World(Ogre::SceneManager* sceneMgr, Storage* storage, int visibilityFlags, bool shaders, Alignment align) - : mStorage(storage) - , mSceneMgr(sceneMgr) - , mVisibilityFlags(visibilityFlags) - , mShaders(shaders) - , mAlign(align) - , mCache(storage->getCellVertices()) + : mShaders(shaders) , mShadows(false) , mSplitShadows(false) + , mAlign(align) + , mStorage(storage) + , mVisibilityFlags(visibilityFlags) + , mSceneMgr(sceneMgr) + , mCache(storage->getCellVertices()) { } diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index 8517a0303e..5a79de3d1a 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -9,8 +9,8 @@ namespace Gui { MWList::MWList() : - mClient(0) - , mScrollView(0) + mScrollView(0) + ,mClient(0) , mItemHeight(0) { } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 013ef1003e..15be7665a8 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -74,13 +74,11 @@ namespace Physic { PhysicActor::PhysicActor(const std::string &name, const std::string &mesh, PhysicEngine *engine, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, float scale) - : mName(name), mEngine(engine), mMesh(mesh) - , mBody(0), mOnGround(false), mInternalCollisionMode(true) + : mCanWaterWalk(false), mWalkingOnWater(false) + , mBody(0), mScale(scale), mForce(0.0f), mOnGround(false) + , mInternalCollisionMode(true) , mExternalCollisionMode(true) - , mForce(0.0f) - , mScale(scale) - , mWalkingOnWater(false) - , mCanWaterWalk(false) + , mMesh(mesh), mName(name), mEngine(engine) { if (!NifBullet::getBoundingBox(mMesh, mHalfExtents, mMeshTranslation, mMeshOrientation)) { @@ -239,8 +237,8 @@ namespace Physic PhysicEngine::PhysicEngine(BulletShapeLoader* shapeLoader) : - mDebugActive(0) - , mSceneMgr(NULL) + mSceneMgr(NULL) + , mDebugActive(0) { // Set up the collision configuration and dispatcher collisionConfiguration = new btDefaultCollisionConfiguration(); diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index 3496478929..5fa284c007 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -99,8 +99,8 @@ public: mManualRender(false), mCountBatch(0), mVertexProgramNoTexture(NULL), - mFragmentProgramNoTexture(NULL), mVertexProgramOneTexture(NULL), + mFragmentProgramNoTexture(NULL), mFragmentProgramOneTexture(NULL) { mTextureAddressMode.u = Ogre::TextureUnitState::TAM_CLAMP; From 7f2bd01f79749d05d18e563c013153376338118e Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 29 Apr 2015 12:08:11 +1000 Subject: [PATCH 041/142] Handle plugins that has 0x00 for levelled list types, for example Ravenloft v5.02d, to use 0x01. --- apps/opencs/model/world/refidadapterimp.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 41d8c65d56..e385543838 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -2,6 +2,7 @@ #define CSM_WOLRD_REFIDADAPTERIMP_H #include +#include #include @@ -1895,6 +1896,20 @@ namespace CSMWorld { return QString("All Levels"); } + else if (mType == CSMWorld::UniversalId::Type_CreatureLevelledList && + record.get().mFlags == 0x00) + { + std::cerr << "Unknown creature leveled list type: " << record.get().mFlags + << ", Using \"All Levels\""<< std::endl; + return QString("All Levels"); + } + else if (mType == CSMWorld::UniversalId::Type_ItemLevelledList && + record.get().mFlags == 0x00) + { + std::cerr << "Unknown item leveled list type: " << record.get().mFlags + << ", Using \"Each\""<< std::endl; + return QString("Each"); + } else throw std::runtime_error("unknown leveled list type"); } From 607a16eb01387aad3239d13378f9a7b294cd840a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 29 Apr 2015 11:36:56 +0200 Subject: [PATCH 042/142] removed leftover ignoreRefNum argument --- components/esm/cellref.cpp | 9 ++++----- components/esm/cellref.hpp | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/components/esm/cellref.cpp b/components/esm/cellref.cpp index ef33f495f1..c3b889df59 100644 --- a/components/esm/cellref.cpp +++ b/components/esm/cellref.cpp @@ -25,13 +25,13 @@ void ESM::RefNum::save (ESMWriter &esm, bool wide, const std::string& tag) const } -void ESM::CellRef::load (ESMReader& esm, bool wideRefNum, bool ignoreRefNum) +void ESM::CellRef::load (ESMReader& esm, bool wideRefNum) { - loadId(esm, wideRefNum, ignoreRefNum); + loadId(esm, wideRefNum); loadData(esm); } -void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum, bool ignoreRefNum) +void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum) { // According to Hrnchamd, this does not belong to the actual ref. Instead, it is a marker indicating that // the following refs are part of a "temp refs" section. A temp ref is not being tracked by the moved references system. @@ -40,8 +40,7 @@ void ESM::CellRef::loadId (ESMReader& esm, bool wideRefNum, bool ignoreRefNum) if (esm.isNextSub ("NAM0")) esm.skipHSub(); - if (!ignoreRefNum) - mRefNum.load (esm, wideRefNum); + mRefNum.load (esm, wideRefNum); mRefID = esm.getHNString ("NAME"); } diff --git a/components/esm/cellref.hpp b/components/esm/cellref.hpp index 0fb449e161..e9959611b3 100644 --- a/components/esm/cellref.hpp +++ b/components/esm/cellref.hpp @@ -100,9 +100,9 @@ namespace ESM Position mPos; /// Calls loadId and loadData - void load (ESMReader& esm, bool wideRefNum = false, bool ignoreRefNum = false); + void load (ESMReader& esm, bool wideRefNum = false); - void loadId (ESMReader& esm, bool wideRefNum = false, bool ignoreRefNum = false); + void loadId (ESMReader& esm, bool wideRefNum = false); /// Implicitly called by load void loadData (ESMReader& esm); From 8e49ccc2f4f7c6a510f7416226623ea0313e3d73 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 29 Apr 2015 20:24:17 +1000 Subject: [PATCH 043/142] Added user setting options. --- apps/opencs/model/settings/usersettings.cpp | 6 ++- apps/opencs/view/world/scriptedit.cpp | 50 +++++++++++++++------ apps/opencs/view/world/scriptedit.hpp | 5 ++- apps/opencs/view/world/scriptsubview.cpp | 45 +++++++++++++++++-- apps/opencs/view/world/scriptsubview.hpp | 9 ++++ 5 files changed, 96 insertions(+), 19 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 6e240c9987..d9db95c710 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -143,6 +143,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() minWidth->setDefaultValue (325); minWidth->setRange (50, 10000); minWidth->setToolTip ("Minimum width of subviews."); + + Setting *monoFont = createSetting (Type_CheckBox, "mono-font", "Use monospace font"); + monoFont->setDefaultValue ("true"); + monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview."); } declareSection ("records", "Records"); @@ -225,7 +229,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() Setting *autoDelete = createSetting (Type_CheckBox, "auto-delete", "Delete row from result table after a successful replace"); autoDelete->setDefaultValue ("true"); } - + { /****************************************************************** * There are three types of values: diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index 991e58ae77..9e0a7e95ad 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -12,6 +12,7 @@ #include "../../model/world/universalid.hpp" #include "../../model/world/tablemimedata.hpp" +#include "../../model/settings/usersettings.hpp" CSVWorld::ScriptEdit::ChangeLock::ChangeLock (ScriptEdit& edit) : mEdit (edit) @@ -30,7 +31,9 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli : QPlainTextEdit (parent), mDocument (document), mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive), - mChangeLocked (0) + mChangeLocked (0), + mLineNumberArea(0), + mShowLineNum(false) { // setAcceptRichText (false); setLineWrapMode (QPlainTextEdit::NoWrap); @@ -75,19 +78,35 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli mUpdateTimer.setSingleShot (true); - // FIXME: make this configurable or provide a font selector dialogue - // FIXME: save QFontInfo somewhere before switching to a new one - QFont font("Monospace"); - font.setStyleHint(QFont::TypeWriter); - setFont(font); + // TODO: provide a font selector dialogue + std::string useMonoFont = + CSMSettings::UserSettings::instance().setting("window/mono-font", "true").toStdString(); + if (useMonoFont == "true") + { + QFont font("Monospace"); + font.setStyleHint(QFont::TypeWriter); + setFont(font); + } - // FIXME: make this configurable - lineNumberArea = new LineNumberArea(this); + mLineNumberArea = new LineNumberArea(this); + updateLineNumberAreaWidth(0); connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); - updateLineNumberAreaWidth(0); + std::string showStatusBar = + CSMSettings::UserSettings::instance().settingValue("window/show-statusbar").toStdString(); + + showLineNum(showStatusBar == "true"); +} + +void CSVWorld::ScriptEdit::showLineNum(bool show) +{ + if(show!=mShowLineNum) + { + mShowLineNum = show; + updateLineNumberAreaWidth(0); + } } bool CSVWorld::ScriptEdit::isChangeLocked() const @@ -176,6 +195,9 @@ void CSVWorld::ScriptEdit::updateHighlighting() int CSVWorld::ScriptEdit::lineNumberAreaWidth() { + if(!mShowLineNum) + return 0; + int digits = 1; int max = qMax(1, blockCount()); while (max >= 10) @@ -197,9 +219,9 @@ void CSVWorld::ScriptEdit::updateLineNumberAreaWidth(int /* newBlockCount */) void CSVWorld::ScriptEdit::updateLineNumberArea(const QRect &rect, int dy) { if (dy) - lineNumberArea->scroll(0, dy); + mLineNumberArea->scroll(0, dy); else - lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + mLineNumberArea->update(0, rect.y(), mLineNumberArea->width(), rect.height()); if (rect.contains(viewport()->rect())) updateLineNumberAreaWidth(0); @@ -210,12 +232,12 @@ void CSVWorld::ScriptEdit::resizeEvent(QResizeEvent *e) QPlainTextEdit::resizeEvent(e); QRect cr = contentsRect(); - lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); + mLineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); } void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent *event) { - QPainter painter(lineNumberArea); + QPainter painter(mLineNumberArea); QTextBlock block = firstVisibleBlock(); int blockNumber = block.blockNumber(); @@ -255,7 +277,7 @@ void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent *event) painter.setPen(Qt::black); } painter.setFont(newFont); - painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), + painter.drawText(0, top, mLineNumberArea->width(), fontMetrics().height(), Qt::AlignRight, number); painter.setFont(font); } diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index 90fe2917e5..3355d40c16 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../../model/world/universalid.hpp" @@ -47,7 +48,8 @@ namespace CSVWorld int mChangeLocked; ScriptHighlighter *mHighlighter; QTimer mUpdateTimer; - QWidget *lineNumberArea; + bool mShowLineNum; + LineNumberArea *mLineNumberArea; public: @@ -61,6 +63,7 @@ namespace CSVWorld void lineNumberAreaPaintEvent(QPaintEvent *event); int lineNumberAreaWidth(); + void showLineNum(bool show); protected: diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index ea9dcee8cd..335cb97af3 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -1,8 +1,11 @@ - #include "scriptsubview.hpp" #include +#include +#include +#include + #include "../../model/doc/document.hpp" #include "../../model/world/universalid.hpp" #include "../../model/world/data.hpp" @@ -13,9 +16,26 @@ #include "scriptedit.hpp" CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: SubView (id), mDocument (document), mColumn (-1) +: SubView (id), mDocument (document), mColumn (-1), mBottom(0), mStatus(0) { - setWidget (mEditor = new ScriptEdit (mDocument, ScriptHighlighter::Mode_General, this)); + QVBoxLayout *layout = new QVBoxLayout; + layout->setContentsMargins (QMargins (0, 0, 0, 0)); + + mBottom = new QWidget(this); + QStackedLayout *bottmLayout = new QStackedLayout(mBottom); + bottmLayout->setContentsMargins (0, 0, 0, 0); + QStatusBar *statusBar = new QStatusBar(mBottom); + mStatus = new QLabel(mBottom); + statusBar->addWidget (mStatus); + bottmLayout->addWidget (statusBar); + mBottom->setLayout (bottmLayout); + + layout->addWidget (mBottom, 0); + layout->insertWidget (0, mEditor = new ScriptEdit (mDocument, ScriptHighlighter::Mode_General, this), 2); + + QWidget *widget = new QWidget; + widget->setLayout (layout); + setWidget (widget); mModel = &dynamic_cast ( *document.getData().getTableModel (CSMWorld::UniversalId::Type_Scripts)); @@ -40,6 +60,25 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: connect (mModel, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)), this, SLOT (rowsAboutToBeRemoved (const QModelIndex&, int, int))); + + updateStatusBar(); + connect(mEditor, SIGNAL(cursorPositionChanged()), this, SLOT(updateStatusBar())); +} + +void CSVWorld::ScriptSubView::setStatusBar (bool show) +{ + mEditor->showLineNum(show); + mBottom->setVisible(show); +} + +void CSVWorld::ScriptSubView::updateStatusBar () +{ + std::ostringstream stream; + + stream << "(" << mEditor->textCursor().blockNumber() + 1 << ", " + << mEditor->textCursor().columnNumber() + 1 << ")"; + + mStatus->setText (QString::fromUtf8 (stream.str().c_str())); } void CSVWorld::ScriptSubView::setEditLock (bool locked) diff --git a/apps/opencs/view/world/scriptsubview.hpp b/apps/opencs/view/world/scriptsubview.hpp index 561476577a..5d85891cf7 100644 --- a/apps/opencs/view/world/scriptsubview.hpp +++ b/apps/opencs/view/world/scriptsubview.hpp @@ -4,6 +4,7 @@ #include "../doc/subview.hpp" class QModelIndex; +class QLabel; namespace CSMDoc { @@ -27,6 +28,8 @@ namespace CSVWorld CSMDoc::Document& mDocument; CSMWorld::IdTable *mModel; int mColumn; + QWidget *mBottom; + QLabel *mStatus; public: @@ -36,6 +39,8 @@ namespace CSVWorld virtual void useHint (const std::string& hint); + virtual void setStatusBar (bool show); + public slots: void textChanged(); @@ -43,6 +48,10 @@ namespace CSVWorld void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void rowsAboutToBeRemoved (const QModelIndex& parent, int start, int end); + + private slots: + + void updateStatusBar(); }; } From 31db37afd460201d83767b7a4f0cd4933a7b96c1 Mon Sep 17 00:00:00 2001 From: k1ll Date: Wed, 19 Jun 2013 20:22:07 +0200 Subject: [PATCH 044/142] FindMygui mingw --- cmake/FindMyGUI.cmake | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/cmake/FindMyGUI.cmake b/cmake/FindMyGUI.cmake index 40fa2373f0..2829a74d35 100644 --- a/cmake/FindMyGUI.cmake +++ b/cmake/FindMyGUI.cmake @@ -19,7 +19,46 @@ include(PreprocessorUtils) # ENDIF (MYGUI_LIBRARIES AND MYGUI_INCLUDE_DIRS) IF (WIN32) #Windows + MESSAGE(STATUS "Looking for MyGUI") + + IF(MINGW) + + FIND_PATH ( MYGUI_INCLUDE_DIRS MyGUI.h PATH_SUFFIXES MYGUI) + FIND_PATH ( MYGUI_PLATFORM_INCLUDE_DIRS MyGUI_OgrePlatform.h PATH_SUFFIXES MYGUI) + FIND_LIBRARY ( MYGUI_LIBRARIES_REL NAMES + libMyGUIEngine${CMAKE_SHARED_LIBRARY_SUFFIX} + libMyGUI.OgrePlatform${CMAKE_STATIC_LIBRARY_SUFFIX} + HINTS + ${MYGUI_LIB_DIR} + PATH_SUFFIXES "" release relwithdebinfo minsizerel ) + + FIND_LIBRARY ( MYGUI_LIBRARIES_DBG NAMES + libMyGUIEngine_d${CMAKE_SHARED_LIBRARY_SUFFIX} + libMyGUI.OgrePlatform_d${CMAKE_STATIC_LIBRARY_SUFFIX} + HINTS + ${MYGUI_LIB_DIR} + PATH_SUFFIXES "" debug ) + + FIND_LIBRARY ( MYGUI_PLATFORM_LIBRARIES_REL NAMES + libMyGUI.OgrePlatform${CMAKE_STATIC_LIBRARY_SUFFIX} + HINTS + ${MYGUI_LIB_DIR} + PATH_SUFFIXES "" release relwithdebinfo minsizerel ) + + FIND_LIBRARY ( MYGUI_PLATFORM_LIBRARIES_DBG NAMES + MyGUI.OgrePlatform_d${CMAKE_STATIC_LIBRARY_SUFFIX} + HINTS + ${MYGUI_LIB_DIR} + PATH_SUFFIXES "" debug ) + + make_library_set ( MYGUI_LIBRARIES ) + make_library_set ( MYGUI_PLATFORM_LIBRARIES ) + + MESSAGE ("${MYGUI_LIBRARIES}") + MESSAGE ("${MYGUI_PLATFORM_LIBRARIES}") + ENDIF(MINGW) + SET(MYGUISDK $ENV{MYGUI_HOME}) IF (MYGUISDK) findpkg_begin ( "MYGUI" ) From 00b7712a5910932f5bb8e333e6a28883f506092a Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 22 Jun 2013 11:33:22 +0200 Subject: [PATCH 045/142] Fix shlwapi include case and add the lib for linking when building for windows --- components/CMakeLists.txt | 4 ++++ components/files/windowspath.cpp | 4 +--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 38fcd88e3e..5bd18d119e 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -170,6 +170,10 @@ if (GIT_CHECKOUT) add_dependencies (components git-version) endif (GIT_CHECKOUT) +if (WIN32) +target_link_libraries(components shlwapi) +endif() + # Fix for not visible pthreads functions for linker with glibc 2.15 if (UNIX AND NOT APPLE) target_link_libraries(components ${CMAKE_THREAD_LIBS_INIT}) diff --git a/components/files/windowspath.cpp b/components/files/windowspath.cpp index 0df782702d..ece4049a87 100644 --- a/components/files/windowspath.cpp +++ b/components/files/windowspath.cpp @@ -6,9 +6,7 @@ #include #include -#include - -#pragma comment(lib, "Shlwapi.lib") +#include #include namespace bconv = boost::locale::conv; From a230050ec8d4d094a5905b0280173fc3e780a09a Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 22 Jun 2013 11:37:17 +0200 Subject: [PATCH 046/142] Boost tr1 unordered map does not work with mingw --- apps/openmw/mwworld/worldimp.cpp | 2 +- components/files/configurationmanager.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 013386f8f9..744057e437 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1,6 +1,6 @@ #include "worldimp.hpp" -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW32__) #include #elif defined HAVE_UNORDERED_MAP #include diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index b0b7fea9a9..24b08c5236 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -1,7 +1,7 @@ #ifndef COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP #define COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP -#ifdef _WIN32 +#if defined(_WIN32) && !defined(__MINGW32__) #include #elif defined HAVE_UNORDERED_MAP #include From de247ec94b26f08b15fff61a3fed070a7e06109c Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 22 Jun 2013 11:48:52 +0200 Subject: [PATCH 047/142] Fix ifdef --- extern/sdl4ogre/sdlwindowhelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/sdl4ogre/sdlwindowhelper.cpp b/extern/sdl4ogre/sdlwindowhelper.cpp index 637fae0efe..6690e3caba 100644 --- a/extern/sdl4ogre/sdlwindowhelper.cpp +++ b/extern/sdl4ogre/sdlwindowhelper.cpp @@ -30,7 +30,7 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, switch (wmInfo.subsystem) { -#ifdef WIN32 +#ifdef _WIN32 case SDL_SYSWM_WINDOWS: // Windows code winHandle = Ogre::StringConverter::toString((uintptr_t)wmInfo.info.win.window); From c61919501dfb4416797c398a957bcf5259748ed5 Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 22 Jun 2013 11:56:18 +0200 Subject: [PATCH 048/142] Fix unnecessary include, ssize_t define and use pretty function instead of funcsig for mingw --- extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp b/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp index b05b16d428..fe36ec39f1 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp +++ b/extern/ogre-ffmpeg-videoplayer/audiodecoder.hpp @@ -21,8 +21,8 @@ extern "C" #endif } -#ifdef _WIN32 -#include +#if defined(_WIN32) && !defined(__MINGW32__) +#include typedef SSIZE_T ssize_t; #endif From b194af4ab27d35a167c69c9b8f6a6f481017b237 Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 6 Jul 2013 13:32:59 +0200 Subject: [PATCH 049/142] Add static qt to components --- components/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 5bd18d119e..e6158c0a25 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -170,6 +170,10 @@ if (GIT_CHECKOUT) add_dependencies (components git-version) endif (GIT_CHECKOUT) +if(MINGW) +target_link_libraries(components ${QT_LIBRARIES}) +endif() + if (WIN32) target_link_libraries(components shlwapi) endif() From 8e094d6fa5ed03434c1fd7e86a1018dc8a895137 Mon Sep 17 00:00:00 2001 From: k1ll Date: Sat, 6 Jul 2013 17:18:11 +0200 Subject: [PATCH 050/142] Add static bullet to components --- components/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index e6158c0a25..01de1c28e1 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -127,6 +127,9 @@ set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui ) find_package(Qt4 COMPONENTS QtCore QtGui) +if(MINGW) +find_package(Bullet REQUIRED COMPONENTS Collision) +endif() if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) add_component_qt_dir (contentselector @@ -171,7 +174,7 @@ if (GIT_CHECKOUT) endif (GIT_CHECKOUT) if(MINGW) -target_link_libraries(components ${QT_LIBRARIES}) +target_link_libraries(components ${QT_LIBRARIES} ${BULLET_LIBRARIES}) endif() if (WIN32) From fe03727ae5fa6e598b151122ad5f3878e52b2e3c Mon Sep 17 00:00:00 2001 From: k1ll Date: Tue, 6 Aug 2013 18:55:17 +0200 Subject: [PATCH 051/142] Don't force linking static boost libraries when building with mingw --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07fffd5776..2c83e26627 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,9 +134,11 @@ endif() # Platform specific if (WIN32) + if(NOT MINGW) set(Boost_USE_STATIC_LIBS ON) set(PLATFORM_INCLUDE_DIR "platform") add_definitions(-DBOOST_ALL_NO_LIB) + endif(NOT MINGW) # Suppress WinMain(), provided by SDL add_definitions(-DSDL_MAIN_HANDLED) From 96d9afec384d16de4876c3e3b74a190afee28732 Mon Sep 17 00:00:00 2001 From: k1ll Date: Fri, 23 May 2014 23:26:05 +0200 Subject: [PATCH 052/142] More header case fixes --- apps/openmw/main.cpp | 2 +- extern/oics/tinyxml.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 070136dfd7..2d2c9af0c9 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -15,7 +15,7 @@ #if defined(_WIN32) // For OutputDebugString #define WIN32_LEAN_AND_MEAN -#include +#include // makes __argc and __argv available on windows #include #endif diff --git a/extern/oics/tinyxml.cpp b/extern/oics/tinyxml.cpp index 21b2d9c9a3..5d8eb475a0 100644 --- a/extern/oics/tinyxml.cpp +++ b/extern/oics/tinyxml.cpp @@ -32,7 +32,7 @@ distribution. #include "tinyxml.h" #ifdef _WIN32 -#include // import MultiByteToWideChar +#include // import MultiByteToWideChar #endif From 901ee5b756ab1d156e055ccf1f5d0624d240c53b Mon Sep 17 00:00:00 2001 From: k1ll Date: Fri, 23 May 2014 23:35:28 +0200 Subject: [PATCH 053/142] Add flag for mingw-w64 unicode support --- apps/mwiniimporter/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/mwiniimporter/CMakeLists.txt b/apps/mwiniimporter/CMakeLists.txt index 790d47dc47..753c86fef6 100644 --- a/apps/mwiniimporter/CMakeLists.txt +++ b/apps/mwiniimporter/CMakeLists.txt @@ -18,6 +18,10 @@ target_link_libraries(openmw-iniimporter components ) +if (MINGW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode") +endif() + if (BUILD_WITH_CODE_COVERAGE) add_definitions (--coverage) target_link_libraries(openmw-iniimporter gcov) From 7b4a9f1ea1d8b8a43674bc914d99960ef5581356 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 30 Apr 2015 06:32:03 +1000 Subject: [PATCH 054/142] Moved script editor settings to its own section. --- apps/opencs/model/settings/usersettings.cpp | 16 ++++++++++++---- apps/opencs/view/world/scriptedit.cpp | 4 ++-- apps/opencs/view/world/scriptsubview.cpp | 13 ++++++++++--- apps/opencs/view/world/scriptsubview.hpp | 2 +- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index d9db95c710..9e00b7d1aa 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -143,10 +143,6 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() minWidth->setDefaultValue (325); minWidth->setRange (50, 10000); minWidth->setToolTip ("Minimum width of subviews."); - - Setting *monoFont = createSetting (Type_CheckBox, "mono-font", "Use monospace font"); - monoFont->setDefaultValue ("true"); - monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview."); } declareSection ("records", "Records"); @@ -230,6 +226,18 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() autoDelete->setDefaultValue ("true"); } + declareSection ("script-editor", "Script Editor"); + { + Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers"); + lineNum->setDefaultValue ("true"); + lineNum->setToolTip ("Show line numbers to the left of the script editor window." + "The current row and column numbers of the text cursor are shown at the bottom."); + + Setting *monoFont = createSetting (Type_CheckBox, "mono-font", "Use monospace font"); + monoFont->setDefaultValue ("true"); + monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview."); + } + { /****************************************************************** * There are three types of values: diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index 9e0a7e95ad..0909c00f9e 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -80,7 +80,7 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli // TODO: provide a font selector dialogue std::string useMonoFont = - CSMSettings::UserSettings::instance().setting("window/mono-font", "true").toStdString(); + CSMSettings::UserSettings::instance().setting("script-editor/mono-font", "true").toStdString(); if (useMonoFont == "true") { QFont font("Monospace"); @@ -95,7 +95,7 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); std::string showStatusBar = - CSMSettings::UserSettings::instance().settingValue("window/show-statusbar").toStdString(); + CSMSettings::UserSettings::instance().settingValue("script-editor/show-linenum").toStdString(); showLineNum(showStatusBar == "true"); } diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index 335cb97af3..c7ddcd82a1 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -12,6 +12,7 @@ #include "../../model/world/columnbase.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/settings/usersettings.hpp" #include "scriptedit.hpp" @@ -65,10 +66,16 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: connect(mEditor, SIGNAL(cursorPositionChanged()), this, SLOT(updateStatusBar())); } -void CSVWorld::ScriptSubView::setStatusBar (bool show) +void CSVWorld::ScriptSubView::updateUserSetting (const QString& name, const QStringList& value) { - mEditor->showLineNum(show); - mBottom->setVisible(show); + if (name != "script-editor/show-linenum") + return; + + std::string showLinenum = + CSMSettings::UserSettings::instance().settingValue("script-editor/show-linenum").toStdString(); + + mEditor->showLineNum(showLinenum == "true"); + mBottom->setVisible(showLinenum == "true"); } void CSVWorld::ScriptSubView::updateStatusBar () diff --git a/apps/opencs/view/world/scriptsubview.hpp b/apps/opencs/view/world/scriptsubview.hpp index 5d85891cf7..1c6474e542 100644 --- a/apps/opencs/view/world/scriptsubview.hpp +++ b/apps/opencs/view/world/scriptsubview.hpp @@ -39,7 +39,7 @@ namespace CSVWorld virtual void useHint (const std::string& hint); - virtual void setStatusBar (bool show); + virtual void updateUserSetting (const QString& name, const QStringList& value); public slots: From 081f3ed263f5077be9e2853d6e5f1b2ec9e468aa Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 1 May 2015 06:08:04 +1000 Subject: [PATCH 055/142] Make font setting selection immediate. --- apps/opencs/view/world/scriptedit.cpp | 19 +++++++++++++------ apps/opencs/view/world/scriptedit.hpp | 3 +++ apps/opencs/view/world/scriptsubview.cpp | 18 ++++++++++-------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index 0909c00f9e..b4f4234f19 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -33,7 +33,9 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive), mChangeLocked (0), mLineNumberArea(0), - mShowLineNum(false) + mShowLineNum(false), + mDefaultFont(font()), + mMonoFont(QFont("Monospace")) { // setAcceptRichText (false); setLineWrapMode (QPlainTextEdit::NoWrap); @@ -79,14 +81,11 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli mUpdateTimer.setSingleShot (true); // TODO: provide a font selector dialogue + mMonoFont.setStyleHint(QFont::TypeWriter); std::string useMonoFont = CSMSettings::UserSettings::instance().setting("script-editor/mono-font", "true").toStdString(); if (useMonoFont == "true") - { - QFont font("Monospace"); - font.setStyleHint(QFont::TypeWriter); - setFont(font); - } + setFont(mMonoFont); mLineNumberArea = new LineNumberArea(this); updateLineNumberAreaWidth(0); @@ -109,6 +108,14 @@ void CSVWorld::ScriptEdit::showLineNum(bool show) } } +void CSVWorld::ScriptEdit::setMonoFont(bool show) +{ + if(show) + setFont(mMonoFont); + else + setFont(mDefaultFont); +} + bool CSVWorld::ScriptEdit::isChangeLocked() const { return mChangeLocked!=0; diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index 3355d40c16..a19cee486b 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -50,6 +50,8 @@ namespace CSVWorld QTimer mUpdateTimer; bool mShowLineNum; LineNumberArea *mLineNumberArea; + QFont mDefaultFont; + QFont mMonoFont; public: @@ -64,6 +66,7 @@ namespace CSVWorld void lineNumberAreaPaintEvent(QPaintEvent *event); int lineNumberAreaWidth(); void showLineNum(bool show); + void setMonoFont(bool show); protected: diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index c7ddcd82a1..411eb3660d 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -68,14 +68,16 @@ CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc: void CSVWorld::ScriptSubView::updateUserSetting (const QString& name, const QStringList& value) { - if (name != "script-editor/show-linenum") - return; - - std::string showLinenum = - CSMSettings::UserSettings::instance().settingValue("script-editor/show-linenum").toStdString(); - - mEditor->showLineNum(showLinenum == "true"); - mBottom->setVisible(showLinenum == "true"); + if (name == "script-editor/show-linenum") + { + std::string showLinenum = value.at(0).toStdString(); + mEditor->showLineNum(showLinenum == "true"); + mBottom->setVisible(showLinenum == "true"); + } + else if (name == "script-editor/mono-font") + { + mEditor->setMonoFont(value.at(0).toStdString() == "true"); + } } void CSVWorld::ScriptSubView::updateStatusBar () From b04aeb6aad5ca7441d3091a85fc871049db0c8e8 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 1 May 2015 12:14:09 +1000 Subject: [PATCH 056/142] Fixed levelled lists flags - now bit masks represented by tick boxes in the dialogue subview. --- apps/opencs/model/world/columns.cpp | 5 +- apps/opencs/model/world/columns.hpp | 11 +- apps/opencs/model/world/commands.cpp | 7 +- apps/opencs/model/world/refidadapterimp.hpp | 134 +++++++++++--------- apps/opencs/model/world/refidcollection.cpp | 4 +- apps/opencs/view/world/dialoguesubview.cpp | 5 +- 6 files changed, 93 insertions(+), 73 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 3d735ddcaf..3172e72e4e 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -222,7 +222,6 @@ namespace CSMWorld { ColumnId_HitSound, "Hit Sound" }, { ColumnId_AreaSound, "Area Sound" }, { ColumnId_BoltSound, "Bolt Sound" }, - { ColumnId_OriginalCell, "Original Cell" }, { ColumnId_PathgridPoints, "Points" }, { ColumnId_PathgridIndex, "Index" }, @@ -267,13 +266,15 @@ namespace CSMWorld { ColumnId_LevelledList,"Levelled List" }, { ColumnId_LevelledItemId,"Item ID" }, { ColumnId_LevelledItemLevel,"Level" }, - { ColumnId_LevelledItemType, "Type" }, + { ColumnId_LevelledItemType, "Calculate all levels <= player" }, + { ColumnId_LevelledItemTypeEach, "Select a new item each instance" }, { ColumnId_LevelledItemChanceNone, "Chance None" }, { ColumnId_PowerList, "Powers" }, { ColumnId_SkillImpact, "Skills" }, { ColumnId_InfoList, "Info List" }, + { ColumnId_OriginalCell, "Original Cell" }, { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 0c525fd11f..b87f6c53d0 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -257,14 +257,15 @@ namespace CSMWorld ColumnId_LevelledItemId = 234, ColumnId_LevelledItemLevel = 235, ColumnId_LevelledItemType = 236, - ColumnId_LevelledItemChanceNone = 237, + ColumnId_LevelledItemTypeEach = 237, + ColumnId_LevelledItemChanceNone = 238, - ColumnId_PowerList = 238, - ColumnId_SkillImpact = 239, // impact from magic effects + ColumnId_PowerList = 239, + ColumnId_SkillImpact = 240, // impact from magic effects - ColumnId_InfoList = 240, + ColumnId_InfoList = 241, - ColumnId_OriginalCell = 241, + ColumnId_OriginalCell = 242, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 2329597279..9a0401081b 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -21,9 +21,12 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI // Replace proxy with actual model mIndex = proxy->mapToSource (index); mModel = proxy->sourceModel(); - } - setText ("Modify " + mModel->headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); + setText ("Modify " + dynamic_cast(mModel)->nestedHeaderData ( + mIndex.parent().column(), mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); + } + else + setText ("Modify " + mModel->headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); } void CSMWorld::ModifyCommand::redo() diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index e385543838..61e8115c0e 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -1830,10 +1830,10 @@ namespace CSMWorld } + // for non-tables template class NestedListLevListRefIdAdapter : public NestedRefIdAdapterBase { - UniversalId::Type mType; // not implemented @@ -1877,45 +1877,27 @@ namespace CSMWorld const Record& record = static_cast&> (data.getRecord (RefIdData::LocalIndex (index, mType))); - switch (subColIndex) + if (mType == UniversalId::Type_CreatureLevelledList) { - case 0: + switch (subColIndex) { - if (mType == CSMWorld::UniversalId::Type_CreatureLevelledList && - record.get().mFlags == 0x01) - { - return QString("All Levels"); - } - else if(mType == CSMWorld::UniversalId::Type_ItemLevelledList && - record.get().mFlags == 0x01) - { - return QString("Each"); - } - else if(mType == CSMWorld::UniversalId::Type_ItemLevelledList && - record.get().mFlags == 0x02) - { - return QString("All Levels"); - } - else if (mType == CSMWorld::UniversalId::Type_CreatureLevelledList && - record.get().mFlags == 0x00) - { - std::cerr << "Unknown creature leveled list type: " << record.get().mFlags - << ", Using \"All Levels\""<< std::endl; - return QString("All Levels"); - } - else if (mType == CSMWorld::UniversalId::Type_ItemLevelledList && - record.get().mFlags == 0x00) - { - std::cerr << "Unknown item leveled list type: " << record.get().mFlags - << ", Using \"Each\""<< std::endl; - return QString("Each"); - } - else - throw std::runtime_error("unknown leveled list type"); + case 0: return QVariant(); // don't allow checkbox editor to be created + case 1: return record.get().mFlags & ESM::CreatureLevList::AllLevels; + case 2: return static_cast (record.get().mChanceNone); + default: + throw std::runtime_error("Trying to access non-existing column in levelled creatues!"); + } + } + else + { + switch (subColIndex) + { + case 0: return record.get().mFlags & ESM::ItemLevList::Each; + case 1: return record.get().mFlags & ESM::ItemLevList::AllLevels; + case 2: return static_cast (record.get().mChanceNone); + default: + throw std::runtime_error("Trying to access non-existing column in levelled items!"); } - case 1: return static_cast (record.get().mChanceNone); - default: - throw std::runtime_error("Trying to access non-existing column in the nested table!"); } } @@ -1926,34 +1908,63 @@ namespace CSMWorld static_cast&> (data.getRecord (RefIdData::LocalIndex (row, mType))); ESXRecordT leveled = record.get(); - switch(subColIndex) + if (mType == UniversalId::Type_CreatureLevelledList) { - case 0: + switch(subColIndex) { - if (mType == CSMWorld::UniversalId::Type_CreatureLevelledList && - value.toString().toStdString() == "All Levels") + case 0: return; // return without saving + case 1: { - leveled.mFlags = 0x01; - break; + if(value.toBool()) + { + leveled.mFlags |= ESM::CreatureLevList::AllLevels; + break; + } + else + { + leveled.mFlags &= ~ESM::CreatureLevList::AllLevels; + break; + } } - else if(mType == CSMWorld::UniversalId::Type_ItemLevelledList && - value.toString().toStdString() == "Each") - { - leveled.mFlags = 0x01; - break; - } - else if(mType == CSMWorld::UniversalId::Type_ItemLevelledList && - value.toString().toStdString() == "All Levels") - { - leveled.mFlags = 0x02; - break; - } - else - return; // return without saving + case 2: leveled.mChanceNone = static_cast(value.toInt()); break; + default: + throw std::runtime_error("Trying to set non-existing column in levelled creatures!"); + } + } + else + { + switch(subColIndex) + { + case 0: + { + if(value.toBool()) + { + leveled.mFlags |= ESM::ItemLevList::Each; + break; + } + else + { + leveled.mFlags &= ~ESM::ItemLevList::Each; + break; + } + } + case 1: + { + if(value.toBool()) + { + leveled.mFlags |= ESM::ItemLevList::AllLevels; + break; + } + else + { + leveled.mFlags &= ~ESM::ItemLevList::AllLevels; + break; + } + } + case 2: leveled.mChanceNone = static_cast(value.toInt()); break; + default: + throw std::runtime_error("Trying to set non-existing column in levelled items!"); } - case 1: leveled.mChanceNone = static_cast(value.toInt()); break; - default: - throw std::runtime_error("Trying to access non-existing column in the nested table!"); } record.setModified (leveled); @@ -1961,7 +1972,7 @@ namespace CSMWorld virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const { - return 2; + return 3; } virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const @@ -1970,6 +1981,7 @@ namespace CSMWorld } }; + // for tables template class NestedLevListRefIdAdapter : public NestedRefIdAdapterBase { diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 4a8f398cd0..1941c505a2 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -514,7 +514,9 @@ CSMWorld::RefIdCollection::RefIdCollection() new NestedListLevListRefIdAdapter (UniversalId::Type_ItemLevelledList))); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), nestedListLevListMap)); mColumns.back().addColumn( - new RefIdColumn (Columns::ColumnId_LevelledItemType, CSMWorld::ColumnBase::Display_String)); + new RefIdColumn (Columns::ColumnId_LevelledItemTypeEach, CSMWorld::ColumnBase::Display_Boolean)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_LevelledItemType, CSMWorld::ColumnBase::Display_Boolean)); mColumns.back().addColumn( new RefIdColumn (Columns::ColumnId_LevelledItemChanceNone, CSMWorld::ColumnBase::Display_Integer)); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index cf3653c1b2..0d0e82dbf3 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -29,8 +29,8 @@ #include "../../model/world/record.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/idtree.hpp" -#include "../../model/doc/document.hpp" #include "../../model/world/commands.hpp" +#include "../../model/doc/document.hpp" #include "recordstatusdelegate.hpp" #include "util.hpp" @@ -444,7 +444,8 @@ void CSVWorld::EditWidget::remake(int row) if (mTable->hasChildren(mTable->index(row, i)) && !(flags & CSMWorld::ColumnBase::Flag_Dialogue_List)) { - mNestedModels.push_back(new CSMWorld::NestedTableProxyModel (mTable->index(row, i), display, dynamic_cast(mTable))); + mNestedModels.push_back(new CSMWorld::NestedTableProxyModel ( + mTable->index(row, i), display, dynamic_cast(mTable))); int idColumn = mTable->findColumnIndex (CSMWorld::Columns::ColumnId_Id); int typeColumn = mTable->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType); From d873c2c6032c5091ce3ab8172573c87435b18b10 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 2 May 2015 13:20:42 +0200 Subject: [PATCH 057/142] focus main input widget when bringing up creator bar (Fixes #2514) --- apps/opencs/view/world/creator.hpp | 3 +++ apps/opencs/view/world/genericcreator.cpp | 5 +++++ apps/opencs/view/world/genericcreator.hpp | 3 +++ apps/opencs/view/world/infocreator.cpp | 5 +++++ apps/opencs/view/world/infocreator.hpp | 5 ++++- apps/opencs/view/world/referencecreator.cpp | 5 +++++ apps/opencs/view/world/referencecreator.hpp | 3 +++ apps/opencs/view/world/tablebottombox.cpp | 2 ++ 8 files changed, 30 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 7c0422c882..506bdab2c9 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -40,6 +40,9 @@ namespace CSVWorld /// Default implementation: Throw an exception if scope!=Scope_Content. virtual void setScope (unsigned int scope); + /// Focus main input widget + virtual void focus() = 0; + signals: void done(); diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index b4cf460403..4269679bfd 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -225,6 +225,11 @@ void CSVWorld::GenericCreator::toggleWidgets(bool active) { } +void CSVWorld::GenericCreator::focus() +{ + mId->setFocus(); +} + void CSVWorld::GenericCreator::setScope (unsigned int scope) { mScopes = scope; diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 6780050825..1f854c69ed 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -101,6 +101,9 @@ namespace CSVWorld virtual void setScope (unsigned int scope); + /// Focus main input widget + virtual void focus(); + private slots: void textChanged (const QString& text); diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index 14034ea7f4..f88b9f0b9a 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -91,6 +91,11 @@ std::string CSVWorld::InfoCreator::getErrors() const return errors; } +void CSVWorld::InfoCreator::focus() +{ + mTopic->setFocus(); +} + void CSVWorld::InfoCreator::topicChanged() { update(); diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index 2296a82973..edc12975cb 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -35,7 +35,10 @@ namespace CSVWorld virtual std::string getErrors() const; ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. - + + /// Focus main input widget + virtual void focus(); + private slots: void topicChanged(); diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 1e3cc00d7d..e9bb04ba7e 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -118,6 +118,11 @@ std::string CSVWorld::ReferenceCreator::getErrors() const return errors; } +void CSVWorld::ReferenceCreator::focus() +{ + mCell->setFocus(); +} + void CSVWorld::ReferenceCreator::cellChanged() { update(); diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 002a62d879..877307c29e 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -39,6 +39,9 @@ namespace CSVWorld ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. + /// Focus main input widget + virtual void focus(); + private slots: void cellChanged(); diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index 239c7410fb..e9d644f61e 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -157,6 +157,7 @@ void CSVWorld::TableBottomBox::createRequest() mLayout->setCurrentWidget (mCreator); setVisible (true); mCreating = true; + mCreator->focus(); } void CSVWorld::TableBottomBox::cloneRequest(const std::string& id, @@ -168,4 +169,5 @@ void CSVWorld::TableBottomBox::cloneRequest(const std::string& id, mCreator->toggleWidgets(false); setVisible (true); mCreating = true; + mCreator->focus(); } From 048d7be87c4a1555f27b08f4efa67722bfdcc56d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 3 May 2015 16:35:10 +0200 Subject: [PATCH 058/142] Adjusted terminology for references/referenceables in OpenMW-CS user-interface (Fixes #2516) --- apps/opencs/model/tools/referencecheck.cpp | 2 +- apps/opencs/model/world/universalid.cpp | 8 ++++---- apps/opencs/view/doc/view.cpp | 4 ++-- apps/opencs/view/render/worldspacewidget.cpp | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/opencs/model/tools/referencecheck.cpp b/apps/opencs/model/tools/referencecheck.cpp index 198c3627f4..be9663e7aa 100644 --- a/apps/opencs/model/tools/referencecheck.cpp +++ b/apps/opencs/model/tools/referencecheck.cpp @@ -28,7 +28,7 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message // Check for empty reference id if (cellRef.mRefID.empty()) { - messages.push_back(std::make_pair(id, " is an empty reference")); + messages.push_back(std::make_pair(id, " is an empty instance (not based on an object)")); } else { // Check for non existing referenced object if (mReferencables.searchId(cellRef.mRefID) == -1) { diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index fbc942f8e2..e496fe79bb 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -38,9 +38,9 @@ namespace { 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, - "Referenceables", 0 }, + "Objects", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, - "References", 0 }, + "Instances", 0 }, { CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 }, @@ -79,7 +79,7 @@ namespace { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, { 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, "Referenceables", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Object", 0 }, { 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" }, @@ -103,7 +103,7 @@ 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, "Reference", 0 }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Instance", 0 }, { 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 }, diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index e430bfa5e3..5636fff943 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -131,11 +131,11 @@ void CSVDoc::View::setupWorldMenu() connect (cells, SIGNAL (triggered()), this, SLOT (addCellsSubView())); world->addAction (cells); - QAction *referenceables = new QAction (tr ("Referenceables"), this); + QAction *referenceables = new QAction (tr ("Objects"), this); connect (referenceables, SIGNAL (triggered()), this, SLOT (addReferenceablesSubView())); world->addAction (referenceables); - QAction *references = new QAction (tr ("References"), this); + QAction *references = new QAction (tr ("Instances"), this); connect (references, SIGNAL (triggered()), this, SLOT (addReferencesSubView())); world->addAction (references); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index 582ccea643..e3e5ce50e6 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -258,7 +258,7 @@ unsigned int CSVRender::WorldspaceWidget::getInteractionMask() const void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons ( CSVWidget::SceneToolToggle2 *tool) { - tool->addButton (Element_Reference, "References"); + tool->addButton (Element_Reference, "Instances"); tool->addButton (Element_Water, "Water"); tool->addButton (Element_Pathgrid, "Pathgrid"); } @@ -267,7 +267,7 @@ void CSVRender::WorldspaceWidget::addEditModeSelectorButtons (CSVWidget::SceneTo { /// \todo replace EditMode with suitable subclasses tool->addButton ( - new EditMode (this, QIcon (":placeholder"), Element_Reference, "Reference editing"), + new EditMode (this, QIcon (":placeholder"), Element_Reference, "Instance editing"), "object"); tool->addButton ( new EditMode (this, QIcon (":placeholder"), Element_Pathgrid, "Pathgrid editing"), From b0c4be231622666eab9253c6e5700e5157559c9c Mon Sep 17 00:00:00 2001 From: dteviot Date: Mon, 4 May 2015 14:52:47 +1200 Subject: [PATCH 059/142] Multi-select + context menu. (Fixes #2480) Content selector, added multi-select + context menu to allow check/uncheck the multi-selected items. --- .../contentselector/view/contentselector.cpp | 40 +++++++++++++++++++ .../contentselector/view/contentselector.hpp | 6 +++ files/ui/contentselector.ui | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/components/contentselector/view/contentselector.cpp b/components/contentselector/view/contentselector.cpp index e3093d5685..2fae8e74b9 100644 --- a/components/contentselector/view/contentselector.cpp +++ b/components/contentselector/view/contentselector.cpp @@ -57,6 +57,17 @@ void ContentSelectorView::ContentSelector::buildAddonView() connect(ui.addonView, SIGNAL(activated(const QModelIndex&)), this, SLOT(slotAddonTableItemActivated(const QModelIndex&))); connect(mContentModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SIGNAL(signalAddonDataChanged(QModelIndex,QModelIndex))); + buildContextMenu(); +} + +void ContentSelectorView::ContentSelector::buildContextMenu() +{ + ui.addonView->setContextMenuPolicy(Qt::CustomContextMenu); + connect(ui.addonView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(slotShowContextMenu(const QPoint&))); + + mContextMenu = new QMenu(ui.addonView); + mContextMenu->addAction(tr("&Check Selected"), this, SLOT(slotCheckMultiSelectedItems())); + mContextMenu->addAction(tr("&Uncheck Selected"), this, SLOT(slotUncheckMultiSelectedItems())); } void ContentSelectorView::ContentSelector::setProfileContent(const QStringList &fileList) @@ -196,3 +207,32 @@ void ContentSelectorView::ContentSelector::slotAddonTableItemActivated(const QMo mContentModel->setData(sourceIndex, checkState, Qt::CheckStateRole); } + +void ContentSelectorView::ContentSelector::slotShowContextMenu(const QPoint& pos) +{ + QPoint globalPos = ui.addonView->viewport()->mapToGlobal(pos); + mContextMenu->exec(globalPos); +} + +void ContentSelectorView::ContentSelector::setCheckStateForMultiSelectedItems(bool checked) +{ + Qt::CheckState checkState = checked ? Qt::Checked : Qt::Unchecked; + foreach(const QModelIndex& index, ui.addonView->selectionModel()->selectedIndexes()) + { + QModelIndex sourceIndex = mAddonProxyModel->mapToSource(index); + if (mContentModel->data(sourceIndex, Qt::CheckStateRole).toInt() != checkState) + { + mContentModel->setData(sourceIndex, checkState, Qt::CheckStateRole); + } + } +} + +void ContentSelectorView::ContentSelector::slotUncheckMultiSelectedItems() +{ + setCheckStateForMultiSelectedItems(false); +} + +void ContentSelectorView::ContentSelector::slotCheckMultiSelectedItems() +{ + setCheckStateForMultiSelectedItems(true); +} diff --git a/components/contentselector/view/contentselector.hpp b/components/contentselector/view/contentselector.hpp index 2507cf6adb..e455807c96 100644 --- a/components/contentselector/view/contentselector.hpp +++ b/components/contentselector/view/contentselector.hpp @@ -14,6 +14,7 @@ namespace ContentSelectorView { Q_OBJECT + QMenu *mContextMenu; QStringList mFilePaths; protected: @@ -51,7 +52,9 @@ namespace ContentSelectorView void buildContentModel(); void buildGameFileView(); void buildAddonView(); + void buildContextMenu(); void setGameFileSelected(int index, bool selected); + void setCheckStateForMultiSelectedItems(bool checked); signals: void signalCurrentGamefileIndexChanged (int); @@ -62,6 +65,9 @@ namespace ContentSelectorView void slotCurrentGameFileIndexChanged(int index); void slotAddonTableItemActivated(const QModelIndex& index); + void slotShowContextMenu(const QPoint& pos); + void slotCheckMultiSelectedItems(); + void slotUncheckMultiSelectedItems(); }; } diff --git a/files/ui/contentselector.ui b/files/ui/contentselector.ui index b9b5ba5a03..7832239b5d 100644 --- a/files/ui/contentselector.ui +++ b/files/ui/contentselector.ui @@ -72,7 +72,7 @@ true - QAbstractItemView::SingleSelection + QAbstractItemView::ExtendedSelection QAbstractItemView::SelectRows From 27751db99afae9368fc29fabbe0bbedb980c3ace Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 4 May 2015 16:23:33 +0200 Subject: [PATCH 060/142] Use btScaledBvhTriangleMeshShape, bump required bullet version to 2.83 --- components/nifbullet/bulletnifloader.cpp | 4 +-- libs/openengine/bullet/physic.cpp | 32 +++++++++++++++++------- libs/openengine/bullet/physic.hpp | 3 +++ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 93c9797b25..3207af0fe8 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -123,7 +123,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) mCompoundShape = NULL; mStaticMesh = NULL; - Nif::NIFFilePtr pnif (Nif::Cache::getInstance().load(mResourceName.substr(0, mResourceName.length()-7))); + Nif::NIFFilePtr pnif (Nif::Cache::getInstance().load(mResourceName)); Nif::NIFFile & nif = *pnif.get (); if (nif.numRoots() < 1) { @@ -134,7 +134,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) // Have to load controlled nodes from the .kf // FIXME: the .kf has to be loaded both for rendering and physics, ideally it should be opened once and then reused mControlledNodes.clear(); - std::string kfname = mResourceName.substr(0, mResourceName.length()-7); + std::string kfname = mResourceName; Misc::StringUtils::toLower(kfname); if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0) kfname.replace(kfname.size()-4, 4, ".kf"); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 013ef1003e..76dbc224c5 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -457,8 +457,7 @@ namespace Physic float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation, bool raycasting, bool placeable) { - std::string sid = (boost::format("%07.3f") % scale).str(); - std::string outputstring = mesh + sid; + std::string outputstring = mesh; //get the shape from the .nif mShapeLoader->load(outputstring,"General"); @@ -477,20 +476,35 @@ namespace Physic btCollisionShape* collisionShape = raycasting ? shape->mRaycastingShape : shape->mCollisionShape; - // If this is an animated compound shape, we must duplicate it so we can animate - // multiple instances independently. - if (!raycasting && !shape->mAnimatedShapes.empty()) - collisionShape = duplicateCollisionShape(collisionShape); - if (raycasting && !shape->mAnimatedRaycastingShapes.empty()) - collisionShape = duplicateCollisionShape(collisionShape); +// TODO: check this from cmake? +#if BT_BULLET_VERSION < 283 +#error "Bullet version 2.83 or later required" +#endif - collisionShape->setLocalScaling( btVector3(scale,scale,scale)); + bool needDelete = false; + if (btBvhTriangleMeshShape* triangleShape = dynamic_cast(shape->mCollisionShape)) + { + btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(triangleShape, btVector3(scale,scale,scale)); + collisionShape = scaled; + needDelete = true; + } + else + { + // If this is an animated compound shape, we must duplicate it so we can animate + // multiple instances independently. + if (!raycasting && !shape->mAnimatedShapes.empty()) + collisionShape = duplicateCollisionShape(collisionShape); + if (raycasting && !shape->mAnimatedRaycastingShapes.empty()) + collisionShape = duplicateCollisionShape(collisionShape); + } //create the real body btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo (0,0, collisionShape); RigidBody* body = new RigidBody(CI,name); body->mPlaceable = placeable; + if (needDelete) + body->mCollisionShape.reset(collisionShape); if (!raycasting && !shape->mAnimatedShapes.empty()) { diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 7784e8941d..7b0906694b 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -63,6 +63,9 @@ namespace Physic virtual ~RigidBody(); std::string mName; + // May be empty if the collision shape is a shared resource + std::auto_ptr mCollisionShape; + // Hack: placeable objects (that can be picked up by the player) have different collision behaviour. // This variable needs to be passed to BulletNifLoader. bool mPlaceable; From 1c334a01ced6b05da2e5da54c09c026927be7386 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 4 May 2015 19:04:06 +0200 Subject: [PATCH 061/142] one more referenceable that escaped the change into object --- apps/opencs/model/world/columns.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 3172e72e4e..9076aa0968 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -172,7 +172,7 @@ namespace CSMWorld { ColumnId_Rank, "Rank" }, { ColumnId_Gender, "Gender" }, { ColumnId_PcRank, "PC Rank" }, - { ColumnId_ReferenceableId, "Referenceable ID" }, + { ColumnId_ReferenceableId, "Object ID" }, { ColumnId_ContainerContent, "Content" }, { ColumnId_ItemCount, "Count" }, From 9f6bc1b3a9b141030b4450a7999d6637882741ce Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 4 May 2015 19:06:02 +0200 Subject: [PATCH 062/142] increased version number --- CMakeLists.txt | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07fffd5776..7c19c57eb0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,8 +19,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/) message(STATUS "Configuring OpenMW...") set(OPENMW_VERSION_MAJOR 0) -set(OPENMW_VERSION_MINOR 35) -set(OPENMW_VERSION_RELEASE 1) +set(OPENMW_VERSION_MINOR 36) +set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_TAGHASH "") diff --git a/README.md b/README.md index 811eb87632..f62800e1fd 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ OpenMW OpenMW is an attempt at recreating the engine for the popular role-playing game Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. -* Version: 0.35.1 +* Version: 0.36.0 * License: GPL (see docs/license/GPL3.txt for more information) * Website: http://www.openmw.org * IRC: #openmw on irc.freenode.net From e9ef9eedae94cee61d71f951fa740eb83953c178 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 5 May 2015 10:51:48 +0200 Subject: [PATCH 063/142] updated changelog --- CHANGELOG.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1766aa21d9..15464b1d72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,42 @@ +0.36.0 +------ + + Bug #923: Editor: Operations-Multithreading is broken + Bug #1317: Erene Llenim in Seyda Neen does not walk around + Bug #1621: "Error Detecting Morrowind Installation" in the default directory + Bug #2216: Creating a clone of the player stops you moving. + Bug #2387: Casting bound weapon spell doesn't switch to "ready weapon" mode + Bug #2407: Default to (0, 0) when "unknown cell" is encountered. + Bug #2411: enchanted item charges don't update/refresh if spell list window is pinned open + Bug #2428: Editor: cloning / creating new container class results in invalid omwaddon file - openmw-0.35 + Bug #2429: Editor - cloning omits some values or sets different values than the original has + Bug #2430: NPC with negative fatigue don't fall (LGNPC Vivec, Foreign Quarter v2.21) + Bug #2432: Error on startup with Uvirith's Legacy enabled + Bug #2435: Editor: changed entries in the objects window are not shown as such + Bug #2437: Editor: changing an entry of a container/NPC/clothing/ingredient/globals will not be saved in the omwaddon file + Bug #2447: Editor doesn't save terrain information + Bug #2451: Editor not listing files with accented characters + Bug #2453: Chargen: sex, race and hair sliders not initialized properly + Bug #2459: Minor terrain clipping through statics due to difference in triangle alignment + Bug #2461: Invisible sound mark has collision in Sandus Ancestral Tomb + Bug #2465: tainted gold stack + Bug #2475: cumulative stacks of 100 point fortify skill speechcraft boosts do not apply correctly + Bug #2498: Editor: crash when issuing undo command after the table subview is closed + Bug #2500: Editor: object table - can't undo delete record + Feature #139: Editor: Global Search & Replace + Feature #1219: Editor: Add dialogue mode only columns + Feature #2024: Hotkey for hand to hand (i.e. unequip any weapon) + Feature #2119: "Always Sneak" key bind + Feature #2262: Editor: Handle moved instances + Feature #2425: Editor: Add start script table + Feature #2426: Editor: start script record verifier + Feature #2480: Launcher: Multiselect entries in the Data Files list + Feature #2505: Editor: optionally show a line number column in the script editor + Feature #2512: Editor: Offer use of monospace fonts in the script editor as an option + Feature #2514: Editor: focus on ID input field on clone/add + Task #2460: OS X: Use Application Support directory as user data path + Task #2516: Editor: Change References / Referenceables terminology + 0.35.1 ------ From 60fffec3452c68ef2675a7c573af0436c051a6d4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 5 May 2015 16:08:01 +0200 Subject: [PATCH 064/142] Collision fix --- libs/openengine/bullet/physic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 22312e3bc9..17d4aeab53 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -480,7 +480,7 @@ namespace Physic #endif bool needDelete = false; - if (btBvhTriangleMeshShape* triangleShape = dynamic_cast(shape->mCollisionShape)) + if (btBvhTriangleMeshShape* triangleShape = dynamic_cast(collisionShape)) { btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(triangleShape, btVector3(scale,scale,scale)); collisionShape = scaled; From 0c461f4424a0912af405530878d559ebd376c3b8 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 9 May 2015 21:21:16 +1000 Subject: [PATCH 065/142] Add TopicInfos special conditions table. --- apps/opencs/model/world/columnbase.cpp | 3 + apps/opencs/model/world/columnbase.hpp | 3 + apps/opencs/model/world/columns.cpp | 21 + apps/opencs/model/world/columns.hpp | 7 +- apps/opencs/model/world/data.cpp | 13 + .../model/world/nestedcoladapterimp.cpp | 413 ++++++++++++++++++ .../model/world/nestedcoladapterimp.hpp | 25 ++ apps/opencs/view/doc/viewmanager.cpp | 4 +- 8 files changed, 487 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 659954f481..cf125aa639 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -81,6 +81,9 @@ bool CSMWorld::ColumnBase::isId (Display display) Display_PartRefType, Display_AiPackageType, Display_YesNo, + Display_InfoCondFunc, + Display_InfoCondVar, + Display_InfoCondComp, Display_None }; diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 71c22a9f07..2d2513774a 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -116,6 +116,9 @@ namespace CSMWorld Display_PartRefType, Display_AiPackageType, Display_YesNo, + Display_InfoCondFunc, + Display_InfoCondVar, + Display_InfoCondComp, //top level columns that nest other columns Display_NestedHeader diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 9076aa0968..89ee6258b5 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -274,6 +274,11 @@ namespace CSMWorld { ColumnId_SkillImpact, "Skills" }, { ColumnId_InfoList, "Info List" }, + { ColumnId_InfoCondition, "Info Conditions" }, + { ColumnId_InfoCondFunc, "Function" }, + { ColumnId_InfoCondVar, "Func/Variable" }, + { ColumnId_InfoCondComp, "Comp" }, + { ColumnId_InfoCondValue, "Value" }, { ColumnId_OriginalCell, "Original Cell" }, { ColumnId_UseValue1, "Use value 1" }, @@ -502,6 +507,18 @@ namespace "No", "Yes", 0 }; + static const char *sInfoCondFunc[] = + { + " ", "Function", "Global", "Local", "Journal", + "Item", "Dead", "Not ID", "Not Faction", "Not Class", + "Not Race", "Not Cell", "Not Local", 0 + }; + + static const char *sInfoCondComp[] = + { + "!=", "<", "<=", "=", ">", ">=", 0 + }; + const char **getEnumNames (CSMWorld::Columns::ColumnId column) { switch (column) @@ -530,6 +547,10 @@ namespace case CSMWorld::Columns::ColumnId_PartRefType: return sPartRefType; case CSMWorld::Columns::ColumnId_AiPackageType: return sAiPackageType; case CSMWorld::Columns::ColumnId_AiWanderRepeat: return sAiWanderRepeat; + case CSMWorld::Columns::ColumnId_InfoCondFunc: return sInfoCondFunc; + // FIXME: don't have dynamic value enum delegate, use Display_String for now + //case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond; + case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp; default: return 0; } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index b87f6c53d0..f971f3fd89 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -264,8 +264,13 @@ namespace CSMWorld ColumnId_SkillImpact = 240, // impact from magic effects ColumnId_InfoList = 241, + ColumnId_InfoCondition = 242, + ColumnId_InfoCondFunc = 243, + ColumnId_InfoCondVar = 244, + ColumnId_InfoCondComp = 245, + ColumnId_InfoCondValue = 246, - ColumnId_OriginalCell = 242, + ColumnId_OriginalCell = 247, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index fc4532fb0e..e2fab0a25b 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -242,6 +242,19 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mTopicInfos.addAdapter (std::make_pair(&mTopicInfos.getColumn(index), new InfoListAdapter ())); mTopicInfos.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_ScriptText, ColumnBase::Display_ScriptLines)); + // Special conditions + mTopicInfos.addColumn (new NestedParentColumn (Columns::ColumnId_InfoCondition)); + index = mTopicInfos.getColumns()-1; + mTopicInfos.addAdapter (std::make_pair(&mTopicInfos.getColumn(index), new InfoConditionAdapter ())); + mTopicInfos.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_InfoCondFunc, ColumnBase::Display_InfoCondFunc)); + // FIXME: don't have dynamic value enum delegate, use Display_String for now + mTopicInfos.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_InfoCondVar, ColumnBase::Display_String)); + mTopicInfos.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_InfoCondComp, ColumnBase::Display_InfoCondComp)); + mTopicInfos.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_Value, ColumnBase::Display_Var)); mJournalInfos.addColumn (new StringIdColumn (true)); mJournalInfos.addColumn (new RecordStateColumn); diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index d29155a478..9cd1a0a3b6 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -528,4 +528,417 @@ namespace CSMWorld { return 1; // fixed at size 1 } + + // ESM::DialInfo::SelectStruct.mSelectRule + // 012345... + // ^^^ ^^ + // ||| || + // ||| |+------------- condition variable string + // ||| +-------------- comparison type, ['0'..'5']; e.g. !=, <, >=, etc + // ||+---------------- function index (encoded, where function == '1') + // |+----------------- function, ['1'..'C']; e.g. Global, Local, Not ID, etc + // +------------------ unknown + // + InfoConditionAdapter::InfoConditionAdapter () {} + + void InfoConditionAdapter::addRow(Record& record, int position) const + { + Info info = record.get(); + + std::vector& conditions = info.mSelects; + + // blank row + ESM::DialInfo::SelectStruct condStruct; + condStruct.mSelectRule = "00000"; + condStruct.mValue = ESM::Variant(); + + conditions.insert(conditions.begin()+position, condStruct); + + record.setModified (info); + } + + void InfoConditionAdapter::removeRow(Record& record, int rowToRemove) const + { + Info info = record.get(); + + std::vector& conditions = info.mSelects; + + if (rowToRemove < 0 || rowToRemove >= static_cast (conditions.size())) + throw std::runtime_error ("index out of range"); + + conditions.erase(conditions.begin()+rowToRemove); + + record.setModified (info); + } + + void InfoConditionAdapter::setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + Info info = record.get(); + + info.mSelects = + static_cast >&>(nestedTable).mNestedTable; + + record.setModified (info); + } + + NestedTableWrapperBase* InfoConditionAdapter::table(const Record& record) const + { + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(record.get().mSelects); + } + + // See the mappings in MWDialogue::SelectWrapper::getArgument + // from ESM::Attribute, ESM::Skill and MWMechanics::CreatureStats (for AI) + static const std::map sEncToInfoFunc = + { + { "00", "Rank Low" }, + { "01", "Rank High" }, + { "02", "Rank Requirement" }, + { "03", "Reputation" }, + { "04", "Health Percent" }, + { "05", "PC Reputation" }, + { "06", "PC Level" }, + { "07", "PC Health Percent" }, + { "08", "PC Magicka" }, // dynamic stat + { "09", "PC Fatigue" }, // dynamic stat + { "10", "PC Strength" }, // attrib + { "11", "PC Block" }, + { "12", "PC Armoror" }, + { "13", "PC Medium Armor" }, + { "14", "PC Heavy Armor" }, + { "15", "PC Blunt Weapon" }, + { "16", "PC Long Blade" }, + { "17", "PC Axe" }, + { "18", "PC Spear" }, + { "19", "PC Athletics" }, + { "20", "PC Enchant" }, + { "21", "PC Destruction" }, + { "22", "PC Alteration" }, + { "23", "PC Illusion" }, + { "24", "PC Conjuration" }, + { "25", "PC Mysticism" }, + { "26", "PC Restoration" }, + { "27", "PC Alchemy" }, + { "28", "PC Unarmored" }, + { "29", "PC Security" }, + { "30", "PC Sneak" }, + { "31", "PC Acrobatics" }, + { "32", "PC Light Armor" }, + { "33", "PC Short Blade" }, + { "34", "PC Marksman" }, + { "35", "PC Merchantile" }, + { "36", "PC Speechcraft" }, + { "37", "PC Hand To Hand" }, + { "38", "PC Sex" }, + { "39", "PC Expelled" }, + { "40", "PC Common Disease" }, + { "41", "PC Blight Disease" }, + { "42", "PC Clothing Modifier" }, + { "43", "PC Crime Level" }, + { "44", "Same Sex" }, + { "45", "Same Race" }, + { "46", "Same Faction" }, + { "47", "Faction Rank Difference" }, + { "48", "Detected" }, + { "49", "Alarmed" }, + { "50", "Choice" }, + { "51", "PC Intelligence" }, // attrib + { "52", "PC Willpower" }, // attrib + { "53", "PC Agility" }, // attrib + { "54", "PC Speed" }, // attrib + { "55", "PC Endurance" }, // attrib + { "56", "PC Personality" }, // attrib + { "57", "PC Luck" }, // attrib + { "58", "PC Corpus" }, + { "59", "Weather" }, + { "60", "PC Vampire" }, + { "61", "Level" }, + { "62", "Attacked" }, + { "63", "Talked To PC" }, + { "64", "PC Health" }, // dynamic stat + { "65", "Creature Target" }, + { "66", "Friend Hit" }, + { "67", "Fight" }, // AI + { "68", "Hello" }, // AI + { "69", "Alarm" }, // AI + { "70", "Flee" }, // AI + { "71", "Should Attack" }, + { "72", "Werewolf" }, + { "73", "PC Werewolf Kills" } + }; + + QVariant InfoConditionAdapter::getData(const Record& record, + int subRowIndex, int subColIndex) const + { + Info info = record.get(); + + std::vector& conditions = info.mSelects; + + if (subRowIndex < 0 || subRowIndex >= static_cast (conditions.size())) + throw std::runtime_error ("index out of range"); + + switch (subColIndex) + { + case 0: + { + char condType = conditions[subRowIndex].mSelectRule[1]; + switch (condType) + { + case '1': return 1; // Function + case '2': return 2; // Global + case '3': return 3; // Local + case '4': return 4; // Journal + case '5': return 5; // Item + case '6': return 6; // Dead + case '7': return 7; // Not ID + case '8': return 8; // Not Factio + case '9': return 9; // Not Class + case 'A': return 10; // Not Race + case 'B': return 11; // Not Cell + case 'C': return 12; // Not Local + default: return QVariant(); // TODO: log an error? + } + } + case 1: + { + if (conditions[subRowIndex].mSelectRule[1] == '1') + { + // throws an exception if the encoding is not found + return sEncToInfoFunc.at(conditions[subRowIndex].mSelectRule.substr(2, 2)).c_str(); + } + else + return QString(conditions[subRowIndex].mSelectRule.substr(5).c_str()); + } + case 2: + { + char compType = conditions[subRowIndex].mSelectRule[4]; + switch (compType) + { + case '0': return 3; // = + case '1': return 0; // != + case '2': return 4; // > + case '3': return 5; // >= + case '4': return 1; // < + case '5': return 2; // <= + default: return QVariant(); // TODO: log an error? + } + } + case 3: + { + switch (conditions[subRowIndex].mValue.getType()) + { + case ESM::VT_String: + { + return QString::fromUtf8 (conditions[subRowIndex].mValue.getString().c_str()); + } + case ESM::VT_Int: + case ESM::VT_Short: + case ESM::VT_Long: + { + return conditions[subRowIndex].mValue.getInteger(); + } + case ESM::VT_Float: + { + return conditions[subRowIndex].mValue.getFloat(); + } + default: return QVariant(); + } + } + default: throw std::runtime_error("Info condition subcolumn index out of range"); + } + } + + static const std::map sInfoFuncToEnc = + { + { "Alarm", "69" }, // AI + { "Alarmed", "49" }, + { "Attacked", "62" }, + { "Choice", "50" }, + { "Creature Target", "65" }, + { "Detected", "48" }, + { "Faction Rank Difference", "47" }, + { "Fight", "67" }, // AI + { "Flee", "70" }, // AI + { "Friend Hit", "66" }, + { "Health Percent", "04" }, + { "Hello", "68" }, // AI + { "Level", "61" }, + { "PC Acrobatics", "31" }, + { "PC Agility", "53" }, // attrib + { "PC Alchemy", "27" }, + { "PC Alteration", "22" }, + { "PC Armoror", "12" }, + { "PC Athletics", "19" }, + { "PC Axe", "17" }, + { "PC Blight Disease", "41" }, + { "PC Block", "11" }, + { "PC Blunt Weapon", "15" }, + { "PC Clothing Modifier", "42" }, + { "PC Common Disease", "40" }, + { "PC Conjuration", "24" }, + { "PC Corpus", "58" }, + { "PC Crime Level", "43" }, + { "PC Destruction", "21" }, + { "PC Enchant", "20" }, + { "PC Endurance", "55" }, // attrib + { "PC Expelled", "39" }, + { "PC Fatigue", "09" }, // dynamic stat + { "PC Hand To Hand", "37" }, + { "PC Health", "64" }, // dynamic stat + { "PC Health Percent", "07" }, + { "PC Heavy Armor", "14" }, + { "PC Illusion", "23" }, + { "PC Intelligence", "51" }, // attrib + { "PC Level", "06" }, + { "PC Light Armor", "32" }, + { "PC Long Blade", "16" }, + { "PC Luck", "57" }, // attrib + { "PC Magicka", "08" }, // dynamic stat + { "PC Marksman", "34" }, + { "PC Medium Armor", "13" }, + { "PC Merchantile", "35" }, + { "PC Mysticism", "25" }, + { "PC Personality", "56" }, // attrib + { "PC Reputation", "05" }, + { "PC Restoration", "26" }, + { "PC Security", "29" }, + { "PC Sex", "38" }, + { "PC Short Blade", "33" }, + { "PC Sneak", "30" }, + { "PC Spear", "18" }, + { "PC Speechcraft", "36" }, + { "PC Speed", "54" }, // attrib + { "PC Strength", "10" }, // attrib + { "PC Unarmored", "28" }, + { "PC Vampire", "60" }, + { "PC Werewolf Kills", "73" }, + { "PC Willpower", "52" }, // attrib + { "Rank Requirement", "02" }, + { "Rank High", "01" }, + { "Rank Low", "00" }, + { "Reputation", "03" }, + { "Same Faction", "46" }, + { "Same Race", "45" }, + { "Same Sex", "44" }, + { "Should Attack", "71" }, + { "Talked To PC", "63" }, + { "Weather", "59" }, + { "Werewolf", "72" } + }; + + void InfoConditionAdapter::setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + Info info = record.get(); + + std::vector& conditions = info.mSelects; + + if (subRowIndex < 0 || subRowIndex >= static_cast (conditions.size())) + throw std::runtime_error ("index out of range"); + + switch (subColIndex) + { + case 0: + { + // See sInfoCondFunc in columns.cpp for the enum values + switch (value.toInt()) + { + // FIXME: when these change the values of the other columns need to change + // correspondingly (and automatically) + case 1: conditions[subRowIndex].mSelectRule[1] = '1'; break; // Function + case 2: conditions[subRowIndex].mSelectRule[1] = '2'; break; // Global + case 3: conditions[subRowIndex].mSelectRule[1] = '3'; break; // Local + case 4: conditions[subRowIndex].mSelectRule[1] = '4'; break; // Journal + case 5: conditions[subRowIndex].mSelectRule[1] = '5'; break; // Item + case 6: conditions[subRowIndex].mSelectRule[1] = '6'; break; // Dead + case 7: conditions[subRowIndex].mSelectRule[1] = '7'; break; // Not ID + case 8: conditions[subRowIndex].mSelectRule[1] = '8'; break; // Not Faction + case 9: conditions[subRowIndex].mSelectRule[1] = '9'; break; // Not Class + case 10: conditions[subRowIndex].mSelectRule[1] = 'A'; break; // Not Race + case 11: conditions[subRowIndex].mSelectRule[1] = 'B'; break; // Not Cell + case 12: conditions[subRowIndex].mSelectRule[1] = 'C'; break; // Not Local + default: return; // return without saving + } + break; + } + case 1: + { + if (conditions[subRowIndex].mSelectRule[1] == '1') + { + // throws an exception if the function is not found + const std::map::const_iterator it = sInfoFuncToEnc.find( + value.toString().toUtf8().constData()); + if (it != sInfoFuncToEnc.end()) + { + std::string rule = conditions[subRowIndex].mSelectRule.substr(0, 2); + rule.append(it->second); + rule.append(std::string(1, conditions[subRowIndex].mSelectRule[4])); + conditions[subRowIndex].mSelectRule = rule.append(value.toString().toUtf8().constData()); + } + else + return; // return without saving; TODO: maybe log an error here + } + else + { + // FIXME: validate the string values before saving, based on the current function + std::string rule = conditions[subRowIndex].mSelectRule.substr(0, 5); + conditions[subRowIndex].mSelectRule = rule.append(value.toString().toUtf8().constData()); + } + break; + } + case 2: + { + // See sInfoCondComp in columns.cpp for the enum values + switch (value.toInt()) + { + case 0: conditions[subRowIndex].mSelectRule[4] = '1'; break; // != + case 1: conditions[subRowIndex].mSelectRule[4] = '4'; break; // < + case 2: conditions[subRowIndex].mSelectRule[4] = '5'; break; // <= + case 3: conditions[subRowIndex].mSelectRule[4] = '0'; break; // = + case 4: conditions[subRowIndex].mSelectRule[4] = '2'; break; // > + case 5: conditions[subRowIndex].mSelectRule[4] = '3'; break; // >= + default: return; // return without saving + } + break; + } + case 3: + { + switch (conditions[subRowIndex].mValue.getType()) + { + case ESM::VT_String: + { + conditions[subRowIndex].mValue.setString (value.toString().toUtf8().constData()); + break; + } + case ESM::VT_Int: + case ESM::VT_Short: + case ESM::VT_Long: + { + conditions[subRowIndex].mValue.setInteger (value.toInt()); + break; + } + case ESM::VT_Float: + { + conditions[subRowIndex].mValue.setFloat (value.toFloat()); + break; + } + default: break; + } + } + default: throw std::runtime_error("Info condition subcolumn index out of range"); + } + + record.setModified (info); + } + + int InfoConditionAdapter::getColumnsCount(const Record& record) const + { + return 4; + } + + int InfoConditionAdapter::getRowsCount(const Record& record) const + { + return static_cast(record.get().mSelects.size()); + } } diff --git a/apps/opencs/model/world/nestedcoladapterimp.hpp b/apps/opencs/model/world/nestedcoladapterimp.hpp index 96dcd943de..ea2037eb82 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.hpp +++ b/apps/opencs/model/world/nestedcoladapterimp.hpp @@ -412,6 +412,31 @@ namespace CSMWorld virtual int getRowsCount(const Record& record) const; }; + + class InfoConditionAdapter : public NestedColumnAdapter + { + public: + InfoConditionAdapter (); + + virtual void addRow(Record& record, int position) const; + + virtual void removeRow(Record& record, int rowToRemove) const; + + virtual void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* table(const Record& record) const; + + virtual QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const; + + virtual void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getColumnsCount(const Record& record) const; + + virtual int getRowsCount(const Record& record) const; + }; } #endif // CSM_WOLRD_NESTEDCOLADAPTERIMP_H diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 5908c67a19..6362f96590 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -90,7 +90,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { CSMWorld::ColumnBase::Display_EffectId, CSMWorld::Columns::ColumnId_EffectId, false }, { CSMWorld::ColumnBase::Display_PartRefType, CSMWorld::Columns::ColumnId_PartRefType, false }, { CSMWorld::ColumnBase::Display_AiPackageType, CSMWorld::Columns::ColumnId_AiPackageType, false }, - { CSMWorld::ColumnBase::Display_YesNo, CSMWorld::Columns::ColumnId_AiWanderRepeat, false } + { CSMWorld::ColumnBase::Display_YesNo, CSMWorld::Columns::ColumnId_AiWanderRepeat, false }, + { CSMWorld::ColumnBase::Display_InfoCondFunc, CSMWorld::Columns::ColumnId_InfoCondFunc, false }, + { CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false } }; for (std::size_t i=0; i Date: Sun, 10 May 2015 05:55:50 +1000 Subject: [PATCH 066/142] For compiling with osx - try using a different syntax for initializing the static maps. --- .../model/world/nestedcoladapterimp.cpp | 296 +++++++++--------- 1 file changed, 148 insertions(+), 148 deletions(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 9cd1a0a3b6..debb7ca2f6 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -592,80 +592,80 @@ namespace CSMWorld // from ESM::Attribute, ESM::Skill and MWMechanics::CreatureStats (for AI) static const std::map sEncToInfoFunc = { - { "00", "Rank Low" }, - { "01", "Rank High" }, - { "02", "Rank Requirement" }, - { "03", "Reputation" }, - { "04", "Health Percent" }, - { "05", "PC Reputation" }, - { "06", "PC Level" }, - { "07", "PC Health Percent" }, - { "08", "PC Magicka" }, // dynamic stat - { "09", "PC Fatigue" }, // dynamic stat - { "10", "PC Strength" }, // attrib - { "11", "PC Block" }, - { "12", "PC Armoror" }, - { "13", "PC Medium Armor" }, - { "14", "PC Heavy Armor" }, - { "15", "PC Blunt Weapon" }, - { "16", "PC Long Blade" }, - { "17", "PC Axe" }, - { "18", "PC Spear" }, - { "19", "PC Athletics" }, - { "20", "PC Enchant" }, - { "21", "PC Destruction" }, - { "22", "PC Alteration" }, - { "23", "PC Illusion" }, - { "24", "PC Conjuration" }, - { "25", "PC Mysticism" }, - { "26", "PC Restoration" }, - { "27", "PC Alchemy" }, - { "28", "PC Unarmored" }, - { "29", "PC Security" }, - { "30", "PC Sneak" }, - { "31", "PC Acrobatics" }, - { "32", "PC Light Armor" }, - { "33", "PC Short Blade" }, - { "34", "PC Marksman" }, - { "35", "PC Merchantile" }, - { "36", "PC Speechcraft" }, - { "37", "PC Hand To Hand" }, - { "38", "PC Sex" }, - { "39", "PC Expelled" }, - { "40", "PC Common Disease" }, - { "41", "PC Blight Disease" }, - { "42", "PC Clothing Modifier" }, - { "43", "PC Crime Level" }, - { "44", "Same Sex" }, - { "45", "Same Race" }, - { "46", "Same Faction" }, - { "47", "Faction Rank Difference" }, - { "48", "Detected" }, - { "49", "Alarmed" }, - { "50", "Choice" }, - { "51", "PC Intelligence" }, // attrib - { "52", "PC Willpower" }, // attrib - { "53", "PC Agility" }, // attrib - { "54", "PC Speed" }, // attrib - { "55", "PC Endurance" }, // attrib - { "56", "PC Personality" }, // attrib - { "57", "PC Luck" }, // attrib - { "58", "PC Corpus" }, - { "59", "Weather" }, - { "60", "PC Vampire" }, - { "61", "Level" }, - { "62", "Attacked" }, - { "63", "Talked To PC" }, - { "64", "PC Health" }, // dynamic stat - { "65", "Creature Target" }, - { "66", "Friend Hit" }, - { "67", "Fight" }, // AI - { "68", "Hello" }, // AI - { "69", "Alarm" }, // AI - { "70", "Flee" }, // AI - { "71", "Should Attack" }, - { "72", "Werewolf" }, - { "73", "PC Werewolf Kills" } + std::make_pair( "00", "Rank Low" ), + std::make_pair( "01", "Rank High" ), + std::make_pair( "02", "Rank Requirement" ), + std::make_pair( "03", "Reputation" ), + std::make_pair( "04", "Health Percent" ), + std::make_pair( "05", "PC Reputation" ), + std::make_pair( "06", "PC Level" ), + std::make_pair( "07", "PC Health Percent" ), + std::make_pair( "08", "PC Magicka" ), // dynamic stat + std::make_pair( "09", "PC Fatigue" ), // dynamic stat + std::make_pair( "10", "PC Strength" ), // attrib + std::make_pair( "11", "PC Block" ), + std::make_pair( "12", "PC Armoror" ), + std::make_pair( "13", "PC Medium Armor" ), + std::make_pair( "14", "PC Heavy Armor" ), + std::make_pair( "15", "PC Blunt Weapon" ), + std::make_pair( "16", "PC Long Blade" ), + std::make_pair( "17", "PC Axe" ), + std::make_pair( "18", "PC Spear" ), + std::make_pair( "19", "PC Athletics" ), + std::make_pair( "20", "PC Enchant" ), + std::make_pair( "21", "PC Destruction" ), + std::make_pair( "22", "PC Alteration" ), + std::make_pair( "23", "PC Illusion" ), + std::make_pair( "24", "PC Conjuration" ), + std::make_pair( "25", "PC Mysticism" ), + std::make_pair( "26", "PC Restoration" ), + std::make_pair( "27", "PC Alchemy" ), + std::make_pair( "28", "PC Unarmored" ), + std::make_pair( "29", "PC Security" ), + std::make_pair( "30", "PC Sneak" ), + std::make_pair( "31", "PC Acrobatics" ), + std::make_pair( "32", "PC Light Armor" ), + std::make_pair( "33", "PC Short Blade" ), + std::make_pair( "34", "PC Marksman" ), + std::make_pair( "35", "PC Merchantile" ), + std::make_pair( "36", "PC Speechcraft" ), + std::make_pair( "37", "PC Hand To Hand" ), + std::make_pair( "38", "PC Sex" ), + std::make_pair( "39", "PC Expelled" ), + std::make_pair( "40", "PC Common Disease" ), + std::make_pair( "41", "PC Blight Disease" ), + std::make_pair( "42", "PC Clothing Modifier" ), + std::make_pair( "43", "PC Crime Level" ), + std::make_pair( "44", "Same Sex" ), + std::make_pair( "45", "Same Race" ), + std::make_pair( "46", "Same Faction" ), + std::make_pair( "47", "Faction Rank Difference" ), + std::make_pair( "48", "Detected" ), + std::make_pair( "49", "Alarmed" ), + std::make_pair( "50", "Choice" ), + std::make_pair( "51", "PC Intelligence" ), // attrib + std::make_pair( "52", "PC Willpower" ), // attrib + std::make_pair( "53", "PC Agility" ), // attrib + std::make_pair( "54", "PC Speed" ), // attrib + std::make_pair( "55", "PC Endurance" ), // attrib + std::make_pair( "56", "PC Personality" ), // attrib + std::make_pair( "57", "PC Luck" ), // attrib + std::make_pair( "58", "PC Corpus" ), + std::make_pair( "59", "Weather" ), + std::make_pair( "60", "PC Vampire" ), + std::make_pair( "61", "Level" ), + std::make_pair( "62", "Attacked" ), + std::make_pair( "63", "Talked To PC" ), + std::make_pair( "64", "PC Health" ), // dynamic stat + std::make_pair( "65", "Creature Target" ), + std::make_pair( "66", "Friend Hit" ), + std::make_pair( "67", "Fight" ), // AI + std::make_pair( "68", "Hello" ), // AI + std::make_pair( "69", "Alarm" ), // AI + std::make_pair( "70", "Flee" ), // AI + std::make_pair( "71", "Should Attack" ), + std::make_pair( "72", "Werewolf" ), + std::make_pair( "73", "PC Werewolf Kills" ) }; QVariant InfoConditionAdapter::getData(const Record& record, @@ -751,80 +751,80 @@ namespace CSMWorld static const std::map sInfoFuncToEnc = { - { "Alarm", "69" }, // AI - { "Alarmed", "49" }, - { "Attacked", "62" }, - { "Choice", "50" }, - { "Creature Target", "65" }, - { "Detected", "48" }, - { "Faction Rank Difference", "47" }, - { "Fight", "67" }, // AI - { "Flee", "70" }, // AI - { "Friend Hit", "66" }, - { "Health Percent", "04" }, - { "Hello", "68" }, // AI - { "Level", "61" }, - { "PC Acrobatics", "31" }, - { "PC Agility", "53" }, // attrib - { "PC Alchemy", "27" }, - { "PC Alteration", "22" }, - { "PC Armoror", "12" }, - { "PC Athletics", "19" }, - { "PC Axe", "17" }, - { "PC Blight Disease", "41" }, - { "PC Block", "11" }, - { "PC Blunt Weapon", "15" }, - { "PC Clothing Modifier", "42" }, - { "PC Common Disease", "40" }, - { "PC Conjuration", "24" }, - { "PC Corpus", "58" }, - { "PC Crime Level", "43" }, - { "PC Destruction", "21" }, - { "PC Enchant", "20" }, - { "PC Endurance", "55" }, // attrib - { "PC Expelled", "39" }, - { "PC Fatigue", "09" }, // dynamic stat - { "PC Hand To Hand", "37" }, - { "PC Health", "64" }, // dynamic stat - { "PC Health Percent", "07" }, - { "PC Heavy Armor", "14" }, - { "PC Illusion", "23" }, - { "PC Intelligence", "51" }, // attrib - { "PC Level", "06" }, - { "PC Light Armor", "32" }, - { "PC Long Blade", "16" }, - { "PC Luck", "57" }, // attrib - { "PC Magicka", "08" }, // dynamic stat - { "PC Marksman", "34" }, - { "PC Medium Armor", "13" }, - { "PC Merchantile", "35" }, - { "PC Mysticism", "25" }, - { "PC Personality", "56" }, // attrib - { "PC Reputation", "05" }, - { "PC Restoration", "26" }, - { "PC Security", "29" }, - { "PC Sex", "38" }, - { "PC Short Blade", "33" }, - { "PC Sneak", "30" }, - { "PC Spear", "18" }, - { "PC Speechcraft", "36" }, - { "PC Speed", "54" }, // attrib - { "PC Strength", "10" }, // attrib - { "PC Unarmored", "28" }, - { "PC Vampire", "60" }, - { "PC Werewolf Kills", "73" }, - { "PC Willpower", "52" }, // attrib - { "Rank Requirement", "02" }, - { "Rank High", "01" }, - { "Rank Low", "00" }, - { "Reputation", "03" }, - { "Same Faction", "46" }, - { "Same Race", "45" }, - { "Same Sex", "44" }, - { "Should Attack", "71" }, - { "Talked To PC", "63" }, - { "Weather", "59" }, - { "Werewolf", "72" } + std::make_pair( "Alarm", "69" ), // AI + std::make_pair( "Alarmed", "49" ), + std::make_pair( "Attacked", "62" ), + std::make_pair( "Choice", "50" ), + std::make_pair( "Creature Target", "65" ), + std::make_pair( "Detected", "48" ), + std::make_pair( "Faction Rank Difference", "47" ), + std::make_pair( "Fight", "67" ), // AI + std::make_pair( "Flee", "70" ), // AI + std::make_pair( "Friend Hit", "66" ), + std::make_pair( "Health Percent", "04" ), + std::make_pair( "Hello", "68" ), // AI + std::make_pair( "Level", "61" ), + std::make_pair( "PC Acrobatics", "31" ), + std::make_pair( "PC Agility", "53" ), // attrib + std::make_pair( "PC Alchemy", "27" ), + std::make_pair( "PC Alteration", "22" ), + std::make_pair( "PC Armoror", "12" ), + std::make_pair( "PC Athletics", "19" ), + std::make_pair( "PC Axe", "17" ), + std::make_pair( "PC Blight Disease", "41" ), + std::make_pair( "PC Block", "11" ), + std::make_pair( "PC Blunt Weapon", "15" ), + std::make_pair( "PC Clothing Modifier", "42" ), + std::make_pair( "PC Common Disease", "40" ), + std::make_pair( "PC Conjuration", "24" ), + std::make_pair( "PC Corpus", "58" ), + std::make_pair( "PC Crime Level", "43" ), + std::make_pair( "PC Destruction", "21" ), + std::make_pair( "PC Enchant", "20" ), + std::make_pair( "PC Endurance", "55" ), // attrib + std::make_pair( "PC Expelled", "39" ), + std::make_pair( "PC Fatigue", "09" ), // dynamic stat + std::make_pair( "PC Hand To Hand", "37" ), + std::make_pair( "PC Health", "64" ), // dynamic stat + std::make_pair( "PC Health Percent", "07" ), + std::make_pair( "PC Heavy Armor", "14" ), + std::make_pair( "PC Illusion", "23" ), + std::make_pair( "PC Intelligence", "51" ), // attrib + std::make_pair( "PC Level", "06" ), + std::make_pair( "PC Light Armor", "32" ), + std::make_pair( "PC Long Blade", "16" ), + std::make_pair( "PC Luck", "57" ), // attrib + std::make_pair( "PC Magicka", "08" ), // dynamic stat + std::make_pair( "PC Marksman", "34" ), + std::make_pair( "PC Medium Armor", "13" ), + std::make_pair( "PC Merchantile", "35" ), + std::make_pair( "PC Mysticism", "25" ), + std::make_pair( "PC Personality", "56" ), // attrib + std::make_pair( "PC Reputation", "05" ), + std::make_pair( "PC Restoration", "26" ), + std::make_pair( "PC Security", "29" ), + std::make_pair( "PC Sex", "38" ), + std::make_pair( "PC Short Blade", "33" ), + std::make_pair( "PC Sneak", "30" ), + std::make_pair( "PC Spear", "18" ), + std::make_pair( "PC Speechcraft", "36" ), + std::make_pair( "PC Speed", "54" ), // attrib + std::make_pair( "PC Strength", "10" ), // attrib + std::make_pair( "PC Unarmored", "28" ), + std::make_pair( "PC Vampire", "60" ), + std::make_pair( "PC Werewolf Kills", "73" ), + std::make_pair( "PC Willpower", "52" ), // attrib + std::make_pair( "Rank Requirement", "02" ), + std::make_pair( "Rank High", "01" ), + std::make_pair( "Rank Low", "00" ), + std::make_pair( "Reputation", "03" ), + std::make_pair( "Same Faction", "46" ), + std::make_pair( "Same Race", "45" ), + std::make_pair( "Same Sex", "44" ), + std::make_pair( "Should Attack", "71" ), + std::make_pair( "Talked To PC", "63" ), + std::make_pair( "Weather", "59" ), + std::make_pair( "Werewolf", "72" ) }; void InfoConditionAdapter::setData(Record& record, From d6ecc64168bf164d7157abe4b8deaf3336fd3d8f Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 10 May 2015 06:17:57 +1000 Subject: [PATCH 067/142] Aggregate types can't be static - osx compiler appears to be more strict. --- .../model/world/nestedcoladapterimp.cpp | 300 +++++++++--------- 1 file changed, 150 insertions(+), 150 deletions(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index debb7ca2f6..f1088829ed 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -590,82 +590,82 @@ namespace CSMWorld // See the mappings in MWDialogue::SelectWrapper::getArgument // from ESM::Attribute, ESM::Skill and MWMechanics::CreatureStats (for AI) - static const std::map sEncToInfoFunc = + const std::map sEncToInfoFunc = { - std::make_pair( "00", "Rank Low" ), - std::make_pair( "01", "Rank High" ), - std::make_pair( "02", "Rank Requirement" ), - std::make_pair( "03", "Reputation" ), - std::make_pair( "04", "Health Percent" ), - std::make_pair( "05", "PC Reputation" ), - std::make_pair( "06", "PC Level" ), - std::make_pair( "07", "PC Health Percent" ), - std::make_pair( "08", "PC Magicka" ), // dynamic stat - std::make_pair( "09", "PC Fatigue" ), // dynamic stat - std::make_pair( "10", "PC Strength" ), // attrib - std::make_pair( "11", "PC Block" ), - std::make_pair( "12", "PC Armoror" ), - std::make_pair( "13", "PC Medium Armor" ), - std::make_pair( "14", "PC Heavy Armor" ), - std::make_pair( "15", "PC Blunt Weapon" ), - std::make_pair( "16", "PC Long Blade" ), - std::make_pair( "17", "PC Axe" ), - std::make_pair( "18", "PC Spear" ), - std::make_pair( "19", "PC Athletics" ), - std::make_pair( "20", "PC Enchant" ), - std::make_pair( "21", "PC Destruction" ), - std::make_pair( "22", "PC Alteration" ), - std::make_pair( "23", "PC Illusion" ), - std::make_pair( "24", "PC Conjuration" ), - std::make_pair( "25", "PC Mysticism" ), - std::make_pair( "26", "PC Restoration" ), - std::make_pair( "27", "PC Alchemy" ), - std::make_pair( "28", "PC Unarmored" ), - std::make_pair( "29", "PC Security" ), - std::make_pair( "30", "PC Sneak" ), - std::make_pair( "31", "PC Acrobatics" ), - std::make_pair( "32", "PC Light Armor" ), - std::make_pair( "33", "PC Short Blade" ), - std::make_pair( "34", "PC Marksman" ), - std::make_pair( "35", "PC Merchantile" ), - std::make_pair( "36", "PC Speechcraft" ), - std::make_pair( "37", "PC Hand To Hand" ), - std::make_pair( "38", "PC Sex" ), - std::make_pair( "39", "PC Expelled" ), - std::make_pair( "40", "PC Common Disease" ), - std::make_pair( "41", "PC Blight Disease" ), - std::make_pair( "42", "PC Clothing Modifier" ), - std::make_pair( "43", "PC Crime Level" ), - std::make_pair( "44", "Same Sex" ), - std::make_pair( "45", "Same Race" ), - std::make_pair( "46", "Same Faction" ), - std::make_pair( "47", "Faction Rank Difference" ), - std::make_pair( "48", "Detected" ), - std::make_pair( "49", "Alarmed" ), - std::make_pair( "50", "Choice" ), - std::make_pair( "51", "PC Intelligence" ), // attrib - std::make_pair( "52", "PC Willpower" ), // attrib - std::make_pair( "53", "PC Agility" ), // attrib - std::make_pair( "54", "PC Speed" ), // attrib - std::make_pair( "55", "PC Endurance" ), // attrib - std::make_pair( "56", "PC Personality" ), // attrib - std::make_pair( "57", "PC Luck" ), // attrib - std::make_pair( "58", "PC Corpus" ), - std::make_pair( "59", "Weather" ), - std::make_pair( "60", "PC Vampire" ), - std::make_pair( "61", "Level" ), - std::make_pair( "62", "Attacked" ), - std::make_pair( "63", "Talked To PC" ), - std::make_pair( "64", "PC Health" ), // dynamic stat - std::make_pair( "65", "Creature Target" ), - std::make_pair( "66", "Friend Hit" ), - std::make_pair( "67", "Fight" ), // AI - std::make_pair( "68", "Hello" ), // AI - std::make_pair( "69", "Alarm" ), // AI - std::make_pair( "70", "Flee" ), // AI - std::make_pair( "71", "Should Attack" ), - std::make_pair( "72", "Werewolf" ), - std::make_pair( "73", "PC Werewolf Kills" ) + { "00", "Rank Low" }, + { "01", "Rank High" }, + { "02", "Rank Requirement" }, + { "03", "Reputation" }, + { "04", "Health Percent" }, + { "05", "PC Reputation" }, + { "06", "PC Level" }, + { "07", "PC Health Percent" }, + { "08", "PC Magicka" }, // dynamic stat + { "09", "PC Fatigue" }, // dynamic stat + { "10", "PC Strength" }, // attrib + { "11", "PC Block" }, + { "12", "PC Armoror" }, + { "13", "PC Medium Armor" }, + { "14", "PC Heavy Armor" }, + { "15", "PC Blunt Weapon" }, + { "16", "PC Long Blade" }, + { "17", "PC Axe" }, + { "18", "PC Spear" }, + { "19", "PC Athletics" }, + { "20", "PC Enchant" }, + { "21", "PC Destruction" }, + { "22", "PC Alteration" }, + { "23", "PC Illusion" }, + { "24", "PC Conjuration" }, + { "25", "PC Mysticism" }, + { "26", "PC Restoration" }, + { "27", "PC Alchemy" }, + { "28", "PC Unarmored" }, + { "29", "PC Security" }, + { "30", "PC Sneak" }, + { "31", "PC Acrobatics" }, + { "32", "PC Light Armor" }, + { "33", "PC Short Blade" }, + { "34", "PC Marksman" }, + { "35", "PC Merchantile" }, + { "36", "PC Speechcraft" }, + { "37", "PC Hand To Hand" }, + { "38", "PC Sex" }, + { "39", "PC Expelled" }, + { "40", "PC Common Disease" }, + { "41", "PC Blight Disease" }, + { "42", "PC Clothing Modifier" }, + { "43", "PC Crime Level" }, + { "44", "Same Sex" }, + { "45", "Same Race" }, + { "46", "Same Faction" }, + { "47", "Faction Rank Difference" }, + { "48", "Detected" }, + { "49", "Alarmed" }, + { "50", "Choice" }, + { "51", "PC Intelligence" }, // attrib + { "52", "PC Willpower" }, // attrib + { "53", "PC Agility" }, // attrib + { "54", "PC Speed" }, // attrib + { "55", "PC Endurance" }, // attrib + { "56", "PC Personality" }, // attrib + { "57", "PC Luck" }, // attrib + { "58", "PC Corpus" }, + { "59", "Weather" }, + { "60", "PC Vampire" }, + { "61", "Level" }, + { "62", "Attacked" }, + { "63", "Talked To PC" }, + { "64", "PC Health" }, // dynamic stat + { "65", "Creature Target" }, + { "66", "Friend Hit" }, + { "67", "Fight" }, // AI + { "68", "Hello" }, // AI + { "69", "Alarm" }, // AI + { "70", "Flee" }, // AI + { "71", "Should Attack" }, + { "72", "Werewolf" }, + { "73", "PC Werewolf Kills" } }; QVariant InfoConditionAdapter::getData(const Record& record, @@ -749,82 +749,82 @@ namespace CSMWorld } } - static const std::map sInfoFuncToEnc = + const std::map sInfoFuncToEnc = { - std::make_pair( "Alarm", "69" ), // AI - std::make_pair( "Alarmed", "49" ), - std::make_pair( "Attacked", "62" ), - std::make_pair( "Choice", "50" ), - std::make_pair( "Creature Target", "65" ), - std::make_pair( "Detected", "48" ), - std::make_pair( "Faction Rank Difference", "47" ), - std::make_pair( "Fight", "67" ), // AI - std::make_pair( "Flee", "70" ), // AI - std::make_pair( "Friend Hit", "66" ), - std::make_pair( "Health Percent", "04" ), - std::make_pair( "Hello", "68" ), // AI - std::make_pair( "Level", "61" ), - std::make_pair( "PC Acrobatics", "31" ), - std::make_pair( "PC Agility", "53" ), // attrib - std::make_pair( "PC Alchemy", "27" ), - std::make_pair( "PC Alteration", "22" ), - std::make_pair( "PC Armoror", "12" ), - std::make_pair( "PC Athletics", "19" ), - std::make_pair( "PC Axe", "17" ), - std::make_pair( "PC Blight Disease", "41" ), - std::make_pair( "PC Block", "11" ), - std::make_pair( "PC Blunt Weapon", "15" ), - std::make_pair( "PC Clothing Modifier", "42" ), - std::make_pair( "PC Common Disease", "40" ), - std::make_pair( "PC Conjuration", "24" ), - std::make_pair( "PC Corpus", "58" ), - std::make_pair( "PC Crime Level", "43" ), - std::make_pair( "PC Destruction", "21" ), - std::make_pair( "PC Enchant", "20" ), - std::make_pair( "PC Endurance", "55" ), // attrib - std::make_pair( "PC Expelled", "39" ), - std::make_pair( "PC Fatigue", "09" ), // dynamic stat - std::make_pair( "PC Hand To Hand", "37" ), - std::make_pair( "PC Health", "64" ), // dynamic stat - std::make_pair( "PC Health Percent", "07" ), - std::make_pair( "PC Heavy Armor", "14" ), - std::make_pair( "PC Illusion", "23" ), - std::make_pair( "PC Intelligence", "51" ), // attrib - std::make_pair( "PC Level", "06" ), - std::make_pair( "PC Light Armor", "32" ), - std::make_pair( "PC Long Blade", "16" ), - std::make_pair( "PC Luck", "57" ), // attrib - std::make_pair( "PC Magicka", "08" ), // dynamic stat - std::make_pair( "PC Marksman", "34" ), - std::make_pair( "PC Medium Armor", "13" ), - std::make_pair( "PC Merchantile", "35" ), - std::make_pair( "PC Mysticism", "25" ), - std::make_pair( "PC Personality", "56" ), // attrib - std::make_pair( "PC Reputation", "05" ), - std::make_pair( "PC Restoration", "26" ), - std::make_pair( "PC Security", "29" ), - std::make_pair( "PC Sex", "38" ), - std::make_pair( "PC Short Blade", "33" ), - std::make_pair( "PC Sneak", "30" ), - std::make_pair( "PC Spear", "18" ), - std::make_pair( "PC Speechcraft", "36" ), - std::make_pair( "PC Speed", "54" ), // attrib - std::make_pair( "PC Strength", "10" ), // attrib - std::make_pair( "PC Unarmored", "28" ), - std::make_pair( "PC Vampire", "60" ), - std::make_pair( "PC Werewolf Kills", "73" ), - std::make_pair( "PC Willpower", "52" ), // attrib - std::make_pair( "Rank Requirement", "02" ), - std::make_pair( "Rank High", "01" ), - std::make_pair( "Rank Low", "00" ), - std::make_pair( "Reputation", "03" ), - std::make_pair( "Same Faction", "46" ), - std::make_pair( "Same Race", "45" ), - std::make_pair( "Same Sex", "44" ), - std::make_pair( "Should Attack", "71" ), - std::make_pair( "Talked To PC", "63" ), - std::make_pair( "Weather", "59" ), - std::make_pair( "Werewolf", "72" ) + { "Alarm", "69" }, // AI + { "Alarmed", "49" }, + { "Attacked", "62" }, + { "Choice", "50" }, + { "Creature Target", "65" }, + { "Detected", "48" }, + { "Faction Rank Difference", "47" }, + { "Fight", "67" }, // AI + { "Flee", "70" }, // AI + { "Friend Hit", "66" }, + { "Health Percent", "04" }, + { "Hello", "68" }, // AI + { "Level", "61" }, + { "PC Acrobatics", "31" }, + { "PC Agility", "53" }, // attrib + { "PC Alchemy", "27" }, + { "PC Alteration", "22" }, + { "PC Armoror", "12" }, + { "PC Athletics", "19" }, + { "PC Axe", "17" }, + { "PC Blight Disease", "41" }, + { "PC Block", "11" }, + { "PC Blunt Weapon", "15" }, + { "PC Clothing Modifier", "42" }, + { "PC Common Disease", "40" }, + { "PC Conjuration", "24" }, + { "PC Corpus", "58" }, + { "PC Crime Level", "43" }, + { "PC Destruction", "21" }, + { "PC Enchant", "20" }, + { "PC Endurance", "55" }, // attrib + { "PC Expelled", "39" }, + { "PC Fatigue", "09" }, // dynamic stat + { "PC Hand To Hand", "37" }, + { "PC Health", "64" }, // dynamic stat + { "PC Health Percent", "07" }, + { "PC Heavy Armor", "14" }, + { "PC Illusion", "23" }, + { "PC Intelligence", "51" }, // attrib + { "PC Level", "06" }, + { "PC Light Armor", "32" }, + { "PC Long Blade", "16" }, + { "PC Luck", "57" }, // attrib + { "PC Magicka", "08" }, // dynamic stat + { "PC Marksman", "34" }, + { "PC Medium Armor", "13" }, + { "PC Merchantile", "35" }, + { "PC Mysticism", "25" }, + { "PC Personality", "56" }, // attrib + { "PC Reputation", "05" }, + { "PC Restoration", "26" }, + { "PC Security", "29" }, + { "PC Sex", "38" }, + { "PC Short Blade", "33" }, + { "PC Sneak", "30" }, + { "PC Spear", "18" }, + { "PC Speechcraft", "36" }, + { "PC Speed", "54" }, // attrib + { "PC Strength", "10" }, // attrib + { "PC Unarmored", "28" }, + { "PC Vampire", "60" }, + { "PC Werewolf Kills", "73" }, + { "PC Willpower", "52" }, // attrib + { "Rank Requirement", "02" }, + { "Rank High", "01" }, + { "Rank Low", "00" }, + { "Reputation", "03" }, + { "Same Faction", "46" }, + { "Same Race", "45" }, + { "Same Sex", "44" }, + { "Should Attack", "71" }, + { "Talked To PC", "63" }, + { "Weather", "59" }, + { "Werewolf", "72" } }; void InfoConditionAdapter::setData(Record& record, From 5fb269336f3d7e78588141a0d21bba15b55db76e Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 10 May 2015 07:02:08 +1000 Subject: [PATCH 068/142] Don't use initializer list --- .../model/world/nestedcoladapterimp.cpp | 312 +++++++++--------- 1 file changed, 159 insertions(+), 153 deletions(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index f1088829ed..8ee4af2f8a 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -590,83 +590,86 @@ namespace CSMWorld // See the mappings in MWDialogue::SelectWrapper::getArgument // from ESM::Attribute, ESM::Skill and MWMechanics::CreatureStats (for AI) - const std::map sEncToInfoFunc = + static std::map populateEncToInfoFunc() { - { "00", "Rank Low" }, - { "01", "Rank High" }, - { "02", "Rank Requirement" }, - { "03", "Reputation" }, - { "04", "Health Percent" }, - { "05", "PC Reputation" }, - { "06", "PC Level" }, - { "07", "PC Health Percent" }, - { "08", "PC Magicka" }, // dynamic stat - { "09", "PC Fatigue" }, // dynamic stat - { "10", "PC Strength" }, // attrib - { "11", "PC Block" }, - { "12", "PC Armoror" }, - { "13", "PC Medium Armor" }, - { "14", "PC Heavy Armor" }, - { "15", "PC Blunt Weapon" }, - { "16", "PC Long Blade" }, - { "17", "PC Axe" }, - { "18", "PC Spear" }, - { "19", "PC Athletics" }, - { "20", "PC Enchant" }, - { "21", "PC Destruction" }, - { "22", "PC Alteration" }, - { "23", "PC Illusion" }, - { "24", "PC Conjuration" }, - { "25", "PC Mysticism" }, - { "26", "PC Restoration" }, - { "27", "PC Alchemy" }, - { "28", "PC Unarmored" }, - { "29", "PC Security" }, - { "30", "PC Sneak" }, - { "31", "PC Acrobatics" }, - { "32", "PC Light Armor" }, - { "33", "PC Short Blade" }, - { "34", "PC Marksman" }, - { "35", "PC Merchantile" }, - { "36", "PC Speechcraft" }, - { "37", "PC Hand To Hand" }, - { "38", "PC Sex" }, - { "39", "PC Expelled" }, - { "40", "PC Common Disease" }, - { "41", "PC Blight Disease" }, - { "42", "PC Clothing Modifier" }, - { "43", "PC Crime Level" }, - { "44", "Same Sex" }, - { "45", "Same Race" }, - { "46", "Same Faction" }, - { "47", "Faction Rank Difference" }, - { "48", "Detected" }, - { "49", "Alarmed" }, - { "50", "Choice" }, - { "51", "PC Intelligence" }, // attrib - { "52", "PC Willpower" }, // attrib - { "53", "PC Agility" }, // attrib - { "54", "PC Speed" }, // attrib - { "55", "PC Endurance" }, // attrib - { "56", "PC Personality" }, // attrib - { "57", "PC Luck" }, // attrib - { "58", "PC Corpus" }, - { "59", "Weather" }, - { "60", "PC Vampire" }, - { "61", "Level" }, - { "62", "Attacked" }, - { "63", "Talked To PC" }, - { "64", "PC Health" }, // dynamic stat - { "65", "Creature Target" }, - { "66", "Friend Hit" }, - { "67", "Fight" }, // AI - { "68", "Hello" }, // AI - { "69", "Alarm" }, // AI - { "70", "Flee" }, // AI - { "71", "Should Attack" }, - { "72", "Werewolf" }, - { "73", "PC Werewolf Kills" } - }; + std::map funcMap; + funcMap["00"] = "Rank Low"; + funcMap["01"] = "Rank High"; + funcMap["02"] = "Rank Requirement"; + funcMap["03"] = "Reputation"; + funcMap["04"] = "Health Percent"; + funcMap["05"] = "PC Reputation"; + funcMap["06"] = "PC Level"; + funcMap["07"] = "PC Health Percent"; + funcMap["08"] = "PC Magicka"; + funcMap["09"] = "PC Fatigue"; + funcMap["10"] = "PC Strength"; + funcMap["11"] = "PC Block"; + funcMap["12"] = "PC Armoror"; + funcMap["13"] = "PC Medium Armor"; + funcMap["14"] = "PC Heavy Armor"; + funcMap["15"] = "PC Blunt Weapon"; + funcMap["16"] = "PC Long Blade"; + funcMap["17"] = "PC Axe"; + funcMap["18"] = "PC Spear"; + funcMap["19"] = "PC Athletics"; + funcMap["20"] = "PC Enchant"; + funcMap["21"] = "PC Destruction"; + funcMap["22"] = "PC Alteration"; + funcMap["23"] = "PC Illusion"; + funcMap["24"] = "PC Conjuration"; + funcMap["25"] = "PC Mysticism"; + funcMap["26"] = "PC Restoration"; + funcMap["27"] = "PC Alchemy"; + funcMap["28"] = "PC Unarmored"; + funcMap["29"] = "PC Security"; + funcMap["30"] = "PC Sneak"; + funcMap["31"] = "PC Acrobatics"; + funcMap["32"] = "PC Light Armor"; + funcMap["33"] = "PC Short Blade"; + funcMap["34"] = "PC Marksman"; + funcMap["35"] = "PC Merchantile"; + funcMap["36"] = "PC Speechcraft"; + funcMap["37"] = "PC Hand To Hand"; + funcMap["38"] = "PC Sex"; + funcMap["39"] = "PC Expelled"; + funcMap["40"] = "PC Common Disease"; + funcMap["41"] = "PC Blight Disease"; + funcMap["42"] = "PC Clothing Modifier"; + funcMap["43"] = "PC Crime Level"; + funcMap["44"] = "Same Sex"; + funcMap["45"] = "Same Race"; + funcMap["46"] = "Same Faction"; + funcMap["47"] = "Faction Rank Difference"; + funcMap["48"] = "Detected"; + funcMap["49"] = "Alarmed"; + funcMap["50"] = "Choice"; + funcMap["51"] = "PC Intelligence"; + funcMap["52"] = "PC Willpower"; + funcMap["53"] = "PC Agility"; + funcMap["54"] = "PC Speed"; + funcMap["55"] = "PC Endurance"; + funcMap["56"] = "PC Personality"; + funcMap["57"] = "PC Luck"; + funcMap["58"] = "PC Corpus"; + funcMap["59"] = "Weather"; + funcMap["60"] = "PC Vampire"; + funcMap["61"] = "Level"; + funcMap["62"] = "Attacked"; + funcMap["63"] = "Talked To PC"; + funcMap["64"] = "PC Health"; + funcMap["65"] = "Creature Target"; + funcMap["66"] = "Friend Hit"; + funcMap["67"] = "Fight"; + funcMap["68"] = "Hello"; + funcMap["69"] = "Alarm"; + funcMap["70"] = "Flee"; + funcMap["71"] = "Should Attack"; + funcMap["72"] = "Werewolf"; + funcMap["73"] = "PC Werewolf Kills"; + return funcMap; + } + static const std::map sEncToInfoFunc = populateEncToInfoFunc(); QVariant InfoConditionAdapter::getData(const Record& record, int subRowIndex, int subColIndex) const @@ -749,83 +752,86 @@ namespace CSMWorld } } - const std::map sInfoFuncToEnc = + static std::map populateInfoFuncToEnc() { - { "Alarm", "69" }, // AI - { "Alarmed", "49" }, - { "Attacked", "62" }, - { "Choice", "50" }, - { "Creature Target", "65" }, - { "Detected", "48" }, - { "Faction Rank Difference", "47" }, - { "Fight", "67" }, // AI - { "Flee", "70" }, // AI - { "Friend Hit", "66" }, - { "Health Percent", "04" }, - { "Hello", "68" }, // AI - { "Level", "61" }, - { "PC Acrobatics", "31" }, - { "PC Agility", "53" }, // attrib - { "PC Alchemy", "27" }, - { "PC Alteration", "22" }, - { "PC Armoror", "12" }, - { "PC Athletics", "19" }, - { "PC Axe", "17" }, - { "PC Blight Disease", "41" }, - { "PC Block", "11" }, - { "PC Blunt Weapon", "15" }, - { "PC Clothing Modifier", "42" }, - { "PC Common Disease", "40" }, - { "PC Conjuration", "24" }, - { "PC Corpus", "58" }, - { "PC Crime Level", "43" }, - { "PC Destruction", "21" }, - { "PC Enchant", "20" }, - { "PC Endurance", "55" }, // attrib - { "PC Expelled", "39" }, - { "PC Fatigue", "09" }, // dynamic stat - { "PC Hand To Hand", "37" }, - { "PC Health", "64" }, // dynamic stat - { "PC Health Percent", "07" }, - { "PC Heavy Armor", "14" }, - { "PC Illusion", "23" }, - { "PC Intelligence", "51" }, // attrib - { "PC Level", "06" }, - { "PC Light Armor", "32" }, - { "PC Long Blade", "16" }, - { "PC Luck", "57" }, // attrib - { "PC Magicka", "08" }, // dynamic stat - { "PC Marksman", "34" }, - { "PC Medium Armor", "13" }, - { "PC Merchantile", "35" }, - { "PC Mysticism", "25" }, - { "PC Personality", "56" }, // attrib - { "PC Reputation", "05" }, - { "PC Restoration", "26" }, - { "PC Security", "29" }, - { "PC Sex", "38" }, - { "PC Short Blade", "33" }, - { "PC Sneak", "30" }, - { "PC Spear", "18" }, - { "PC Speechcraft", "36" }, - { "PC Speed", "54" }, // attrib - { "PC Strength", "10" }, // attrib - { "PC Unarmored", "28" }, - { "PC Vampire", "60" }, - { "PC Werewolf Kills", "73" }, - { "PC Willpower", "52" }, // attrib - { "Rank Requirement", "02" }, - { "Rank High", "01" }, - { "Rank Low", "00" }, - { "Reputation", "03" }, - { "Same Faction", "46" }, - { "Same Race", "45" }, - { "Same Sex", "44" }, - { "Should Attack", "71" }, - { "Talked To PC", "63" }, - { "Weather", "59" }, - { "Werewolf", "72" } - }; + std::map encMap; + encMap["Alarm"] = "69"; // AI + encMap["Alarmed"] = "49"; + encMap["Attacked"] = "62"; + encMap["Choice"] = "50"; + encMap["Creature Target"] = "65"; + encMap["Detected"] = "48"; + encMap["Faction Rank Difference"] ="47"; + encMap["Fight"] = "67"; // AI + encMap["Flee"] = "70"; // AI + encMap["Friend Hit"] = "66"; + encMap["Health Percent"] = "04"; + encMap["Hello"] = "68"; // AI + encMap["Level"] = "61"; + encMap["PC Acrobatics"] = "31"; + encMap["PC Agility"] = "53"; // attrib + encMap["PC Alchemy"] = "27"; + encMap["PC Alteration"] = "22"; + encMap["PC Armoror"] = "12"; + encMap["PC Athletics"] = "19"; + encMap["PC Axe"] = "17"; + encMap["PC Blight Disease"] = "41"; + encMap["PC Block"] = "11"; + encMap["PC Blunt Weapon"] = "15"; + encMap["PC Clothing Modifier"] = "42"; + encMap["PC Common Disease"] = "40"; + encMap["PC Conjuration"] = "24"; + encMap["PC Corpus"] = "58"; + encMap["PC Crime Level"] = "43"; + encMap["PC Destruction"] = "21"; + encMap["PC Enchant"] = "20"; + encMap["PC Endurance"] = "55"; // attrib + encMap["PC Expelled"] = "39"; + encMap["PC Fatigue"] = "09"; // dynamic stat + encMap["PC Hand To Hand"] = "37"; + encMap["PC Health"] = "64"; // dynamic stat + encMap["PC Health Percent"] = "07"; + encMap["PC Heavy Armor"] = "14"; + encMap["PC Illusion"] = "23"; + encMap["PC Intelligence"] = "51"; // attrib + encMap["PC Level"] = "06"; + encMap["PC Light Armor"] = "32"; + encMap["PC Long Blade"] = "16"; + encMap["PC Luck"] = "57"; // attrib + encMap["PC Magicka"] = "08"; // dynamic stat + encMap["PC Marksman"] = "34"; + encMap["PC Medium Armor"] = "13"; + encMap["PC Merchantile"] = "35"; + encMap["PC Mysticism"] = "25"; + encMap["PC Personality"] = "56"; // attrib + encMap["PC Reputation"] = "05"; + encMap["PC Restoration"] = "26"; + encMap["PC Security"] = "29"; + encMap["PC Sex"] = "38"; + encMap["PC Short Blade"] = "33"; + encMap["PC Sneak"] = "30"; + encMap["PC Spear"] = "18"; + encMap["PC Speechcraft"] = "36"; + encMap["PC Speed"] = "54"; // attrib + encMap["PC Strength"] = "10"; // attrib + encMap["PC Unarmored"] = "28"; + encMap["PC Vampire"] = "60"; + encMap["PC Werewolf Kills"] = "73"; + encMap["PC Willpower"] = "52"; // attrib + encMap["Rank Requirement"] = "02"; + encMap["Rank High"] = "01"; + encMap["Rank Low"] = "00"; + encMap["Reputation"] = "03"; + encMap["Same Faction"] = "46"; + encMap["Same Race"] = "45"; + encMap["Same Sex"] = "44"; + encMap["Should Attack"] = "71"; + encMap["Talked To PC"] = "63"; + encMap["Weather"] = "59"; + encMap["Werewolf"] = "72"; + return encMap; + } + static const std::map sInfoFuncToEnc = populateInfoFuncToEnc(); void InfoConditionAdapter::setData(Record& record, const QVariant& value, int subRowIndex, int subColIndex) const @@ -867,7 +873,7 @@ namespace CSMWorld if (conditions[subRowIndex].mSelectRule[1] == '1') { // throws an exception if the function is not found - const std::map::const_iterator it = sInfoFuncToEnc.find( + const std::map::const_iterator it = sInfoFuncToEnc.find( value.toString().toUtf8().constData()); if (it != sInfoFuncToEnc.end()) { From 587efcfe9db6f2fa6194971368b256cd006c1b49 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 10 May 2015 07:49:18 +1000 Subject: [PATCH 069/142] Use better initial value type. Fix exception while saving values. --- apps/opencs/model/world/nestedcoladapterimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 8ee4af2f8a..8c62fb59b4 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -551,6 +551,7 @@ namespace CSMWorld ESM::DialInfo::SelectStruct condStruct; condStruct.mSelectRule = "00000"; condStruct.mValue = ESM::Variant(); + condStruct.mValue.setType(ESM::VT_Int); // default to ints conditions.insert(conditions.begin()+position, condStruct); @@ -688,6 +689,7 @@ namespace CSMWorld char condType = conditions[subRowIndex].mSelectRule[1]; switch (condType) { + case '0': return 0; // blank space case '1': return 1; // Function case '2': return 2; // Global case '3': return 3; // Local @@ -931,6 +933,7 @@ namespace CSMWorld } default: break; } + break; } default: throw std::runtime_error("Info condition subcolumn index out of range"); } From ab21c0551c6f5c3ccb63f6f2670a5f39c2c4294a Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 10 May 2015 13:34:45 +1000 Subject: [PATCH 070/142] Provide a default encoding when changing to "Function". --- apps/opencs/model/world/nestedcoladapterimp.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 8c62fb59b4..4c720ba24d 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -854,7 +854,14 @@ namespace CSMWorld { // FIXME: when these change the values of the other columns need to change // correspondingly (and automatically) - case 1: conditions[subRowIndex].mSelectRule[1] = '1'; break; // Function + case 1: + { + conditions[subRowIndex].mSelectRule[1] = '1'; // Function + // default to "Rank Low" + conditions[subRowIndex].mSelectRule[2] = '0'; + conditions[subRowIndex].mSelectRule[3] = '0'; + break; + } case 2: conditions[subRowIndex].mSelectRule[1] = '2'; break; // Global case 3: conditions[subRowIndex].mSelectRule[1] = '3'; break; // Local case 4: conditions[subRowIndex].mSelectRule[1] = '4'; break; // Journal @@ -874,7 +881,6 @@ namespace CSMWorld { if (conditions[subRowIndex].mSelectRule[1] == '1') { - // throws an exception if the function is not found const std::map::const_iterator it = sInfoFuncToEnc.find( value.toString().toUtf8().constData()); if (it != sInfoFuncToEnc.end()) From 8e35ad54bd280a7a540624b1ce6c6267c79ee007 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 10 May 2015 11:17:52 +0200 Subject: [PATCH 071/142] temporarily remove the test for bullet version --- libs/openengine/bullet/physic.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 22312e3bc9..c0da03651a 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -475,9 +475,9 @@ namespace Physic btCollisionShape* collisionShape = raycasting ? shape->mRaycastingShape : shape->mCollisionShape; // TODO: check this from cmake? -#if BT_BULLET_VERSION < 283 -#error "Bullet version 2.83 or later required" -#endif +//#if BT_BULLET_VERSION < 283 +//#error "Bullet version 2.83 or later required" +//#endif bool needDelete = false; if (btBvhTriangleMeshShape* triangleShape = dynamic_cast(shape->mCollisionShape)) From 2b84598e852694650d2fbe8886e7fea31131c793 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 10 May 2015 20:52:29 +1000 Subject: [PATCH 072/142] Remove duplicated but reversed map. --- .../model/world/nestedcoladapterimp.cpp | 102 +++--------------- 1 file changed, 13 insertions(+), 89 deletions(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 4c720ba24d..a0d7645767 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -754,87 +754,6 @@ namespace CSMWorld } } - static std::map populateInfoFuncToEnc() - { - std::map encMap; - encMap["Alarm"] = "69"; // AI - encMap["Alarmed"] = "49"; - encMap["Attacked"] = "62"; - encMap["Choice"] = "50"; - encMap["Creature Target"] = "65"; - encMap["Detected"] = "48"; - encMap["Faction Rank Difference"] ="47"; - encMap["Fight"] = "67"; // AI - encMap["Flee"] = "70"; // AI - encMap["Friend Hit"] = "66"; - encMap["Health Percent"] = "04"; - encMap["Hello"] = "68"; // AI - encMap["Level"] = "61"; - encMap["PC Acrobatics"] = "31"; - encMap["PC Agility"] = "53"; // attrib - encMap["PC Alchemy"] = "27"; - encMap["PC Alteration"] = "22"; - encMap["PC Armoror"] = "12"; - encMap["PC Athletics"] = "19"; - encMap["PC Axe"] = "17"; - encMap["PC Blight Disease"] = "41"; - encMap["PC Block"] = "11"; - encMap["PC Blunt Weapon"] = "15"; - encMap["PC Clothing Modifier"] = "42"; - encMap["PC Common Disease"] = "40"; - encMap["PC Conjuration"] = "24"; - encMap["PC Corpus"] = "58"; - encMap["PC Crime Level"] = "43"; - encMap["PC Destruction"] = "21"; - encMap["PC Enchant"] = "20"; - encMap["PC Endurance"] = "55"; // attrib - encMap["PC Expelled"] = "39"; - encMap["PC Fatigue"] = "09"; // dynamic stat - encMap["PC Hand To Hand"] = "37"; - encMap["PC Health"] = "64"; // dynamic stat - encMap["PC Health Percent"] = "07"; - encMap["PC Heavy Armor"] = "14"; - encMap["PC Illusion"] = "23"; - encMap["PC Intelligence"] = "51"; // attrib - encMap["PC Level"] = "06"; - encMap["PC Light Armor"] = "32"; - encMap["PC Long Blade"] = "16"; - encMap["PC Luck"] = "57"; // attrib - encMap["PC Magicka"] = "08"; // dynamic stat - encMap["PC Marksman"] = "34"; - encMap["PC Medium Armor"] = "13"; - encMap["PC Merchantile"] = "35"; - encMap["PC Mysticism"] = "25"; - encMap["PC Personality"] = "56"; // attrib - encMap["PC Reputation"] = "05"; - encMap["PC Restoration"] = "26"; - encMap["PC Security"] = "29"; - encMap["PC Sex"] = "38"; - encMap["PC Short Blade"] = "33"; - encMap["PC Sneak"] = "30"; - encMap["PC Spear"] = "18"; - encMap["PC Speechcraft"] = "36"; - encMap["PC Speed"] = "54"; // attrib - encMap["PC Strength"] = "10"; // attrib - encMap["PC Unarmored"] = "28"; - encMap["PC Vampire"] = "60"; - encMap["PC Werewolf Kills"] = "73"; - encMap["PC Willpower"] = "52"; // attrib - encMap["Rank Requirement"] = "02"; - encMap["Rank High"] = "01"; - encMap["Rank Low"] = "00"; - encMap["Reputation"] = "03"; - encMap["Same Faction"] = "46"; - encMap["Same Race"] = "45"; - encMap["Same Sex"] = "44"; - encMap["Should Attack"] = "71"; - encMap["Talked To PC"] = "63"; - encMap["Weather"] = "59"; - encMap["Werewolf"] = "72"; - return encMap; - } - static const std::map sInfoFuncToEnc = populateInfoFuncToEnc(); - void InfoConditionAdapter::setData(Record& record, const QVariant& value, int subRowIndex, int subColIndex) const { @@ -881,16 +800,21 @@ namespace CSMWorld { if (conditions[subRowIndex].mSelectRule[1] == '1') { - const std::map::const_iterator it = sInfoFuncToEnc.find( - value.toString().toUtf8().constData()); - if (it != sInfoFuncToEnc.end()) + std::map::const_iterator it = sEncToInfoFunc.begin(); + for (;it != sEncToInfoFunc.end(); ++it) { - std::string rule = conditions[subRowIndex].mSelectRule.substr(0, 2); - rule.append(it->second); - rule.append(std::string(1, conditions[subRowIndex].mSelectRule[4])); - conditions[subRowIndex].mSelectRule = rule.append(value.toString().toUtf8().constData()); + if (it->second == value.toString().toUtf8().constData()) + { + std::string rule = conditions[subRowIndex].mSelectRule.substr(0, 2); + rule.append(it->first); + // leave old values for undo (NOTE: may not be vanilla's behaviour) + rule.append(conditions[subRowIndex].mSelectRule.substr(4)); + conditions[subRowIndex].mSelectRule = rule; + break; + } } - else + + if (it == sEncToInfoFunc.end()) return; // return without saving; TODO: maybe log an error here } else From e4ffb985a153b1b4cc3a1c6c44ce4ba27d7b7170 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 10 May 2015 13:32:01 +0200 Subject: [PATCH 073/142] Revert "Collision fix" This reverts commit 60fffec3452c68ef2675a7c573af0436c051a6d4. --- libs/openengine/bullet/physic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index cf7dea1db0..c0da03651a 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -480,7 +480,7 @@ namespace Physic //#endif bool needDelete = false; - if (btBvhTriangleMeshShape* triangleShape = dynamic_cast(collisionShape)) + if (btBvhTriangleMeshShape* triangleShape = dynamic_cast(shape->mCollisionShape)) { btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(triangleShape, btVector3(scale,scale,scale)); collisionShape = scaled; From 107bf818e726827ee57856462c04a4403ed13f17 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 10 May 2015 13:35:21 +0200 Subject: [PATCH 074/142] Revert "Use btScaledBvhTriangleMeshShape, bump required bullet version to 2.83" This reverts commit 27751db99afae9368fc29fabbe0bbedb980c3ace. Conflicts: libs/openengine/bullet/physic.cpp --- components/nifbullet/bulletnifloader.cpp | 4 +-- libs/openengine/bullet/physic.cpp | 32 +++++++----------------- libs/openengine/bullet/physic.hpp | 3 --- 3 files changed, 11 insertions(+), 28 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 3207af0fe8..93c9797b25 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -123,7 +123,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) mCompoundShape = NULL; mStaticMesh = NULL; - Nif::NIFFilePtr pnif (Nif::Cache::getInstance().load(mResourceName)); + Nif::NIFFilePtr pnif (Nif::Cache::getInstance().load(mResourceName.substr(0, mResourceName.length()-7))); Nif::NIFFile & nif = *pnif.get (); if (nif.numRoots() < 1) { @@ -134,7 +134,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) // Have to load controlled nodes from the .kf // FIXME: the .kf has to be loaded both for rendering and physics, ideally it should be opened once and then reused mControlledNodes.clear(); - std::string kfname = mResourceName; + std::string kfname = mResourceName.substr(0, mResourceName.length()-7); Misc::StringUtils::toLower(kfname); if(kfname.size() > 4 && kfname.compare(kfname.size()-4, 4, ".nif") == 0) kfname.replace(kfname.size()-4, 4, ".kf"); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index c0da03651a..15be7665a8 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -455,7 +455,8 @@ namespace Physic float scale, const Ogre::Vector3 &position, const Ogre::Quaternion &rotation, Ogre::Vector3* scaledBoxTranslation, Ogre::Quaternion* boxRotation, bool raycasting, bool placeable) { - std::string outputstring = mesh; + std::string sid = (boost::format("%07.3f") % scale).str(); + std::string outputstring = mesh + sid; //get the shape from the .nif mShapeLoader->load(outputstring,"General"); @@ -474,35 +475,20 @@ namespace Physic btCollisionShape* collisionShape = raycasting ? shape->mRaycastingShape : shape->mCollisionShape; -// TODO: check this from cmake? -//#if BT_BULLET_VERSION < 283 -//#error "Bullet version 2.83 or later required" -//#endif + // If this is an animated compound shape, we must duplicate it so we can animate + // multiple instances independently. + if (!raycasting && !shape->mAnimatedShapes.empty()) + collisionShape = duplicateCollisionShape(collisionShape); + if (raycasting && !shape->mAnimatedRaycastingShapes.empty()) + collisionShape = duplicateCollisionShape(collisionShape); - bool needDelete = false; - if (btBvhTriangleMeshShape* triangleShape = dynamic_cast(shape->mCollisionShape)) - { - btScaledBvhTriangleMeshShape* scaled = new btScaledBvhTriangleMeshShape(triangleShape, btVector3(scale,scale,scale)); - collisionShape = scaled; - needDelete = true; - } - else - { - // If this is an animated compound shape, we must duplicate it so we can animate - // multiple instances independently. - if (!raycasting && !shape->mAnimatedShapes.empty()) - collisionShape = duplicateCollisionShape(collisionShape); - if (raycasting && !shape->mAnimatedRaycastingShapes.empty()) - collisionShape = duplicateCollisionShape(collisionShape); - } + collisionShape->setLocalScaling( btVector3(scale,scale,scale)); //create the real body btRigidBody::btRigidBodyConstructionInfo CI = btRigidBody::btRigidBodyConstructionInfo (0,0, collisionShape); RigidBody* body = new RigidBody(CI,name); body->mPlaceable = placeable; - if (needDelete) - body->mCollisionShape.reset(collisionShape); if (!raycasting && !shape->mAnimatedShapes.empty()) { diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 7b0906694b..7784e8941d 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -63,9 +63,6 @@ namespace Physic virtual ~RigidBody(); std::string mName; - // May be empty if the collision shape is a shared resource - std::auto_ptr mCollisionShape; - // Hack: placeable objects (that can be picked up by the player) have different collision behaviour. // This variable needs to be passed to BulletNifLoader. bool mPlaceable; From ca53457a1c572851491fe8d6e1238ee5bd608ae5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 May 2015 01:46:34 +0200 Subject: [PATCH 075/142] Correct the map icons used for detect spells (Fixes #2519) --- apps/openmw/mwgui/mapwindow.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 02e8ffdfed..269b43a71f 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -468,21 +468,17 @@ namespace MWGui return; std::string markerTexture; - MyGUI::Colour markerColour; if (type == MWBase::World::Detect_Creature) { - markerTexture = "textures\\menu_map_dcreature.dds"; - markerColour = MyGUI::Colour(1,0,0,1); + markerTexture = "textures\\detect_animal_icon.dds"; } if (type == MWBase::World::Detect_Key) { - markerTexture = "textures\\menu_map_dkey.dds"; - markerColour = MyGUI::Colour(0,1,0,1); + markerTexture = "textures\\detect_key_icon.dds"; } if (type == MWBase::World::Detect_Enchantment) { - markerTexture = "textures\\menu_map_dmagic.dds"; - markerColour = MyGUI::Colour(0,0,1,1); + markerTexture = "textures\\detect_enchantment_icon.dds"; } int counter = 0; @@ -499,7 +495,7 @@ namespace MWGui widgetCoord, MyGUI::Align::Default); markerWidget->setDepth(Local_MarkerAboveFogLayer); markerWidget->setImageTexture(markerTexture); - markerWidget->setColour(markerColour); + markerWidget->setImageCoord(MyGUI::IntCoord(0,0,8,8)); markerWidget->setNeedMouseFocus(false); mMagicMarkerWidgets.push_back(markerWidget); } From 033719ccd70db35d3d67d4d707bb2de3c4c184b4 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 May 2015 02:11:35 +0200 Subject: [PATCH 076/142] Correct the icon used for custom map markers --- apps/openmw/mwgui/mapwindow.cpp | 12 ++++++------ files/mygui/openmw_resources.xml | 9 +++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 269b43a71f..9adfeffe88 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -300,17 +300,17 @@ namespace MWGui MarkerUserData markerPos; MyGUI::IntPoint widgetPos = getMarkerPosition(marker.mWorldX, marker.mWorldY, markerPos); - MyGUI::IntCoord widgetCoord(widgetPos.left - 4, - widgetPos.top - 4, - 8, 8); - MarkerWidget* markerWidget = mLocalMap->createWidget("MarkerButton", + MyGUI::IntCoord widgetCoord(widgetPos.left - 8, + widgetPos.top - 8, + 16, 16); + MarkerWidget* markerWidget = mLocalMap->createWidget("CustomMarkerButton", widgetCoord, MyGUI::Align::Default); markerWidget->setDepth(Local_MarkerAboveFogLayer); markerWidget->setUserString("ToolTipType", "Layout"); markerWidget->setUserString("ToolTipLayout", "TextToolTipOneLine"); markerWidget->setUserString("Caption_TextOneLine", MyGUI::TextIterator::toTagsString(marker.mNote)); - markerWidget->setNormalColour(MyGUI::Colour(1.0f, 0.3f, 0.3f)); - markerWidget->setHoverColour(MyGUI::Colour(1.0f, 0.5f, 0.5f)); + markerWidget->setNormalColour(MyGUI::Colour(0.6f, 0.6f, 0.6f)); + markerWidget->setHoverColour(MyGUI::Colour(1.0f, 1.0f, 1.0f)); markerWidget->setUserData(marker); markerWidget->setNeedMouseFocus(true); customMarkerCreated(markerWidget); diff --git a/files/mygui/openmw_resources.xml b/files/mygui/openmw_resources.xml index 423281a621..305cb0c0da 100644 --- a/files/mygui/openmw_resources.xml +++ b/files/mygui/openmw_resources.xml @@ -31,6 +31,15 @@ + + + + + + + + + From b312f50b1f609355011fc89763df6aeeec0ab8cf Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 6 May 2015 02:12:55 +0200 Subject: [PATCH 077/142] Fix regression with detect spells detecting deleted objects (Fixes #2518) --- apps/openmw/mwworld/worldimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 013386f8f9..0f81106248 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2956,7 +2956,7 @@ namespace MWWorld Ogre::Vector3(mDetector.getRefData().getPosition().pos)) >= mSquaredDist) return true; - if (!ptr.getRefData().isEnabled()) + if (!ptr.getRefData().isEnabled() || ptr.getRefData().isDeleted()) return true; // Consider references inside containers as well (except if we are looking for a Creature, they cannot be in containers) From eef8f717973d69f1242db16db4517156d37f1d77 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 7 May 2015 16:46:59 +0200 Subject: [PATCH 078/142] Add a comment --- apps/openmw/mwworld/cellstore.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwworld/cellstore.hpp b/apps/openmw/mwworld/cellstore.hpp index d7036d6b19..672b6046b6 100644 --- a/apps/openmw/mwworld/cellstore.hpp +++ b/apps/openmw/mwworld/cellstore.hpp @@ -120,6 +120,7 @@ namespace MWWorld /// Call functor (ref) for each reference. functor must return a bool. Returning /// false will abort the iteration. + /// \attention This function also lists deleted (count 0) objects! /// \return Iteration completed? /// /// \note Creatures and NPCs are handled last. From 3b8b217888469c839c53ca4945deaeb88ac4d6bf Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 8 May 2015 02:22:39 +0200 Subject: [PATCH 079/142] Fix no punishment for stealing when taking an item with the inventory opened --- apps/openmw/mwgui/inventorywindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 80b246e840..9aa8a8ea1d 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -594,6 +594,8 @@ namespace MWGui MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWBase::Environment::get().getWorld()->breakInvisibility(player); + MWBase::Environment::get().getMechanicsManager()->itemTaken(player, object, MWWorld::Ptr(), count); + // add to player inventory // can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object MWWorld::Ptr newObject = *player.getClass().getContainerStore (player).add (object, object.getRefData().getCount(), player); @@ -612,8 +614,6 @@ namespace MWGui throw std::runtime_error("Added item not found"); mDragAndDrop->startDrag(i, mSortModel, mTradeModel, mItemView, count); - MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, MWWorld::Ptr(), count); - MWBase::Environment::get().getWindowManager()->updateSpellWindow(); } From ac88326909d80223815a84743578a0c2adcbb583 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 8 May 2015 23:57:23 +0200 Subject: [PATCH 080/142] Exit out of choice when no responses are found (Fixes #2525) --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index b928738ddd..0b9fd65d20 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -485,6 +485,12 @@ namespace MWDialogue executeScript (info->mResultScript); } + else + { + mChoice = -1; + mIsInChoice = false; + MWBase::Environment::get().getWindowManager()->getDialogueWindow()->clearChoices(); + } } } From 9d86e5b02803550d7406a6cff53d6e12534d3a16 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 10 May 2015 13:04:50 +0200 Subject: [PATCH 081/142] GetSpellEffects returns true for active abilities (Fixes #2530) --- apps/openmw/mwmechanics/spells.cpp | 14 ++++++++++++++ apps/openmw/mwmechanics/spells.hpp | 3 +++ apps/openmw/mwscript/miscextensions.cpp | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index 04225b43eb..b1829964be 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -143,6 +143,20 @@ namespace MWMechanics return mSelectedSpell; } + bool Spells::isSpellActive(const std::string &id) const + { + TContainer::const_iterator found = mSpells.find(id); + if (found != mSpells.end()) + { + const ESM::Spell *spell = + MWBase::Environment::get().getWorld()->getStore().get().find (id); + + return (spell->mData.mType==ESM::Spell::ST_Ability || spell->mData.mType==ESM::Spell::ST_Blight || + spell->mData.mType==ESM::Spell::ST_Disease || spell->mData.mType==ESM::Spell::ST_Curse); + } + return false; + } + bool Spells::hasCommonDisease() const { for (TIterator iter = mSpells.begin(); iter!=mSpells.end(); ++iter) diff --git a/apps/openmw/mwmechanics/spells.hpp b/apps/openmw/mwmechanics/spells.hpp index 064b2c1e5d..6b41499395 100644 --- a/apps/openmw/mwmechanics/spells.hpp +++ b/apps/openmw/mwmechanics/spells.hpp @@ -98,6 +98,9 @@ namespace MWMechanics const std::string getSelectedSpell() const; ///< May return an empty string. + bool isSpellActive(const std::string& id) const; + ///< Are we under the effects of the given spell ID? + bool hasCommonDisease() const; bool hasBlightDisease() const; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 29f586a653..38106340ae 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -595,7 +595,8 @@ namespace MWScript std::string id = runtime.getStringLiteral(runtime[0].mInteger); runtime.pop(); - runtime.push(ptr.getClass().getCreatureStats(ptr).getActiveSpells().isSpellActive(id)); + const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); + runtime.push(stats.getActiveSpells().isSpellActive(id) || stats.getSpells().isSpellActive(id)); } }; From c819180aa1299422f42f94b82cc58d48f6c76a6c Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 10 May 2015 13:09:22 +0200 Subject: [PATCH 082/142] Minor cleanup --- apps/openmw/mwgui/spellbuyingwindow.cpp | 8 +------- apps/openmw/mwscript/statsextensions.cpp | 10 ++-------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 57b02940e1..76a1d51e5b 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -127,13 +127,7 @@ namespace MWGui bool SpellBuyingWindow::playerHasSpell(const std::string &id) { MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::Spells& playerSpells = player.getClass().getCreatureStats (player).getSpells(); - for (MWMechanics::Spells::TIterator it = playerSpells.begin(); it != playerSpells.end(); ++it) - { - if (Misc::StringUtils::ciEqual(id, it->first)) - return true; - } - return false; + return player.getClass().getCreatureStats(player).getSpells().hasSpell(id); } void SpellBuyingWindow::onSpellButtonClick(MyGUI::Widget* _sender) diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index d825b085e7..80f46e4573 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -515,14 +515,8 @@ namespace MWScript Interpreter::Type_Integer value = 0; - for (MWMechanics::Spells::TIterator iter ( - ptr.getClass().getCreatureStats (ptr).getSpells().begin()); - iter!=ptr.getClass().getCreatureStats (ptr).getSpells().end(); ++iter) - if (iter->first==id) - { - value = 1; - break; - } + if (ptr.getClass().getCreatureStats(ptr).getSpells().hasSpell(id)) + value = 1; runtime.push (value); } From 97c35da441f1de47aeb523cb3f1594b6195caf91 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 10 May 2015 15:34:07 +0200 Subject: [PATCH 083/142] Change exterior water level to z=-1 (Fixes #1405) --- apps/openmw/mwworld/scene.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 8d689240b6..f5a9b8960d 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -256,12 +256,13 @@ namespace MWWorld insertCell (*cell, true, loadingListener); mRendering.cellAdded (cell); - bool waterEnabled = cell->getCell()->hasWater(); + bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior(); mRendering.setWaterEnabled(waterEnabled); + float waterLevel = cell->isExterior() ? -1.f : cell->getWaterLevel(); if (waterEnabled) { - mPhysics->enableWater(cell->getWaterLevel()); - mRendering.setWaterHeight(cell->getWaterLevel()); + mPhysics->enableWater(waterLevel); + mRendering.setWaterHeight(waterLevel); } else mPhysics->disableWater(); From 58a2ad663cee7de5e9f419af80485c97ca890c63 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 11 May 2015 16:24:52 +0200 Subject: [PATCH 084/142] Fix regression of sleep interruption chance --- apps/openmw/mwgui/waitdialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index f74b068912..94905dd9e8 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -155,8 +155,9 @@ namespace MWGui if (!region->mSleepList.empty()) { // figure out if player will be woken while sleeping + int x = OEngine::Misc::Rng::rollDice(hoursToWait); float fSleepRandMod = world->getStore().get().find("fSleepRandMod")->getFloat(); - if (OEngine::Misc::Rng::rollProbability() > fSleepRandMod) + if (x > fSleepRandMod * hoursToWait) { float fSleepRestMod = world->getStore().get().find("fSleepRestMod")->getFloat(); mInterruptAt = hoursToWait - int(fSleepRestMod * hoursToWait); From 5abeab21edb1854955bb0865b3cf6d22b2d48a38 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 11 May 2015 16:55:09 +0200 Subject: [PATCH 085/142] Various integer/floating point roll adjustments based on wiki --- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwgui/pickpocketitemmodel.cpp | 2 +- apps/openmw/mwmechanics/combat.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 8404b95234..192bdf2ce8 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -251,7 +251,7 @@ namespace MWClass float hitchance = MWMechanics::getHitChance(ptr, victim, ref->mBase->mData.mCombat); - if(OEngine::Misc::Rng::rollProbability() >= hitchance/100.0f) + if(OEngine::Misc::Rng::roll0to99() >= hitchance) { victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 1d58dc87e3..3ca57aca88 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -515,7 +515,7 @@ namespace MWClass float hitchance = MWMechanics::getHitChance(ptr, victim, ptr.getClass().getSkill(ptr, weapskill)); - if (OEngine::Misc::Rng::rollProbability() >= hitchance / 100.0f) + if (OEngine::Misc::Rng::roll0to99() >= hitchance) { othercls.onHit(victim, 0.0f, false, weapon, ptr, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, ptr); diff --git a/apps/openmw/mwgui/pickpocketitemmodel.cpp b/apps/openmw/mwgui/pickpocketitemmodel.cpp index bc7c5528e8..b8ac20f99d 100644 --- a/apps/openmw/mwgui/pickpocketitemmodel.cpp +++ b/apps/openmw/mwgui/pickpocketitemmodel.cpp @@ -20,7 +20,7 @@ namespace MWGui { for (size_t i = 0; igetItemCount(); ++i) { - if (chance <= OEngine::Misc::Rng::roll0to99()) + if (OEngine::Misc::Rng::roll0to99() > chance) mHiddenItems.push_back(mSourceModel->getItem(i)); } } diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index c5fc34507b..045f0108ca 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -187,7 +187,7 @@ namespace MWMechanics int skillValue = attacker.getClass().getSkill(attacker, weapon.getClass().getEquipmentSkill(weapon)); - if (OEngine::Misc::Rng::rollProbability() >= getHitChance(attacker, victim, skillValue) / 100.0f) + if (OEngine::Misc::Rng::roll0to99() >= getHitChance(attacker, victim, skillValue)) { victim.getClass().onHit(victim, 0.0f, false, projectile, attacker, false); MWMechanics::reduceWeaponCondition(0.f, false, weapon, attacker); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index da8d49db0f..c829154e27 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -737,7 +737,7 @@ namespace MWMechanics float x = 0; float y = 0; - float roll = OEngine::Misc::Rng::rollClosedProbability() * 100; + int roll = OEngine::Misc::Rng::roll0to99(); if (type == PT_Admire) { From 538e550b2b2b9f0d71a7adca8d4e89912b3a1d70 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 13 May 2015 10:30:44 +1000 Subject: [PATCH 086/142] Fix for Bug #2543. Spells magic effect id typo. --- apps/opencs/model/world/nestedcoladapterimp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.hpp b/apps/opencs/model/world/nestedcoladapterimp.hpp index ea2037eb82..776a908bad 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.hpp +++ b/apps/opencs/model/world/nestedcoladapterimp.hpp @@ -311,7 +311,7 @@ namespace CSMWorld case 0: { if (effect.mEffectID >=0 && effect.mEffectID < ESM::MagicEffect::Length) - return effect.mRange; + return effect.mEffectID; else throw std::runtime_error("Magic effects ID unexpected value"); } From 7f12fc47706076545505c9c0f80c7b6ed3cad531 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 13 May 2015 13:39:04 +1000 Subject: [PATCH 087/142] Fix for Bug #2544. Add a default mNpdtType to ESM::Npc::blank(). --- components/esm/loadnpc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm/loadnpc.cpp b/components/esm/loadnpc.cpp index 751c7f252b..44d2987853 100644 --- a/components/esm/loadnpc.cpp +++ b/components/esm/loadnpc.cpp @@ -143,7 +143,7 @@ namespace ESM void NPC::blank() { - mNpdtType = 0; + mNpdtType = NPC_DEFAULT; mNpdt52.mLevel = 0; mNpdt52.mStrength = mNpdt52.mIntelligence = mNpdt52.mWillpower = mNpdt52.mAgility = mNpdt52.mSpeed = mNpdt52.mEndurance = mNpdt52.mPersonality = mNpdt52.mLuck = 0; From 5cf50227b4e0a1318606df0c5e56c7f41a5dd9fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 13 May 2015 19:53:50 +0200 Subject: [PATCH 088/142] updated changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15464b1d72..3219edd9ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Bug #923: Editor: Operations-Multithreading is broken Bug #1317: Erene Llenim in Seyda Neen does not walk around + Bug #1405: Water rendering glitch near Seyda Neen lighthouse Bug #1621: "Error Detecting Morrowind Installation" in the default directory Bug #2216: Creating a clone of the player stops you moving. Bug #2387: Casting bound weapon spell doesn't switch to "ready weapon" mode @@ -23,6 +24,10 @@ Bug #2475: cumulative stacks of 100 point fortify skill speechcraft boosts do not apply correctly Bug #2498: Editor: crash when issuing undo command after the table subview is closed Bug #2500: Editor: object table - can't undo delete record + Bug #2518: OpenMW detect spell returns false positives + Bug #2521: NPCs don't react to stealing when inventory menu is open. + Bug #2525: Can't click on red dialogue choice [rise of house telvanni][60fffec] + Bug #2530: GetSpellEffects not working as in vanilla Feature #139: Editor: Global Search & Replace Feature #1219: Editor: Add dialogue mode only columns Feature #2024: Hotkey for hand to hand (i.e. unequip any weapon) @@ -34,6 +39,7 @@ Feature #2505: Editor: optionally show a line number column in the script editor Feature #2512: Editor: Offer use of monospace fonts in the script editor as an option Feature #2514: Editor: focus on ID input field on clone/add + Feature #2519: it is not possible to change icons that appear on the map after casting the Detect spells Task #2460: OS X: Use Application Support directory as user data path Task #2516: Editor: Change References / Referenceables terminology From c9d519f36c62611a768936018fe185a011a4d6a0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 14 May 2015 14:48:29 +0200 Subject: [PATCH 089/142] focus search input field when opening search subview (Fixes #2534) --- apps/opencs/view/tools/searchbox.cpp | 7 +++++++ apps/opencs/view/tools/searchbox.hpp | 2 ++ apps/opencs/view/tools/searchsubview.cpp | 8 +++++++- apps/opencs/view/tools/searchsubview.hpp | 4 ++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/tools/searchbox.cpp b/apps/opencs/view/tools/searchbox.cpp index ca55207875..1307c1aab1 100644 --- a/apps/opencs/view/tools/searchbox.cpp +++ b/apps/opencs/view/tools/searchbox.cpp @@ -153,6 +153,11 @@ void CSVTools::SearchBox::setEditLock (bool locked) mReplace.setEnabled (!locked); } +void CSVTools::SearchBox::focus() +{ + mInput.currentWidget()->setFocus(); +} + void CSVTools::SearchBox::modeSelected (int index) { switch (index) @@ -172,6 +177,8 @@ void CSVTools::SearchBox::modeSelected (int index) break; } + mInput.currentWidget()->setFocus(); + updateSearchButton(); } diff --git a/apps/opencs/view/tools/searchbox.hpp b/apps/opencs/view/tools/searchbox.hpp index 433c096936..fe56966d11 100644 --- a/apps/opencs/view/tools/searchbox.hpp +++ b/apps/opencs/view/tools/searchbox.hpp @@ -49,6 +49,8 @@ namespace CSVTools void setEditLock (bool locked); + void focus(); + private slots: void modeSelected (int index); diff --git a/apps/opencs/view/tools/searchsubview.cpp b/apps/opencs/view/tools/searchsubview.cpp index 32c26ee969..dc670af40a 100644 --- a/apps/opencs/view/tools/searchsubview.cpp +++ b/apps/opencs/view/tools/searchsubview.cpp @@ -60,6 +60,12 @@ void CSVTools::SearchSubView::replace (bool selection) } } +void CSVTools::SearchSubView::showEvent (QShowEvent *event) +{ + CSVDoc::SubView::showEvent (event); + mSearchBox.focus(); +} + CSVTools::SearchSubView::SearchSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : CSVDoc::SubView (id), mDocument (document), mLocked (false) { @@ -83,7 +89,7 @@ CSVTools::SearchSubView::SearchSubView (const CSMWorld::UniversalId& id, CSMDoc: SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&))); connect (mTable, SIGNAL (replaceRequest()), this, SLOT (replaceRequest())); - + connect (&document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (stateChanged (int, CSMDoc::Document *))); diff --git a/apps/opencs/view/tools/searchsubview.hpp b/apps/opencs/view/tools/searchsubview.hpp index 6dedd6ef2b..2e96b98b50 100644 --- a/apps/opencs/view/tools/searchsubview.hpp +++ b/apps/opencs/view/tools/searchsubview.hpp @@ -32,6 +32,10 @@ namespace CSVTools private: void replace (bool selection); + + protected: + + void showEvent (QShowEvent *event); public: From f92d801fafa64ea3cabd78886a3d6dae2760b5af Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 15 May 2015 12:32:29 +1000 Subject: [PATCH 090/142] Jump to the added/cloned record (or undeleted record in case of undo). Should resolve Feature #2541. Controlled by radio buttons on user preferences settings. --- apps/opencs/model/settings/usersettings.cpp | 8 +++ apps/opencs/view/world/table.cpp | 54 +++++++++++++++++++-- apps/opencs/view/world/table.hpp | 4 ++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 9e00b7d1aa..41ce593b75 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -206,6 +206,14 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() shiftCtrlDoubleClick->setDeclaredValues (values); shiftCtrlDoubleClick->setDefaultValue (editRecordAndClose); shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:

" + toolTip); + + QString defaultValue = "Jump and Select"; + QStringList jumpValues = QStringList() << defaultValue << "Jump Only" << "No Jump"; + + Setting *jumpToAdded = createSetting (Type_RadioButton, "jump-to-added", + "Jump to the added or cloned record."); + jumpToAdded->setDefaultValue (defaultValue); + jumpToAdded->setDeclaredValues (jumpValues); } declareSection ("search", "Search & Replace"); diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 5a650f98a1..44150bbc6a 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -21,6 +21,7 @@ #include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/commanddispatcher.hpp" +#include "../../model/settings/usersettings.hpp" #include "recordstatusdelegate.hpp" #include "util.hpp" @@ -255,6 +256,24 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, : mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0), DragRecordTable(document) { + CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); + QString jumpSetting = settings.settingValue ("table-input/jump-to-added"); + if (jumpSetting.isEmpty() || jumpSetting == "Jump and Select") // default + { + mJumpToAddedRecord = true; + mUnselectAfterJump = false; + } + else if(jumpSetting == "Jump Only") + { + mJumpToAddedRecord = true; + mUnselectAfterJump = true; + } + else + { + mJumpToAddedRecord = false; + mUnselectAfterJump = false; + } + mModel = &dynamic_cast (*mDocument.getData().getTableModel (id)); mProxyModel = new CSMWorld::IdTableProxyModel (this); @@ -346,7 +365,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, addAction (mExtendedRevertAction); connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), - this, SLOT (tableSizeUpdate())); + this, SLOT (rowsInsertedEvent(const QModelIndex&, int, int))); /// \note This signal could instead be connected to a slot that filters out changes not affecting /// the records status column (for permanence reasons) @@ -517,9 +536,27 @@ void CSVWorld::Table::previewRecord() } } -void CSVWorld::Table::updateUserSetting - (const QString &name, const QStringList &list) +void CSVWorld::Table::updateUserSetting (const QString &name, const QStringList &list) { + if (name=="table-input/jump-to-added") + { + if(list.isEmpty() || list.at(0) == "Jump and Select") // default + { + mJumpToAddedRecord = true; + mUnselectAfterJump = false; + } + else if(list.at(0) == "Jump Only") + { + mJumpToAddedRecord = true; + mUnselectAfterJump = true; + } + else // No Jump + { + mJumpToAddedRecord = false; + mUnselectAfterJump = false; + } + } + if (name=="records/type-format" || name=="records/status-format") { int columns = mModel->columnCount(); @@ -700,3 +737,14 @@ std::vector< CSMWorld::UniversalId > CSVWorld::Table::getDraggedRecords() const return idToDrag; } +void CSVWorld::Table::rowsInsertedEvent(const QModelIndex& parent, int start, int end) +{ + tableSizeUpdate(); + if(mJumpToAddedRecord) + { + selectRow(end); + + if(mUnselectAfterJump) + clearSelection(); + } +} diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 75161b8b65..becb21f65d 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -67,6 +67,8 @@ namespace CSVWorld CSMWorld::CommandDispatcher *mDispatcher; CSMWorld::UniversalId mEditCellId; std::map mDoubleClickActions; + bool mJumpToAddedRecord; + bool mUnselectAfterJump; private: @@ -139,6 +141,8 @@ namespace CSVWorld void recordFilterChanged (boost::shared_ptr filter); void updateUserSetting (const QString &name, const QStringList &list); + + void rowsInsertedEvent(const QModelIndex& parent, int start, int end); }; } From 28617c8beb8cf3353033b2d946d6f2bd93c3a561 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 15 May 2015 12:33:31 +1000 Subject: [PATCH 091/142] Update table size status for removed rows. --- apps/opencs/view/world/table.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 44150bbc6a..86daf8af7b 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -364,6 +364,9 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, connect (mExtendedRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeExtendedRevert())); addAction (mExtendedRevertAction); + connect (mProxyModel, SIGNAL (rowsRemoved (const QModelIndex&, int, int)), + this, SLOT (tableSizeUpdate())); + connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), this, SLOT (rowsInsertedEvent(const QModelIndex&, int, int))); From 27000fb36b8a2ffdfb4d57087b5751cb1e7526b0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 15 May 2015 14:09:35 +0200 Subject: [PATCH 092/142] don't reject single precision float values in value filters (Fixes #2533) --- apps/opencs/model/filter/valuenode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/filter/valuenode.cpp b/apps/opencs/model/filter/valuenode.cpp index 72cf5896bf..6fdae3e1ba 100644 --- a/apps/opencs/model/filter/valuenode.cpp +++ b/apps/opencs/model/filter/valuenode.cpp @@ -27,7 +27,7 @@ bool CSMFilter::ValueNode::test (const CSMWorld::IdTableBase& table, int row, QVariant data = table.data (index); if (data.type()!=QVariant::Double && data.type()!=QVariant::Bool && data.type()!=QVariant::Int && - data.type()!=QVariant::UInt) + data.type()!=QVariant::UInt && data.type()!=static_cast (QMetaType::Float)) return false; double value = data.toDouble(); From 60a835c16d0ae58e1fed8fe933dad752c4e03a5d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 16 May 2015 10:18:11 +0200 Subject: [PATCH 093/142] stop script editor from eating undo/redo shortcuts (Fixes #2506) --- apps/opencs/view/world/scriptedit.cpp | 13 +++++++++++++ apps/opencs/view/world/scriptedit.hpp | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index b4f4234f19..2e05fa110e 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -25,6 +25,19 @@ CSVWorld::ScriptEdit::ChangeLock::~ChangeLock() --mEdit.mChangeLocked; } +bool CSVWorld::ScriptEdit::event (QEvent *event) +{ + // ignore undo and redo shortcuts + if (event->type()==QEvent::ShortcutOverride) + { + QKeyEvent *keyEvent = static_cast (event); + + if (keyEvent->matches (QKeySequence::Undo) || keyEvent->matches (QKeySequence::Redo)) + return true; + } + + return QPlainTextEdit::event (event); +} CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighlighter::Mode mode, QWidget* parent) diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index a19cee486b..fb577e60e4 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -53,6 +53,10 @@ namespace CSVWorld QFont mDefaultFont; QFont mMonoFont; + protected: + + bool event (QEvent *event); + public: ScriptEdit (const CSMDoc::Document& document, ScriptHighlighter::Mode mode, From 7d321e0fb7faba64cbb5f11dea2ea8dbf70bdb27 Mon Sep 17 00:00:00 2001 From: Nikolay Kasyanov Date: Sat, 16 May 2015 13:18:04 +0300 Subject: [PATCH 094/142] Fix #2557 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don’t show main dialog right away if wizard is selected. --- apps/launcher/main.cpp | 6 ++++-- apps/launcher/maindialog.cpp | 10 +++++----- apps/launcher/maindialog.hpp | 8 +++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 11ea568692..ba06861107 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -59,14 +59,16 @@ int main(int argc, char *argv[]) Launcher::MainDialog mainWin; - if (!mainWin.showFirstRunDialog()) + Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog(); + if (result == Launcher::FirstRunDialogResultFailure) return 0; // if (!mainWin.setup()) { // return 0; // } - mainWin.show(); + if (result == Launcher::FirstRunDialogResultContinue) + mainWin.show(); int returnValue = app.exec(); SDL_Quit(); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 00e6a9aa29..fd36993bfb 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -148,10 +148,10 @@ void Launcher::MainDialog::createPages() } -bool Launcher::MainDialog::showFirstRunDialog() +Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog() { if (!setupLauncherSettings()) - return false; + return FirstRunDialogResultFailure; if (mLauncherSettings.value(QString("General/firstrun"), QString("true")) == QLatin1String("true")) { @@ -176,14 +176,14 @@ bool Launcher::MainDialog::showFirstRunDialog() if (msgBox.clickedButton() == wizardButton) { if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false)) { - return false; + return FirstRunDialogResultFailure; } else { - return true; + return FirstRunDialogResultWizard; } } } - return setup(); + return setup() ? FirstRunDialogResultContinue : FirstRunDialogResultFailure; } bool Launcher::MainDialog::setup() diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 0708f70026..4c21dbaf4f 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -31,6 +31,12 @@ namespace Launcher class UnshieldThread; class SettingsPage; + typedef enum { + FirstRunDialogResultFailure, + FirstRunDialogResultContinue, + FirstRunDialogResultWizard + } FirstRunDialogResult; + #ifndef WIN32 bool expansions(Launcher::UnshieldThread& cd); #endif @@ -44,7 +50,7 @@ namespace Launcher ~MainDialog(); bool setup(); - bool showFirstRunDialog(); + FirstRunDialogResult showFirstRunDialog(); bool reloadSettings(); bool writeSettings(); From 1b41f6c4c54bbb8f46393bb8f57fcdf00ef820f5 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 16 May 2015 12:29:26 +0200 Subject: [PATCH 095/142] Sleep interruption fix --- apps/openmw/mwgui/waitdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 94905dd9e8..28e3be5911 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -157,7 +157,7 @@ namespace MWGui // figure out if player will be woken while sleeping int x = OEngine::Misc::Rng::rollDice(hoursToWait); float fSleepRandMod = world->getStore().get().find("fSleepRandMod")->getFloat(); - if (x > fSleepRandMod * hoursToWait) + if (x < fSleepRandMod * hoursToWait) { float fSleepRestMod = world->getStore().get().find("fSleepRestMod")->getFloat(); mInterruptAt = hoursToWait - int(fSleepRestMod * hoursToWait); From 34f106749a3b302f00f9c0172e1a5911dca4c6df Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 17 May 2015 10:38:15 +0200 Subject: [PATCH 096/142] removed a redundant typedef --- apps/launcher/maindialog.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/launcher/maindialog.hpp b/apps/launcher/maindialog.hpp index 4c21dbaf4f..c903099901 100644 --- a/apps/launcher/maindialog.hpp +++ b/apps/launcher/maindialog.hpp @@ -31,11 +31,12 @@ namespace Launcher class UnshieldThread; class SettingsPage; - typedef enum { + enum FirstRunDialogResult + { FirstRunDialogResultFailure, FirstRunDialogResultContinue, FirstRunDialogResultWizard - } FirstRunDialogResult; + }; #ifndef WIN32 bool expansions(Launcher::UnshieldThread& cd); From b9856162b33ff4f0d1a1d46d68b64373496b29ba Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 17 May 2015 10:38:54 +0200 Subject: [PATCH 097/142] updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3219edd9ac..466c2ef253 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Bug #2521: NPCs don't react to stealing when inventory menu is open. Bug #2525: Can't click on red dialogue choice [rise of house telvanni][60fffec] Bug #2530: GetSpellEffects not working as in vanilla + Bug #2557: Crash on first launch after choosing "Run installation wizard" Feature #139: Editor: Global Search & Replace Feature #1219: Editor: Add dialogue mode only columns Feature #2024: Hotkey for hand to hand (i.e. unequip any weapon) From e9ca02216201fdb64e1dcd59a6a385d8a4c067d5 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 17 May 2015 20:45:13 +1000 Subject: [PATCH 098/142] Add an optional horizontal scrollbar to the main view window. Should resolve Feature #2549. - TableSubviews and DialogueSubviews now provide size hints - Option to stop the growth of the window at the screen boundary for multi-monitor setup with different resolution. - Three options: Grow Only: No change to current, except the use of size hints Scrollbar Only: Simple addition of a scrollbar, the view window does not grow Grow then Scroll: Window grows as per current behaviour. The scrollbar appears once it cannot grow any further. --- apps/opencs/model/settings/usersettings.cpp | 14 ++ apps/opencs/view/doc/subview.cpp | 16 +++ apps/opencs/view/doc/subview.hpp | 13 ++ apps/opencs/view/doc/view.cpp | 145 +++++++++++++++++++- apps/opencs/view/doc/view.hpp | 5 + apps/opencs/view/world/dialoguesubview.cpp | 12 +- apps/opencs/view/world/tablesubview.cpp | 12 +- 7 files changed, 213 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 41ce593b75..bd31b6e384 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -143,6 +143,20 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() minWidth->setDefaultValue (325); minWidth->setRange (50, 10000); minWidth->setToolTip ("Minimum width of subviews."); + + QString defaultScroll = "Scrollbar Only"; + QStringList scrollValues = QStringList() << defaultScroll << "Grow Only" << "Grow then Scroll"; + + Setting *mainwinScroll = createSetting (Type_RadioButton, "mainwindow-scrollbar", + "Add a horizontal scrollbar to the main view window."); + mainwinScroll->setDefaultValue (defaultScroll); + mainwinScroll->setDeclaredValues (scrollValues); + + Setting *grow = createSetting (Type_CheckBox, "grow-limit", "Grow Limit Screen"); + grow->setDefaultValue ("false"); + grow->setToolTip ("When \"Grow then Scroll\" option is selected, the window size grows to" + " the width of the virtual desktop. \nIf this option is selected the the window growth" + "is limited to the current screen."); } declareSection ("records", "Records"); diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index df1e7ee492..09128d9191 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -43,3 +43,19 @@ void CSVDoc::SubView::closeRequest() { emit closeRequest (this); } + +CSVDoc::SizeHintWidget::SizeHintWidget(QWidget *parent) : QWidget(parent) +{} + +CSVDoc::SizeHintWidget::~SizeHintWidget() +{} + +QSize CSVDoc::SizeHintWidget::sizeHint() const +{ + return mSize; +} + +void CSVDoc::SizeHintWidget::setSizeHint(const QSize &size) +{ + mSize = size; +} diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index a8aa3cda1e..f327107c21 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -8,6 +8,7 @@ #include "subviewfactory.hpp" #include +#include class QUndoStack; @@ -70,6 +71,18 @@ namespace CSVDoc void closeRequest(); }; + + class SizeHintWidget : public QWidget + { + QSize mSize; + + public: + SizeHintWidget(QWidget *parent = 0); + ~SizeHintWidget(); + + virtual QSize sizeHint() const; + void setSizeHint(const QSize &size); + }; } #endif diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 5636fff943..16b96ed4d3 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -9,6 +9,10 @@ #include #include #include +#include +#include +#include +#include #include "../../model/doc/document.hpp" #include "../../model/settings/usersettings.hpp" @@ -16,6 +20,7 @@ #include "../../model/world/idtable.hpp" #include "../world/subviews.hpp" +#include "../world/tablesubview.hpp" #include "../tools/subviews.hpp" @@ -334,8 +339,15 @@ void CSVDoc::View::updateTitle() void CSVDoc::View::updateSubViewIndicies(SubView *view) { if(view && mSubViews.contains(view)) + { mSubViews.removeOne(view); + // adjust (reduce) the scroll area (even floating), except when it is "Scrollbar Only" + CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); + if(settings.settingValue ("window/mainwindow-scrollbar") == "Grow then Scroll") + updateScrollbar(); + } + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); bool hideTitle = userSettings.setting ("window/hide-subview", QString ("false"))=="true" && @@ -381,7 +393,7 @@ void CSVDoc::View::updateActions() CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), - mViewTotal (totalViews) + mViewTotal (totalViews), mScroll(0), mScrollbarOnly(false) { int width = CSMSettings::UserSettings::instance().settingValue ("window/default-width").toInt(); @@ -400,7 +412,18 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks); - setCentralWidget (&mSubViewWindow); + CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); + if(settings.settingValue ("window/mainwindow-scrollbar") == "Grow Only") + { + setCentralWidget (&mSubViewWindow); + } + else + { + mScroll = new QScrollArea(this); + mScroll->setWidgetResizable(true); + mScroll->setWidget(&mSubViewWindow); + setCentralWidget(mScroll); + } mOperations = new Operations; addDockWidget (Qt::BottomDockWidgetArea, mOperations); @@ -527,6 +550,59 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin view->setStatusBar (mShowStatusBar->isChecked()); + // Work out how to deal with additional subviews + // + // Policy for "Grow then Scroll": + // + // - Increase the horizontal width of the mainwindow until it becomes greater than or equal + // to the screen (monitor) width. + // - Move the mainwindow position sideways if necessary to fit within the screen. + // - Any more additions increases the size of the mSubViewWindow (horizontal scrollbar + // should become visible) + // - Move the scroll bar to the newly added subview + // + CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); + QString mainwinScroll = settings.settingValue ("window/mainwindow-scrollbar"); + if (mainwinScroll.isEmpty() || mainwinScroll == "Scrollbar Only") + mScrollbarOnly = true; + else if(mainwinScroll == "Grow Only") + mScrollbarOnly = false; + else + mScrollbarOnly = false; + + QDesktopWidget *dw = QApplication::desktop(); + QRect rect; + if(settings.settingValue ("window/grow-limit") == "true") + rect = dw->screenGeometry(this); + else + rect = dw->screenGeometry(dw->screen(dw->screenNumber(this))); + + if (!mScrollbarOnly && mScroll && mSubViews.size() > 1) + { + int newWidth = width()+minWidth; + int frameWidth = frameGeometry().width() - width(); + if (newWidth+frameWidth <= rect.width()) + { + resize(newWidth, height()); + // WARNING: below code assumes that new subviews are added to the right + if (x() > rect.width()-(newWidth+frameWidth)) + move(rect.width()-(newWidth+frameWidth), y()); // shift left to stay within the screen + } + else + { + // full width + resize(rect.width()-frameWidth, height()); + mSubViewWindow.setMinimumWidth(mSubViewWindow.width()+minWidth); + move(0, y()); + } + + // Make the new subview visible, setFocus() or raise() don't seem to work + // On Ubuntu the scrollbar does not go right to the end, even if using + // mScroll->horizontalScrollBar()->setValue(mScroll->horizontalScrollBar()->maximum()); + if (mSubViewWindow.width() > rect.width()) + mScroll->horizontalScrollBar()->setValue(mSubViewWindow.width()); + } + mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); updateSubViewIndicies(); @@ -774,6 +850,48 @@ void CSVDoc::View::updateUserSetting (const QString &name, const QStringList &li { subView->updateUserSetting (name, list); } + + if (name=="window/mainwindow-scrollbar") + { + if(list.at(0) != "Grow Only") + { + if (mScroll) + { + if (list.at(0).isEmpty() || list.at(0) == "Scrollbar Only") + { + mScrollbarOnly = true; + mSubViewWindow.setMinimumWidth(0); + } + else + { + if(!mScrollbarOnly) + return; + + mScrollbarOnly = false; + updateScrollbar(); + } + } + else + { + mScroll = new QScrollArea(this); + mScroll->setWidgetResizable(true); + mScroll->setWidget(&mSubViewWindow); + setCentralWidget(mScroll); + } + } + else + { + if (mScroll) + { + mScroll->takeWidget(); + setCentralWidget (&mSubViewWindow); + mScroll->deleteLater(); + mScroll = 0; + } + else + return; + } + } } void CSVDoc::View::toggleShowStatusBar (bool show) @@ -815,3 +933,26 @@ void CSVDoc::View::closeRequest (SubView *subView) else if (mViewManager.closeRequest (this)) mViewManager.removeDocAndView (mDocument); } + +void CSVDoc::View::updateScrollbar() +{ + QRect rect; + QWidget *topLevel = QApplication::topLevelAt(pos()); + if (topLevel) + rect = topLevel->rect(); + else + rect = this->rect(); + + int newWidth = 0; + for (int i = 0; i < mSubViews.size(); ++i) + { + newWidth += mSubViews[i]->width(); + } + + int frameWidth = frameGeometry().width() - width(); + + if ((newWidth+frameWidth) >= rect.width()) + mSubViewWindow.setMinimumWidth(newWidth); + else + mSubViewWindow.setMinimumWidth(0); +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 32d7159c28..1d44cb7f5a 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -10,6 +10,7 @@ class QAction; class QDockWidget; +class QScrollArea; namespace CSMDoc { @@ -47,6 +48,8 @@ namespace CSVDoc SubViewFactoryManager mSubViewFactory; QMainWindow mSubViewWindow; GlobalDebugProfileMenu *mGlobalDebugProfileMenu; + QScrollArea *mScroll; + bool mScrollbarOnly; // not implemented @@ -87,6 +90,8 @@ namespace CSVDoc /// User preference function void resizeViewHeight (int height); + void updateScrollbar(); + public: View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 0d0e82dbf3..ccab576fa0 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "../../model/world/nestedtableproxymodel.hpp" #include "../../model/world/columnbase.hpp" @@ -581,7 +583,15 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM changeCurrentId(id.getId()); - QWidget *mainWidget = new QWidget(this); + //QWidget *mainWidget = new QWidget(this); + CSVDoc::SizeHintWidget *mainWidget = new CSVDoc::SizeHintWidget; + + const QRect rect = QApplication::desktop()->screenGeometry(this); + int frameHeight = 40; // set a reasonable default + QWidget *topLevel = QApplication::topLevelAt(pos()); + if (topLevel) + frameHeight = topLevel->frameGeometry().height() - topLevel->height(); + mainWidget->setSizeHint(QSize(400, rect.height()-frameHeight)); // FIXME: 400 QHBoxLayout *buttonsLayout = new QHBoxLayout; QToolButton* prevButton = new QToolButton(mainWidget); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 729b6b8d77..dde04fb3f7 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -3,6 +3,9 @@ #include #include +#include +#include +#include #include "../../model/doc/document.hpp" #include "../../model/world/tablemimedata.hpp" @@ -30,11 +33,18 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->insertWidget (0, mFilterBox); - QWidget *widget = new QWidget; + CSVDoc::SizeHintWidget *widget = new CSVDoc::SizeHintWidget; widget->setLayout (layout); setWidget (widget); + // prefer height of the screen and full width of the table + const QRect rect = QApplication::desktop()->screenGeometry(this); + int frameHeight = 40; // set a reasonable default + QWidget *topLevel = QApplication::topLevelAt(pos()); + if (topLevel) + frameHeight = topLevel->frameGeometry().height() - topLevel->height(); + widget->setSizeHint(QSize(mTable->horizontalHeader()->length(), rect.height()-frameHeight)); connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)), this, SLOT (editRequest (const CSMWorld::UniversalId&, const std::string&))); From 93c3bb37167a2887f2c5d07c2265a1bf63fb650b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 17 May 2015 14:27:17 +0200 Subject: [PATCH 099/142] fixed subview-closing related crash (Fixes #2564) --- apps/opencs/view/doc/view.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 5636fff943..e10f85c64a 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -811,7 +811,10 @@ void CSVDoc::View::closeRequest (SubView *subView) if (mSubViews.size()>1 || mViewTotal<=1 || userSettings.setting ("window/hide-subview", QString ("false"))!="true") + { subView->deleteLater(); + mSubViews.removeOne (subView); + } else if (mViewManager.closeRequest (this)) mViewManager.removeDocAndView (mDocument); } From 7b207a795468c7f9603655722f33a54a2476de52 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 17 May 2015 14:31:53 +0200 Subject: [PATCH 100/142] added shortcut for closing subviews (Fixes #2558) --- apps/opencs/view/doc/subview.cpp | 18 ++++++++++++++++++ apps/opencs/view/doc/subview.hpp | 2 ++ 2 files changed, 20 insertions(+) diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index df1e7ee492..f4f0c6afe8 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -2,6 +2,24 @@ #include "view.hpp" +#include +#include +#include + +bool CSVDoc::SubView::event (QEvent *event) +{ + if (event->type()==QEvent::ShortcutOverride) + { + QKeyEvent *keyEvent = static_cast (event); + + if (keyEvent->key()==Qt::Key_W && keyEvent->modifiers()==(Qt::ShiftModifier | Qt::ControlModifier)) + emit closeRequest(); + return true; + } + + return QDockWidget::event (event); +} + CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) { diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index a8aa3cda1e..b323f9ed92 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -34,6 +34,8 @@ namespace CSVDoc void setUniversalId(const CSMWorld::UniversalId& id); + bool event (QEvent *event); + public: SubView (const CSMWorld::UniversalId& id); From 8bcfac1ea3779ad3ac18b2dfedecb291f5c98418 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 17 May 2015 16:25:13 +0200 Subject: [PATCH 101/142] Fix adjustPosition not always working correctly (Fixes #2563) moveObject was returning an incorrect Ptr for cell movements. --- apps/openmw/mwbase/world.hpp | 4 +- .../mwscript/transformationextensions.cpp | 7 ++-- apps/openmw/mwworld/worldimp.cpp | 37 +++++++++---------- apps/openmw/mwworld/worldimp.hpp | 4 +- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 9e6c6d9bf3..c110e94d61 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -286,8 +286,8 @@ namespace MWBase virtual MWWorld::Ptr moveObject (const MWWorld::Ptr& ptr, float x, float y, float z) = 0; ///< @return an updated Ptr in case the Ptr's cell changes - virtual void - moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z) = 0; + virtual MWWorld::Ptr moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z) = 0; + ///< @return an updated Ptr virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0; diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp index f87983ce88..414ef7fb7d 100644 --- a/apps/openmw/mwscript/transformationextensions.cpp +++ b/apps/openmw/mwscript/transformationextensions.cpp @@ -370,18 +370,17 @@ namespace MWScript // another morrowind oddity: player will be moved to the exterior cell at this location, // non-player actors will move within the cell they are in. - MWWorld::Ptr updated; if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr()) { MWWorld::CellStore* cell = MWBase::Environment::get().getWorld()->getExterior(cx,cy); MWBase::Environment::get().getWorld()->moveObject(ptr,cell,x,y,z); - updated = MWWorld::Ptr(ptr.getBase(), cell); + ptr = MWWorld::Ptr(ptr.getBase(), cell); } else { - updated = MWBase::Environment::get().getWorld()->moveObject(ptr, x, y, z); + ptr = MWBase::Environment::get().getWorld()->moveObject(ptr, x, y, z); } - dynamic_cast(runtime.getContext()).updatePtr(updated); + dynamic_cast(runtime.getContext()).updatePtr(ptr); float ax = Ogre::Radian(ptr.getRefData().getPosition().rot[0]).valueDegrees(); float ay = Ogre::Radian(ptr.getRefData().getPosition().rot[1]).valueDegrees(); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0f81106248..bb0402c4e5 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1108,7 +1108,7 @@ namespace MWWorld } } - void World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z) + MWWorld::Ptr World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z) { ESM::Position pos = ptr.getRefData().getPosition(); @@ -1123,6 +1123,7 @@ namespace MWWorld CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL; // currCell == NULL 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 (currCell != newCell) { @@ -1140,6 +1141,7 @@ namespace MWWorld mWorldScene->changeToExteriorCell(pos, false); } addContainerScripts (getPlayerPtr(), newCell); + newPtr = getPlayerPtr(); } else { @@ -1147,7 +1149,7 @@ namespace MWWorld bool newCellActive = mWorldScene->isCellActive(*newCell); if (!currCellActive && newCellActive) { - MWWorld::Ptr newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos); + newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos); mWorldScene->addObjectToScene(newPtr); std::string script = newPtr.getClass().getScript(newPtr); @@ -1163,23 +1165,21 @@ namespace MWWorld removeContainerScripts (ptr); haveToMove = false; - MWWorld::Ptr newPtr = ptr.getClass() - .copyToCell(ptr, *newCell); + newPtr = ptr.getClass().copyToCell(ptr, *newCell); newPtr.getRefData().setBaseNode(0); } else if (!currCellActive && !newCellActive) - ptr.getClass().copyToCell(ptr, *newCell); + newPtr = ptr.getClass().copyToCell(ptr, *newCell); else // both cells active { - MWWorld::Ptr copy = - ptr.getClass().copyToCell(ptr, *newCell, pos); + newPtr = ptr.getClass().copyToCell(ptr, *newCell, pos); - mRendering->updateObjectCell(ptr, copy); + mRendering->updateObjectCell(ptr, newPtr); ptr.getRefData().setBaseNode(NULL); - MWBase::Environment::get().getSoundManager()->updatePtr (ptr, copy); + MWBase::Environment::get().getSoundManager()->updatePtr (ptr, newPtr); MWBase::MechanicsManager *mechMgr = MWBase::Environment::get().getMechanicsManager(); - mechMgr->updateCell(ptr, copy); + mechMgr->updateCell(ptr, newPtr); std::string script = ptr.getClass().getScript(ptr); @@ -1187,22 +1187,23 @@ namespace MWWorld { mLocalScripts.remove(ptr); removeContainerScripts (ptr); - mLocalScripts.add(script, copy); - addContainerScripts (copy, newCell); + mLocalScripts.add(script, newPtr); + addContainerScripts (newPtr, newCell); } } ptr.getRefData().setCount(0); } } - if (haveToMove && ptr.getRefData().getBaseNode()) + if (haveToMove && newPtr.getRefData().getBaseNode()) { - mRendering->moveObject(ptr, vec); - mPhysics->moveObject (ptr); + mRendering->moveObject(newPtr, vec); + mPhysics->moveObject (newPtr); } if (isPlayer) { mWorldScene->playerMoved (vec); } + return newPtr; } MWWorld::Ptr World::moveObjectImp(const Ptr& ptr, float x, float y, float z) @@ -1216,11 +1217,7 @@ namespace MWWorld cell = getExterior(cellX, cellY); } - moveObject(ptr, cell, x, y, z); - - MWWorld::Ptr updated = ptr; - updated.mCell = cell; - return updated; + return moveObject(ptr, cell, x, y, z); } MWWorld::Ptr World::moveObject (const Ptr& ptr, float x, float y, float z) diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 63d6506de0..bf25c20bbd 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -348,7 +348,9 @@ namespace MWWorld virtual MWWorld::Ptr moveObject (const Ptr& ptr, float x, float y, float z); ///< @return an updated Ptr in case the Ptr's cell changes - virtual void moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z); + + virtual MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z); + ///< @return an updated Ptr virtual void scaleObject (const Ptr& ptr, float scale); From cfcfb173205bb1148b7b40f20b3eb75eb6791295 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 18 May 2015 07:12:02 +1000 Subject: [PATCH 102/142] Updates to optional horizontal scrollbar. - move SizeHintWidget out to separate files - remove redundant logic in view.cpp - remove sizehint from dialogue subview - add tooltip hints in user preferences --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/settings/usersettings.cpp | 4 ++++ apps/opencs/view/doc/sizehint.cpp | 17 ++++++++++++++++ apps/opencs/view/doc/sizehint.hpp | 22 +++++++++++++++++++++ apps/opencs/view/doc/subview.cpp | 16 --------------- apps/opencs/view/doc/subview.hpp | 13 ------------ apps/opencs/view/doc/view.cpp | 7 +------ apps/opencs/view/world/dialoguesubview.cpp | 12 +---------- apps/opencs/view/world/tablesubview.cpp | 1 + 9 files changed, 47 insertions(+), 47 deletions(-) create mode 100644 apps/opencs/view/doc/sizehint.cpp create mode 100644 apps/opencs/view/doc/sizehint.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 9fb80324ec..438f3c6941 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -46,7 +46,7 @@ opencs_units_noqt (model/tools opencs_units (view/doc viewmanager view operations operation subview startup filedialog newgame - filewidget adjusterwidget loader globaldebugprofilemenu runlogsubview + filewidget adjusterwidget loader globaldebugprofilemenu runlogsubview sizehint ) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index bd31b6e384..ea002c5edd 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -151,6 +151,10 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "Add a horizontal scrollbar to the main view window."); mainwinScroll->setDefaultValue (defaultScroll); mainwinScroll->setDeclaredValues (scrollValues); + mainwinScroll->setToolTip ("Scrollbar Only: Simple addition of scrollbars, the view window does not grow" + " automatically.\n" + "Grow Only: Original Editor behaviour. The view window grows as subviews are added. No scrollbars.\n" + "Grow then Scroll: The view window grows. The scrollbar appears once it cannot grow any further."); Setting *grow = createSetting (Type_CheckBox, "grow-limit", "Grow Limit Screen"); grow->setDefaultValue ("false"); diff --git a/apps/opencs/view/doc/sizehint.cpp b/apps/opencs/view/doc/sizehint.cpp new file mode 100644 index 0000000000..038bd9e4d1 --- /dev/null +++ b/apps/opencs/view/doc/sizehint.cpp @@ -0,0 +1,17 @@ +#include "sizehint.hpp" + +CSVDoc::SizeHintWidget::SizeHintWidget(QWidget *parent) : QWidget(parent) +{} + +CSVDoc::SizeHintWidget::~SizeHintWidget() +{} + +QSize CSVDoc::SizeHintWidget::sizeHint() const +{ + return mSize; +} + +void CSVDoc::SizeHintWidget::setSizeHint(const QSize &size) +{ + mSize = size; +} diff --git a/apps/opencs/view/doc/sizehint.hpp b/apps/opencs/view/doc/sizehint.hpp new file mode 100644 index 0000000000..cf5a02580e --- /dev/null +++ b/apps/opencs/view/doc/sizehint.hpp @@ -0,0 +1,22 @@ +#ifndef CSV_DOC_SIZEHINT_H +#define CSV_DOC_SIZEHINT_H + +#include +#include + +namespace CSVDoc +{ + class SizeHintWidget : public QWidget + { + QSize mSize; + + public: + SizeHintWidget(QWidget *parent = 0); + ~SizeHintWidget(); + + virtual QSize sizeHint() const; + void setSizeHint(const QSize &size); + }; +} + +#endif // CSV_DOC_SIZEHINT_H diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index 09128d9191..df1e7ee492 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -43,19 +43,3 @@ void CSVDoc::SubView::closeRequest() { emit closeRequest (this); } - -CSVDoc::SizeHintWidget::SizeHintWidget(QWidget *parent) : QWidget(parent) -{} - -CSVDoc::SizeHintWidget::~SizeHintWidget() -{} - -QSize CSVDoc::SizeHintWidget::sizeHint() const -{ - return mSize; -} - -void CSVDoc::SizeHintWidget::setSizeHint(const QSize &size) -{ - mSize = size; -} diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index f327107c21..a8aa3cda1e 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -8,7 +8,6 @@ #include "subviewfactory.hpp" #include -#include class QUndoStack; @@ -71,18 +70,6 @@ namespace CSVDoc void closeRequest(); }; - - class SizeHintWidget : public QWidget - { - QSize mSize; - - public: - SizeHintWidget(QWidget *parent = 0); - ~SizeHintWidget(); - - virtual QSize sizeHint() const; - void setSizeHint(const QSize &size); - }; } #endif diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 16b96ed4d3..47810a1155 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -563,12 +563,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin // CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); QString mainwinScroll = settings.settingValue ("window/mainwindow-scrollbar"); - if (mainwinScroll.isEmpty() || mainwinScroll == "Scrollbar Only") - mScrollbarOnly = true; - else if(mainwinScroll == "Grow Only") - mScrollbarOnly = false; - else - mScrollbarOnly = false; + mScrollbarOnly = mainwinScroll.isEmpty() || mainwinScroll == "Scrollbar Only"; QDesktopWidget *dw = QApplication::desktop(); QRect rect; diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index ccab576fa0..0d0e82dbf3 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include "../../model/world/nestedtableproxymodel.hpp" #include "../../model/world/columnbase.hpp" @@ -583,15 +581,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM changeCurrentId(id.getId()); - //QWidget *mainWidget = new QWidget(this); - CSVDoc::SizeHintWidget *mainWidget = new CSVDoc::SizeHintWidget; - - const QRect rect = QApplication::desktop()->screenGeometry(this); - int frameHeight = 40; // set a reasonable default - QWidget *topLevel = QApplication::topLevelAt(pos()); - if (topLevel) - frameHeight = topLevel->frameGeometry().height() - topLevel->height(); - mainWidget->setSizeHint(QSize(400, rect.height()-frameHeight)); // FIXME: 400 + QWidget *mainWidget = new QWidget(this); QHBoxLayout *buttonsLayout = new QHBoxLayout; QToolButton* prevButton = new QToolButton(mainWidget); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index dde04fb3f7..af0b644475 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -10,6 +10,7 @@ #include "../../model/doc/document.hpp" #include "../../model/world/tablemimedata.hpp" +#include "../doc/sizehint.hpp" #include "../filter/filterbox.hpp" #include "table.hpp" #include "tablebottombox.hpp" From 7494340b66500c08aa6f6f7fe41c957d293cdcab Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 18 May 2015 22:08:36 +1000 Subject: [PATCH 103/142] Add the remaining NPC data for editing with dialogue subview. Should resolve Bug #2547. --- apps/opencs/model/world/columns.cpp | 15 + apps/opencs/model/world/columns.hpp | 15 + apps/opencs/model/world/refidadapterimp.cpp | 350 +++++++++++++++++++- apps/opencs/model/world/refidadapterimp.hpp | 95 ++++++ apps/opencs/model/world/refidcollection.cpp | 56 ++++ apps/opencs/view/world/dialoguesubview.cpp | 6 +- 6 files changed, 535 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 89ee6258b5..2bfe79464f 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -281,6 +281,21 @@ namespace CSMWorld { ColumnId_InfoCondValue, "Value" }, { ColumnId_OriginalCell, "Original Cell" }, + { ColumnId_NpcAttributes, "Attributes" }, + { ColumnId_NpcSkills, "Skills" }, + { ColumnId_UChar, "Value [0..255]" }, + { ColumnId_NpcMisc, "Misc" }, + { ColumnId_NpcLevel, "Level" }, + { ColumnId_NpcFactionID, "Faction ID" }, + { ColumnId_NpcHealth, "Health" }, + { ColumnId_NpcMana, "Mana" }, + { ColumnId_NpcFatigue, "Fatigue" }, + { ColumnId_NpcDisposition, "Disposition" }, + { ColumnId_NpcReputation, "Reputation" }, + { ColumnId_NpcRank, "Rank" }, + { ColumnId_NpcGold, "Gold" }, + { ColumnId_NpcPersistence, "Persistent" }, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index f971f3fd89..b2234ad49c 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -272,6 +272,21 @@ namespace CSMWorld ColumnId_OriginalCell = 247, + ColumnId_NpcAttributes = 248, + ColumnId_NpcSkills = 249, + ColumnId_UChar = 250, + ColumnId_NpcMisc = 251, + ColumnId_NpcLevel = 252, + ColumnId_NpcFactionID = 253, + ColumnId_NpcHealth = 254, + ColumnId_NpcMana = 255, + ColumnId_NpcFatigue = 256, + ColumnId_NpcDisposition = 257, + ColumnId_NpcReputation = 258, + ColumnId_NpcRank = 259, + ColumnId_NpcGold = 260, + ColumnId_NpcPersistence = 261, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 98c1b6f0f3..a5f0b22449 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -468,7 +468,10 @@ CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) mClass(NULL), mFaction(NULL), mHair(NULL), - mHead(NULL) + mHead(NULL), + mAttributes(NULL), + mSkills(NULL), + mMisc(NULL) {} CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns) @@ -496,6 +499,17 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re if (column==mColumns.mHead) return QString::fromUtf8 (record.get().mHead.c_str()); + if (column==mColumns.mAttributes || column==mColumns.mSkills) + { + if ((record.get().mFlags & ESM::NPC::Autocalc) != 0) + return QVariant(); + else + return true; + } + + if (column==mColumns.mMisc) + return true; + std::map::const_iterator iter = mColumns.mFlags.find (column); @@ -538,6 +552,340 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d } } +CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter () +{} + +void CSMWorld::NpcAttributesRefIdAdapter::addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::NpcAttributesRefIdAdapter::removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::NpcAttributesRefIdAdapter::setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + ESM::NPC npc = record.get(); + + // store the whole struct + npc.mNpdt52 = + static_cast > &>(nestedTable).mNestedTable.at(0); + + record.setModified (npc); +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::NpcAttributesRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + + // return the whole struct + std::vector wrap; + wrap.push_back(record.get().mNpdt52); + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(wrap); +} + +QVariant CSMWorld::NpcAttributesRefIdAdapter::getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + + const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52; + + if (subColIndex == 0) + switch (subRowIndex) + { + case 0: return QString("Strength"); + case 1: return QString("Intelligence"); + case 2: return QString("Willpower"); + case 3: return QString("Agility"); + case 4: return QString("Speed"); + case 5: return QString("Endurance"); + case 6: return QString("Personality"); + case 7: return QString("Luck"); + default: return QVariant(); // throw an exception here? + } + else if (subColIndex == 1) + switch (subRowIndex) + { + case 0: return static_cast(npcStruct.mStrength); + case 1: return static_cast(npcStruct.mIntelligence); + case 2: return static_cast(npcStruct.mWillpower); + case 3: return static_cast(npcStruct.mAgility); + case 4: return static_cast(npcStruct.mSpeed); + case 5: return static_cast(npcStruct.mEndurance); + case 6: return static_cast(npcStruct.mPersonality); + case 7: return static_cast(npcStruct.mLuck); + default: return QVariant(); // throw an exception here? + } + else + return QVariant(); // throw an exception here? +} + +void CSMWorld::NpcAttributesRefIdAdapter::setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc))); + ESM::NPC npc = record.get(); + ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52; + + if (subColIndex == 1) + switch(subRowIndex) + { + case 0: npcStruct.mStrength = static_cast(value.toInt()); break; + case 1: npcStruct.mIntelligence = static_cast(value.toInt()); break; + case 2: npcStruct.mWillpower = static_cast(value.toInt()); break; + case 3: npcStruct.mAgility = static_cast(value.toInt()); break; + case 4: npcStruct.mSpeed = static_cast(value.toInt()); break; + case 5: npcStruct.mEndurance = static_cast(value.toInt()); break; + case 6: npcStruct.mPersonality = static_cast(value.toInt()); break; + case 7: npcStruct.mLuck = static_cast(value.toInt()); break; + default: return; // throw an exception here? + } + else + return; // throw an exception here? + + record.setModified (npc); +} + +int CSMWorld::NpcAttributesRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + return 2; +} + +int CSMWorld::NpcAttributesRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + // There are 8 attributes + return 8; +} + +CSMWorld::NpcSkillsRefIdAdapter::NpcSkillsRefIdAdapter () +{} + +void CSMWorld::NpcSkillsRefIdAdapter::addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::NpcSkillsRefIdAdapter::removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const +{ + // Do nothing, this table cannot be changed by the user +} + +void CSMWorld::NpcSkillsRefIdAdapter::setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + ESM::NPC npc = record.get(); + + // store the whole struct + npc.mNpdt52 = + static_cast > &>(nestedTable).mNestedTable.at(0); + + record.setModified (npc); +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::NpcSkillsRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + + // return the whole struct + std::vector wrap; + wrap.push_back(record.get().mNpdt52); + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(wrap); +} + +QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + + const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52; + + if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length) + std::cout << "getNestedDatat index" << std::endl; + //throw std::runtime_error ("index out of range"); + + if (subColIndex == 0) + return QString(ESM::Skill::sSkillNames[subRowIndex].c_str()); + else if (subColIndex == 1) + return static_cast(npcStruct.mSkills[subRowIndex]); + else + return QVariant(); // throw an exception here? +} + +void CSMWorld::NpcSkillsRefIdAdapter::setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc))); + ESM::NPC npc = record.get(); + ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52; + + if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length) + std::cout << "setNestedDatat index" << std::endl; + //throw std::runtime_error ("index out of range"); + + if (subColIndex == 1) + npcStruct.mSkills[subRowIndex] = static_cast(value.toInt()); + else + return; // throw an exception here? + + record.setModified (npc); +} + +int CSMWorld::NpcSkillsRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + return 2; +} + +int CSMWorld::NpcSkillsRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + // There are 27 skills + return ESM::Skill::Length; +} + +CSMWorld::NpcMiscRefIdAdapter::NpcMiscRefIdAdapter () +{} + +CSMWorld::NpcMiscRefIdAdapter::~NpcMiscRefIdAdapter() +{} + +void CSMWorld::NpcMiscRefIdAdapter::addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const +{ + throw std::logic_error ("cannot add a row to a fixed table"); +} + +void CSMWorld::NpcMiscRefIdAdapter::removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const +{ + throw std::logic_error ("cannot remove a row to a fixed table"); +} + +void CSMWorld::NpcMiscRefIdAdapter::setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const +{ + throw std::logic_error ("table operation not supported"); +} + +CSMWorld::NestedTableWrapperBase* CSMWorld::NpcMiscRefIdAdapter::nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const +{ + throw std::logic_error ("table operation not supported"); +} + +QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const +{ + const Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); + + bool autoCalc = (record.get().mFlags & ESM::NPC::Autocalc) != 0; + + if (autoCalc) + switch (subColIndex) + { + case 0: return static_cast(record.get().mNpdt12.mLevel); + case 1: return QVariant(); + case 2: return QVariant(); + case 3: return QVariant(); + case 4: return QVariant(); + case 5: return static_cast(record.get().mNpdt12.mDisposition); + case 6: return static_cast(record.get().mNpdt12.mReputation); + case 7: return static_cast(record.get().mNpdt12.mRank); + case 8: return record.get().mNpdt12.mGold; + case 9: return record.get().mPersistent == true; + default: return QVariant(); // throw an exception here? + } + else + switch (subColIndex) + { + case 0: return static_cast(record.get().mNpdt52.mLevel); + case 1: return static_cast(record.get().mNpdt52.mFactionID); + case 2: return static_cast(record.get().mNpdt52.mHealth); + case 3: return static_cast(record.get().mNpdt52.mMana); + case 4: return static_cast(record.get().mNpdt52.mFatigue); + case 5: return static_cast(record.get().mNpdt52.mDisposition); + case 6: return static_cast(record.get().mNpdt52.mReputation); + case 7: return static_cast(record.get().mNpdt52.mRank); + case 8: return record.get().mNpdt52.mGold; + case 9: return record.get().mPersistent == true; + default: return QVariant(); // throw an exception here? + } +} + +void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const +{ + Record& record = + static_cast&> (data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Npc))); + ESM::NPC npc = record.get(); + + bool autoCalc = (record.get().mFlags & ESM::NPC::Autocalc) != 0; + + if (autoCalc) + switch(subColIndex) + { + case 0: npc.mNpdt12.mLevel = static_cast(value.toInt()); break; + case 1: return; + case 2: return; + case 3: return; + case 4: return; + case 5: npc.mNpdt12.mDisposition = static_cast(value.toInt()); break; + case 6: npc.mNpdt12.mReputation = static_cast(value.toInt()); break; + case 7: npc.mNpdt12.mRank = static_cast(value.toInt()); break; + case 8: npc.mNpdt12.mGold = value.toInt(); break; + case 9: npc.mPersistent = value.toBool(); break; + default: return; // throw an exception here? + } + else + switch(subColIndex) + { + case 0: npc.mNpdt52.mLevel = static_cast(value.toInt()); break; + case 1: npc.mNpdt52.mFactionID = static_cast(value.toInt()); break; + case 2: npc.mNpdt52.mHealth = static_cast(value.toInt()); break; + case 3: npc.mNpdt52.mMana = static_cast(value.toInt()); break; + case 4: npc.mNpdt52.mFatigue = static_cast(value.toInt()); break; + case 5: npc.mNpdt52.mDisposition = static_cast(value.toInt()); break; + case 6: npc.mNpdt52.mReputation = static_cast(value.toInt()); break; + case 7: npc.mNpdt52.mRank = static_cast(value.toInt()); break; + case 8: npc.mNpdt52.mGold = value.toInt(); break; + case 9: npc.mPersistent = value.toBool(); break; + default: return; // throw an exception here? + } + + record.setModified (npc); +} + +int CSMWorld::NpcMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const +{ + return 10; // Level, FactionID, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold, Persist +} + +int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const +{ + return 1; // fixed at size 1 +} + CSMWorld::WeaponColumns::WeaponColumns (const EnchantableColumns& columns) : EnchantableColumns (columns) {} diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 61e8115c0e..143b46c44b 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -792,6 +792,9 @@ namespace CSMWorld const RefIdColumn *mFaction; const RefIdColumn *mHair; const RefIdColumn *mHead; + const RefIdColumn *mAttributes; // depends on npc type + const RefIdColumn *mSkills; // depends on npc type + const RefIdColumn *mMisc; // may depend on npc type, e.g. FactionID NpcColumns (const ActorColumns& actorColumns); }; @@ -842,8 +845,100 @@ namespace CSMWorld ///< If the data type does not match an exception is thrown. }; + class NestedRefIdAdapterBase; + class NpcAttributesRefIdAdapter : public NestedRefIdAdapterBase + { + public: + + NpcAttributesRefIdAdapter (); + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const; + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const; + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const; + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + }; + + class NpcSkillsRefIdAdapter : public NestedRefIdAdapterBase + { + public: + + NpcSkillsRefIdAdapter (); + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const; + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const; + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const; + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + }; + + class NpcMiscRefIdAdapter : public NestedRefIdAdapterBase + { + NpcMiscRefIdAdapter (const NpcMiscRefIdAdapter&); + NpcMiscRefIdAdapter& operator= (const NpcMiscRefIdAdapter&); + + public: + + NpcMiscRefIdAdapter (); + virtual ~NpcMiscRefIdAdapter(); + + virtual void addNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int position) const; + + virtual void removeNestedRow (const RefIdColumn *column, + RefIdData& data, int index, int rowToRemove) const; + + virtual void setNestedTable (const RefIdColumn* column, + RefIdData& data, int index, const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* nestedTable (const RefIdColumn* column, + const RefIdData& data, int index) const; + + virtual QVariant getNestedData (const RefIdColumn *column, + const RefIdData& data, int index, int subRowIndex, int subColIndex) const; + + virtual void setNestedData (const RefIdColumn *column, + RefIdData& data, int row, const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const; + + virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const; + }; + template class EffectsListAdapter; diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 1941c505a2..9d9e9826af 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -427,6 +427,62 @@ CSMWorld::RefIdCollection::RefIdCollection() npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal)); + // Need a way to add a table of stats and values (rather than adding a long list of + // entries in the dialogue subview) E.g. attributes+stats(health, mana, fatigue), skills + // These needs to be driven from the autocalculated setting. + + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcAttributes, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + npcColumns.mAttributes = &mColumns.back(); + std::map attrMap; + attrMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcAttributesRefIdAdapter())); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), attrMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcAttributes, CSMWorld::ColumnBase::Display_String, false, false)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer)); + + // Nested table + mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcSkills, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue)); + npcColumns.mSkills = &mColumns.back(); + std::map skillsMap; + skillsMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcSkillsRefIdAdapter())); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), skillsMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcSkills, CSMWorld::ColumnBase::Display_String, false, false)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_UChar, CSMWorld::ColumnBase::Display_Integer)); + + // Nested list + mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcMisc, + ColumnBase::Display_NestedHeader, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List)); + npcColumns.mMisc = &mColumns.back(); + std::map miscMap; + miscMap.insert(std::make_pair(UniversalId::Type_Npc, new NpcMiscRefIdAdapter())); + mNestedAdapters.push_back (std::make_pair(&mColumns.back(), miscMap)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcLevel, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcFactionID, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcHealth, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcMana, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcFatigue, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcDisposition, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcReputation, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcGold, CSMWorld::ColumnBase::Display_Integer)); + mColumns.back().addColumn( + new RefIdColumn (Columns::ColumnId_NpcPersistence, CSMWorld::ColumnBase::Display_Boolean)); + WeaponColumns weaponColumns (enchantableColumns); mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponType, ColumnBase::Display_WeaponType)); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 0d0e82dbf3..4b4afc6668 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "../../model/world/nestedtableproxymodel.hpp" #include "../../model/world/columnbase.hpp" @@ -511,7 +512,7 @@ void CSVWorld::EditWidget::remake(int row) mNestedTableMapper->setModel(mNestedModels.back()); // FIXME: lack MIME support? mNestedTableDispatcher = - new DialogueDelegateDispatcher (this, mTable, mCommandDispatcher, mDocument, mNestedModels.back()); + new DialogueDelegateDispatcher (0/*this*/, mTable, mCommandDispatcher, mDocument, mNestedModels.back()); mNestedTableMapper->setItemDelegate(mNestedTableDispatcher); int columnCount = @@ -763,6 +764,9 @@ void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index) CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); + int y = mEditWidget->verticalScrollBar()->value(); + mEditWidget->remake (index.row()); + mEditWidget->verticalScrollBar()->setValue(y); } } From 0ecfd9119f1c7ec5c2326c7d15a1b1a1813fa354 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 19 May 2015 06:56:38 +1000 Subject: [PATCH 104/142] Add the remaining Race data for editing with dialogue subview. Should resolve Bug #2546. --- apps/opencs/model/world/columnbase.cpp | 1 + apps/opencs/model/world/columnbase.hpp | 1 + apps/opencs/model/world/columns.cpp | 8 + apps/opencs/model/world/columns.hpp | 7 + apps/opencs/model/world/data.cpp | 18 +++ .../model/world/nestedcoladapterimp.cpp | 153 ++++++++++++++++++ .../model/world/nestedcoladapterimp.hpp | 51 ++++++ apps/opencs/view/doc/viewmanager.cpp | 3 +- 8 files changed, 241 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index cf125aa639..087a1df7bd 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -84,6 +84,7 @@ bool CSMWorld::ColumnBase::isId (Display display) Display_InfoCondFunc, Display_InfoCondVar, Display_InfoCondComp, + Display_RaceSkill, Display_None }; diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 2d2513774a..d6dd4b291b 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -119,6 +119,7 @@ namespace CSMWorld Display_InfoCondFunc, Display_InfoCondVar, Display_InfoCondComp, + Display_RaceSkill, //top level columns that nest other columns Display_NestedHeader diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 2bfe79464f..daf537c0c9 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -296,6 +296,13 @@ namespace CSMWorld { ColumnId_NpcGold, "Gold" }, { ColumnId_NpcPersistence, "Persistent" }, + { ColumnId_RaceAttributes, "Attributes" }, + { ColumnId_RaceMaleValue, "Male" }, + { ColumnId_RaceFemaleValue, "Female" }, + { ColumnId_RaceSkillBonus, "Skill Bonus" }, + { ColumnId_RaceSkill, "Skills" }, + { ColumnId_RaceBonus, "Bonus" }, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, @@ -566,6 +573,7 @@ namespace // FIXME: don't have dynamic value enum delegate, use Display_String for now //case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond; case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp; + case CSMWorld::Columns::ColumnId_RaceSkill: return sSkills; default: return 0; } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index b2234ad49c..85276a695f 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -287,6 +287,13 @@ namespace CSMWorld ColumnId_NpcGold = 260, ColumnId_NpcPersistence = 261, + ColumnId_RaceAttributes = 262, + ColumnId_RaceMaleValue = 263, + ColumnId_RaceFemaleValue = 264, + ColumnId_RaceSkillBonus = 265, + ColumnId_RaceSkill = 266, + ColumnId_RaceBonus = 267, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index e2fab0a25b..fa7e48a0ea 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -136,6 +136,24 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new SpellListAdapter ())); mRaces.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String)); + // Race attributes + mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceAttributes)); + index = mRaces.getColumns()-1; + mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter())); + mRaces.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_RaceAttributes, ColumnBase::Display_String, false)); + mRaces.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_RaceMaleValue, ColumnBase::Display_Integer)); + mRaces.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_RaceFemaleValue, ColumnBase::Display_Integer)); + // Race skill bonus + mRaces.addColumn (new NestedParentColumn (Columns::ColumnId_RaceSkillBonus)); + index = mRaces.getColumns()-1; + mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter())); + mRaces.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_RaceSkill, ColumnBase::Display_RaceSkill)); + mRaces.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer)); mSounds.addColumn (new StringIdColumn); mSounds.addColumn (new RecordStateColumn); diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index a0d7645767..7efe14dee2 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -880,4 +880,157 @@ namespace CSMWorld { return static_cast(record.get().mSelects.size()); } + + RaceAttributeAdapter::RaceAttributeAdapter () {} + + void RaceAttributeAdapter::addRow(Record& record, int position) const + { + // Do nothing, this table cannot be changed by the user + } + + void RaceAttributeAdapter::removeRow(Record& record, int rowToRemove) const + { + // Do nothing, this table cannot be changed by the user + } + + void RaceAttributeAdapter::setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + ESM::Race race = record.get(); + + race.mData = + static_cast >&>(nestedTable).mNestedTable.at(0); + + record.setModified (race); + } + + NestedTableWrapperBase* RaceAttributeAdapter::table(const Record& record) const + { + std::vector wrap; + wrap.push_back(record.get().mData); + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(wrap); + } + + QVariant RaceAttributeAdapter::getData(const Record& record, + int subRowIndex, int subColIndex) const + { + ESM::Race race = record.get(); + + if (subRowIndex < 0 || subRowIndex >= ESM::Attribute::Length) + throw std::runtime_error ("index out of range"); + + switch (subColIndex) + { + case 0: return QString(ESM::Attribute::sAttributeNames[subRowIndex].c_str()); + case 1: return race.mData.mAttributeValues[subRowIndex].mMale; + case 2: return race.mData.mAttributeValues[subRowIndex].mFemale; + default: throw std::runtime_error("Race Attribute subcolumn index out of range"); + } + } + + void RaceAttributeAdapter::setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + ESM::Race race = record.get(); + + if (subRowIndex < 0 || subRowIndex >= ESM::Attribute::Length) + throw std::runtime_error ("index out of range"); + + switch (subColIndex) + { + case 0: return; // throw an exception here? + case 1: race.mData.mAttributeValues[subRowIndex].mMale = value.toInt(); break; + case 2: race.mData.mAttributeValues[subRowIndex].mFemale = value.toInt(); break; + default: throw std::runtime_error("Race Attribute subcolumn index out of range"); + } + + record.setModified (race); + } + + int RaceAttributeAdapter::getColumnsCount(const Record& record) const + { + return 3; // attrib, male, female + } + + int RaceAttributeAdapter::getRowsCount(const Record& record) const + { + return ESM::Attribute::Length; // there are 8 attributes + } + + RaceSkillsBonusAdapter::RaceSkillsBonusAdapter () {} + + void RaceSkillsBonusAdapter::addRow(Record& record, int position) const + { + // Do nothing, this table cannot be changed by the user + } + + void RaceSkillsBonusAdapter::removeRow(Record& record, int rowToRemove) const + { + // Do nothing, this table cannot be changed by the user + } + + void RaceSkillsBonusAdapter::setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + ESM::Race race = record.get(); + + race.mData = + static_cast >&>(nestedTable).mNestedTable.at(0); + + record.setModified (race); + } + + NestedTableWrapperBase* RaceSkillsBonusAdapter::table(const Record& record) const + { + std::vector wrap; + wrap.push_back(record.get().mData); + // deleted by dtor of NestedTableStoring + return new NestedTableWrapper >(wrap); + } + + QVariant RaceSkillsBonusAdapter::getData(const Record& record, + int subRowIndex, int subColIndex) const + { + ESM::Race race = record.get(); + + if (subRowIndex < 0 || subRowIndex >= static_cast(sizeof(race.mData.mBonus)/sizeof(race.mData.mBonus[0]))) + throw std::runtime_error ("index out of range"); + + switch (subColIndex) + { + case 0: return race.mData.mBonus[subRowIndex].mSkill; // can be -1 + case 1: return race.mData.mBonus[subRowIndex].mBonus; + default: throw std::runtime_error("Race skill bonus subcolumn index out of range"); + } + } + + void RaceSkillsBonusAdapter::setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + ESM::Race race = record.get(); + + if (subRowIndex < 0 || subRowIndex >= static_cast(sizeof(race.mData.mBonus)/sizeof(race.mData.mBonus[0]))) + throw std::runtime_error ("index out of range"); + + switch (subColIndex) + { + case 0: race.mData.mBonus[subRowIndex].mSkill = value.toInt(); break; // can be -1 + case 1: race.mData.mBonus[subRowIndex].mBonus = value.toInt(); break; + default: throw std::runtime_error("Race skill bonus subcolumn index out of range"); + } + + record.setModified (race); + } + + int RaceSkillsBonusAdapter::getColumnsCount(const Record& record) const + { + return 2; // skill, bonus + } + + int RaceSkillsBonusAdapter::getRowsCount(const Record& record) const + { + // there are 7 skill bonuses + return static_cast(sizeof(record.get().mData.mBonus)/sizeof(record.get().mData.mBonus[0])); + } } diff --git a/apps/opencs/model/world/nestedcoladapterimp.hpp b/apps/opencs/model/world/nestedcoladapterimp.hpp index 776a908bad..4b1e2cd09e 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.hpp +++ b/apps/opencs/model/world/nestedcoladapterimp.hpp @@ -8,6 +8,7 @@ #include // for converting magic effect id to string & back #include // for converting skill names #include // for converting attributes +#include #include "nestedcolumnadapter.hpp" #include "nestedtablewrapper.hpp" @@ -437,6 +438,56 @@ namespace CSMWorld virtual int getRowsCount(const Record& record) const; }; + + class RaceAttributeAdapter : public NestedColumnAdapter + { + public: + RaceAttributeAdapter (); + + virtual void addRow(Record& record, int position) const; + + virtual void removeRow(Record& record, int rowToRemove) const; + + virtual void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* table(const Record& record) const; + + virtual QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const; + + virtual void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getColumnsCount(const Record& record) const; + + virtual int getRowsCount(const Record& record) const; + }; + + class RaceSkillsBonusAdapter : public NestedColumnAdapter + { + public: + RaceSkillsBonusAdapter (); + + virtual void addRow(Record& record, int position) const; + + virtual void removeRow(Record& record, int rowToRemove) const; + + virtual void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* table(const Record& record) const; + + virtual QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const; + + virtual void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getColumnsCount(const Record& record) const; + + virtual int getRowsCount(const Record& record) const; + }; } #endif // CSM_WOLRD_NESTEDCOLADAPTERIMP_H diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 6362f96590..97b7aac19a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -92,7 +92,8 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) { CSMWorld::ColumnBase::Display_AiPackageType, CSMWorld::Columns::ColumnId_AiPackageType, false }, { CSMWorld::ColumnBase::Display_YesNo, CSMWorld::Columns::ColumnId_AiWanderRepeat, false }, { CSMWorld::ColumnBase::Display_InfoCondFunc, CSMWorld::Columns::ColumnId_InfoCondFunc, false }, - { CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false } + { CSMWorld::ColumnBase::Display_InfoCondComp, CSMWorld::Columns::ColumnId_InfoCondComp, false }, + { CSMWorld::ColumnBase::Display_RaceSkill, CSMWorld::Columns::ColumnId_RaceSkill, true }, }; for (std::size_t i=0; i Date: Tue, 19 May 2015 19:19:52 +1000 Subject: [PATCH 105/142] Fix occasional crash with DialogueSubView, e.g. when deleting a row of a subtable. --- apps/opencs/view/world/dialoguesubview.cpp | 57 ++++++++++++---------- apps/opencs/view/world/dialoguesubview.hpp | 2 +- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 4b4afc6668..fee302e2c7 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -348,16 +348,19 @@ CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher() CSVWorld::EditWidget::~EditWidget() { for (unsigned i = 0; i < mNestedModels.size(); ++i) - { delete mNestedModels[i]; - } - delete mNestedTableDispatcher; + + if (mDispatcher) + delete mDispatcher; + + if (mNestedTableDispatcher) + delete mNestedTableDispatcher; } CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, bool createAndDelete) : -mDispatcher(this, table, commandDispatcher, document), +mDispatcher(0), mNestedTableDispatcher(NULL), QScrollArea(parent), mWidgetMapper(NULL), @@ -369,41 +372,41 @@ mTable(table) { remake (row); - connect(&mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), + connect(mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); } void CSVWorld::EditWidget::remake(int row) { for (unsigned i = 0; i < mNestedModels.size(); ++i) - { delete mNestedModels[i]; - } - mNestedModels.clear(); - delete mNestedTableDispatcher; - if (mMainWidget) - { - delete mMainWidget; - mMainWidget = 0; - } - mMainWidget = new QWidget (this); + mNestedModels.clear(); + + if (mDispatcher) + delete mDispatcher; + mDispatcher = new DialogueDelegateDispatcher(0/*this*/, mTable, mCommandDispatcher, mDocument); + + if (mNestedTableDispatcher) + delete mNestedTableDispatcher; //not sure if widget mapper can handle deleting the widgets that were mapped if (mWidgetMapper) - { delete mWidgetMapper; - mWidgetMapper = 0; - } - if (mNestedTableMapper) - { - delete mNestedTableMapper; - mNestedTableMapper = 0; - } - mWidgetMapper = new QDataWidgetMapper (this); + mWidgetMapper = new QDataWidgetMapper (this); mWidgetMapper->setModel(mTable); - mWidgetMapper->setItemDelegate(&mDispatcher); + mWidgetMapper->setItemDelegate(mDispatcher); + + if (mNestedTableMapper) + delete mNestedTableMapper; + + if (mMainWidget) + { + QWidget *del = this->takeWidget(); + del->deleteLater(); + } + mMainWidget = new QWidget (this); QFrame* line = new QFrame(mMainWidget); line->setObjectName(QString::fromUtf8("line")); @@ -476,8 +479,8 @@ void CSVWorld::EditWidget::remake(int row) } else if (!(flags & CSMWorld::ColumnBase::Flag_Dialogue_List)) { - mDispatcher.makeDelegate (display); - QWidget* editor = mDispatcher.makeEditor (display, (mTable->index (row, i))); + mDispatcher->makeDelegate (display); + QWidget* editor = mDispatcher->makeEditor (display, (mTable->index (row, i))); if (editor) { diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index b5a44d266f..8783d935f6 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -165,7 +165,7 @@ namespace CSVWorld Q_OBJECT QDataWidgetMapper *mWidgetMapper; QDataWidgetMapper *mNestedTableMapper; - DialogueDelegateDispatcher mDispatcher; + DialogueDelegateDispatcher *mDispatcher; DialogueDelegateDispatcher *mNestedTableDispatcher; QWidget* mMainWidget; CSMWorld::IdTable* mTable; From b27a879352b155205a9809f567007e97bf7dd1a6 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 19 May 2015 22:01:40 +1000 Subject: [PATCH 106/142] Add the remaining Cell data for editing with dialogue subview. Should resolve Bug #2551. - NOTE: the interior water flag and water level logic needs reviewing - does not automatically disable region names for interiors without mQuasiEx flag - Colour values can't be entered as RGB - Region names are not drop down menus --- apps/opencs/model/world/columns.cpp | 11 +- apps/opencs/model/world/columns.hpp | 11 +- apps/opencs/model/world/data.cpp | 25 ++- apps/opencs/model/world/data.hpp | 2 +- .../model/world/nestedcoladapterimp.cpp | 161 +++++++++++++++++- .../model/world/nestedcoladapterimp.hpp | 26 +++ 6 files changed, 230 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index daf537c0c9..ee7a00ca0f 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -62,7 +62,7 @@ namespace CSMWorld { ColumnId_StarterSpell, "Starter Spell" }, { ColumnId_AlwaysSucceeds, "Always Succeeds" }, { ColumnId_SleepForbidden, "Sleep Forbidden" }, - { ColumnId_InteriorWater, "Interior Water" }, + { ColumnId_Water, "Has Water" }, { ColumnId_InteriorSky, "Interior Sky" }, { ColumnId_Model, "Model" }, { ColumnId_Script, "Script" }, @@ -303,6 +303,15 @@ namespace CSMWorld { ColumnId_RaceSkill, "Skills" }, { ColumnId_RaceBonus, "Bonus" }, + { ColumnId_Interior, "Interior" }, + { ColumnId_Ambient, "Ambient" }, + { ColumnId_Sunlight, "Sunlight" }, + { ColumnId_Fog, "Fog" }, + { ColumnId_FogDensity, "Fog Density" }, + { ColumnId_WaterLevel, "Water Level" }, + { ColumnId_InteriorWater, "Interior Water" }, + { ColumnId_MapColor, "Map Color" }, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 85276a695f..3a345b3ecd 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -57,7 +57,7 @@ namespace CSMWorld ColumnId_StarterSpell = 42, ColumnId_AlwaysSucceeds = 43, ColumnId_SleepForbidden = 44, - ColumnId_InteriorWater = 45, + ColumnId_Water = 45, ColumnId_InteriorSky = 46, ColumnId_Model = 47, ColumnId_Script = 48, @@ -294,6 +294,15 @@ namespace CSMWorld ColumnId_RaceSkill = 266, ColumnId_RaceBonus = 267, + ColumnId_Interior = 268, + ColumnId_Ambient = 269, + ColumnId_Sunlight = 270, + ColumnId_Fog = 271, + ColumnId_FogDensity = 272, + ColumnId_WaterLevel = 273, + ColumnId_InteriorWater = 274, + ColumnId_MapColor = 275, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index fa7e48a0ea..00349d4765 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -287,10 +287,31 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mCells.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Cell)); mCells.addColumn (new NameColumn); mCells.addColumn (new FlagColumn (Columns::ColumnId_SleepForbidden, ESM::Cell::NoSleep)); - mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater)); + mCells.addColumn (new FlagColumn (Columns::ColumnId_Water, ESM::Cell::HasWater)); mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx)); mCells.addColumn (new RegionColumn); mCells.addColumn (new RefNumCounterColumn); + // Misc Cell data + mCells.addColumn (new NestedParentColumn (Columns::ColumnId_Cell, + ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List)); + index = mCells.getColumns()-1; + mCells.addAdapter (std::make_pair(&mCells.getColumn(index), new CellListAdapter ())); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_Interior, ColumnBase::Display_Boolean)); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_Ambient, ColumnBase::Display_Integer)); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_Sunlight, ColumnBase::Display_Integer)); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_Fog, ColumnBase::Display_Integer)); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_FogDensity, ColumnBase::Display_Float)); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_InteriorWater, ColumnBase::Display_Boolean)); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_WaterLevel, ColumnBase::Display_Float)); + mCells.getNestableColumn(index)->addColumn( + new NestedChildColumn (Columns::ColumnId_MapColor, ColumnBase::Display_Integer)); mEnchantments.addColumn (new StringIdColumn); mEnchantments.addColumn (new RecordStateColumn); @@ -465,7 +486,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc addModel (new IdTree (&mTopicInfos, &mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo); addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo); - addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell); + addModel (new IdTree (&mCells, &mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell); addModel (new IdTree (&mEnchantments, &mEnchantments), UniversalId::Type_Enchantment); addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart); addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 8689b98c0c..060e47bd95 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -88,7 +88,7 @@ namespace CSMWorld IdCollection mStartScripts; NestedInfoCollection mTopicInfos; InfoCollection mJournalInfos; - IdCollection mCells; + NestedIdCollection mCells; IdCollection mLandTextures; IdCollection mLand; RefIdCollection mReferenceables; diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 7efe14dee2..a63ebe672d 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -481,7 +481,7 @@ namespace CSMWorld void InfoListAdapter::removeRow(Record& record, int rowToRemove) const { - throw std::logic_error ("cannot add a row to a fixed table"); + throw std::logic_error ("cannot remove a row to a fixed table"); } void InfoListAdapter::setTable(Record& record, @@ -1033,4 +1033,163 @@ namespace CSMWorld // there are 7 skill bonuses return static_cast(sizeof(record.get().mData.mBonus)/sizeof(record.get().mData.mBonus[0])); } + + CellListAdapter::CellListAdapter () {} + + void CellListAdapter::addRow(Record& record, int position) const + { + throw std::logic_error ("cannot add a row to a fixed table"); + } + + void CellListAdapter::removeRow(Record& record, int rowToRemove) const + { + throw std::logic_error ("cannot remove a row to a fixed table"); + } + + void CellListAdapter::setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const + { + throw std::logic_error ("table operation not supported"); + } + + NestedTableWrapperBase* CellListAdapter::table(const Record& record) const + { + throw std::logic_error ("table operation not supported"); + } + + QVariant CellListAdapter::getData(const Record& record, + int subRowIndex, int subColIndex) const + { + CSMWorld::Cell cell = record.get(); + + bool isInterior = (cell.mData.mFlags & ESM::Cell::Interior) != 0; + bool behaveLikeExterior = (cell.mData.mFlags & ESM::Cell::QuasiEx) != 0; + + switch (subColIndex) + { + case 0: return isInterior; + case 1: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mAmbient : QVariant(); + case 2: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mSunlight : QVariant(); + case 3: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mFog : QVariant(); + case 4: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mFogDensity : QVariant(); + case 5: return (isInterior && !behaveLikeExterior) ? cell.mWaterInt==true : QVariant(); + case 6: + { + if (isInterior && !behaveLikeExterior && cell.mWaterInt) + return cell.mWater; + else + return QVariant(); + } + case 7: return isInterior ? QVariant() : cell.mMapColor; // TODO: how to select? + //case 8: return isInterior ? behaveLikeExterior : QVariant(); + default: throw std::runtime_error("Cell subcolumn index out of range"); + } + } + + void CellListAdapter::setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const + { + CSMWorld::Cell cell = record.get(); + + bool isInterior = (cell.mData.mFlags & ESM::Cell::Interior) != 0; + bool behaveLikeExterior = (cell.mData.mFlags & ESM::Cell::QuasiEx) != 0; + + switch (subColIndex) + { + case 0: + { + if (value.toBool()) + cell.mData.mFlags |= ESM::Cell::Interior; + else + cell.mData.mFlags &= ~ESM::Cell::Interior; + break; + } + case 1: + { + if (isInterior && !behaveLikeExterior) + cell.mAmbi.mAmbient = static_cast(value.toInt()); + else + return; // return without saving + break; + } + case 2: + { + if (isInterior && !behaveLikeExterior) + cell.mAmbi.mSunlight = static_cast(value.toInt()); + else + return; // return without saving + break; + } + case 3: + { + if (isInterior && !behaveLikeExterior) + cell.mAmbi.mFog = static_cast(value.toInt()); + else + return; // return without saving + break; + } + case 4: + { + if (isInterior && !behaveLikeExterior) + cell.mAmbi.mFogDensity = value.toFloat(); + else + return; // return without saving + break; + } + case 5: + { + if (isInterior && !behaveLikeExterior) + cell.mWaterInt = value.toBool(); + else + return; // return without saving + break; + } + case 6: + { + if (isInterior && !behaveLikeExterior && cell.mWaterInt) + cell.mWater = value.toFloat(); + else + return; // return without saving + break; + } + case 7: + { + if (!isInterior) + cell.mMapColor = value.toInt(); + else + return; // return without saving + break; + } +#if 0 + // redundant since this flag is shown in the main table as "Interior Sky" + // keep here for documenting the logic based on vanilla + case 8: + { + if (isInterior) + { + if (value.toBool()) + cell.mData.mFlags |= ESM::Cell::QuasiEx; + else + cell.mData.mFlags &= ~ESM::Cell::QuasiEx; + } + else + return; // return without saving + break; + } +#endif + default: throw std::runtime_error("Cell subcolumn index out of range"); + } + + record.setModified (cell); + } + + int CellListAdapter::getColumnsCount(const Record& record) const + { + return 8; + } + + int CellListAdapter::getRowsCount(const Record& record) const + { + return 1; // fixed at size 1 + } } diff --git a/apps/opencs/model/world/nestedcoladapterimp.hpp b/apps/opencs/model/world/nestedcoladapterimp.hpp index 4b1e2cd09e..81c52588bb 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.hpp +++ b/apps/opencs/model/world/nestedcoladapterimp.hpp @@ -12,6 +12,7 @@ #include "nestedcolumnadapter.hpp" #include "nestedtablewrapper.hpp" +#include "cell.hpp" namespace ESM { @@ -488,6 +489,31 @@ namespace CSMWorld virtual int getRowsCount(const Record& record) const; }; + + class CellListAdapter : public NestedColumnAdapter + { + public: + CellListAdapter (); + + virtual void addRow(Record& record, int position) const; + + virtual void removeRow(Record& record, int rowToRemove) const; + + virtual void setTable(Record& record, + const NestedTableWrapperBase& nestedTable) const; + + virtual NestedTableWrapperBase* table(const Record& record) const; + + virtual QVariant getData(const Record& record, + int subRowIndex, int subColIndex) const; + + virtual void setData(Record& record, + const QVariant& value, int subRowIndex, int subColIndex) const; + + virtual int getColumnsCount(const Record& record) const; + + virtual int getRowsCount(const Record& record) const; + }; } #endif // CSM_WOLRD_NESTEDCOLADAPTERIMP_H From 196be7283d07cb371d699fdb1f9d4b19c6841774 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 19 May 2015 21:39:17 +0300 Subject: [PATCH 107/142] Reset an activated reference after activation's exectution (Fix #1738) --- apps/openmw/mwscript/interpretercontext.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index a8c04aa4bc..df675aebbd 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -505,7 +505,10 @@ namespace MWScript boost::shared_ptr action = (ptr.getClass().activate(ptr, actor)); action->execute (actor); if (mActivated == ptr) + { mActivationHandled = true; + mActivated = MWWorld::Ptr(); + } } float InterpreterContext::getSecondsPassed() const From ca7829032eac7e43e0edb58cf4d27137433f0aee Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 20 May 2015 11:45:16 +0200 Subject: [PATCH 108/142] updated credits file --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index 0cd961c613..4fef9233aa 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -98,6 +98,7 @@ Programmers Sebastian Wick (swick) Sergey Shambir sir_herrbatka + smbas Stefan Galowicz (bogglez) Stanislav Bobrov (Jiub) Sylvain Thesnieres (Garvek) From 1d0b8587a1682dd1116b0a254f4b0ea4416fefd9 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 20 May 2015 21:14:17 +1000 Subject: [PATCH 109/142] Use HasWater bit flag rather than mWaterInt bool. --- apps/opencs/model/world/columns.cpp | 3 +-- apps/opencs/model/world/columns.hpp | 5 ++-- apps/opencs/model/world/data.cpp | 4 +-- .../model/world/nestedcoladapterimp.cpp | 27 +++++++------------ 4 files changed, 14 insertions(+), 25 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index ee7a00ca0f..c937997a92 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -62,7 +62,7 @@ namespace CSMWorld { ColumnId_StarterSpell, "Starter Spell" }, { ColumnId_AlwaysSucceeds, "Always Succeeds" }, { ColumnId_SleepForbidden, "Sleep Forbidden" }, - { ColumnId_Water, "Has Water" }, + { ColumnId_InteriorWater, "Interior Water" }, { ColumnId_InteriorSky, "Interior Sky" }, { ColumnId_Model, "Model" }, { ColumnId_Script, "Script" }, @@ -309,7 +309,6 @@ namespace CSMWorld { ColumnId_Fog, "Fog" }, { ColumnId_FogDensity, "Fog Density" }, { ColumnId_WaterLevel, "Water Level" }, - { ColumnId_InteriorWater, "Interior Water" }, { ColumnId_MapColor, "Map Color" }, { ColumnId_UseValue1, "Use value 1" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 3a345b3ecd..191bbdea8c 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -57,7 +57,7 @@ namespace CSMWorld ColumnId_StarterSpell = 42, ColumnId_AlwaysSucceeds = 43, ColumnId_SleepForbidden = 44, - ColumnId_Water = 45, + ColumnId_InteriorWater = 45, ColumnId_InteriorSky = 46, ColumnId_Model = 47, ColumnId_Script = 48, @@ -300,8 +300,7 @@ namespace CSMWorld ColumnId_Fog = 271, ColumnId_FogDensity = 272, ColumnId_WaterLevel = 273, - ColumnId_InteriorWater = 274, - ColumnId_MapColor = 275, + ColumnId_MapColor = 274, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 00349d4765..920c7db719 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -287,7 +287,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mCells.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Cell)); mCells.addColumn (new NameColumn); mCells.addColumn (new FlagColumn (Columns::ColumnId_SleepForbidden, ESM::Cell::NoSleep)); - mCells.addColumn (new FlagColumn (Columns::ColumnId_Water, ESM::Cell::HasWater)); + mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater)); mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx)); mCells.addColumn (new RegionColumn); mCells.addColumn (new RefNumCounterColumn); @@ -306,8 +306,6 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc new NestedChildColumn (Columns::ColumnId_Fog, ColumnBase::Display_Integer)); mCells.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_FogDensity, ColumnBase::Display_Float)); - mCells.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_InteriorWater, ColumnBase::Display_Boolean)); mCells.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_WaterLevel, ColumnBase::Display_Float)); mCells.getNestableColumn(index)->addColumn( diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index a63ebe672d..8c897f71cb 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -1064,6 +1064,7 @@ namespace CSMWorld bool isInterior = (cell.mData.mFlags & ESM::Cell::Interior) != 0; bool behaveLikeExterior = (cell.mData.mFlags & ESM::Cell::QuasiEx) != 0; + bool interiorWater = (cell.mData.mFlags & ESM::Cell::HasWater) != 0; switch (subColIndex) { @@ -1072,16 +1073,15 @@ namespace CSMWorld case 2: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mSunlight : QVariant(); case 3: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mFog : QVariant(); case 4: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mFogDensity : QVariant(); - case 5: return (isInterior && !behaveLikeExterior) ? cell.mWaterInt==true : QVariant(); - case 6: + case 5: { - if (isInterior && !behaveLikeExterior && cell.mWaterInt) + if (isInterior && !behaveLikeExterior && interiorWater) return cell.mWater; else return QVariant(); } - case 7: return isInterior ? QVariant() : cell.mMapColor; // TODO: how to select? - //case 8: return isInterior ? behaveLikeExterior : QVariant(); + case 6: return isInterior ? QVariant() : cell.mMapColor; // TODO: how to select? + //case 7: return isInterior ? behaveLikeExterior : QVariant(); default: throw std::runtime_error("Cell subcolumn index out of range"); } } @@ -1093,6 +1093,7 @@ namespace CSMWorld bool isInterior = (cell.mData.mFlags & ESM::Cell::Interior) != 0; bool behaveLikeExterior = (cell.mData.mFlags & ESM::Cell::QuasiEx) != 0; + bool interiorWater = (cell.mData.mFlags & ESM::Cell::HasWater) != 0; switch (subColIndex) { @@ -1138,21 +1139,13 @@ namespace CSMWorld } case 5: { - if (isInterior && !behaveLikeExterior) - cell.mWaterInt = value.toBool(); - else - return; // return without saving - break; - } - case 6: - { - if (isInterior && !behaveLikeExterior && cell.mWaterInt) + if (isInterior && !behaveLikeExterior && interiorWater) cell.mWater = value.toFloat(); else return; // return without saving break; } - case 7: + case 6: { if (!isInterior) cell.mMapColor = value.toInt(); @@ -1163,7 +1156,7 @@ namespace CSMWorld #if 0 // redundant since this flag is shown in the main table as "Interior Sky" // keep here for documenting the logic based on vanilla - case 8: + case 7: { if (isInterior) { @@ -1185,7 +1178,7 @@ namespace CSMWorld int CellListAdapter::getColumnsCount(const Record& record) const { - return 8; + return 7; } int CellListAdapter::getRowsCount(const Record& record) const From 2fc964ca7372b7f67055706c661f79202ddbe539 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 21 May 2015 13:11:07 +1000 Subject: [PATCH 110/142] Grey out disabled entries rather than hiding them. --- .../model/world/nestedcoladapterimp.cpp | 20 ++++++++++------ apps/opencs/model/world/refidadapterimp.cpp | 10 ++++---- apps/opencs/model/world/refidadapterimp.hpp | 2 +- apps/opencs/view/world/dialoguesubview.cpp | 23 ++++++++++++++++++- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/apps/opencs/model/world/nestedcoladapterimp.cpp b/apps/opencs/model/world/nestedcoladapterimp.cpp index 8c897f71cb..b7d09777d4 100644 --- a/apps/opencs/model/world/nestedcoladapterimp.cpp +++ b/apps/opencs/model/world/nestedcoladapterimp.cpp @@ -1069,19 +1069,25 @@ namespace CSMWorld switch (subColIndex) { case 0: return isInterior; - case 1: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mAmbient : QVariant(); - case 2: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mSunlight : QVariant(); - case 3: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mFog : QVariant(); - case 4: return (isInterior && !behaveLikeExterior) ? cell.mAmbi.mFogDensity : QVariant(); + case 1: return (isInterior && !behaveLikeExterior) ? + cell.mAmbi.mAmbient : QVariant(QVariant::UserType); + case 2: return (isInterior && !behaveLikeExterior) ? + cell.mAmbi.mSunlight : QVariant(QVariant::UserType); + case 3: return (isInterior && !behaveLikeExterior) ? + cell.mAmbi.mFog : QVariant(QVariant::UserType); + case 4: return (isInterior && !behaveLikeExterior) ? + cell.mAmbi.mFogDensity : QVariant(QVariant::UserType); case 5: { if (isInterior && !behaveLikeExterior && interiorWater) return cell.mWater; else - return QVariant(); + return QVariant(QVariant::UserType); } - case 6: return isInterior ? QVariant() : cell.mMapColor; // TODO: how to select? - //case 7: return isInterior ? behaveLikeExterior : QVariant(); + case 6: return isInterior ? + QVariant(QVariant::UserType) : cell.mMapColor; // TODO: how to select? + //case 7: return isInterior ? + //behaveLikeExterior : QVariant(QVariant::UserType); default: throw std::runtime_error("Cell subcolumn index out of range"); } } diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index a5f0b22449..ee045afd0b 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -502,7 +502,7 @@ QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const Re if (column==mColumns.mAttributes || column==mColumns.mSkills) { if ((record.get().mFlags & ESM::NPC::Autocalc) != 0) - return QVariant(); + return QVariant(QVariant::UserType); else return true; } @@ -805,10 +805,10 @@ QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column switch (subColIndex) { case 0: return static_cast(record.get().mNpdt12.mLevel); - case 1: return QVariant(); - case 2: return QVariant(); - case 3: return QVariant(); - case 4: return QVariant(); + case 1: return QVariant(QVariant::UserType); + case 2: return QVariant(QVariant::UserType); + case 3: return QVariant(QVariant::UserType); + case 4: return QVariant(QVariant::UserType); case 5: return static_cast(record.get().mNpdt12.mDisposition); case 6: return static_cast(record.get().mNpdt12.mReputation); case 7: return static_cast(record.get().mNpdt12.mRank); diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 143b46c44b..3411429d05 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -1976,7 +1976,7 @@ namespace CSMWorld { switch (subColIndex) { - case 0: return QVariant(); // don't allow checkbox editor to be created + case 0: return QVariant(QVariant::UserType); // disable the checkbox editor case 1: return record.get().mFlags & ESM::CreatureLevList::AllLevels; case 2: return static_cast (record.get().mChanceNone); default: diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index fee302e2c7..0a5eb52027 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -461,7 +461,14 @@ void CSVWorld::EditWidget::remake(int row) NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this); // FIXME: does not work well when enum delegates are used //table->resizeColumnsToContents(); - table->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::CurrentChanged); + + if(mTable->index(row, i).data().type() == QVariant::UserType) + { + table->setEditTriggers(QAbstractItemView::NoEditTriggers); + table->setEnabled(false); + } + else + table->setEditTriggers(QAbstractItemView::SelectedClicked | QAbstractItemView::CurrentChanged); int rows = mTable->rowCount(mTable->index(row, i)); int rowHeight = (rows == 0) ? table->horizontalHeader()->height() : table->rowHeight(0); @@ -473,6 +480,8 @@ void CSVWorld::EditWidget::remake(int row) new QLabel (mTable->headerData (i, Qt::Horizontal, Qt::DisplayRole).toString(), mMainWidget); label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + if(mTable->index(row, i).data().type() == QVariant::UserType) + label->setEnabled(false); tablesLayout->addWidget(label); tablesLayout->addWidget(table); @@ -503,6 +512,12 @@ void CSVWorld::EditWidget::remake(int row) unlockedLayout->addWidget (editor, unlocked, 1); ++unlocked; } + + if(mTable->index(row, i).data().type() == QVariant::UserType) + { + editor->setEnabled(false); + label->setEnabled(false); + } } } else @@ -550,6 +565,12 @@ void CSVWorld::EditWidget::remake(int row) unlockedLayout->addWidget (label, unlocked, 0); unlockedLayout->addWidget (editor, unlocked, 1); ++unlocked; + + if(mNestedModels.back()->index(0, col).data().type() == QVariant::UserType) + { + editor->setEnabled(false); + label->setEnabled(false); + } } } mNestedTableMapper->setCurrentModelIndex(mNestedModels.back()->index(0, 0)); From 8f8fdedcde09552f79114357d78ed3bda2f2eba7 Mon Sep 17 00:00:00 2001 From: Nicola Bodill Date: Thu, 21 May 2015 14:20:35 +1000 Subject: [PATCH 111/142] Some more edits Responding to sirherrbatka's feedback. --- manual/opencs/files_and_directories.tex | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/manual/opencs/files_and_directories.tex b/manual/opencs/files_and_directories.tex index 1b07fe267a..55d3011b46 100644 --- a/manual/opencs/files_and_directories.tex +++ b/manual/opencs/files_and_directories.tex @@ -1,8 +1,8 @@ \section{Files and Directories} \subsection{Introduction} -This section of the manual describes the directories and file types used by OpenCS. A file is a resource for storing data, identified by its -filename extension (e.g. .exe, .jpg, .txt), whereas a directory is a folder or file system structure in which these files are stored. You -are most likely already familiar with these concepts. +This section of the manual describes the directories and file types used by OpenCS. A file is a resource for storing data (e.g. .exe, .jpg, .txt), +whereas a directory is a folder or file system structure which points to these files (or other directories). You are most likely already familiar +with these concepts. \subsection{Used terms} %TODO @@ -15,7 +15,7 @@ files and several other folders. The location of the user directory is hard code %TODO list paths. In addition to the user directory, both \OMW{} and \OCS{} need a place to store the game’s actual data files: for example, the textures, models, sounds and records of in-game objects. We support multiple paths to these files (termed \textbf{data paths}), -as specified in the configuration. Usually, one data path points to the directory where \MW{} is installed, however, you are +as specified in the configuration. Usually, one data path points to the directory where \MW{} is installed; however, you are free to specify as many data paths as you would like. In addition, one particular data path, as described below, is used to store newly created content files. @@ -23,7 +23,7 @@ newly created content files. \BS{} \MW{} engine uses two file types: ESM (master) and ESP (plugin). The distinction between the two is often confusing. You would expect that the ESM (master) file is used to specify a single master which is modified by the ESP files (plugins), and indeed: this is the basic idea. However, the original expansions are also ESM files, even though they can be described as very large plugins. -There were technical reasons behind this decision -- somewhat valid in the case of the original engine, but a more logical file system is +There were technical reasons behind this decision -- somewhat valid in the case of the original engine -- but a more logical file system is much preferable. \OMW{} achieves this through the creation of our own types of content file. We support both ESM and ESP files, but, in order to make use of \OMW{}'s new features, one should consider using new file types designed @@ -42,9 +42,9 @@ Furthermore, our content files’ extensions are .omwaddon for addon files and . \subparagraph{\MW{} content files} Using our content files is the recommended solution for projects that employ the \OMW{} engine. However, some players will wish to use the original \MW{} engine, despite its large flaws and lacking features\footnote{If this is wrong, we are a very successful project. Yay!}. -In addition, since 2002 thousands of ESP/ESM files have been created, some with truly outstanding content. Because of this, \OCS{} is -committed to supporting ESP/ESM files. If you do decide to use ESP/ESM files rather than our own content files, you are most likely aiming -for original engine compatibility. This subject is covered in the very last section of the manual. +In addition, since 2002, thousands of ESP/ESM files have been created, some with truly outstanding content. Because of this, \OCS{} +will support ESP/ESM files, although this will impose limitations on the user. If you do decide to use ESP/ESM files rather than our own content +files, you are most likely aiming for original engine compatibility. This subject is covered in the very last section of the manual. %not finished TODO add the said section. Most likely when more features are present. The actual creation of new files is described in the next chapter. Here we are going to focus only on the essential information needed From 9767910f0615e8c5f68502798f1aae0a55bc420b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 21 May 2015 17:51:20 +0200 Subject: [PATCH 112/142] updated credits file --- AUTHORS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index 4fef9233aa..fb83a1a91d 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -110,6 +110,12 @@ Programmers Vincent Heuken vocollapse +Manual +------ + + Bodillium + sir_herrbatka + Packagers --------- From aecd9a275e34d5e539e90713ca0e4158220f526d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 22 May 2015 06:09:55 +1000 Subject: [PATCH 113/142] Remove debugging comments. --- apps/opencs/model/world/refidadapterimp.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index ee045afd0b..0bb565e519 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -721,8 +721,7 @@ QVariant CSMWorld::NpcSkillsRefIdAdapter::getNestedData (const RefIdColumn *colu const ESM::NPC::NPDTstruct52& npcStruct = record.get().mNpdt52; if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length) - std::cout << "getNestedDatat index" << std::endl; - //throw std::runtime_error ("index out of range"); + throw std::runtime_error ("index out of range"); if (subColIndex == 0) return QString(ESM::Skill::sSkillNames[subRowIndex].c_str()); @@ -741,8 +740,7 @@ void CSMWorld::NpcSkillsRefIdAdapter::setNestedData (const RefIdColumn *column, ESM::NPC::NPDTstruct52& npcStruct = npc.mNpdt52; if (subRowIndex < 0 || subRowIndex >= ESM::Skill::Length) - std::cout << "setNestedDatat index" << std::endl; - //throw std::runtime_error ("index out of range"); + throw std::runtime_error ("index out of range"); if (subColIndex == 1) npcStruct.mSkills[subRowIndex] = static_cast(value.toInt()); From d27b92e9f1b093798cbe2404ed0b998c8f3b750f Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 22 May 2015 00:57:47 +0300 Subject: [PATCH 114/142] Avoid gaps between local indexes in RefIdData after removal of records (Fix #2545) --- apps/opencs/model/world/refiddata.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/refiddata.cpp b/apps/opencs/model/world/refiddata.cpp index f67ab21526..7f5c25f368 100644 --- a/apps/opencs/model/world/refiddata.cpp +++ b/apps/opencs/model/world/refiddata.cpp @@ -176,7 +176,6 @@ void CSMWorld::RefIdData::erase (const LocalIndex& index, int count) { std::map::iterator iter = mRecordContainers.find (index.second); - if (iter==mRecordContainers.end()) throw std::logic_error ("invalid local index type"); @@ -189,6 +188,20 @@ void CSMWorld::RefIdData::erase (const LocalIndex& index, int count) mIndex.erase (result); } + // Adjust the local indexes to avoid gaps between them after removal of records + int recordIndex = index.first + count; + int recordCount = iter->second->getSize(); + while (recordIndex < recordCount) + { + std::map::iterator recordIndexFound = + mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(recordIndex))); + if (recordIndexFound != mIndex.end()) + { + recordIndexFound->second.first -= count; + } + ++recordIndex; + } + iter->second->erase (index.first, count); } From 396fba7fa9891dad8c11dd4877278467cd9e19b8 Mon Sep 17 00:00:00 2001 From: Rohit Nirmal Date: Thu, 30 Apr 2015 19:24:27 -0500 Subject: [PATCH 115/142] Silence -Wreorder warnings, and remove -Wno-reorder. --- CMakeLists.txt | 2 +- apps/launcher/graphicspage.cpp | 4 +-- apps/launcher/settingspage.cpp | 4 +-- apps/opencs/editor.cpp | 4 +-- apps/opencs/model/doc/document.cpp | 3 +- apps/opencs/model/filter/valuenode.cpp | 2 +- apps/opencs/model/settings/connector.cpp | 2 +- .../opencs/model/tools/referenceablecheck.cpp | 2 +- apps/opencs/model/tools/tools.cpp | 4 +-- apps/opencs/model/world/columnbase.cpp | 2 +- apps/opencs/model/world/commanddispatcher.cpp | 2 +- apps/opencs/model/world/commands.cpp | 18 +++++----- apps/opencs/model/world/refidadapterimp.cpp | 2 +- apps/opencs/view/doc/filedialog.cpp | 2 +- apps/opencs/view/render/cell.cpp | 2 +- apps/opencs/view/render/mousestate.cpp | 10 +++--- apps/opencs/view/render/textoverlay.cpp | 4 +-- apps/opencs/view/render/worldspacewidget.cpp | 2 +- apps/opencs/view/settings/booleanview.cpp | 2 +- apps/opencs/view/settings/dialog.cpp | 2 +- apps/opencs/view/settings/frame.cpp | 4 +-- apps/opencs/view/settings/listview.cpp | 2 +- apps/opencs/view/settings/page.cpp | 2 +- apps/opencs/view/settings/spinbox.cpp | 2 +- apps/opencs/view/settings/view.cpp | 6 ++-- apps/opencs/view/world/dialoguesubview.cpp | 10 +++--- apps/opencs/view/world/dragrecordtable.cpp | 2 +- apps/opencs/view/world/genericcreator.cpp | 4 +-- apps/opencs/view/world/scenesubview.cpp | 2 +- apps/opencs/view/world/scriptedit.cpp | 9 ++--- apps/opencs/view/world/table.cpp | 4 +-- apps/openmw/mwbase/environment.cpp | 4 +-- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 13 ++++--- apps/openmw/mwgui/alchemywindow.cpp | 4 +-- apps/openmw/mwgui/bookpage.cpp | 16 ++++----- apps/openmw/mwgui/bookwindow.cpp | 2 +- apps/openmw/mwgui/companionwindow.cpp | 6 ++-- apps/openmw/mwgui/container.cpp | 6 ++-- apps/openmw/mwgui/dialogue.cpp | 4 +-- apps/openmw/mwgui/draganddrop.cpp | 6 ++-- apps/openmw/mwgui/inventorywindow.cpp | 16 ++++----- apps/openmw/mwgui/itemmodel.cpp | 12 +++---- apps/openmw/mwgui/jailscreen.cpp | 4 +-- apps/openmw/mwgui/journalbooks.cpp | 6 ++-- apps/openmw/mwgui/journalviewmodel.cpp | 2 +- apps/openmw/mwgui/loadingscreen.cpp | 6 ++-- apps/openmw/mwgui/mapwindow.cpp | 22 ++++++------ apps/openmw/mwgui/messagebox.cpp | 6 ++-- apps/openmw/mwgui/sortfilteritemmodel.cpp | 2 +- apps/openmw/mwgui/spellbuyingwindow.cpp | 2 +- apps/openmw/mwgui/spellcreationdialog.cpp | 6 ++-- apps/openmw/mwgui/tooltips.cpp | 6 ++-- apps/openmw/mwgui/waitdialog.cpp | 2 +- apps/openmw/mwgui/windowbase.cpp | 2 +- apps/openmw/mwmechanics/aiavoiddoor.cpp | 2 +- apps/openmw/mwmechanics/aicombat.cpp | 6 ++-- apps/openmw/mwmechanics/aiescort.cpp | 7 ++-- apps/openmw/mwmechanics/aifollow.cpp | 12 +++---- apps/openmw/mwmechanics/aiwander.cpp | 2 +- apps/openmw/mwmechanics/character.cpp | 2 +- apps/openmw/mwmechanics/creaturestats.cpp | 16 ++++----- apps/openmw/mwmechanics/npcstats.cpp | 6 ++-- apps/openmw/mwmechanics/obstacle.cpp | 2 +- apps/openmw/mwmechanics/pathgrid.cpp | 4 +-- apps/openmw/mwrender/globalmap.cpp | 5 +-- apps/openmw/mwrender/water.cpp | 6 ++-- apps/openmw/mwsound/soundmanagerimp.cpp | 6 ++-- apps/openmw/mwworld/action.cpp | 2 +- apps/openmw/mwworld/esmloader.cpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 8 ++--- apps/openmw/mwworld/physicssystem.cpp | 2 +- apps/openmw/mwworld/player.cpp | 2 +- apps/openmw/mwworld/refdata.cpp | 18 +++++----- apps/openmw/mwworld/weather.cpp | 9 +++-- apps/openmw/mwworld/worldimp.cpp | 14 ++++---- components/compiler/lineparser.cpp | 4 +-- components/interpreter/runtime.cpp | 2 +- .../ogre-ffmpeg-videoplayer/audiodecoder.cpp | 14 ++++---- extern/ogre-ffmpeg-videoplayer/videostate.cpp | 8 +++-- extern/oics/ICSControl.cpp | 4 +-- extern/oics/ICSInputControlSystem.cpp | 36 +++++++++---------- extern/sdl4ogre/sdlinputwrapper.cpp | 36 +++++++++---------- extern/shiny/Main/Factory.cpp | 12 +++---- extern/shiny/Main/MaterialInstance.cpp | 6 ++-- extern/shiny/Main/Platform.cpp | 4 +-- extern/shiny/Main/ShaderSet.cpp | 2 +- 86 files changed, 270 insertions(+), 268 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c19c57eb0..1fefc673ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,7 +351,7 @@ endif() # CXX Compiler settings if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -std=c++98 -pedantic -Wno-long-long") if (CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE) execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE CLANG_VERSION) diff --git a/apps/launcher/graphicspage.cpp b/apps/launcher/graphicspage.cpp index cdb51348c8..5176d7fa0d 100644 --- a/apps/launcher/graphicspage.cpp +++ b/apps/launcher/graphicspage.cpp @@ -36,13 +36,13 @@ QString getAspect(int x, int y) } Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, GraphicsSettings &graphicsSetting, QWidget *parent) - : mOgre(NULL) + : QWidget(parent) + , mOgre(NULL) , mSelectedRenderSystem(NULL) , mOpenGLRenderSystem(NULL) , mDirect3DRenderSystem(NULL) , mCfgMgr(cfg) , mGraphicsSettings(graphicsSetting) - , QWidget(parent) { setObjectName ("GraphicsPage"); setupUi(this); diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 34b4b41a9e..843b513914 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -18,10 +18,10 @@ using namespace Process; Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings, Config::LauncherSettings &launcherSettings, MainDialog *parent) - : mCfgMgr(cfg) + : QWidget(parent) + , mCfgMgr(cfg) , mGameSettings(gameSettings) , mLauncherSettings(launcherSettings) - , QWidget(parent) , mMain(parent) { setupUi(this); diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 1d31c83969..53a9e9e838 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -23,8 +23,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) : mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr), - mViewManager (mDocumentManager), - mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL), mPid(""), mLock() + mViewManager (mDocumentManager), mPid(""), + mLock(), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) { std::pair > config = readConfig(); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 31d0aaccdd..a73201ec0f 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2251,11 +2251,12 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, const std::vector& blacklistedScripts) : mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager), - mTools (*this), mResDir(resDir), + mTools (*this), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), mSavingOperation (*this, mProjectPath, encoding), mSaving (&mSavingOperation), + mResDir(resDir), mRunner (mProjectPath), mPhysics(boost::shared_ptr()) { if (mContentFiles.empty()) diff --git a/apps/opencs/model/filter/valuenode.cpp b/apps/opencs/model/filter/valuenode.cpp index 6fdae3e1ba..6fdb5cb021 100644 --- a/apps/opencs/model/filter/valuenode.cpp +++ b/apps/opencs/model/filter/valuenode.cpp @@ -9,7 +9,7 @@ CSMFilter::ValueNode::ValueNode (int columnId, Type lowerType, Type upperType, double lower, double upper) -: mColumnId (columnId), mLowerType (lowerType), mUpperType (upperType), mLower (lower), mUpper (upper){} +: mColumnId (columnId), mLower (lower), mUpper (upper), mLowerType (lowerType), mUpperType (upperType){} bool CSMFilter::ValueNode::test (const CSMWorld::IdTableBase& table, int row, const std::map& columns) const diff --git a/apps/opencs/model/settings/connector.cpp b/apps/opencs/model/settings/connector.cpp index 5e1d64544d..3cf21123c5 100644 --- a/apps/opencs/model/settings/connector.cpp +++ b/apps/opencs/model/settings/connector.cpp @@ -4,7 +4,7 @@ CSMSettings::Connector::Connector(CSVSettings::View *master, QObject *parent) - : mMasterView (master), QObject(parent) + : QObject(parent), mMasterView (master) {} void CSMSettings::Connector::addSlaveView (CSVSettings::View *view, diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index 5190aacd59..c0991a330d 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -11,8 +11,8 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage( const CSMWorld::IdCollection& faction) : mReferencables(referenceable), - mClasses(classes), mRaces(races), + mClasses(classes), mFactions(faction), mPlayerPresent(false) { diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 970a8ac4fe..99e462b1d2 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -103,8 +103,8 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() } CSMTools::Tools::Tools (CSMDoc::Document& document) -: mDocument (document), mData (document.getData()), mVerifierOperation (0), mNextReportNumber (0), - mSearchOperation (0) +: mDocument (document), mData (document.getData()), mVerifierOperation (0), + mSearchOperation (0), mNextReportNumber (0) { // index 0: load error log mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index cf125aa639..53987b23c9 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -3,7 +3,7 @@ #include "columns.hpp" CSMWorld::ColumnBase::ColumnBase (int columnId, Display displayType, int flags) - : mColumnId (columnId), mDisplayType (displayType), mFlags (flags) + : mColumnId (columnId), mFlags (flags), mDisplayType (displayType) {} CSMWorld::ColumnBase::~ColumnBase() {} diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 2d32624872..b9d5bd7fec 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -83,7 +83,7 @@ std::vector CSMWorld::CommandDispatcher::getRevertableRecords() con CSMWorld::CommandDispatcher::CommandDispatcher (CSMDoc::Document& document, const CSMWorld::UniversalId& id, QObject *parent) -: QObject (parent), mDocument (document), mId (id), mLocked (false) +: QObject (parent), mLocked (false), mDocument (document), mId (id) {} void CSMWorld::CommandDispatcher::setEditLock (bool locked) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 9a0401081b..fbb4de7562 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -235,12 +235,12 @@ CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTree& model, int nestedRow, int parentColumn, QUndoCommand* parent) : - mId(id), - mModel(model), - mParentColumn(parentColumn), QUndoCommand(parent), - mNestedRow(nestedRow), - NestedTableStoring(model, id, parentColumn) + NestedTableStoring(model, id, parentColumn), + mModel(model), + mId(id), + mParentColumn(parentColumn), + mNestedRow(nestedRow) { std::string title = model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData(); @@ -263,12 +263,12 @@ void CSMWorld::DeleteNestedCommand::undo() } CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent) - : mModel(model), + : QUndoCommand(parent), + NestedTableStoring(model, id, parentColumn), + mModel(model), mId(id), mNewRow(nestedRow), - mParentColumn(parentColumn), - QUndoCommand(parent), - NestedTableStoring(model, id, parentColumn) + mParentColumn(parentColumn) { std::string title = model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData(); diff --git a/apps/opencs/model/world/refidadapterimp.cpp b/apps/opencs/model/world/refidadapterimp.cpp index 98c1b6f0f3..c784e14ce2 100644 --- a/apps/opencs/model/world/refidadapterimp.cpp +++ b/apps/opencs/model/world/refidadapterimp.cpp @@ -13,7 +13,7 @@ CSMWorld::PotionColumns::PotionColumns (const InventoryColumns& columns) CSMWorld::PotionRefIdAdapter::PotionRefIdAdapter (const PotionColumns& columns, const RefIdColumn *autoCalc) : InventoryRefIdAdapter (UniversalId::Type_Potion, columns), - mAutoCalc (autoCalc), mColumns(columns) + mColumns(columns), mAutoCalc (autoCalc) {} QVariant CSMWorld::PotionRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, diff --git a/apps/opencs/view/doc/filedialog.cpp b/apps/opencs/view/doc/filedialog.cpp index 1b3196112d..eeec81109f 100644 --- a/apps/opencs/view/doc/filedialog.cpp +++ b/apps/opencs/view/doc/filedialog.cpp @@ -18,7 +18,7 @@ #include "adjusterwidget.hpp" CSVDoc::FileDialog::FileDialog(QWidget *parent) : - QDialog(parent), mSelector (0), mFileWidget (0), mAdjusterWidget (0), mDialogBuilt(false), mAction(ContentAction_Undefined) + QDialog(parent), mSelector (0), mAction(ContentAction_Undefined), mFileWidget (0), mAdjusterWidget (0), mDialogBuilt(false) { ui.setupUi (this); resize(400, 400); diff --git a/apps/opencs/view/render/cell.cpp b/apps/opencs/view/render/cell.cpp index a030ea11f8..99658e1c8f 100644 --- a/apps/opencs/view/render/cell.cpp +++ b/apps/opencs/view/render/cell.cpp @@ -55,7 +55,7 @@ bool CSVRender::Cell::addObjects (int start, int end) CSVRender::Cell::Cell (CSMWorld::Data& data, Ogre::SceneManager *sceneManager, const std::string& id, boost::shared_ptr physics, const Ogre::Vector3& origin) -: mData (data), mId (Misc::StringUtils::lowerCase (id)), mSceneMgr(sceneManager), mPhysics(physics), mX(0), mY(0) +: mData (data), mId (Misc::StringUtils::lowerCase (id)), mPhysics(physics), mSceneMgr(sceneManager), mX(0), mY(0) { mCellNode = sceneManager->getRootSceneNode()->createChildSceneNode(); mCellNode->setPosition (origin); diff --git a/apps/opencs/view/render/mousestate.cpp b/apps/opencs/view/render/mousestate.cpp index a94f4f8ab1..206820194d 100644 --- a/apps/opencs/view/render/mousestate.cpp +++ b/apps/opencs/view/render/mousestate.cpp @@ -56,11 +56,11 @@ namespace CSVRender // MouseState::MouseState(WorldspaceWidget *parent) - : mParent(parent), mPhysics(parent->mDocument.getPhysics()), mSceneManager(parent->getSceneManager()) - , mCurrentObj(""), mMouseState(Mouse_Default), mOldPos(0,0), mMouseEventTimer(0), mPlane(0) - , mGrabbedSceneNode(""), mOrigObjPos(Ogre::Vector3()), mOrigMousePos(Ogre::Vector3()) - , mCurrentMousePos(Ogre::Vector3()), mOffset(0.0f) - , mColIndexPosX(0), mColIndexPosY(0), mColIndexPosZ(0), mIdTableModel(0) + : mMouseState(Mouse_Default), mParent(parent), mPhysics(parent->mDocument.getPhysics()) + , mSceneManager(parent->getSceneManager()), mOldPos(0,0), mCurrentObj(""), mGrabbedSceneNode("") + , mMouseEventTimer(0), mPlane(0), mOrigObjPos(Ogre::Vector3()), mOrigMousePos(Ogre::Vector3()) + , mCurrentMousePos(Ogre::Vector3()), mOffset(0.0f), mIdTableModel(0), mColIndexPosX(0) + , mColIndexPosY(0), mColIndexPosZ(0) { const CSMWorld::RefCollection& references = mParent->mDocument.getData().getReferences(); diff --git a/apps/opencs/view/render/textoverlay.cpp b/apps/opencs/view/render/textoverlay.cpp index 656ea959c7..c41d5f3180 100644 --- a/apps/opencs/view/render/textoverlay.cpp +++ b/apps/opencs/view/render/textoverlay.cpp @@ -27,8 +27,8 @@ namespace CSVRender // http://www.ogre3d.org/tikiwiki/Creating+dynamic+textures // http://www.ogre3d.org/tikiwiki/ManualObject TextOverlay::TextOverlay(const Ogre::MovableObject* obj, const Ogre::Camera* camera, const Ogre::String& id) - : mOverlay(0), mCaption(""), mDesc(""), mEnabled(true), mCamera(camera), mObj(obj), mId(id) - , mOnScreen(false) , mInstance(0), mFontHeight(16) // FIXME: make font height configurable + : mOverlay(0), mCaption(""), mDesc(""), mObj(obj), mCamera(camera), mFontHeight(16), mId(id) + , mEnabled(true), mOnScreen(false), mInstance(0) // FIXME: make font height configurable { if(id == "" || !camera || !obj) throw std::runtime_error("TextOverlay could not be created."); diff --git a/apps/opencs/view/render/worldspacewidget.cpp b/apps/opencs/view/render/worldspacewidget.cpp index e3e5ce50e6..e888148186 100644 --- a/apps/opencs/view/render/worldspacewidget.cpp +++ b/apps/opencs/view/render/worldspacewidget.cpp @@ -22,7 +22,7 @@ #include "editmode.hpp" CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) -: SceneWidget (parent), mDocument(document), mSceneElements(0), mRun(0), mPhysics(boost::shared_ptr()), mMouse(0), +: SceneWidget (parent), mSceneElements(0), mRun(0), mDocument(document), mPhysics(boost::shared_ptr()), mMouse(0), mInteractionMask (0) { setAcceptDrops(true); diff --git a/apps/opencs/view/settings/booleanview.cpp b/apps/opencs/view/settings/booleanview.cpp index 29f9775af4..8c759cabb0 100644 --- a/apps/opencs/view/settings/booleanview.cpp +++ b/apps/opencs/view/settings/booleanview.cpp @@ -12,7 +12,7 @@ CSVSettings::BooleanView::BooleanView (CSMSettings::Setting *setting, Page *parent) - : mType(setting->type()), View (setting, parent) + : View (setting, parent), mType(setting->type()) { foreach (const QString &value, setting->declaredValues()) { diff --git a/apps/opencs/view/settings/dialog.cpp b/apps/opencs/view/settings/dialog.cpp index 0b12312661..e8832e2bcc 100644 --- a/apps/opencs/view/settings/dialog.cpp +++ b/apps/opencs/view/settings/dialog.cpp @@ -23,7 +23,7 @@ #include CSVSettings::Dialog::Dialog(QMainWindow *parent) - : mStackedWidget (0), mDebugMode (false), SettingWindow (parent) + : SettingWindow (parent), mStackedWidget (0), mDebugMode (false) { setWindowTitle(QString::fromUtf8 ("User Settings")); diff --git a/apps/opencs/view/settings/frame.cpp b/apps/opencs/view/settings/frame.cpp index 32e094274e..454d3fefa4 100644 --- a/apps/opencs/view/settings/frame.cpp +++ b/apps/opencs/view/settings/frame.cpp @@ -7,8 +7,8 @@ const QString CSVSettings::Frame::sInvisibleBoxStyle = CSVSettings::Frame::Frame (bool isVisible, const QString &title, QWidget *parent) - : mIsHorizontal (true), mLayout (new SettingLayout()), - QGroupBox (title, parent) + : QGroupBox (title, parent), mIsHorizontal (true), + mLayout (new SettingLayout()) { setFlat (true); mVisibleBoxStyle = styleSheet(); diff --git a/apps/opencs/view/settings/listview.cpp b/apps/opencs/view/settings/listview.cpp index 36cdbb0ae6..0876b39820 100644 --- a/apps/opencs/view/settings/listview.cpp +++ b/apps/opencs/view/settings/listview.cpp @@ -7,7 +7,7 @@ CSVSettings::ListView::ListView(CSMSettings::Setting *setting, Page *parent) - : mComboBox (0), mAbstractItemView (0), View(setting, parent) + : View(setting, parent), mAbstractItemView (0), mComboBox (0) { QWidget *widget = buildWidget(setting->isMultiLine(), setting->widgetWidth()); diff --git a/apps/opencs/view/settings/page.cpp b/apps/opencs/view/settings/page.cpp index e846840b87..c009cdd7a5 100644 --- a/apps/opencs/view/settings/page.cpp +++ b/apps/opencs/view/settings/page.cpp @@ -19,7 +19,7 @@ QMap CSVSettings::Page::Page (const QString &pageName, QList settingList, SettingWindow *parent, const QString& label) -: mParent(parent), mIsEditorPage (false), Frame(false, "", parent), mLabel (label) +: Frame(false, "", parent), mParent(parent), mIsEditorPage (false), mLabel (label) { setObjectName (pageName); diff --git a/apps/opencs/view/settings/spinbox.cpp b/apps/opencs/view/settings/spinbox.cpp index c70fc36d12..043107bb76 100644 --- a/apps/opencs/view/settings/spinbox.cpp +++ b/apps/opencs/view/settings/spinbox.cpp @@ -3,7 +3,7 @@ #include CSVSettings::SpinBox::SpinBox(QWidget *parent) - : mValueList(QStringList()), QSpinBox(parent) + : QSpinBox(parent), mValueList(QStringList()) { setRange (0, 0); } diff --git a/apps/opencs/view/settings/view.cpp b/apps/opencs/view/settings/view.cpp index 39c7f89b22..21cf55fddd 100644 --- a/apps/opencs/view/settings/view.cpp +++ b/apps/opencs/view/settings/view.cpp @@ -12,12 +12,12 @@ CSVSettings::View::View(CSMSettings::Setting *setting, Page *parent) - : mDataModel(0), mParentPage (parent), + : Frame(true, setting->getLabel(), parent), + mParentPage (parent), mDataModel(0), mHasFixedValues (!setting->declaredValues().isEmpty()), mIsMultiValue (setting->isMultiValue()), mViewKey (setting->page() + '/' + setting->name()), - mSerializable (setting->serializable()), - Frame(true, setting->getLabel(), parent) + mSerializable (setting->serializable()) { if (!setting->getToolTip().isEmpty()) setToolTip (setting->getToolTip()); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 0d0e82dbf3..647accd4c3 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -356,15 +356,15 @@ CSVWorld::EditWidget::~EditWidget() CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMWorld::CommandDispatcher& commandDispatcher, CSMDoc::Document& document, bool createAndDelete) : -mDispatcher(this, table, commandDispatcher, document), -mNestedTableDispatcher(NULL), QScrollArea(parent), mWidgetMapper(NULL), mNestedTableMapper(NULL), +mDispatcher(this, table, commandDispatcher, document), +mNestedTableDispatcher(NULL), mMainWidget(NULL), +mTable(table), mCommandDispatcher (commandDispatcher), -mDocument (document), -mTable(table) +mDocument (document) { remake (row); @@ -571,8 +571,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM SubView (id), mEditWidget(0), mMainLayout(NULL), - mUndoStack(document.getUndoStack()), mTable(dynamic_cast(document.getData().getTableModel(id))), + mUndoStack(document.getUndoStack()), mLocked(false), mDocument(document), mCommandDispatcher (document, CSMWorld::UniversalId::getParentType (id.getType())) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index f45c458091..7032fee6d2 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -17,8 +17,8 @@ void CSVWorld::DragRecordTable::startDragFromTable (const CSVWorld::DragRecordTa } CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* parent) : -mDocument(document), QTableView(parent), +mDocument(document), mEditLock(false) {} diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 4269679bfd..a123e127f9 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -129,9 +129,9 @@ void CSVWorld::GenericCreator::addScope (const QString& name, CSMWorld::Scope sc CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, bool relaxedIdRules) -: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false), mCloneMode (false), +: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false), mClonedType (CSMWorld::UniversalId::Type_None), mScopes (CSMWorld::Scope_Content), mScope (0), - mScopeLabel (0) + mScopeLabel (0), mCloneMode (false) { mLayout = new QHBoxLayout; mLayout->setContentsMargins (0, 0, 0, 0); diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index 3fdf2f6e5c..aa21612599 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -27,7 +27,7 @@ #include "creator.hpp" CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: SubView (id), mLayout(new QHBoxLayout), mDocument(document), mScene(NULL), mToolbar(NULL) +: SubView (id), mScene(NULL), mLayout(new QHBoxLayout), mDocument(document), mToolbar(NULL) { QVBoxLayout *layout = new QVBoxLayout; diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index 2e05fa110e..2f0d82ae1c 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -42,13 +42,14 @@ bool CSVWorld::ScriptEdit::event (QEvent *event) CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighlighter::Mode mode, QWidget* parent) : QPlainTextEdit (parent), - mDocument (document), - mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive), mChangeLocked (0), - mLineNumberArea(0), mShowLineNum(false), + mLineNumberArea(0), mDefaultFont(font()), - mMonoFont(QFont("Monospace")) + mMonoFont(QFont("Monospace")), + mDocument (document), + mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive) + { // setAcceptRichText (false); setLineWrapMode (QPlainTextEdit::NoWrap); diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 86daf8af7b..b8972edbe4 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -253,8 +253,8 @@ void CSVWorld::Table::mouseDoubleClickEvent (QMouseEvent *event) CSVWorld::Table::Table (const CSMWorld::UniversalId& id, bool createAndDelete, bool sorting, CSMDoc::Document& document) -: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0), - DragRecordTable(document) +: DragRecordTable(document), mCreateAction (0), + mCloneAction(0),mRecordStatusDisplay (0) { CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance(); QString jumpSetting = settings.settingValue ("table-input/jump-to-added"); diff --git a/apps/openmw/mwbase/environment.cpp b/apps/openmw/mwbase/environment.cpp index 3bc15746ec..a90eec5bf6 100644 --- a/apps/openmw/mwbase/environment.cpp +++ b/apps/openmw/mwbase/environment.cpp @@ -17,8 +17,8 @@ MWBase::Environment *MWBase::Environment::sThis = 0; MWBase::Environment::Environment() : mWorld (0), mSoundManager (0), mScriptManager (0), mWindowManager (0), - mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mFrameDuration (0), - mStateManager (0) + mMechanicsManager (0), mDialogueManager (0), mJournal (0), mInputManager (0), mStateManager (0), + mFrameDuration (0) { assert (!sThis); sThis = this; diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 0b9fd65d20..1785575fcf 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -48,12 +48,15 @@ namespace MWDialogue { DialogueManager::DialogueManager (const Compiler::Extensions& extensions, bool scriptVerbose, Translation::Storage& translationDataStorage) : - mCompilerContext (MWScript::CompilerContext::Type_Dialogue), - mErrorStream(std::cout.rdbuf()),mErrorHandler(mErrorStream) - , mTemporaryDispositionChange(0.f) - , mPermanentDispositionChange(0.f), mScriptVerbose (scriptVerbose) - , mTranslationDataStorage(translationDataStorage) + mTranslationDataStorage(translationDataStorage) + , mCompilerContext (MWScript::CompilerContext::Type_Dialogue) + , mErrorStream(std::cout.rdbuf()) + , mErrorHandler(mErrorStream) , mTalkedTo(false) + , mTemporaryDispositionChange(0.f) + , mPermanentDispositionChange(0.f) + , mScriptVerbose (scriptVerbose) + { mChoice = -1; mIsInChoice = false; diff --git a/apps/openmw/mwgui/alchemywindow.cpp b/apps/openmw/mwgui/alchemywindow.cpp index b28e4de09f..a54744370c 100644 --- a/apps/openmw/mwgui/alchemywindow.cpp +++ b/apps/openmw/mwgui/alchemywindow.cpp @@ -26,10 +26,10 @@ namespace MWGui { AlchemyWindow::AlchemyWindow() : WindowBase("openmw_alchemy_window.layout") - , mApparatus (4) - , mIngredients (4) , mSortModel(NULL) , mAlchemy(new MWMechanics::Alchemy()) + , mApparatus (4) + , mIngredients (4) { getWidget(mCreateButton, "CreateButton"); getWidget(mCancelButton, "CancelButton"); diff --git a/apps/openmw/mwgui/bookpage.cpp b/apps/openmw/mwgui/bookpage.cpp index 962e594aeb..cfb49ebffb 100644 --- a/apps/openmw/mwgui/bookpage.cpp +++ b/apps/openmw/mwgui/bookpage.cpp @@ -228,8 +228,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter Typesetter (size_t width, size_t height) : mPageWidth (width), mPageHeight(height), mSection (NULL), mLine (NULL), mRun (NULL), - mCurrentAlignment (AlignLeft), - mCurrentContent (NULL) + mCurrentContent (NULL), + mCurrentAlignment (AlignLeft) { mBook = boost::make_shared (); } @@ -697,10 +697,10 @@ namespace GlyphStream (MyGUI::IFont* font, float left, float top, float Z, MyGUI::Vertex* vertices, RenderXform const & renderXform) : - mZ(Z), mOrigin (left, top), - mFont (font), mVertices (vertices), - mRenderXform (renderXform), - mC(0) + mZ(Z), + mC(0), mFont (font), mOrigin (left, top), + mVertices (vertices), + mRenderXform (renderXform) { mVertexColourType = MyGUI::RenderManager::getInstance().getVertexFormat(); } @@ -801,10 +801,10 @@ protected: TextFormat (MyGUI::IFont* id, PageDisplay * display) : mFont (id), + mCountVertex (0), mTexture (NULL), mRenderItem (NULL), - mDisplay (display), - mCountVertex (0) + mDisplay (display) { } diff --git a/apps/openmw/mwgui/bookwindow.cpp b/apps/openmw/mwgui/bookwindow.cpp index 55a9b61918..6863994b8a 100644 --- a/apps/openmw/mwgui/bookwindow.cpp +++ b/apps/openmw/mwgui/bookwindow.cpp @@ -18,9 +18,9 @@ namespace MWGui BookWindow::BookWindow () : WindowBase("openmw_book.layout") + , mCurrentPage(0) , mTakeButtonShow(true) , mTakeButtonAllowed(true) - , mCurrentPage(0) { getWidget(mCloseButton, "CloseButton"); mCloseButton->eventMouseButtonClick += MyGUI::newDelegate(this, &BookWindow::onCloseButtonClicked); diff --git a/apps/openmw/mwgui/companionwindow.cpp b/apps/openmw/mwgui/companionwindow.cpp index fe47437cad..4433f9ef8c 100644 --- a/apps/openmw/mwgui/companionwindow.cpp +++ b/apps/openmw/mwgui/companionwindow.cpp @@ -37,11 +37,11 @@ namespace MWGui CompanionWindow::CompanionWindow(DragAndDrop *dragAndDrop, MessageBoxManager* manager) : WindowBase("openmw_companion_window.layout") + , mSortModel(NULL) + , mModel(NULL) + , mSelectedItem(-1) , mDragAndDrop(dragAndDrop) , mMessageBoxManager(manager) - , mSelectedItem(-1) - , mModel(NULL) - , mSortModel(NULL) { getWidget(mCloseButton, "CloseButton"); getWidget(mProfitLabel, "ProfitLabel"); diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 579730f42f..1317e1e253 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -33,10 +33,10 @@ namespace MWGui ContainerWindow::ContainerWindow(DragAndDrop* dragAndDrop) : WindowBase("openmw_container_window.layout") , mDragAndDrop(dragAndDrop) - , mSelectedItem(-1) - , mModel(NULL) - , mSortModel(NULL) , mPickpocketDetected(false) + , mSortModel(NULL) + , mModel(NULL) + , mSelectedItem(-1) { getWidget(mDisposeCorpseButton, "DisposeCorpseButton"); getWidget(mTakeButton, "TakeButton"); diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 1b07522f38..692cea952d 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -248,10 +248,10 @@ namespace MWGui DialogueWindow::DialogueWindow() : WindowBase("openmw_dialogue_window.layout") - , mPersuasionDialog() - , mEnabled(false) , mServices(0) + , mEnabled(false) , mGoodbye(false) + , mPersuasionDialog() { // Centre dialog center(); diff --git a/apps/openmw/mwgui/draganddrop.cpp b/apps/openmw/mwgui/draganddrop.cpp index fcb381b954..55aeb969c5 100644 --- a/apps/openmw/mwgui/draganddrop.cpp +++ b/apps/openmw/mwgui/draganddrop.cpp @@ -20,12 +20,12 @@ namespace MWGui DragAndDrop::DragAndDrop() - : mDraggedWidget(NULL) - , mDraggedCount(0) + : mIsOnDragAndDrop(false) + , mDraggedWidget(NULL) , mSourceModel(NULL) , mSourceView(NULL) , mSourceSortModel(NULL) - , mIsOnDragAndDrop(false) + , mDraggedCount(0) { } diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index 9aa8a8ea1d..af24f3f794 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -50,17 +50,17 @@ namespace MWGui InventoryWindow::InventoryWindow(DragAndDrop* dragAndDrop) : WindowPinnableBase("openmw_inventory_window.layout") - , mTrading(false) + , mDragAndDrop(dragAndDrop) + , mPreviewDirty(true) + , mPreviewResize(true) + , mSelectedItem(-1) + , mSortModel(NULL) + , mTradeModel(NULL) + , mGuiMode(GM_Inventory) , mLastXSize(0) , mLastYSize(0) , mPreview(new MWRender::InventoryPreview(MWBase::Environment::get().getWorld ()->getPlayerPtr())) - , mPreviewDirty(true) - , mPreviewResize(true) - , mDragAndDrop(dragAndDrop) - , mSortModel(NULL) - , mTradeModel(NULL) - , mSelectedItem(-1) - , mGuiMode(GM_Inventory) + , mTrading(false) { mMainWidget->castType()->eventWindowChangeCoord += MyGUI::newDelegate(this, &InventoryWindow::onWindowResize); diff --git a/apps/openmw/mwgui/itemmodel.cpp b/apps/openmw/mwgui/itemmodel.cpp index 8224fd55b0..9fce6e84dd 100644 --- a/apps/openmw/mwgui/itemmodel.cpp +++ b/apps/openmw/mwgui/itemmodel.cpp @@ -14,10 +14,10 @@ namespace MWGui { ItemStack::ItemStack(const MWWorld::Ptr &base, ItemModel *creator, size_t count) - : mCreator(creator) - , mCount(count) + : mType(Type_Normal) , mFlags(0) - , mType(Type_Normal) + , mCreator(creator) + , mCount(count) , mBase(base) { if (base.getClass().getEnchantment(base) != "") @@ -59,10 +59,10 @@ namespace MWGui } ItemStack::ItemStack() - : mCreator(NULL) - , mCount(0) + : mType(Type_Normal) , mFlags(0) - , mType(Type_Normal) + , mCreator(NULL) + , mCount(0) { } diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index 5c0a6ec5f2..936da2d8e2 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -19,9 +19,9 @@ namespace MWGui { JailScreen::JailScreen() : WindowBase("openmw_jail_screen.layout"), - mTimeAdvancer(0.01f), mDays(1), - mFadeTimeRemaining(0) + mFadeTimeRemaining(0), + mTimeAdvancer(0.01f) { getWidget(mProgressBar, "ProgressBar"); diff --git a/apps/openmw/mwgui/journalbooks.cpp b/apps/openmw/mwgui/journalbooks.cpp index 34a8525628..f84fb517bc 100644 --- a/apps/openmw/mwgui/journalbooks.cpp +++ b/apps/openmw/mwgui/journalbooks.cpp @@ -68,8 +68,8 @@ namespace AddJournalEntry (MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* body_style, MWGui::BookTypesetter::Style* header_style, bool add_header) : AddEntry (typesetter, body_style), - mHeaderStyle (header_style), - mAddHeader (add_header) + mAddHeader (add_header), + mHeaderStyle (header_style) { } @@ -94,7 +94,7 @@ namespace AddTopicEntry (MWGui::BookTypesetter::Ptr typesetter, MWGui::BookTypesetter::Style* body_style, MWGui::BookTypesetter::Style* header_style, intptr_t contentId) : - AddEntry (typesetter, body_style), mHeaderStyle (header_style), mContentId (contentId) + AddEntry (typesetter, body_style), mContentId (contentId), mHeaderStyle (header_style) { } diff --git a/apps/openmw/mwgui/journalviewmodel.cpp b/apps/openmw/mwgui/journalviewmodel.cpp index 9a47070c2f..d05257e46c 100644 --- a/apps/openmw/mwgui/journalviewmodel.cpp +++ b/apps/openmw/mwgui/journalviewmodel.cpp @@ -92,7 +92,7 @@ struct JournalViewModelImpl : JournalViewModel JournalViewModelImpl const * mModel; BaseEntry (JournalViewModelImpl const * model, iterator_t itr) : - mModel (model), itr (itr), loaded (false) + itr (itr), mModel (model), loaded (false) {} virtual ~BaseEntry () {} diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 3204c65482..db7b320183 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -32,11 +32,11 @@ namespace MWGui { LoadingScreen::LoadingScreen(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* rw) - : mSceneMgr(sceneMgr) + : WindowBase("openmw_loading_screen.layout") + , mSceneMgr(sceneMgr) , mWindow(rw) - , WindowBase("openmw_loading_screen.layout") - , mLastRenderTime(0) , mLastWallpaperChangeTime(0) + , mLastRenderTime(0) , mProgress(0) , mVSyncWasEnabled(false) { diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 9adfeffe88..c594327961 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -144,16 +144,16 @@ namespace MWGui : mCurX(0) , mCurY(0) , mInterior(false) - , mFogOfWar(true) , mLocalMap(NULL) + , mCompass(NULL) , mPrefix() , mChanged(true) + , mFogOfWar(true) + , mMapWidgetSize(0) + , mCustomMarkers(markers) + , mMarkerUpdateTimer(0.0f) , mLastDirectionX(0.0f) , mLastDirectionY(0.0f) - , mCompass(NULL) - , mMarkerUpdateTimer(0.0f) - , mCustomMarkers(markers) - , mMapWidgetSize(0) { mCustomMarkers.eventMarkersChanged += MyGUI::newDelegate(this, &LocalMapBase::updateCustomMarkers); } @@ -550,16 +550,16 @@ namespace MWGui MapWindow::MapWindow(CustomMarkerCollection &customMarkers, DragAndDrop* drag, const std::string& cacheDir) : WindowPinnableBase("openmw_map_window.layout") - , NoDrop(drag, mMainWidget) , LocalMapBase(customMarkers) - , mGlobal(false) + , NoDrop(drag, mMainWidget) , mGlobalMap(0) - , mGlobalMapRender(0) - , mEditNoteDialog() - , mEventBoxGlobal(NULL) - , mEventBoxLocal(NULL) , mGlobalMapImage(NULL) , mGlobalMapOverlay(NULL) + , mGlobal(false) + , mEventBoxGlobal(NULL) + , mEventBoxLocal(NULL) + , mGlobalMapRender(0) + , mEditNoteDialog() { static bool registered = false; if (!registered) diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index b7c67e68bf..6e81ed6262 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -161,10 +161,10 @@ namespace MWGui MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message) : Layout("openmw_messagebox.layout") - , mMessageBoxManager(parMessageBoxManager) - , mMessage(message) , mCurrentTime(0) , mMaxTime(0) + , mMessageBoxManager(parMessageBoxManager) + , mMessage(message) { // defines mBottomPadding = 48; @@ -195,8 +195,8 @@ namespace MWGui InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector& buttons) : WindowModal("openmw_interactive_messagebox.layout") , mMessageBoxManager(parMessageBoxManager) + , mTextButtonPadding(0) , mButtonPressed(-1) - , mTextButtonPadding(0) { WindowModal::open(); diff --git a/apps/openmw/mwgui/sortfilteritemmodel.cpp b/apps/openmw/mwgui/sortfilteritemmodel.cpp index 6c164df888..183ab07ff9 100644 --- a/apps/openmw/mwgui/sortfilteritemmodel.cpp +++ b/apps/openmw/mwgui/sortfilteritemmodel.cpp @@ -70,9 +70,9 @@ namespace MWGui SortFilterItemModel::SortFilterItemModel(ItemModel *sourceModel) : mCategory(Category_All) + , mFilter(0) , mShowEquipped(true) , mSortByType(true) - , mFilter(0) { mSourceModel = sourceModel; } diff --git a/apps/openmw/mwgui/spellbuyingwindow.cpp b/apps/openmw/mwgui/spellbuyingwindow.cpp index 76a1d51e5b..ae7b7588ab 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.cpp +++ b/apps/openmw/mwgui/spellbuyingwindow.cpp @@ -23,8 +23,8 @@ namespace MWGui SpellBuyingWindow::SpellBuyingWindow() : WindowBase("openmw_spell_buying_window.layout") - , mCurrentY(0) , mLastPos(0) + , mCurrentY(0) { setCoord(0, 0, 450, 300); diff --git a/apps/openmw/mwgui/spellcreationdialog.cpp b/apps/openmw/mwgui/spellcreationdialog.cpp index c744d3ed63..1c670838f4 100644 --- a/apps/openmw/mwgui/spellcreationdialog.cpp +++ b/apps/openmw/mwgui/spellcreationdialog.cpp @@ -483,15 +483,15 @@ namespace MWGui EffectEditorBase::EffectEditorBase(Type type) - : mAddEffectDialog() - , mAvailableEffectsList(NULL) + : mAvailableEffectsList(NULL) , mUsedEffectsView(NULL) + , mAddEffectDialog() , mSelectAttributeDialog(NULL) , mSelectSkillDialog(NULL) , mSelectedEffect(0) , mSelectedKnownEffectId(0) - , mType(type) , mConstantEffect(false) + , mType(type) { mAddEffectDialog.eventEffectAdded += MyGUI::newDelegate(this, &EffectEditorBase::onEffectAdded); mAddEffectDialog.eventEffectModified += MyGUI::newDelegate(this, &EffectEditorBase::onEffectModified); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 4e83c25db3..34896c0bd2 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -30,15 +30,15 @@ namespace MWGui ToolTips::ToolTips() : Layout("openmw_tooltips.layout") - , mFullHelp(false) - , mEnabled(true) , mFocusToolTipX(0.0) , mFocusToolTipY(0.0) + , mHorizontalScrollIndex(0) , mDelay(0.0) , mRemainingDelay(0.0) , mLastMouseX(0) , mLastMouseY(0) - , mHorizontalScrollIndex(0) + , mEnabled(true) + , mFullHelp(false) { getWidget(mDynamicToolTipBox, "DynamicToolTipBox"); diff --git a/apps/openmw/mwgui/waitdialog.cpp b/apps/openmw/mwgui/waitdialog.cpp index 28e3be5911..ed261e7eb0 100644 --- a/apps/openmw/mwgui/waitdialog.cpp +++ b/apps/openmw/mwgui/waitdialog.cpp @@ -50,13 +50,13 @@ namespace MWGui WaitDialog::WaitDialog() : WindowBase("openmw_wait_dialog.layout") - , mProgressBar() , mTimeAdvancer(0.05f) , mSleeping(false) , mHours(1) , mManualHours(1) , mFadeTimeRemaining(0) , mInterruptAt(-1) + , mProgressBar() { getWidget(mDateTimeText, "DateTimeText"); getWidget(mRestText, "RestText"); diff --git a/apps/openmw/mwgui/windowbase.cpp b/apps/openmw/mwgui/windowbase.cpp index 8fdcf6b207..899f8a5e84 100644 --- a/apps/openmw/mwgui/windowbase.cpp +++ b/apps/openmw/mwgui/windowbase.cpp @@ -78,7 +78,7 @@ void WindowModal::close() } NoDrop::NoDrop(DragAndDrop *drag, MyGUI::Widget *widget) - : mDrag(drag), mWidget(widget), mTransparent(false) + : mWidget(widget), mDrag(drag), mTransparent(false) { if (!mWidget) throw std::runtime_error("NoDrop needs a non-NULL widget!"); diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index a73d955c56..fccace55c2 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -13,7 +13,7 @@ #include "steering.hpp" MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::Ptr& doorPtr) -: AiPackage(), mDoorPtr(doorPtr), mDuration(1), mAdjAngle(0) +: AiPackage(), mDuration(1), mDoorPtr(doorPtr), mAdjAngle(0) { } diff --git a/apps/openmw/mwmechanics/aicombat.cpp b/apps/openmw/mwmechanics/aicombat.cpp index 2f68087e58..649f259d9a 100644 --- a/apps/openmw/mwmechanics/aicombat.cpp +++ b/apps/openmw/mwmechanics/aicombat.cpp @@ -111,17 +111,17 @@ namespace MWMechanics mTimerAttack(0), mTimerReact(0), mTimerCombatMove(0), + mReadyToAttack(false), mAttack(false), mFollowTarget(false), mCombatMove(false), - mReadyToAttack(false), - mForceNoShortcut(false), + mLastTargetPos(0,0,0), mCell(NULL), mCurrentAction(), mActionCooldown(0), mStrength(), mMinMaxAttackDurationInitialised(false), - mLastTargetPos(0,0,0), + mForceNoShortcut(false), mLastActorPos(0,0,0), mMovement(){} }; diff --git a/apps/openmw/mwmechanics/aiescort.cpp b/apps/openmw/mwmechanics/aiescort.cpp index 91bf7c9b03..f9ebefe136 100644 --- a/apps/openmw/mwmechanics/aiescort.cpp +++ b/apps/openmw/mwmechanics/aiescort.cpp @@ -49,12 +49,11 @@ namespace MWMechanics } AiEscort::AiEscort(const ESM::AiSequence::AiEscort *escort) - : mActorId(escort->mTargetId), mX(escort->mData.mX), mY(escort->mData.mY), mZ(escort->mData.mZ) + : mActorId(escort->mTargetId), mCellId(escort->mCellId), mX(escort->mData.mX), mY(escort->mData.mY), mZ(escort->mData.mZ) + , mMaxDist(450) + , mRemainingDuration(escort->mRemainingDuration) , mCellX(std::numeric_limits::max()) , mCellY(std::numeric_limits::max()) - , mCellId(escort->mCellId) - , mRemainingDuration(escort->mRemainingDuration) - , mMaxDist(450) { } diff --git a/apps/openmw/mwmechanics/aifollow.cpp b/apps/openmw/mwmechanics/aifollow.cpp index 161f4bb905..ddfc145812 100644 --- a/apps/openmw/mwmechanics/aifollow.cpp +++ b/apps/openmw/mwmechanics/aifollow.cpp @@ -32,27 +32,27 @@ int AiFollow::mFollowIndexCounter = 0; AiFollow::AiFollow(const std::string &actorId,float duration, float x, float y, float z) : mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z) -, mActorRefId(actorId), mCellId(""), mActorId(-1), mFollowIndex(mFollowIndexCounter++), mActive(false) +, mActorRefId(actorId), mActorId(-1), mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++) { } AiFollow::AiFollow(const std::string &actorId,const std::string &cellId,float duration, float x, float y, float z) : mAlwaysFollow(false), mCommanded(false), mRemainingDuration(duration), mX(x), mY(y), mZ(z) -, mActorRefId(actorId), mCellId(cellId), mActorId(-1), mFollowIndex(mFollowIndexCounter++), mActive(false) +, mActorRefId(actorId), mActorId(-1), mCellId(cellId), mActive(false), mFollowIndex(mFollowIndexCounter++) { } AiFollow::AiFollow(const std::string &actorId, bool commanded) : mAlwaysFollow(true), mCommanded(commanded), mRemainingDuration(0), mX(0), mY(0), mZ(0) -, mActorRefId(actorId), mCellId(""), mActorId(-1), mFollowIndex(mFollowIndexCounter++), mActive(false) +, mActorRefId(actorId), mActorId(-1), mCellId(""), mActive(false), mFollowIndex(mFollowIndexCounter++) { } AiFollow::AiFollow(const ESM::AiSequence::AiFollow *follow) - : mAlwaysFollow(follow->mAlwaysFollow), mRemainingDuration(follow->mRemainingDuration) + : mAlwaysFollow(follow->mAlwaysFollow), mCommanded(follow->mCommanded), mRemainingDuration(follow->mRemainingDuration) , mX(follow->mData.mX), mY(follow->mData.mY), mZ(follow->mData.mZ) - , mActorRefId(follow->mTargetId), mActorId(-1), mCellId(follow->mCellId) - , mCommanded(follow->mCommanded), mFollowIndex(mFollowIndexCounter++), mActive(follow->mActive) + , mActorRefId(follow->mTargetId), mActorId(-1) + , mCellId(follow->mCellId), mActive(follow->mActive), mFollowIndex(mFollowIndexCounter++) { } diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 560e756ce2..0766369747 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -786,10 +786,10 @@ namespace MWMechanics AiWander::AiWander (const ESM::AiSequence::AiWander* wander) : mDistance(wander->mData.mDistance) , mDuration(wander->mData.mDuration) - , mStartTime(MWWorld::TimeStamp(wander->mStartTime)) , mTimeOfDay(wander->mData.mTimeOfDay) , mRepeat(wander->mData.mShouldRepeat != 0) , mStoredInitialActorPosition(wander->mStoredInitialActorPosition) + , mStartTime(MWWorld::TimeStamp(wander->mStartTime)) { if (mStoredInitialActorPosition) mInitialActorPosition = wander->mInitialActorPosition; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index ffde59aee6..399b51151b 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -642,8 +642,8 @@ CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Anim , mJumpState(JumpState_None) , mWeaponType(WeapType_None) , mSkipAnim(false) - , mSecondsOfRunning(0) , mSecondsOfSwimming(0) + , mSecondsOfRunning(0) , mTurnAnimationThreshold(0) { if(!mAnimation) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 4c338e23fc..308e720279 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -15,16 +15,12 @@ namespace MWMechanics int CreatureStats::sActorId = 0; CreatureStats::CreatureStats() - : mLevel (0), mDead (false), mDied (false), mMurdered(false), mFriendlyHits (0), - mTalkedTo (false), mAlarmed (false), - mAttacked (false), - mAttackingOrSpell(false), - mIsWerewolf(false), - mFallHeight(0), mRecalcMagicka(false), mKnockdown(false), mKnockdownOneFrame(false), - mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), - mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), - mLastRestock(0,0), mGoldPool(0), mActorId(-1), - mDeathAnimation(0) + : mDrawState (DrawState_Nothing), mDead (false), mDied (false), mMurdered(false), mFriendlyHits (0), + mTalkedTo (false), mAlarmed (false), mAttacked (false), mAttackingOrSpell(false), + mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), + mHitRecovery(false), mBlock(false), mMovementFlags(0), mAttackStrength(0.f), + mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), + mDeathAnimation(0), mIsWerewolf(false), mLevel (0) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 7f468f6d41..94819e6260 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -25,12 +25,12 @@ #include "../mwbase/soundmanager.hpp" MWMechanics::NpcStats::NpcStats() - : mBounty (0) -, mLevelProgress(0) -, mDisposition(0) + : mDisposition (0) , mReputation(0) , mCrimeId(-1) +, mBounty(0) , mWerewolfKills (0) +, mLevelProgress(0) , mTimeToStartDrowning(20.0) { mSkillIncreases.resize (ESM::Attribute::Length, 0); diff --git a/apps/openmw/mwmechanics/obstacle.cpp b/apps/openmw/mwmechanics/obstacle.cpp index 6bf81e8611..7cfa6fcd5f 100644 --- a/apps/openmw/mwmechanics/obstacle.cpp +++ b/apps/openmw/mwmechanics/obstacle.cpp @@ -63,10 +63,10 @@ namespace MWMechanics ObstacleCheck::ObstacleCheck(): mPrevX(0) // to see if the moved since last time , mPrevY(0) - , mDistSameSpot(-1) // avoid calculating it each time , mWalkState(State_Norm) , mStuckDuration(0) , mEvadeDuration(0) + , mDistSameSpot(-1) // avoid calculating it each time { } diff --git a/apps/openmw/mwmechanics/pathgrid.cpp b/apps/openmw/mwmechanics/pathgrid.cpp index c1e094bb1e..4e9bc89048 100644 --- a/apps/openmw/mwmechanics/pathgrid.cpp +++ b/apps/openmw/mwmechanics/pathgrid.cpp @@ -51,12 +51,12 @@ namespace MWMechanics { PathgridGraph::PathgridGraph() : mCell(NULL) - , mIsGraphConstructed(false) , mPathgrid(NULL) + , mIsExterior(0) , mGraph(0) + , mIsGraphConstructed(false) , mSCCId(0) , mSCCIndex(0) - , mIsExterior(0) { } diff --git a/apps/openmw/mwrender/globalmap.cpp b/apps/openmw/mwrender/globalmap.cpp index 95d4429d6f..90cf270497 100644 --- a/apps/openmw/mwrender/globalmap.cpp +++ b/apps/openmw/mwrender/globalmap.cpp @@ -25,10 +25,11 @@ namespace MWRender GlobalMap::GlobalMap(const std::string &cacheDir) : mCacheDir(cacheDir) - , mMinX(0), mMaxX(0) - , mMinY(0), mMaxY(0) , mWidth(0) , mHeight(0) + , mMinX(0), mMaxX(0) + , mMinY(0), mMaxY(0) + { mCellSize = Settings::Manager::getInt("global map cell size", "Map"); } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index a16b156ae3..f2175ced57 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -186,10 +186,10 @@ void PlaneReflection::setVisibilityMask (int flags) Water::Water (Ogre::Camera *camera, RenderingManager* rend, const MWWorld::Fallback* fallback) : mCamera (camera), mSceneMgr (camera->getSceneManager()), - mIsUnderwater(false), mVisibilityFlags(0), - mActive(1), mToggled(1), + mIsUnderwater(false), mActive(1), + mToggled(1), mWaterTimer(0.f), mRendering(rend), - mWaterTimer(0.f), + mVisibilityFlags(0), mReflection(NULL), mRefraction(NULL), mSimulation(NULL), diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 06c40dd8e8..c7fb9ea506 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -33,13 +33,13 @@ namespace MWSound , mMasterVolume(1.0f) , mSFXVolume(1.0f) , mMusicVolume(1.0f) - , mFootstepsVolume(1.0f) , mVoiceVolume(1.0f) - , mPausedSoundTypes(0) + , mFootstepsVolume(1.0f) + , mListenerUnderwater(false) , mListenerPos(0,0,0) , mListenerDir(1,0,0) , mListenerUp(0,0,1) - , mListenerUnderwater(false) + , mPausedSoundTypes(0) { if(!useSound) return; diff --git a/apps/openmw/mwworld/action.cpp b/apps/openmw/mwworld/action.cpp index 1c360fd4dd..5e1fb41a6c 100644 --- a/apps/openmw/mwworld/action.cpp +++ b/apps/openmw/mwworld/action.cpp @@ -11,7 +11,7 @@ const MWWorld::Ptr& MWWorld::Action::getTarget() const return mTarget; } -MWWorld::Action::Action (bool keepSound, const Ptr& target) : mKeepSound (keepSound), mTarget (target), mSoundOffset(0) +MWWorld::Action::Action (bool keepSound, const Ptr& target) : mKeepSound (keepSound), mSoundOffset(0), mTarget (target) {} MWWorld::Action::~Action() {} diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 13a786d008..b12d646e70 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -9,8 +9,8 @@ namespace MWWorld EsmLoader::EsmLoader(MWWorld::ESMStore& store, std::vector& readers, ToUTF8::Utf8Encoder* encoder, Loading::Listener& listener) : ContentLoader(listener) - , mStore(store) , mEsm(readers) + , mStore(store) , mEncoder(encoder) { } diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 2de3abc750..a2e445d581 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -96,10 +96,10 @@ void MWWorld::InventoryStore::readEquipmentState(const MWWorld::ContainerStoreIt } MWWorld::InventoryStore::InventoryStore() - : mSelectedEnchantItem(end()) + : mListener(NULL) , mUpdatesEnabled (true) , mFirstAutoEquip(true) - , mListener(NULL) + , mSelectedEnchantItem(end()) , mRechargingItemsUpToDate(false) { initSlots (mSlots); @@ -107,12 +107,12 @@ MWWorld::InventoryStore::InventoryStore() MWWorld::InventoryStore::InventoryStore (const InventoryStore& store) : ContainerStore (store) - , mSelectedEnchantItem(end()) , mMagicEffects(store.mMagicEffects) - , mFirstAutoEquip(store.mFirstAutoEquip) , mListener(store.mListener) , mUpdatesEnabled(store.mUpdatesEnabled) + , mFirstAutoEquip(store.mFirstAutoEquip) , mPermanentMagicEffectMagnitudes(store.mPermanentMagicEffectMagnitudes) + , mSelectedEnchantItem(end()) , mRechargingItemsUpToDate(false) { copySlots (store); diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index d31ae520bd..bec4c6db32 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -499,7 +499,7 @@ namespace MWWorld PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) : - mRender(_rend), mEngine(0), mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0) + mRender(_rend), mEngine(0), mTimeAccum(0.0f), mWaterHeight(0), mWaterEnabled(false) { // Create physics. shapeLoader is deleted by the physic engine NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 58718074ee..0b81532e18 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -32,10 +32,10 @@ namespace MWWorld Player::Player (const ESM::NPC *player, const MWBase::World& world) : mCellStore(0), mLastKnownExteriorPosition(0,0,0), + mMarkedCell(NULL), mAutoMove(false), mForwardBackward(0), mTeleported(false), - mMarkedCell(NULL), mCurrentCrimeId(-1), mPaidCrimeId(-1) { diff --git a/apps/openmw/mwworld/refdata.cpp b/apps/openmw/mwworld/refdata.cpp index 14a315a81b..ae985f8574 100644 --- a/apps/openmw/mwworld/refdata.cpp +++ b/apps/openmw/mwworld/refdata.cpp @@ -37,7 +37,7 @@ namespace MWWorld } RefData::RefData() - : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false), mDeleted(false) + : mBaseNode(0), mDeleted(false), mHasLocals (false), mEnabled (true), mCount (1), mCustomData (0), mChanged(false) { for (int i=0; i<3; ++i) { @@ -48,10 +48,10 @@ namespace MWWorld } RefData::RefData (const ESM::CellRef& cellRef) - : mBaseNode(0), mHasLocals (false), mEnabled (true), mCount (1), mPosition (cellRef.mPos), + : mBaseNode(0), mDeleted(false), mHasLocals (false), mEnabled (true), + mCount (1), mPosition (cellRef.mPos), mCustomData (0), - mChanged(false), // Loading from ESM/ESP files -> assume unchanged - mDeleted(false) + mChanged(false) // Loading from ESM/ESP files -> assume unchanged { mLocalRotation.rot[0]=0; mLocalRotation.rot[1]=0; @@ -59,10 +59,12 @@ namespace MWWorld } RefData::RefData (const ESM::ObjectState& objectState) - : mBaseNode (0), mHasLocals (false), mEnabled (objectState.mEnabled != 0), - mCount (objectState.mCount), mPosition (objectState.mPosition), mCustomData (0), - mChanged(true), // Loading from a savegame -> assume changed - mDeleted(false) + : mBaseNode (0), mDeleted(false), mHasLocals (false), + mEnabled (objectState.mEnabled != 0), + mCount (objectState.mCount), + mPosition (objectState.mPosition), + mCustomData (0), + mChanged(true) // Loading from a savegame -> assume changed { for (int i=0; i<3; ++i) mLocalRotation.rot[i] = objectState.mLocalRotation[i]; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index a9ca8e72b5..41ed7c20da 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -114,11 +114,10 @@ float WeatherManager::calculateAngleFade (const std::string& moonName, float ang } WeatherManager::WeatherManager(MWRender::RenderingManager* rendering,MWWorld::Fallback* fallback) : - mHour(14), mCurrentWeather("clear"), mNextWeather(""), mFirstUpdate(true), - mWeatherUpdateTime(0), mThunderFlash(0), mThunderChance(0), - mThunderChanceNeeded(50), mThunderSoundDelay(0), mRemainingTransitionTime(0), - mTimePassed(0), mFallback(fallback), mWindSpeed(0.f), mRendering(rendering), mIsStorm(false), - mStormDirection(0,1,0) + mHour(14), mWindSpeed(0.f), mIsStorm(false), mStormDirection(0,1,0), mFallback(fallback), + mRendering(rendering), mCurrentWeather("clear"), mNextWeather(""), mFirstUpdate(true), + mRemainingTransitionTime(0), mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50), + mTimePassed(0), mWeatherUpdateTime(0), mThunderSoundDelay(0) { //Globals mThunderSoundID0 = mFallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_0"); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bb0402c4e5..b1bac2f4b0 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -147,14 +147,12 @@ namespace MWWorld const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, ToUTF8::Utf8Encoder* encoder, const std::map& fallbackMap, int activationDistanceOverride, const std::string& startCell, const std::string& startupScript) - : mPlayer (0), mLocalScripts (mStore), + : mFallback(fallbackMap), mPlayer (0), mLocalScripts (mStore), mSky (true), mCells (mStore, mEsm), - mActivationDistanceOverride (activationDistanceOverride), - mFallback(fallbackMap), mTeleportEnabled(true), mLevitationEnabled(true), - mGodMode(false), mContentFiles (contentFiles), - mGoToJail(false), mDaysInPrison(0), - mStartCell (startCell), mStartupScript(startupScript), - mScriptsEnabled(true) + mGodMode(false), mScriptsEnabled(true), mContentFiles (contentFiles), + mActivationDistanceOverride (activationDistanceOverride), mStartupScript(startupScript), + mStartCell (startCell), mTeleportEnabled(true), + mLevitationEnabled(true), mGoToJail(false), mDaysInPrison(0) { mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); @@ -2939,7 +2937,7 @@ namespace MWWorld struct AddDetectedReference { AddDetectedReference(std::vector& out, Ptr detector, World::DetectionType type, float squaredDist) - : mOut(out), mDetector(detector), mType(type), mSquaredDist(squaredDist) + : mOut(out), mDetector(detector), mSquaredDist(squaredDist), mType(type) { } diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 88b5f5ddb3..a71672916b 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -56,8 +56,8 @@ namespace Compiler LineParser::LineParser (ErrorHandler& errorHandler, const Context& context, Locals& locals, Literals& literals, std::vector& code, bool allowExpression) : Parser (errorHandler, context), mLocals (locals), mLiterals (literals), mCode (code), - mState (BeginState), mExprParser (errorHandler, context, locals, literals), - mAllowExpression (allowExpression), mButtons(0), mType(0), mReferenceMember(false) + mState (BeginState), mReferenceMember(false), mButtons(0), mType(0), + mExprParser (errorHandler, context, locals, literals), mAllowExpression (allowExpression) {} bool LineParser::parseInt (int value, const TokenLoc& loc, Scanner& scanner) diff --git a/components/interpreter/runtime.cpp b/components/interpreter/runtime.cpp index c71aef95c5..dc3da07a8d 100644 --- a/components/interpreter/runtime.cpp +++ b/components/interpreter/runtime.cpp @@ -7,7 +7,7 @@ namespace Interpreter { - Runtime::Runtime() : mContext (0), mCode (0), mPC (0), mCodeSize(0) {} + Runtime::Runtime() : mContext (0), mCode (0), mCodeSize(0), mPC (0) {} int Runtime::getPC() const { diff --git a/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp b/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp index 1a56802dae..77e6b4b6c0 100644 --- a/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp +++ b/extern/ogre-ffmpeg-videoplayer/audiodecoder.cpp @@ -60,21 +60,21 @@ struct AudioResampler MovieAudioDecoder::MovieAudioDecoder(VideoState* videoState) : mVideoState(videoState) , mAVStream(*videoState->audio_st) - , mFrame(av_frame_alloc()) + , mOutputSampleFormat(AV_SAMPLE_FMT_NONE) + , mOutputChannelLayout(0) + , mOutputSampleRate(0) , mFramePos(0) , mFrameSize(0) , mAudioClock(0.0) + , mDataBuf(NULL) + , mFrameData(NULL) + , mDataBufLen(0) + , mFrame(av_frame_alloc()) , mAudioDiffAccum(0.0) , mAudioDiffAvgCoef(exp(log(0.01 / AUDIO_DIFF_AVG_NB))) /* Correct audio only if larger error than this */ , mAudioDiffThreshold(2.0 * 0.050/* 50 ms */) , mAudioDiffAvgCount(0) - , mOutputSampleFormat(AV_SAMPLE_FMT_NONE) - , mOutputSampleRate(0) - , mOutputChannelLayout(0) - , mDataBuf(NULL) - , mFrameData(NULL) - , mDataBufLen(0) { mAudioResampler.reset(new AudioResampler()); } diff --git a/extern/ogre-ffmpeg-videoplayer/videostate.cpp b/extern/ogre-ffmpeg-videoplayer/videostate.cpp index 66c7c2ad50..877906f6df 100644 --- a/extern/ogre-ffmpeg-videoplayer/videostate.cpp +++ b/extern/ogre-ffmpeg-videoplayer/videostate.cpp @@ -59,16 +59,18 @@ namespace Video { VideoState::VideoState() - : format_ctx(NULL), av_sync_type(AV_SYNC_DEFAULT) + : mAudioFactory(NULL) + , format_ctx(NULL) + , av_sync_type(AV_SYNC_DEFAULT) , audio_st(NULL) , video_st(NULL), frame_last_pts(0.0) , video_clock(0.0), sws_context(NULL), rgbaFrame(NULL), pictq_size(0) , pictq_rindex(0), pictq_windex(0) - , mQuit(false), mPaused(false) - , mAudioFactory(NULL) , mSeekRequested(false) , mSeekPos(0) , mVideoEnded(false) + , mPaused(false) + , mQuit(false) { mFlushPktData = flush_pkt.data; diff --git a/extern/oics/ICSControl.cpp b/extern/oics/ICSControl.cpp index 974d69f081..1e9679d1f8 100644 --- a/extern/oics/ICSControl.cpp +++ b/extern/oics/ICSControl.cpp @@ -32,9 +32,9 @@ namespace ICS { Control::Control(const std::string& name, bool autoChangeDirectionOnLimitsAfterStop, bool autoReverseToInitialValue , float initialValue, float stepSize, float stepsPerSeconds, bool axisBindable) - : mName(name) - , mValue(initialValue) + : mValue(initialValue) , mInitialValue(initialValue) + , mName(name) , mStepSize(stepSize) , mStepsPerSeconds(stepsPerSeconds) , mAutoReverseToInitialValue(autoReverseToInitialValue) diff --git a/extern/oics/ICSInputControlSystem.cpp b/extern/oics/ICSInputControlSystem.cpp index 2599c57614..a8aedfd2e5 100644 --- a/extern/oics/ICSInputControlSystem.cpp +++ b/extern/oics/ICSInputControlSystem.cpp @@ -32,13 +32,13 @@ namespace ICS , DetectingBindingListener* detectingBindingListener , InputControlSystemLog* log, size_t channelCount) : mFileName(file) + , mLog(log) , mDetectingBindingListener(detectingBindingListener) , mDetectingBindingControl(NULL) - , mLog(log) - , mXmouseAxisBinded(false), mYmouseAxisBinded(false) - , mClientHeight(1) - , mClientWidth(1) , mDetectingBindingDirection(Control::STOP) + , mXmouseAxisBinded(false), mYmouseAxisBinded(false) + , mClientWidth(1) + , mClientHeight(1) { ICS_LOG(" - Creating InputControlSystem - "); @@ -539,10 +539,10 @@ namespace ICS } binder.SetAttribute( "direction", "DECREASE" ); control.InsertEndChild(binder); - } - JoystickIDList::const_iterator it = mJoystickIDList.begin(); - while(it!=mJoystickIDList.end()) - { + } + JoystickIDList::const_iterator it = mJoystickIDList.begin(); + while(it!=mJoystickIDList.end()) + { int deviceID = *it; if(getJoystickAxisBinding(*o, deviceID, Control/*::ControlChangingDirection*/::INCREASE) != /*NamedAxis::*/UNASSIGNED) @@ -552,8 +552,8 @@ namespace ICS binder.SetAttribute( "axis", ToString( getJoystickAxisBinding(*o, deviceID, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); - binder.SetAttribute( "direction", "INCREASE" ); - + binder.SetAttribute( "direction", "INCREASE" ); + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability control.InsertEndChild(binder); @@ -567,8 +567,8 @@ namespace ICS binder.SetAttribute( "axis", ToString( getJoystickAxisBinding(*o, deviceID, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); - binder.SetAttribute( "direction", "DECREASE" ); - + binder.SetAttribute( "direction", "DECREASE" ); + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability control.InsertEndChild(binder); @@ -582,8 +582,8 @@ namespace ICS binder.SetAttribute( "button", ToString( getJoystickButtonBinding(*o, deviceID, Control/*::ControlChangingDirection*/::INCREASE)).c_str() ); - binder.SetAttribute( "direction", "INCREASE" ); - + binder.SetAttribute( "direction", "INCREASE" ); + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability control.InsertEndChild(binder); @@ -597,13 +597,13 @@ namespace ICS binder.SetAttribute( "button", ToString( getJoystickButtonBinding(*o, deviceID, Control/*::ControlChangingDirection*/::DECREASE)).c_str() ); - binder.SetAttribute( "direction", "DECREASE" ); - + binder.SetAttribute( "direction", "DECREASE" ); + binder.SetAttribute( "deviceId", deviceID ); //completely useless, but required for backwards compatability control.InsertEndChild(binder); - } - it++; + } + it++; } diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index aaf669ff43..7e3536ab40 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -10,28 +10,28 @@ namespace SFO /// \brief General purpose wrapper for OGRE applications around SDL's event /// queue, mostly used for handling input-related events. InputWrapper::InputWrapper(SDL_Window* window, Ogre::RenderWindow* ogreWindow, bool grab) : - mSDLWindow(window), - mOgreWindow(ogreWindow), - mWarpCompensate(false), - mMouseRelative(false), - mGrabPointer(false), - mWrapPointer(false), - mMouseZ(0), - mMouseY(0), - mMouseX(0), - mMouseInWindow(true), - mConListener(NULL), - mKeyboardListener(NULL), mMouseListener(NULL), + mKeyboardListener(NULL), mWindowListener(NULL), - mWindowHasFocus(true), - mWantGrab(false), - mWantRelative(false), - mWantMouseVisible(false), - mAllowGrab(grab), + mConListener(NULL), mWarpX(0), mWarpY(0), - mFirstMouseMove(true) + mWarpCompensate(false), + mWrapPointer(false), + mAllowGrab(grab), + mWantMouseVisible(false), + mWantGrab(false), + mWantRelative(false), + mGrabPointer(false), + mMouseRelative(false), + mFirstMouseMove(true), + mMouseZ(0), + mMouseX(0), + mMouseY(0), + mWindowHasFocus(true), + mMouseInWindow(true), + mSDLWindow(window), + mOgreWindow(ogreWindow) { _setupOISKeys(); } diff --git a/extern/shiny/Main/Factory.cpp b/extern/shiny/Main/Factory.cpp index d7c4234cb7..d0b86cbf94 100644 --- a/extern/shiny/Main/Factory.cpp +++ b/extern/shiny/Main/Factory.cpp @@ -29,17 +29,17 @@ namespace sh } Factory::Factory (Platform* platform) - : mPlatform(platform) - , mShadersEnabled(true) + : mShadersEnabled(true) , mShaderDebugOutputEnabled(false) - , mCurrentLanguage(Language_None) - , mListener(NULL) - , mCurrentConfiguration(NULL) - , mCurrentLodConfiguration(NULL) , mReadMicrocodeCache(false) , mWriteMicrocodeCache(false) , mReadSourceCache(false) , mWriteSourceCache(false) + , mCurrentConfiguration(NULL) + , mCurrentLodConfiguration(NULL) + , mCurrentLanguage(Language_None) + , mListener(NULL) + , mPlatform(platform) { assert (!sThis); sThis = this; diff --git a/extern/shiny/Main/MaterialInstance.cpp b/extern/shiny/Main/MaterialInstance.cpp index c69d134010..5d1a8e7f9d 100644 --- a/extern/shiny/Main/MaterialInstance.cpp +++ b/extern/shiny/Main/MaterialInstance.cpp @@ -9,11 +9,11 @@ namespace sh { MaterialInstance::MaterialInstance (const std::string& name, Factory* f) - : mName(name) + : mFailedToCreate(false) + , mListener(NULL) + , mName(name) , mShadersEnabled(true) , mFactory(f) - , mListener(NULL) - , mFailedToCreate(false) { } diff --git a/extern/shiny/Main/Platform.cpp b/extern/shiny/Main/Platform.cpp index 3eb7f4ad34..f09956e0fd 100644 --- a/extern/shiny/Main/Platform.cpp +++ b/extern/shiny/Main/Platform.cpp @@ -7,9 +7,9 @@ namespace sh { Platform::Platform (const std::string& basePath) - : mBasePath(basePath) - , mCacheFolder("./") + : mCacheFolder("./") , mFactory(NULL) + , mBasePath(basePath) { } diff --git a/extern/shiny/Main/ShaderSet.cpp b/extern/shiny/Main/ShaderSet.cpp index 8fb530d394..4e19948ad9 100644 --- a/extern/shiny/Main/ShaderSet.cpp +++ b/extern/shiny/Main/ShaderSet.cpp @@ -15,9 +15,9 @@ namespace sh ShaderSet::ShaderSet (const std::string& type, const std::string& cgProfile, const std::string& hlslProfile, const std::string& sourceFile, const std::string& basePath, const std::string& name, PropertySetGet* globalSettingsPtr) : mBasePath(basePath) - , mName(name) , mCgProfile(cgProfile) , mHlslProfile(hlslProfile) + , mName(name) { if (type == "vertex") mType = GPT_Vertex; From a5183aefbe41a99dd1481249bb180f3314966c81 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 22 May 2015 23:53:25 +0300 Subject: [PATCH 116/142] Add record state tracking to the ModifyCommand (Fix #2555) --- apps/opencs/model/world/commands.cpp | 15 ++++++++++++++- apps/opencs/model/world/commands.hpp | 4 ++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 9a0401081b..11cb911765 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -14,7 +14,7 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand* parent) -: QUndoCommand (parent), mModel (&model), mIndex (index), mNew (new_) +: QUndoCommand (parent), mModel (&model), mIndex (index), mNew (new_), mHasRecordState(false) { if (QAbstractProxyModel *proxy = dynamic_cast (&model)) { @@ -27,6 +27,15 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI } else setText ("Modify " + mModel->headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); + + // Remember record state before the modification + if (CSMWorld::IdTable *table = dynamic_cast(mModel)) + { + mHasRecordState = true; + int stateColumnIndex = table->findColumnIndex(Columns::ColumnId_Modification); + mRecordStateIndex = table->index(mIndex.row(), stateColumnIndex); + mOldRecordState = static_cast(table->data(mRecordStateIndex).toInt()); + } } void CSMWorld::ModifyCommand::redo() @@ -38,6 +47,10 @@ void CSMWorld::ModifyCommand::redo() void CSMWorld::ModifyCommand::undo() { mModel->setData (mIndex, mOld); + if (mHasRecordState) + { + mModel->setData(mRecordStateIndex, mOldRecordState); + } } diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index f133761450..cdd398153c 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -31,6 +31,10 @@ namespace CSMWorld QVariant mNew; QVariant mOld; + bool mHasRecordState; + QModelIndex mRecordStateIndex; + CSMWorld::RecordBase::State mOldRecordState; + public: ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, From 10ca6cf3796b3035d97b50d6ac092bc36ee21600 Mon Sep 17 00:00:00 2001 From: Cramal Date: Sat, 23 May 2015 14:39:16 +0900 Subject: [PATCH 117/142] debug latex code --- manual/opencs/tables.tex | 2 -- 1 file changed, 2 deletions(-) diff --git a/manual/opencs/tables.tex b/manual/opencs/tables.tex index b47d5f3d4e..5034898729 100644 --- a/manual/opencs/tables.tex +++ b/manual/opencs/tables.tex @@ -92,5 +92,3 @@ when you hover your reticle over the object. This is a library of all the items, triggers, containers, NPCs, etc. in the game. There are several kinds of Record Types. Depending on which type a record is, it will need specific information to function. For example, an NPC needs a value attached to its aggression level. A chest, of course, does not. All Record Types contain at least a model. How else would the player see them? Usually they also have a Name, which is what you see when you hover your reticle over the object. Please refer to the Record Types section for an overview of what each type of Referenceable does and what you can tell OpenCS about these objects. - -\end{description} From 45f6e3b39ef99b4be5ec33e9027e0e010cb79a48 Mon Sep 17 00:00:00 2001 From: Cramal Date: Sat, 23 May 2015 14:40:04 +0900 Subject: [PATCH 118/142] debug latex code --- manual/opencs/recordtypes.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manual/opencs/recordtypes.tex b/manual/opencs/recordtypes.tex index afe5a67e35..4dbfbe2864 100644 --- a/manual/opencs/recordtypes.tex +++ b/manual/opencs/recordtypes.tex @@ -9,8 +9,8 @@ Let's go through all Record Types and discuss what you can tell OpenCS about the \item[Activator:] When the player enters the same cell as this object, a script is started. Often it also has a \textbf{Script} attached to it, though it not mandatory. These scripts are small bits of code written in a special scripting language that OpenCS can read and interpret. \item[Potion:] This is a potion that is not self-made. It has an \textbf{Icon} for your inventory, Aside from the self-explanatory \textbf{Weight} and \textbf{Coin Value}, it has an attribute called \textbf{Auto Calc} set to ``False''. This means that the effects of this potion are preconfigured. This does not happen when the player makes their own potion. \item[Apparatus:] This is a tool to make potions. Again there's an icon for your inventory as well as a weight and a coin value. It also has a \textbf{Quality} value attached to it: higher the number, the better the effect on your potions will be. The \textbf{Apparatus Type} describes if the item is a Calcinator, Retort, Alembir or Mortar & Pestal. Each has a different effect on the potion the player makes. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Alchemy#Tools}{UESP page on Alchemy Tools}. - \item[Armor:] This type of item adds \textbf{Enchantment Points} to the mix. Every piece of clothing or armor has a ''pool'' of potential magicka that gets unlocked when you enchant it. Strong enchantments consume more magicka from this pool: the stronger the enchantment, the more Enchantment Points each cast will take up. For more information on this subject, please refer to the \href{Enchant page on UESP}{http://www.uesp.net/wiki/Morrowind:Enchant}. \textbf{Health} means the amount of hit points this piece of armor has. If it sustains enough damage, the armor will be destroyed. Finally, \textbf{Armor Value} tells the game how much points to add to the player character's Armor Rating. - \item[Book:] This includes scrolls and notes. For the game to make the distinction between books and scrolls, an extra property, \textbf{Scroll}, has been added. Under the \textbf{Skill} column a scroll or book can have an in-game skill listed. Reading this item will raise the player's level in that specific skill. For more information on this, please refer to the \href{Skill Books page on UESP}{http://www.uesp.net/wiki/Morrowind:Skill_Books}. + \item[Armor:] This type of item adds \textbf{Enchantment Points} to the mix. Every piece of clothing or armor has a ''pool'' of potential magicka that gets unlocked when you enchant it. Strong enchantments consume more magicka from this pool: the stronger the enchantment, the more Enchantment Points each cast will take up. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Enchant}{Enchant page on UESP}. \textbf{Health} means the amount of hit points this piece of armor has. If it sustains enough damage, the armor will be destroyed. Finally, \textbf{Armor Value} tells the game how much points to add to the player character's Armor Rating. + \item[Book:] This includes scrolls and notes. For the game to make the distinction between books and scrolls, an extra property, \textbf{Scroll}, has been added. Under the \textbf{Skill} column a scroll or book can have an in-game skill listed. Reading this item will raise the player's level in that specific skill. For more information on this, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Skill_Books}{Skill Books page on UESP}. \item[Clothing:] These items work just like Armors, but confer no protective properties. Rather than ``Armor Type'', these items have a ``Clothing Type''. \item[Container:] This is all the stuff that stores items, from chests to sacks to plants. Its \textbf{Capacity} shows how much stuff you can put in the container. You can compare it to the maximum allowed load a player character can carry (who will get over-encumbered and unable to move if he crosses this threshold). A container, however, will just refuse to take the item in question when it gets ''over-encumbered''. \textbf{Organic Container}s are containers such as plants. Containers that \textbf{Respawn} are not safe to store stuff in. After a certain amount of time they will reset to their default contents, meaning that everything in it is gone forever. \item[Creature:] These can be monsters, animals and the like. From 63c3d8df2e38dac647e6f50a4a1e5c0e14a2e4da Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 23 May 2015 09:46:48 +0200 Subject: [PATCH 119/142] updated credits file --- AUTHORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.md b/AUTHORS.md index fb83a1a91d..ce76c104e1 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -114,6 +114,7 @@ Manual ------ Bodillium + Cramal sir_herrbatka Packagers From 21af1913e1d1e30dc3fc91e503ff862dba0fae1d Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 24 May 2015 19:18:54 +1000 Subject: [PATCH 120/142] Ensure ColumnId names are unique. --- apps/opencs/model/world/columns.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index c937997a92..9491c32469 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -176,7 +176,7 @@ namespace CSMWorld { ColumnId_ContainerContent, "Content" }, { ColumnId_ItemCount, "Count" }, - { ColumnId_InventoryItemId, "ID"}, + { ColumnId_InventoryItemId, "Item ID"}, { ColumnId_CombatState, "Combat" }, { ColumnId_MagicState, "Magic" }, @@ -188,10 +188,10 @@ namespace CSMWorld { ColumnId_ActorInventory, "Inventory" }, { ColumnId_SpellList, "Spells" }, - { ColumnId_SpellId, "ID"}, + { ColumnId_SpellId, "Spell ID"}, { ColumnId_NpcDestinations, "Destinations" }, - { ColumnId_DestinationCell, "Cell"}, + { ColumnId_DestinationCell, "Dest Cell"}, { ColumnId_PosX, "Dest X"}, { ColumnId_PosY, "Dest Y"}, { ColumnId_PosZ, "Dest Z"}, @@ -224,17 +224,17 @@ namespace CSMWorld { ColumnId_BoltSound, "Bolt Sound" }, { ColumnId_PathgridPoints, "Points" }, - { ColumnId_PathgridIndex, "Index" }, + { ColumnId_PathgridIndex, "pIndex" }, { ColumnId_PathgridPosX, "X" }, { ColumnId_PathgridPosY, "Y" }, { ColumnId_PathgridPosZ, "Z" }, { ColumnId_PathgridEdges, "Edges" }, - { ColumnId_PathgridEdgeIndex, "Index" }, + { ColumnId_PathgridEdgeIndex, "eIndex" }, { ColumnId_PathgridEdge0, "Point 0" }, { ColumnId_PathgridEdge1, "Point 1" }, { ColumnId_RegionSounds, "Sounds" }, - { ColumnId_SoundName, "Name" }, + { ColumnId_SoundName, "Sound Name" }, { ColumnId_SoundChance, "Chance" }, { ColumnId_FactionReactions, "Reactions" }, @@ -250,7 +250,7 @@ namespace CSMWorld { ColumnId_AiPackageList, "Ai Packages" }, { ColumnId_AiPackageType, "Package" }, { ColumnId_AiWanderDist, "Wander Dist" }, - { ColumnId_AiDuration, "Duration" }, + { ColumnId_AiDuration, "Ai Duration" }, { ColumnId_AiWanderToD, "Wander ToD" }, { ColumnId_AiWanderIdle, "Wander Idle" }, { ColumnId_AiWanderRepeat, "Wander Repeat" }, @@ -260,11 +260,11 @@ namespace CSMWorld { ColumnId_PartRefList, "Part Reference" }, { ColumnId_PartRefType, "Type" }, - { ColumnId_PartRefMale, "Male" }, - { ColumnId_PartRefFemale, "Female" }, + { ColumnId_PartRefMale, "Male Part" }, + { ColumnId_PartRefFemale, "Female Part" }, { ColumnId_LevelledList,"Levelled List" }, - { ColumnId_LevelledItemId,"Item ID" }, + { ColumnId_LevelledItemId,"Levelled Item" }, { ColumnId_LevelledItemLevel,"Level" }, { ColumnId_LevelledItemType, "Calculate all levels <= player" }, { ColumnId_LevelledItemTypeEach, "Select a new item each instance" }, @@ -278,7 +278,7 @@ namespace CSMWorld { ColumnId_InfoCondFunc, "Function" }, { ColumnId_InfoCondVar, "Func/Variable" }, { ColumnId_InfoCondComp, "Comp" }, - { ColumnId_InfoCondValue, "Value" }, + { ColumnId_InfoCondValue, "Values" }, { ColumnId_OriginalCell, "Original Cell" }, { ColumnId_NpcAttributes, "Attributes" }, From 22420c3a83e5294bbf9d2ef73383d7fc151ca87f Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sun, 24 May 2015 23:19:06 +1000 Subject: [PATCH 121/142] Close DialogueSubView if the corresponding record is deleted. Should resolve Bug #2575. - ToDo: Doesn't seem to shrink the widget width properly (when horizontal scrollbar is active) --- apps/opencs/view/world/dialoguesubview.cpp | 19 +++++++++++++++++++ apps/opencs/view/world/dialoguesubview.hpp | 2 ++ 2 files changed, 21 insertions(+) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 647accd4c3..0860cf2b2c 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -578,6 +578,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mCommandDispatcher (document, CSMWorld::UniversalId::getParentType (id.getType())) { connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&))); + connect(mTable, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex&, int, int))); changeCurrentId(id.getId()); @@ -740,6 +741,9 @@ void CSVWorld::DialogueSubView::nextId () void CSVWorld::DialogueSubView::setEditLock (bool locked) { + if (!mEditWidget) // hack to indicate that mCurrentId is no longer valid + return; + mLocked = locked; QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); @@ -766,6 +770,21 @@ void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index) } } +void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (currentIndex.isValid() && currentIndex.row() >= start && currentIndex.row() <= end) + { + if(mEditWidget) + { + delete mEditWidget; + mEditWidget = 0; + } + emit closeRequest(this); + } +} + void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor, const QModelIndex& index, const CSMWorld::UniversalId& id, diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index b5a44d266f..6d12d62c14 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -235,6 +235,8 @@ namespace CSVWorld const CSMDoc::Document* document); void requestFocus (const std::string& id); + + void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); }; } From e6d2821b78affea63b588988f1b338dcc4667315 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 25 May 2015 09:15:07 +1000 Subject: [PATCH 122/142] Refresh table filters when the model is updated. Should resolve Bug #2579. --- apps/opencs/model/world/idtableproxymodel.cpp | 6 ++++++ apps/opencs/model/world/idtableproxymodel.hpp | 2 ++ apps/opencs/view/world/table.cpp | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index 93c1749c63..84869716e2 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -53,3 +53,9 @@ bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModel { return QSortFilterProxyModel::lessThan(left, right); } + +void CSMWorld::IdTableProxyModel::refreshFilter() +{ + updateColumnMap(); + invalidateFilter(); +} diff --git a/apps/opencs/model/world/idtableproxymodel.hpp b/apps/opencs/model/world/idtableproxymodel.hpp index 23e3193fb2..8683c2b9e5 100644 --- a/apps/opencs/model/world/idtableproxymodel.hpp +++ b/apps/opencs/model/world/idtableproxymodel.hpp @@ -34,6 +34,8 @@ namespace CSMWorld void setFilter (const boost::shared_ptr& filter); + void refreshFilter(); + protected: bool lessThan(const QModelIndex &left, const QModelIndex &right) const; diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index b8972edbe4..bb3dfa4d32 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -649,6 +649,10 @@ void CSVWorld::Table::tableSizeUpdate() } emit tableSizeChanged (size, deleted, modified); + + // not really related to tableSizeUpdate() but placed here for convenience rather than + // creating a bunch of extra connections & slot + mProxyModel->refreshFilter(); } void CSVWorld::Table::selectionSizeUpdate() From 3c82e6d03401795d1e147a8e2f5d32e812eb9c4a Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 25 May 2015 16:36:42 +1000 Subject: [PATCH 123/142] Retrieve the correct index for the type of record being un-deleted. --- apps/opencs/model/world/idtable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index a0dd0b47bd..36b3f5c970 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -160,7 +160,7 @@ void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& reco if (index==-1) { - int index = mIdCollection->getAppendIndex (id); + int index = mIdCollection->getAppendIndex (id, type); beginInsertRows (QModelIndex(), index, index); From 18f047f50e1f720bafd486a1185f113f2dc35d60 Mon Sep 17 00:00:00 2001 From: Cramal Date: Mon, 25 May 2015 18:40:13 +0900 Subject: [PATCH 124/142] Moving to Object/Instance terminology + minor spelling corrections --- manual/opencs/creating_file.tex | 2 +- manual/opencs/main.tex | 2 ++ manual/opencs/recordmodification.tex | 16 ++++++++-------- manual/opencs/recordtypes.tex | 8 ++++---- manual/opencs/tables.tex | 18 +++++++++--------- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/manual/opencs/creating_file.tex b/manual/opencs/creating_file.tex index 317e453b73..8cab33fb9b 100644 --- a/manual/opencs/creating_file.tex +++ b/manual/opencs/creating_file.tex @@ -17,7 +17,7 @@ It is simple. When you click either \textbf{Create new Addon} you will be asked The last thing to do is to name your your addon and click create. \paragraph{Selecting File for Editing} -Clicking \textbf{Edit A Content File} will show somewhat similar window. Here you should select your Game file with drop down menu. If you want to edit this game file, simply click \textbf{OK} button. If you want to alter addon depending on that file, mark it with checkbox and than click \textbf{Ok} button. +Clicking \textbf{Edit A Content File} will show somewhat similar window. Here you should select your Game file with drop down menu. If you want to edit this game file, simply click \textbf{OK} button. If you want to alter addon depending on that file, mark it with check-box and than click \textbf{Ok} button. \subsection{Advanced} If you are paying attention, you noticed any extra icon with wrench. This one will open small settings window. Those are general OpenCS settings. We will cover this is separate section.\\ diff --git a/manual/opencs/main.tex b/manual/opencs/main.tex index f3a46c1b7b..fd85baee4f 100644 --- a/manual/opencs/main.tex +++ b/manual/opencs/main.tex @@ -25,7 +25,9 @@ \title{OpenCS User Manual} \maketitle +\newpage \tableofcontents{} +\newpage \input{files_and_directories} \input{creating_file} \input{windows} diff --git a/manual/opencs/recordmodification.tex b/manual/opencs/recordmodification.tex index b1cf866d65..570bd4a95b 100644 --- a/manual/opencs/recordmodification.tex +++ b/manual/opencs/recordmodification.tex @@ -1,17 +1,17 @@ \section{Records Modification} \subsection{Introduction} -So far you learned how to browse trough records stored inside the content files, but not how to modify them using the \OCS{} editor. Although browsing is certainly a usefull ability on it's own, You probabbly counted on doing actual editing with this editor. There are few ways user can alter records stored in the content files, each suited for certain class of a problem. In this section We will describe how to do change records using tables interface and edit panel. +So far you learned how to browse trough records stored inside the content files, but not how to modify them using the \OCS{} editor. Although browsing is certainly a useful ability on it's own, You probably counted on doing actual editing with this editor. There are few ways user can alter records stored in the content files, each suited for certain class of a problem. In this section We will describe how to do change records using tables interface and edit panel. \subsubsection{Glossary} \begin{description} - \item[Edit Panel] Interface element used inside the \OCS{} to present records data for editing. Unlike table it showes only one record at the time. However it also presents fields that are not visible inside the table. It is also safe to say that Edit Panel presents data in way that is easier to read thanks to it's horizontal layout. + \item[Edit Panel] Interface element used inside the \OCS{} to present records data for editing. Unlike table it shows only one record at the time. However it also presents fields that are not visible inside the table. It is also safe to say that Edit Panel presents data in way that is easier to read thanks to it's horizontal layout. \end{description} \subsection{Edit Panel Interface} -Edit Panel is designed to aid you with record modification tasks. As It has been said, it uses vertical layout and presents some additional fields when compared with the table -- and some fields, even if they are actually displayed in the table, clearly ill-suited for modification isnide of them (this applies to fields that holds long text strings -- like descriptions). It also displays visual difference beetween non-editable field and editable.\\ +Edit Panel is designed to aid you with record modification tasks. As It has been said, it uses vertical layout and presents some additional fields when compared with the table -- and some fields, even if they are actually displayed in the table, clearly ill-suited for modification inside of them (this applies to fields that holds long text strings -- like descriptions). It also displays visual difference between non-editable field and editable.\\ To open edit panel, please open context menu on any record and choose edit action. This will open edit panel in the same window as your table and will present you the record fields. First data fields are actually not user editable and presented in the form of the text labels at the top of the edit panel. Lower data fields are presented in the form of actually user-editable widgets. Those includes spinboxes, text edits and text fields\footnote{Those are actually a valid terms used to describe classes of the user interface elements. If you don't understand those, don't worry -- those are very standard {GUI} elements present in almost every application since the rise of the desktop metaphor.}. Once you will finish editing one of those fields, data will be updated. There is no apply button of any sort -- simply use one of those widgets and be merry.\\ -In addition to that you probabbly noticed some icons in the bar located at the very bottom of the edit panel. Those can be used to perform the following actions: +In addition to that you probably noticed some icons in the bar located at the very bottom of the edit panel. Those can be used to perform the following actions: \begin{description} \item[Preview] This will launch simple preview panel -- which will be described later. @@ -20,7 +20,7 @@ In addition to that you probabbly noticed some icons in the bar located at the v \end{description} \subsection{Verification tool} -As you could notice there is nothing that can stop you from breaking the game by violating record fields logic, and yet -- it is something that you are always trying to avoid. To adress this problem \OCS{} utilizes so called verification tool (or verifer as many prefer to call it) that basicly goes trough all records and checks if it contains any illogical fields. This includes for instance torch duration equal 0\footnote{Interestingly negative values are perfectly fine: they indicate that light source has no duration limit at all. There are records like this in the original game.} or characters without name, race or any other record with a mandatory field missing.\\ -This tool is even more usefull than it seems. If you somehow delete race that is used by some of the characters, all those characters will be suddenly broken. As a rule of thumb it is a good idea to use verifer before saving your content file.\\ -To launch this usefull tool %don't remember, todo... -Resoults are presented as a yet another table with short (and hopefully descriptive enough) description of the identified problem. It is worth noticing that some records located in the \MW{} esm files are listed by the verification tool -- it is not fault of our tool: those records are just broken. For instance, you actually may find the 0 duration torch. However, those records are usually not placed in game world itself -- and that's good since \MW{} game engine will crash if player equip light source like this!\footnote{We would like to thanks \BS{} for such a usefull testing material. It makes us feel special.} +As you could notice there is nothing that can stop you from breaking the game by violating record fields logic, and yet -- it is something that you are always trying to avoid. To address this problem \OCS{} utilizes so called verification tool (or verifer as many prefer to call it) that basically goes trough all records and checks if it contains any illogical fields. This includes for instance torch duration equal 0\footnote{Interestingly negative values are perfectly fine: they indicate that light source has no duration limit at all. There are records like this in the original game.} or characters without name, race or any other record with a mandatory field missing.\\ +This tool is even more useful than it seems. If you somehow delete race that is used by some of the characters, all those characters will be suddenly broken. As a rule of thumb it is a good idea to use verifer before saving your content file.\\ +To launch this useful tool %don't remember, todo... +Results are presented as a yet another table with short (and hopefully descriptive enough) description of the identified problem. It is worth noticing that some records located in the \MW{} esm files are listed by the verification tool -- it is not fault of our tool: those records are just broken. For instance, you actually may find the 0 duration torch. However, those records are usually not placed in game world itself -- and that's good since \MW{} game engine will crash if player equip light source like this!\footnote{We would like to thanks \BS{} for such a useful testing material. It makes us feel special.} diff --git a/manual/opencs/recordtypes.tex b/manual/opencs/recordtypes.tex index 4dbfbe2864..6db338e7ed 100644 --- a/manual/opencs/recordtypes.tex +++ b/manual/opencs/recordtypes.tex @@ -1,15 +1,15 @@ \section{Record Types} \subsection{Introduction} -A gameworld contains many objects, such as chests, weapons and monsters. All these objects are merely instances of templates that we call Referenceables. The OpenCS Referenceables table contains information about each of these template objects, eg. its value and weight in the case of items and an aggression level in the case of NPCs. +A gameworld contains many items, such as chests, weapons and monsters. All these items are merely instances of templates that we call \textbf{Objects}. The OpenCS \textbf{Objects} table contains information about each of these template objects, eg. its value and weight in the case of items and an aggression level in the case of NPCs. Let's go through all Record Types and discuss what you can tell OpenCS about them. \begin{description} \item[Activator:] When the player enters the same cell as this object, a script is started. Often it also has a \textbf{Script} attached to it, though it not mandatory. These scripts are small bits of code written in a special scripting language that OpenCS can read and interpret. - \item[Potion:] This is a potion that is not self-made. It has an \textbf{Icon} for your inventory, Aside from the self-explanatory \textbf{Weight} and \textbf{Coin Value}, it has an attribute called \textbf{Auto Calc} set to ``False''. This means that the effects of this potion are preconfigured. This does not happen when the player makes their own potion. - \item[Apparatus:] This is a tool to make potions. Again there's an icon for your inventory as well as a weight and a coin value. It also has a \textbf{Quality} value attached to it: higher the number, the better the effect on your potions will be. The \textbf{Apparatus Type} describes if the item is a Calcinator, Retort, Alembir or Mortar & Pestal. Each has a different effect on the potion the player makes. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Alchemy#Tools}{UESP page on Alchemy Tools}. - \item[Armor:] This type of item adds \textbf{Enchantment Points} to the mix. Every piece of clothing or armor has a ''pool'' of potential magicka that gets unlocked when you enchant it. Strong enchantments consume more magicka from this pool: the stronger the enchantment, the more Enchantment Points each cast will take up. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Enchant}{Enchant page on UESP}. \textbf{Health} means the amount of hit points this piece of armor has. If it sustains enough damage, the armor will be destroyed. Finally, \textbf{Armor Value} tells the game how much points to add to the player character's Armor Rating. + \item[Potion:] This is a potion that is not self-made. It has an \textbf{Icon} for your inventory, Aside from the self-explanatory \textbf{Weight} and \textbf{Coin Value}, it has an attribute called \textbf{Auto Calc} set to ``False''. This means that the effects of this potion are pre-configured. This does not happen when the player makes their own potion. + \item[Apparatus:] This is a tool to make potions. Again there's an icon for your inventory as well as a weight and a coin value. It also has a \textbf{Quality} value attached to it: higher the number, the better the effect on your potions will be. The \textbf{Apparatus Type} describes if the item is a Calcinator, Retort, Alembic or Mortar & Pestle. Each has a different effect on the potion the player makes. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Alchemy#Tools}{UESP page on Alchemy Tools}. + \item[Armor:] This type of item adds \textbf{Enchantment Points} to the mix. Every piece of clothing or armor has a ''pool'' of potential Magicka that gets unlocked when you enchant it. Strong enchantments consume more Magicka from this pool: the stronger the enchantment, the more Enchantment Points each cast will take up. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Enchant}{Enchant page on UESP}. \textbf{Health} means the amount of hit points this piece of armor has. If it sustains enough damage, the armor will be destroyed. Finally, \textbf{Armor Value} tells the game how much points to add to the player character's Armor Rating. \item[Book:] This includes scrolls and notes. For the game to make the distinction between books and scrolls, an extra property, \textbf{Scroll}, has been added. Under the \textbf{Skill} column a scroll or book can have an in-game skill listed. Reading this item will raise the player's level in that specific skill. For more information on this, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Skill_Books}{Skill Books page on UESP}. \item[Clothing:] These items work just like Armors, but confer no protective properties. Rather than ``Armor Type'', these items have a ``Clothing Type''. \item[Container:] This is all the stuff that stores items, from chests to sacks to plants. Its \textbf{Capacity} shows how much stuff you can put in the container. You can compare it to the maximum allowed load a player character can carry (who will get over-encumbered and unable to move if he crosses this threshold). A container, however, will just refuse to take the item in question when it gets ''over-encumbered''. \textbf{Organic Container}s are containers such as plants. Containers that \textbf{Respawn} are not safe to store stuff in. After a certain amount of time they will reset to their default contents, meaning that everything in it is gone forever. diff --git a/manual/opencs/tables.tex b/manual/opencs/tables.tex index 5034898729..51aac50fd7 100644 --- a/manual/opencs/tables.tex +++ b/manual/opencs/tables.tex @@ -14,7 +14,7 @@ Let's browse through the various screens and see what all these tables show. \begin{description} \item[Record:] An entry in \OCS{} representing an item, location, sound, NPC or anything else. - \item[Reference, Referenceable:] When an item is placed in the world, it isn't an isolated and unique object. For example, the game world might contain a lot of exquisite belts on different NPCs and in many crates, but they all refer to one specific record in the game's library: the Exquisite Belt record. In this case, all those belts in crates and on NPCs are references. The central Exquisite Belt record is called a referenceable. This allows modders to make changes to all items of the same type. For example, if you want all exquisite belts to have 4000 enchantment points rather than 400, you will only need to change the referenceable Exquisite Belt rather than all exquisite belts references individually. + \item[Instance, Object:] When an item is placed in the world, it isn't an isolated and unique object. For example, the game world might contain a lot of exquisite belts on different NPCs and in many crates, but they all refer to one specific record in the game's library: the Exquisite Belt record. In this case, all those belts in crates and on NPCs are \textbf{instances}. The central Exquisite Belt record is called a \textbf{object}. This allows modders to make changes to all items of the same type. For example, if you want all exquisite belts to have 4000 enchantment points rather than 400, you will only need to change the \textbf{object}} Exquisite Belt rather than all exquisite belts \textbf{instances}} individually. \end{description} \subsubsection{Recurring Terms} @@ -29,7 +29,7 @@ optionally the Bloodmoon and Tribunal expansions. \item[Modified] means that the record is part of the base game, but has been changed in some way. \item[Deleted] means that this record used to be part of the base game, but has been removed as an entry. This does not mean, however, that the occurrences in the game itself have been removed! For example, if you remove the CharGen\_Bed entry from morrowind.esm, it does not mean the bedroll in the basement -of the Census and Excise Office in Seyda Neen is gone. You're going to have to delete that reference yourself or make sure that that object is replaced +of the Census and Excise Office in Seyda Neen is gone. You're going to have to delete that instance yourself or make sure that that object is replaced by something that still exists otherwise you will get crashes in the worst case scenario. \end{description} @@ -37,12 +37,12 @@ by something that still exists otherwise you will get crashes in the worst case The contents of the game world can be changed by choosing one of the options in the appropriate menu at the top of the screen. \subsubsection{Regions} -This describes the general areas of Vvardenfell. Each of these areas has different rules about things such as encounters and weather. +This describes the general areas of the gameworld. Each of these areas has different rules about things such as encounters and weather. \begin{description} \item[Name:] This is how the game will show your location in-game. - \item[Map Colour:] This is a six-digit hexidecimal representation of the colour used to identify the region on the map available in - World > Region Map. If you do not have an application with a colour picker, you can use your favourite search engine to find a colour picker online. + \item[Map Colour:] This is a six-digit hexadecimal representation of the color used to identify the region on the map available in + World > Region Map. If you do not have an application with a color picker, you can use your favorite search engine to find a color picker on-line. \item[Sleep Encounter:] These are the rules for what kind of enemies you might encounter when you sleep outside in the wild. \end{description} @@ -52,7 +52,7 @@ why would the computer need to keep track the exact locations of NPCs walking th be quite useless and bring your system to its knees! So the world has been divided up into squares we call "cells". Once your character enters a cell, the game will load everything that is going on in that cell so you can interact with it. -In the original \MW{} this could be seen when you were travelling and you would see a small loading bar at the bottom of the screen; +In the original \MW{} this could be seen when you were traveling and you would see a small loading bar at the bottom of the screen; you had just entered a new cell and the game would have to load all the items and NPCs. The Cells screen in \OCS{} provides you with a list of cells in the game, both the interior cells (houses, dungeons, mines, etc.) and the exterior cells (the outside world). @@ -71,7 +71,7 @@ in the game, both the interior cells (houses, dungeons, mines, etc.) and the ext \item[Interior Sky:] Should this interior cell have a sky? This is a rather unique case. The \TB{} expansion took place in a city on the mainland. Normally this would require the city to be composed of exterior cells so it has a sky, weather and the like. But if the player is - in an exterior cell and looks at his in-game map, he sees Vvardenfell with an overview of all exterior cells. The player would have to see + in an exterior cell and looks at his in-game map, he sees the map of the gameworld with an overview of all exterior cells. The player would have to see the city's very own map, as if he was walking around in an interior cell. So the developers decided to create a workaround and take a bit of both: The whole city would technically work exactly like an interior cell, @@ -83,7 +83,7 @@ in the game, both the interior cells (houses, dungeons, mines, etc.) and the ext \end{description} -\subsubsection{Referenceables} +\subsubsection{Objects} This is a library of all the items, triggers, containers, NPCs, etc. in the game. There are several kinds of Record Types. Depending on which type a record is, it will need specific information to function. For example, an NPC needs a value attached to its aggression level. A chest, of course, does not. All Record Types contain at least a~model. How else would the player see them? Usually they also have a Name, which is what you see @@ -91,4 +91,4 @@ when you hover your reticle over the object. This is a library of all the items, triggers, containers, NPCs, etc. in the game. There are several kinds of Record Types. Depending on which type a record is, it will need specific information to function. For example, an NPC needs a value attached to its aggression level. A chest, of course, does not. All Record Types contain at least a model. How else would the player see them? Usually they also have a Name, which is what you see when you hover your reticle over the object. -Please refer to the Record Types section for an overview of what each type of Referenceable does and what you can tell OpenCS about these objects. +Please refer to the Record Types section for an overview of what each type of object does and what you can tell OpenCS about these objects. From ad77c662aaffab0db65712187ae80dba556611ce Mon Sep 17 00:00:00 2001 From: Cramal Date: Mon, 25 May 2015 18:44:21 +0900 Subject: [PATCH 125/142] correct latex error --- manual/opencs/tables.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/opencs/tables.tex b/manual/opencs/tables.tex index 51aac50fd7..984157f88f 100644 --- a/manual/opencs/tables.tex +++ b/manual/opencs/tables.tex @@ -14,7 +14,7 @@ Let's browse through the various screens and see what all these tables show. \begin{description} \item[Record:] An entry in \OCS{} representing an item, location, sound, NPC or anything else. - \item[Instance, Object:] When an item is placed in the world, it isn't an isolated and unique object. For example, the game world might contain a lot of exquisite belts on different NPCs and in many crates, but they all refer to one specific record in the game's library: the Exquisite Belt record. In this case, all those belts in crates and on NPCs are \textbf{instances}. The central Exquisite Belt record is called a \textbf{object}. This allows modders to make changes to all items of the same type. For example, if you want all exquisite belts to have 4000 enchantment points rather than 400, you will only need to change the \textbf{object}} Exquisite Belt rather than all exquisite belts \textbf{instances}} individually. + \item[Instance, Object:] When an item is placed in the world, it isn't an isolated and unique object. For example, the game world might contain a lot of exquisite belts on different NPCs and in many crates, but they all refer to one specific record in the game's library: the Exquisite Belt record. In this case, all those belts in crates and on NPCs are \textbf{instances}. The central Exquisite Belt record is called a \textbf{object}. This allows modders to make changes to all items of the same type. For example, if you want all exquisite belts to have 4000 enchantment points rather than 400, you will only need to change the \textbf{object} Exquisite Belt rather than all exquisite belts \textbf{instances} individually. \end{description} \subsubsection{Recurring Terms} From 08484a46c7e8ed17202eb28d1cbf4f43799e5320 Mon Sep 17 00:00:00 2001 From: Cramal Date: Mon, 25 May 2015 18:45:42 +0900 Subject: [PATCH 126/142] remove latex error --- manual/opencs/recordtypes.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/opencs/recordtypes.tex b/manual/opencs/recordtypes.tex index 6db338e7ed..661f5ac7d5 100644 --- a/manual/opencs/recordtypes.tex +++ b/manual/opencs/recordtypes.tex @@ -8,7 +8,7 @@ Let's go through all Record Types and discuss what you can tell OpenCS about the \begin{description} \item[Activator:] When the player enters the same cell as this object, a script is started. Often it also has a \textbf{Script} attached to it, though it not mandatory. These scripts are small bits of code written in a special scripting language that OpenCS can read and interpret. \item[Potion:] This is a potion that is not self-made. It has an \textbf{Icon} for your inventory, Aside from the self-explanatory \textbf{Weight} and \textbf{Coin Value}, it has an attribute called \textbf{Auto Calc} set to ``False''. This means that the effects of this potion are pre-configured. This does not happen when the player makes their own potion. - \item[Apparatus:] This is a tool to make potions. Again there's an icon for your inventory as well as a weight and a coin value. It also has a \textbf{Quality} value attached to it: higher the number, the better the effect on your potions will be. The \textbf{Apparatus Type} describes if the item is a Calcinator, Retort, Alembic or Mortar & Pestle. Each has a different effect on the potion the player makes. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Alchemy#Tools}{UESP page on Alchemy Tools}. + \item[Apparatus:] This is a tool to make potions. Again there's an icon for your inventory as well as a weight and a coin value. It also has a \textbf{Quality} value attached to it: higher the number, the better the effect on your potions will be. The \textbf{Apparatus Type} describes if the item is a Calcinator, Retort, Alembic or Mortar \& Pestle. Each has a different effect on the potion the player makes. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Alchemy#Tools}{UESP page on Alchemy Tools}. \item[Armor:] This type of item adds \textbf{Enchantment Points} to the mix. Every piece of clothing or armor has a ''pool'' of potential Magicka that gets unlocked when you enchant it. Strong enchantments consume more Magicka from this pool: the stronger the enchantment, the more Enchantment Points each cast will take up. For more information on this subject, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Enchant}{Enchant page on UESP}. \textbf{Health} means the amount of hit points this piece of armor has. If it sustains enough damage, the armor will be destroyed. Finally, \textbf{Armor Value} tells the game how much points to add to the player character's Armor Rating. \item[Book:] This includes scrolls and notes. For the game to make the distinction between books and scrolls, an extra property, \textbf{Scroll}, has been added. Under the \textbf{Skill} column a scroll or book can have an in-game skill listed. Reading this item will raise the player's level in that specific skill. For more information on this, please refer to the \href{http://www.uesp.net/wiki/Morrowind:Skill_Books}{Skill Books page on UESP}. \item[Clothing:] These items work just like Armors, but confer no protective properties. Rather than ``Armor Type'', these items have a ``Clothing Type''. From 95f740ec40b76db5892ef9c93ef35480fb6a00a7 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Mon, 25 May 2015 22:28:41 +1000 Subject: [PATCH 127/142] Give CSVWorld::EditWidget::mMainWidget a chance to clean up its children. Should resolve Bug #2578. --- apps/opencs/view/world/dialoguesubview.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 2cf30dcbe0..7a25a7fc14 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -378,6 +378,13 @@ mDocument (document) void CSVWorld::EditWidget::remake(int row) { + if (mMainWidget) + { + QWidget *del = this->takeWidget(); + del->deleteLater(); + } + mMainWidget = new QWidget (this); + for (unsigned i = 0; i < mNestedModels.size(); ++i) delete mNestedModels[i]; @@ -401,12 +408,6 @@ void CSVWorld::EditWidget::remake(int row) if (mNestedTableMapper) delete mNestedTableMapper; - if (mMainWidget) - { - QWidget *del = this->takeWidget(); - del->deleteLater(); - } - mMainWidget = new QWidget (this); QFrame* line = new QFrame(mMainWidget); line->setObjectName(QString::fromUtf8("line")); From ec808843c3614e4615a6c7afb6f0acc5a28a94c7 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 26 May 2015 13:35:10 +1000 Subject: [PATCH 128/142] Do not rebuild the dialogue subview unless required. Should resolve Bug #2581. The loss of focus was caused by each text change (i.e. character entry) to a QPlainTextEdit resulting in dataChanged() signal which in turn rebuilt the dialogue subview. Changes in this commit include: - Do not send signal to update entire row if only a single item has changed. - Do not rebuild the dialogue subview unless the data item that triggers a conditional display is changed. - Add column flags to indicate whether the data in this column should rebuild the dialogue subview. - Return the correct flags for nested columns - Disable, rather than grey out, checkbox that does not apply to creature levelled list --- apps/opencs/model/world/columnbase.cpp | 4 ++-- apps/opencs/model/world/columnbase.hpp | 8 ++++--- apps/opencs/model/world/columnimp.hpp | 4 ++-- apps/opencs/model/world/data.cpp | 21 +++++++++++------ apps/opencs/model/world/idtable.cpp | 3 +-- apps/opencs/model/world/idtree.cpp | 6 ++--- apps/opencs/model/world/refidadapterimp.hpp | 2 +- apps/opencs/model/world/refidcollection.cpp | 3 ++- apps/opencs/view/world/dialoguesubview.cpp | 26 +++++++++++++++++---- 9 files changed, 52 insertions(+), 25 deletions(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 0e0ff11d40..3d13538c03 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -138,8 +138,8 @@ bool CSMWorld::NestableColumn::hasChildren() const } CSMWorld::NestedChildColumn::NestedChildColumn (int id, - CSMWorld::ColumnBase::Display display, bool isEditable) - : NestableColumn (id, display, CSMWorld::ColumnBase::Flag_Dialogue) , mIsEditable(isEditable) + CSMWorld::ColumnBase::Display display, int flags, bool isEditable) + : NestableColumn (id, display, flags) , mIsEditable(isEditable) {} bool CSMWorld::NestedChildColumn::isEditable () const diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index d6dd4b291b..70b2a35b76 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -25,7 +25,8 @@ namespace CSMWorld { Flag_Table = 1, // column should be displayed in table view Flag_Dialogue = 2, // column should be displayed in dialogue view - Flag_Dialogue_List = 4 // column should be diaplyed in dialogue view + Flag_Dialogue_List = 4, // column should be diaplyed in dialogue view + Flag_Dialogue_Refresh = 8 // refresh dialogue view if this column is modified }; enum Display @@ -183,7 +184,7 @@ namespace CSMWorld template struct NestedParentColumn : public Column { - NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue) : Column (id, + NestedParentColumn (int id, int flags = Flag_Dialogue) : Column (id, ColumnBase::Display_NestedHeader, flags) {} @@ -200,7 +201,8 @@ namespace CSMWorld struct NestedChildColumn : public NestableColumn { - NestedChildColumn (int id, Display display, bool isEditable = true); + NestedChildColumn (int id, + Display display, int flags = Flag_Dialogue, bool isEditable = true); virtual bool isEditable() const; diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index cbe0d74c41..64a1cf3d70 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -467,8 +467,8 @@ namespace CSMWorld int mMask; bool mInverted; - FlagColumn (int columnId, int mask, bool inverted = false) - : Column (columnId, ColumnBase::Display_Boolean), mMask (mask), + FlagColumn (int columnId, int mask, int flags = Flag_Table | Flag_Dialogue, bool inverted = false) + : Column (columnId, ColumnBase::Display_Boolean, flags), mMask (mask), mInverted (inverted) {} diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 920c7db719..c27c068f10 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -141,7 +141,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mRaces.getColumns()-1; mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter())); mRaces.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_RaceAttributes, ColumnBase::Display_String, false)); + new NestedChildColumn (Columns::ColumnId_RaceAttributes, ColumnBase::Display_String, + ColumnBase::Flag_Dialogue, false)); mRaces.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_RaceMaleValue, ColumnBase::Display_Integer)); mRaces.getNestableColumn(index)->addColumn( @@ -287,8 +288,10 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mCells.addColumn (new FixedRecordTypeColumn (UniversalId::Type_Cell)); mCells.addColumn (new NameColumn); mCells.addColumn (new FlagColumn (Columns::ColumnId_SleepForbidden, ESM::Cell::NoSleep)); - mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater)); - mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx)); + mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); + mCells.addColumn (new FlagColumn (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); mCells.addColumn (new RegionColumn); mCells.addColumn (new RefNumCounterColumn); // Misc Cell data @@ -297,7 +300,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mCells.getColumns()-1; mCells.addAdapter (std::make_pair(&mCells.getColumn(index), new CellListAdapter ())); mCells.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_Interior, ColumnBase::Display_Boolean)); + new NestedChildColumn (Columns::ColumnId_Interior, ColumnBase::Display_Boolean, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); mCells.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_Ambient, ColumnBase::Display_Integer)); mCells.getNestableColumn(index)->addColumn( @@ -346,7 +350,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mBodyParts.addColumn (new BodyPartTypeColumn); mBodyParts.addColumn (new VampireColumn); mBodyParts.addColumn (new FlagColumn (Columns::ColumnId_Female, ESM::BodyPart::BPF_Female)); - mBodyParts.addColumn (new FlagColumn (Columns::ColumnId_Playable, ESM::BodyPart::BPF_NotPlayable, true)); + mBodyParts.addColumn (new FlagColumn (Columns::ColumnId_Playable, + ESM::BodyPart::BPF_NotPlayable, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true)); mBodyParts.addColumn (new MeshTypeColumn); mBodyParts.addColumn (new ModelColumn); mBodyParts.addColumn (new RaceColumn); @@ -393,7 +398,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc // new objects deleted in dtor of NestableColumn // WARNING: The order of the columns below are assumed in PathgridPointListAdapter mPathgrids.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_PathgridIndex, ColumnBase::Display_Integer, false)); + new NestedChildColumn (Columns::ColumnId_PathgridIndex, ColumnBase::Display_Integer, + ColumnBase::Flag_Dialogue, false)); mPathgrids.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_PathgridPosX, ColumnBase::Display_Integer)); mPathgrids.getNestableColumn(index)->addColumn( @@ -405,7 +411,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc index = mPathgrids.getColumns()-1; mPathgrids.addAdapter (std::make_pair(&mPathgrids.getColumn(index), new PathgridEdgeListAdapter ())); mPathgrids.getNestableColumn(index)->addColumn( - new NestedChildColumn (Columns::ColumnId_PathgridEdgeIndex, ColumnBase::Display_Integer, false)); + new NestedChildColumn (Columns::ColumnId_PathgridEdgeIndex, ColumnBase::Display_Integer, + ColumnBase::Flag_Dialogue, false)); mPathgrids.getNestableColumn(index)->addColumn( new NestedChildColumn (Columns::ColumnId_PathgridEdge0, ColumnBase::Display_Integer)); mPathgrids.getNestableColumn(index)->addColumn( diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 36b3f5c970..04aa271ccc 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -74,8 +74,7 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value { mIdCollection->setData (index.row(), index.column(), value); - emit dataChanged (CSMWorld::IdTable::index (index.row(), 0), - CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); + emit dataChanged (index, index); return true; } diff --git a/apps/opencs/model/world/idtree.cpp b/apps/opencs/model/world/idtree.cpp index 06db09a0fc..7351c03a77 100644 --- a/apps/opencs/model/world/idtree.cpp +++ b/apps/opencs/model/world/idtree.cpp @@ -74,7 +74,7 @@ QVariant CSMWorld::IdTree::nestedHeaderData(int section, int subSection, Qt::Ori return tr(parentColumn->nestedColumn(subSection).getTitle().c_str()); if (role==ColumnBase::Role_Flags) - return idCollection()->getColumn (section).mFlags; + return parentColumn->nestedColumn(subSection).mFlags; if (role==ColumnBase::Role_Display) return parentColumn->nestedColumn(subSection).mDisplayType; @@ -92,8 +92,8 @@ bool CSMWorld::IdTree::setData (const QModelIndex &index, const QVariant &value, mNestedCollection->setNestedData(parentAddress.first, parentAddress.second, value, index.row(), index.column()); - emit dataChanged (CSMWorld::IdTree::index (parentAddress.first, 0), - CSMWorld::IdTree::index (parentAddress.first, idCollection()->getColumns()-1)); + emit dataChanged (index, index); + return true; } else diff --git a/apps/opencs/model/world/refidadapterimp.hpp b/apps/opencs/model/world/refidadapterimp.hpp index 3411429d05..869996da5b 100644 --- a/apps/opencs/model/world/refidadapterimp.hpp +++ b/apps/opencs/model/world/refidadapterimp.hpp @@ -1976,7 +1976,7 @@ namespace CSMWorld { switch (subColIndex) { - case 0: return QVariant(QVariant::UserType); // disable the checkbox editor + case 0: return QVariant(); // disable the checkbox editor case 1: return record.get().mFlags & ESM::CreatureLevList::AllLevels; case 2: return static_cast (record.get().mChanceNone); default: diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index 9d9e9826af..cda19c87bb 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -245,7 +245,8 @@ CSMWorld::RefIdCollection::RefIdCollection() actorsColumns.mServices.insert (std::make_pair (&mColumns.back(), sServiceTable[i].mFlag)); } - mColumns.push_back (RefIdColumn (Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean)); + mColumns.push_back (RefIdColumn (Columns::ColumnId_AutoCalc, ColumnBase::Display_Boolean, + ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); const RefIdColumn *autoCalc = &mColumns.back(); mColumns.push_back (RefIdColumn (Columns::ColumnId_ApparatusType, diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 2cf30dcbe0..03fa532c55 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -787,14 +787,32 @@ void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index) { QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - if (currentIndex.isValid() && index.row() == currentIndex.row()) + if (currentIndex.isValid() && + (index.parent().isValid() ? index.parent().row() : index.row()) == currentIndex.row()) { CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); - int y = mEditWidget->verticalScrollBar()->value(); - mEditWidget->remake (index.row()); - mEditWidget->verticalScrollBar()->setValue(y); + + // Check if the changed data should force refresh (rebuild) the dialogue subview + int flags = 0; + if (index.parent().isValid()) // TODO: check that index is topLeft + { + flags = static_cast(mTable)->nestedHeaderData (index.parent().column(), + index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); + } + else + { + flags = mTable->headerData (index.column(), + Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); + } + + if (flags & CSMWorld::ColumnBase::Flag_Dialogue_Refresh) + { + int y = mEditWidget->verticalScrollBar()->value(); + mEditWidget->remake (index.parent().isValid() ? index.parent().row() : index.row()); + mEditWidget->verticalScrollBar()->setValue(y); + } } } From 2f29c2c077491f378e3abad231010e1643c64319 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 26 May 2015 13:58:58 +1000 Subject: [PATCH 129/142] Qualify the scope of Flag_Dialogue. --- apps/opencs/model/world/columnbase.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 70b2a35b76..bf8378e37b 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -184,7 +184,7 @@ namespace CSMWorld template struct NestedParentColumn : public Column { - NestedParentColumn (int id, int flags = Flag_Dialogue) : Column (id, + NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue) : Column (id, ColumnBase::Display_NestedHeader, flags) {} @@ -202,7 +202,7 @@ namespace CSMWorld struct NestedChildColumn : public NestableColumn { NestedChildColumn (int id, - Display display, int flags = Flag_Dialogue, bool isEditable = true); + Display display, int flags = ColumnBase::Flag_Dialogue, bool isEditable = true); virtual bool isEditable() const; From aafcaf32c5ba50bb1b92c44dda31e1d0f4ba1d5b Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 26 May 2015 16:12:54 +1000 Subject: [PATCH 130/142] Qualify the scope of Flag_Dialogue. (another one) --- apps/opencs/model/world/columnimp.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 64a1cf3d70..6b496e0ca7 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -467,7 +467,8 @@ namespace CSMWorld int mMask; bool mInverted; - FlagColumn (int columnId, int mask, int flags = Flag_Table | Flag_Dialogue, bool inverted = false) + FlagColumn (int columnId, int mask, + int flags = ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, bool inverted = false) : Column (columnId, ColumnBase::Display_Boolean, flags), mMask (mask), mInverted (inverted) {} From f06ddd47c40f100a9610af3baf8b572d6308bbed Mon Sep 17 00:00:00 2001 From: cc9cii Date: Tue, 26 May 2015 17:38:22 +1000 Subject: [PATCH 131/142] Return the correct range for a given topic. Should resolve Bug #2569. --- apps/opencs/model/world/infocollection.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/apps/opencs/model/world/infocollection.cpp b/apps/opencs/model/world/infocollection.cpp index f2d81823cf..a508d28f3d 100644 --- a/apps/opencs/model/world/infocollection.cpp +++ b/apps/opencs/model/world/infocollection.cpp @@ -173,6 +173,17 @@ CSMWorld::InfoCollection::Range CSMWorld::InfoCollection::getTopicRange (const s RecordConstIterator begin = getRecords().begin()+iter->second; + while (begin != getRecords().begin()) + { + if (!Misc::StringUtils::ciEqual(begin->get().mTopicId, topic2)) + { + // we've gone one too far, go back + ++begin; + break; + } + --begin; + } + // Find end RecordConstIterator end = begin; From 5fd107a95c7a763d3fe7a84d433b8bc7de1dac69 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 27 May 2015 10:19:26 +1000 Subject: [PATCH 132/142] Fix crash with array out of bounds when refNum index is incorrect. --- components/esm/loadcell.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/esm/loadcell.cpp b/components/esm/loadcell.cpp index 0f8897c488..94f4b0b6e7 100644 --- a/components/esm/loadcell.cpp +++ b/components/esm/loadcell.cpp @@ -18,9 +18,11 @@ namespace ///< Translate 8bit/24bit code (stored in refNum.mIndex) into a proper refNum void adjustRefNum (ESM::RefNum& refNum, ESM::ESMReader& reader) { - int local = (refNum.mIndex & 0xff000000) >> 24; + unsigned int local = (refNum.mIndex & 0xff000000) >> 24; - if (local) + // If we have an index value that does not make sense, assume that it was an addition + // by the present plugin (but a faulty one) + if (local && local <= reader.getGameFiles().size()) { // If the most significant 8 bits are used, then this reference already exists. // In this case, do not spawn a new reference, but overwrite the old one. From b7044ac119b6bbbdd7b74749c5201a462fec0d59 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 27 May 2015 10:27:57 +1000 Subject: [PATCH 133/142] Fix crash loading some addon files. Should resolve Bug #2583. - This may be a bug within QSortFilterProxyModel - It isn't 100% clear what aspects of these addon files cause the issue, but something about them causes Qt to lose track of its internal row numbers. --- apps/opencs/model/world/idtableproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index 84869716e2..987d274620 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -46,7 +46,7 @@ void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr Date: Wed, 27 May 2015 15:55:00 +1000 Subject: [PATCH 134/142] Object verifier check to see if the script used by that object actually exists. Should resolve Bug #2582. --- .../opencs/model/tools/referenceablecheck.cpp | 83 ++++++++++++++++--- .../opencs/model/tools/referenceablecheck.hpp | 20 +++-- apps/opencs/model/tools/tools.cpp | 14 ++-- 3 files changed, 93 insertions(+), 24 deletions(-) diff --git a/apps/opencs/model/tools/referenceablecheck.cpp b/apps/opencs/model/tools/referenceablecheck.cpp index c0991a330d..548fcd36f6 100644 --- a/apps/opencs/model/tools/referenceablecheck.cpp +++ b/apps/opencs/model/tools/referenceablecheck.cpp @@ -8,12 +8,14 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage( const CSMWorld::RefIdData& referenceable, const CSMWorld::IdCollection& races, const CSMWorld::IdCollection& classes, - const CSMWorld::IdCollection& faction) + const CSMWorld::IdCollection& faction, + const CSMWorld::IdCollection& scripts) : mReferencables(referenceable), mRaces(races), mClasses(classes), mFactions(faction), + mScripts(scripts), mPlayerPresent(false) { } @@ -245,6 +247,9 @@ void CSMTools::ReferenceableCheckStage::bookCheck( CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Book, book.mId); inventoryItemCheck(book, messages, id.toString(), true); + + // Check that mentioned scripts exist + scriptCheck(book, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::activatorCheck( @@ -265,6 +270,9 @@ void CSMTools::ReferenceableCheckStage::activatorCheck( //Checking for model, IIRC all activators should have a model if (activator.mModel.empty()) messages.push_back (std::make_pair (id, activator.mId + " has no model")); + + // Check that mentioned scripts exist + scriptCheck(activator, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::potionCheck( @@ -284,6 +292,9 @@ void CSMTools::ReferenceableCheckStage::potionCheck( inventoryItemCheck(potion, messages, id.toString()); //IIRC potion can have empty effects list just fine. + + // Check that mentioned scripts exist + scriptCheck(potion, messages, id.toString()); } @@ -305,6 +316,9 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck( inventoryItemCheck(apparatus, messages, id.toString()); toolCheck(apparatus, messages, id.toString()); + + // Check that mentioned scripts exist + scriptCheck(apparatus, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::armorCheck( @@ -331,6 +345,9 @@ void CSMTools::ReferenceableCheckStage::armorCheck( //checking for health. Only positive numbers are allowed, or 0 is illegal if (armor.mData.mHealth <= 0) messages.push_back (std::make_pair (id, armor.mId + " has non positive health")); + + // Check that mentioned scripts exist + scriptCheck(armor, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::clothingCheck( @@ -348,6 +365,9 @@ void CSMTools::ReferenceableCheckStage::clothingCheck( const ESM::Clothing& clothing = (dynamic_cast& >(baseRecord)).get(); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Clothing, clothing.mId); inventoryItemCheck(clothing, messages, id.toString(), true); + + // Check that mentioned scripts exist + scriptCheck(clothing, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::containerCheck( @@ -377,6 +397,9 @@ void CSMTools::ReferenceableCheckStage::containerCheck( //checking for name if (container.mName.empty()) messages.push_back (std::make_pair (id, container.mId + " has an empty name")); + + // Check that mentioned scripts exist + scriptCheck(container, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::creatureCheck ( @@ -444,6 +467,9 @@ void CSMTools::ReferenceableCheckStage::creatureCheck ( //TODO, find meaning of other values if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures messages.push_back (std::make_pair (id, creature.mId + " has negative gold ")); + + // Check that mentioned scripts exist + scriptCheck(creature, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::doorCheck( @@ -455,15 +481,18 @@ void CSMTools::ReferenceableCheckStage::doorCheck( if (baseRecord.isDeleted()) return; - const ESM::Door& Door = (dynamic_cast&>(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Door, Door.mId); + const ESM::Door& door = (dynamic_cast&>(baseRecord)).get(); + CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Door, door.mId); //usual, name or model - if (Door.mName.empty()) - messages.push_back (std::make_pair (id, Door.mId + " has an empty name")); + if (door.mName.empty()) + messages.push_back (std::make_pair (id, door.mId + " has an empty name")); - if (Door.mModel.empty()) - messages.push_back (std::make_pair (id, Door.mId + " has no model")); + if (door.mModel.empty()) + messages.push_back (std::make_pair (id, door.mId + " has no model")); + + // Check that mentioned scripts exist + scriptCheck(door, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::ingredientCheck( @@ -478,10 +507,13 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck( return; } - const ESM::Ingredient& Ingredient = (dynamic_cast& >(baseRecord)).get(); - CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Ingredient, Ingredient.mId); + const ESM::Ingredient& ingredient = (dynamic_cast& >(baseRecord)).get(); + CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Ingredient, ingredient.mId); - inventoryItemCheck(Ingredient, messages, id.toString()); + inventoryItemCheck(ingredient, messages, id.toString()); + + // Check that mentioned scripts exist + scriptCheck(ingredient, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::creaturesLevListCheck( @@ -542,6 +574,9 @@ void CSMTools::ReferenceableCheckStage::lightCheck( if (light.mData.mTime == 0) messages.push_back (std::make_pair (id, light.mId + " has zero duration")); } + + // Check that mentioned scripts exist + scriptCheck(light, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::lockpickCheck( @@ -562,6 +597,9 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck( inventoryItemCheck(lockpick, messages, id.toString()); toolCheck(lockpick, messages, id.toString(), true); + + // Check that mentioned scripts exist + scriptCheck(lockpick, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::miscCheck( @@ -580,6 +618,9 @@ void CSMTools::ReferenceableCheckStage::miscCheck( CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Miscellaneous, miscellaneous.mId); inventoryItemCheck(miscellaneous, messages, id.toString()); + + // Check that mentioned scripts exist + scriptCheck(miscellaneous, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::npcCheck ( @@ -697,6 +738,9 @@ void CSMTools::ReferenceableCheckStage::npcCheck ( messages.push_back (std::make_pair (id, npc.mId + " has no hair")); //TODO: reputation, Disposition, rank, everything else + + // Check that mentioned scripts exist + scriptCheck(npc, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::weaponCheck( @@ -773,6 +817,9 @@ void CSMTools::ReferenceableCheckStage::weaponCheck( messages.push_back (std::make_pair (id, weapon.mId + " has negative reach")); } } + + // Check that mentioned scripts exist + scriptCheck(weapon, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::probeCheck( @@ -792,6 +839,9 @@ void CSMTools::ReferenceableCheckStage::probeCheck( inventoryItemCheck(probe, messages, id.toString()); toolCheck(probe, messages, id.toString(), true); + + // Check that mentioned scripts exist + scriptCheck(probe, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::repairCheck ( @@ -808,6 +858,9 @@ void CSMTools::ReferenceableCheckStage::repairCheck ( inventoryItemCheck (repair, messages, id.toString()); toolCheck (repair, messages, id.toString(), true); + + // Check that mentioned scripts exist + scriptCheck(repair, messages, id.toString()); } void CSMTools::ReferenceableCheckStage::staticCheck ( @@ -919,3 +972,13 @@ template void CSMTools::ReferenceableCheckStage::listCheck ( someList.mId + " contains item with non-positive level")); } } + +template void CSMTools::ReferenceableCheckStage::scriptCheck ( + const Tool& someTool, CSMDoc::Messages& messages, const std::string& someID) +{ + if (!someTool.mScript.empty()) + { + if (mScripts.searchId(someTool.mScript) == -1) + messages.push_back (std::make_pair (someID, someTool.mId + " refers to an unknown script \""+someTool.mScript+"\"")); + } +} diff --git a/apps/opencs/model/tools/referenceablecheck.hpp b/apps/opencs/model/tools/referenceablecheck.hpp index ac7ed70821..a34f3a7891 100644 --- a/apps/opencs/model/tools/referenceablecheck.hpp +++ b/apps/opencs/model/tools/referenceablecheck.hpp @@ -15,7 +15,8 @@ namespace CSMTools ReferenceableCheckStage (const CSMWorld::RefIdData& referenceable, const CSMWorld::IdCollection& races, const CSMWorld::IdCollection& classes, - const CSMWorld::IdCollection& factions); + const CSMWorld::IdCollection& factions, + const CSMWorld::IdCollection& scripts); virtual void perform(int stage, CSMDoc::Messages& messages); virtual int setup(); @@ -46,26 +47,30 @@ namespace CSMTools //FINAL CHECK void finalCheck (CSMDoc::Messages& messages); - //TEMPLATE CHECKS - template void inventoryItemCheck(const ITEM& someItem, + //TEMPLATE CHECKS + template void inventoryItemCheck(const ITEM& someItem, CSMDoc::Messages& messages, const std::string& someID, bool enchantable); //for all enchantable items. - template void inventoryItemCheck(const ITEM& someItem, + template void inventoryItemCheck(const ITEM& someItem, CSMDoc::Messages& messages, const std::string& someID); //for non-enchantable items. - template void toolCheck(const TOOL& someTool, + template void toolCheck(const TOOL& someTool, CSMDoc::Messages& messages, const std::string& someID, bool canbebroken); //for tools with uses. - template void toolCheck(const TOOL& someTool, + template void toolCheck(const TOOL& someTool, CSMDoc::Messages& messages, const std::string& someID); //for tools without uses. - template void listCheck(const LIST& someList, + template void listCheck(const LIST& someList, + CSMDoc::Messages& messages, + const std::string& someID); + + template void scriptCheck(const TOOL& someTool, CSMDoc::Messages& messages, const std::string& someID); @@ -73,6 +78,7 @@ namespace CSMTools const CSMWorld::IdCollection& mRaces; const CSMWorld::IdCollection& mClasses; const CSMWorld::IdCollection& mFactions; + const CSMWorld::IdCollection& mScripts; bool mPlayerPresent; }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 99e462b1d2..979f724860 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -81,7 +81,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() mVerifierOperation->appendStage (new SpellCheckStage (mData.getSpells())); - mVerifierOperation->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); + mVerifierOperation->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions(), mData.getScripts())); mVerifierOperation->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions())); @@ -114,7 +114,7 @@ CSMTools::Tools::Tools (CSMDoc::Document& document) connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); connect (&mSearch, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); } CSMTools::Tools::~Tools() @@ -130,7 +130,7 @@ CSMTools::Tools::~Tools() mSearch.abortAndWait(); delete mSearchOperation; } - + for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) delete iter->second; } @@ -149,7 +149,7 @@ CSMWorld::UniversalId CSMTools::Tools::newSearch() { mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true))); - return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1); + return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1); } void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Search& search) @@ -159,11 +159,11 @@ void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Se if (!mSearchOperation) { mSearchOperation = new SearchOperation (mDocument); - mSearch.setOperation (mSearchOperation); + mSearch.setOperation (mSearchOperation); } mSearchOperation->configure (search); - + mSearch.start(); } @@ -198,7 +198,7 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog && id.getType()!=CSMWorld::UniversalId::Type_Search) throw std::logic_error ("invalid request for report model: " + id.toString()); - + return mReports.at (id.getIndex()); } From 3a31468af07548a17d2a0cd45020bb9aa552c349 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 27 May 2015 22:12:11 +1000 Subject: [PATCH 135/142] Pathgrid record verifier. Feature #2000. --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/tools/pathgridcheck.cpp | 158 ++++++++++++++++++++++ apps/opencs/model/tools/pathgridcheck.hpp | 31 +++++ apps/opencs/model/tools/tools.cpp | 3 + 4 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/model/tools/pathgridcheck.cpp create mode 100644 apps/opencs/model/tools/pathgridcheck.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 438f3c6941..78b2deb7a8 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -40,7 +40,7 @@ opencs_units (model/tools opencs_units_noqt (model/tools mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck - startscriptcheck search searchoperation searchstage + startscriptcheck search searchoperation searchstage pathgridcheck ) diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp new file mode 100644 index 0000000000..71f596f4f4 --- /dev/null +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -0,0 +1,158 @@ +#include "pathgridcheck.hpp" + +#include +#include + +#include "../world/universalid.hpp" +#include "../world/idcollection.hpp" +#include "../world/subcellcollection.hpp" +#include "../world/pathgrid.hpp" + + +CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection& pathgrids) +: mPathgrids (pathgrids) +{} + +int CSMTools::PathgridCheckStage::setup() +{ + return mPathgrids.getSize(); +} + +void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& messages) +{ + const CSMWorld::Record& record = mPathgrids.getRecord (stage); + + if (record.isDeleted()) + return; + + const CSMWorld::Pathgrid& pathgrid = record.get(); + + CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Pathgrid, pathgrid.mId); + + // check the number of pathgrid points + if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) + messages.push_back (std::make_pair (id, pathgrid.mId + " has less points than expected")); + else if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) + messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected")); + + struct Point + { + unsigned char mConnectionNum; + std::vector mOtherIndex; + Point() : mConnectionNum(0), mOtherIndex(0) {} + }; + std::vector pointList(pathgrid.mPoints.size()); + std::vector duplList; + + for (unsigned int i = 0; i < pathgrid.mEdges.size(); ++i) + { + if (pathgrid.mEdges[i].mV0 < static_cast(pathgrid.mPoints.size()) && pathgrid.mEdges[i].mV0 >= 0) + { + pointList[pathgrid.mEdges[i].mV0].mConnectionNum++; + // first check for duplicate edges + unsigned int j = 0; + for (; j < pointList[pathgrid.mEdges[i].mV0].mOtherIndex.size(); ++j) + { + if (pointList[pathgrid.mEdges[i].mV0].mOtherIndex[j] == pathgrid.mEdges[i].mV1) + { + std::ostringstream ss; + ss << "has a duplicate edge between points" << pathgrid.mEdges[i].mV0 + << " and " << pathgrid.mEdges[i].mV1; + messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + break; + } + } + + // only add if not a duplicate + if (j == pointList[pathgrid.mEdges[i].mV0].mOtherIndex.size()) + pointList[pathgrid.mEdges[i].mV0].mOtherIndex.push_back(pathgrid.mEdges[i].mV1); + } + else + { + std::ostringstream ss; + ss << " has an edge connecting a non-existent point " << pathgrid.mEdges[i].mV0; + messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + } + } + + for (unsigned int i = 0; i < pathgrid.mPoints.size(); ++i) + { + // check the connection number for each point matches the edge connections + if (pathgrid.mPoints[i].mConnectionNum > pointList[i].mConnectionNum) + { + std::ostringstream ss; + ss << " has has less edges than expected for point " << i; + messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + } + else if (pathgrid.mPoints[i].mConnectionNum < pointList[i].mConnectionNum) + { + std::ostringstream ss; + ss << " has has more edges than expected for point " << i; + messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + } + + // check that edges are bidirectional + bool foundReverse = false; + for (unsigned int j = 0; j < pointList[i].mOtherIndex.size(); ++j) + { + for (unsigned int k = 0; k < pointList[pointList[i].mOtherIndex[j]].mOtherIndex.size(); ++k) + { + if (pointList[pointList[i].mOtherIndex[j]].mOtherIndex[k] == static_cast(i)) + { + foundReverse = true; + break; + } + } + + if (!foundReverse) + { + std::ostringstream ss; + ss << " has a missing edge between points " << i << " and " << pointList[i].mOtherIndex[j]; + messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + } + } + + // check duplicate points + // FIXME: how to do this efficiently? + for (unsigned int j = 0; j < pathgrid.mPoints.size(); ++j) + { + if (j == i) + continue; + + if (pathgrid.mPoints[i].mX == pathgrid.mPoints[j].mX && + pathgrid.mPoints[i].mY == pathgrid.mPoints[j].mY && + pathgrid.mPoints[i].mZ == pathgrid.mPoints[j].mZ) + { + std::vector::const_iterator it = find(duplList.begin(), duplList.end(), i); + if (it == duplList.end()) + { + std::ostringstream ss; + ss << " has a duplicated point (" << i + << ") x=" << pathgrid.mPoints[i].mX + << ", y=" << pathgrid.mPoints[i].mY + << ", z=" << pathgrid.mPoints[i].mZ; + messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + + duplList.push_back(i); + break; + } + } + } + } + + // check pathgrid points that are not connected to anything + for (unsigned int i = 0; i < pointList.size(); ++i) + { + if (pointList[i].mConnectionNum == 0) + { + std::ostringstream ss; + ss << " has an orphaned point (" << i + << ") x=" << pathgrid.mPoints[i].mX + << ", y=" << pathgrid.mPoints[i].mY + << ", z=" << pathgrid.mPoints[i].mZ; + messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + } + } + + // TODO: check whether there are disconnected graphs +} diff --git a/apps/opencs/model/tools/pathgridcheck.hpp b/apps/opencs/model/tools/pathgridcheck.hpp new file mode 100644 index 0000000000..c90dbc8ed9 --- /dev/null +++ b/apps/opencs/model/tools/pathgridcheck.hpp @@ -0,0 +1,31 @@ +#ifndef CSM_TOOLS_PATHGRIDCHECK_H +#define CSM_TOOLS_PATHGRIDCHECK_H + +#include "../world/collection.hpp" + +#include "../doc/stage.hpp" + +namespace CSMWorld +{ + struct Pathgrid; + template + class SubCellCollection; +} + +namespace CSMTools +{ + class PathgridCheckStage : public CSMDoc::Stage + { + const CSMWorld::SubCellCollection >& mPathgrids; + + public: + + PathgridCheckStage (const CSMWorld::SubCellCollection >& pathgrids); + + virtual int setup(); + + virtual void perform (int stage, CSMDoc::Messages& messages); + }; +} + +#endif // CSM_TOOLS_PATHGRIDCHECK_H diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 99e462b1d2..fd15696975 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -26,6 +26,7 @@ #include "referencecheck.hpp" #include "startscriptcheck.hpp" #include "searchoperation.hpp" +#include "pathgridcheck.hpp" CSMDoc::OperationHolder *CSMTools::Tools::get (int type) { @@ -96,6 +97,8 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), mData.getRaces() )); + mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids())); + mVerifier.setOperation (mVerifierOperation); } From 674a124bc6efe5afeba544a5ebb9eb3fd8e855ef Mon Sep 17 00:00:00 2001 From: cc9cii Date: Wed, 27 May 2015 22:27:32 +1000 Subject: [PATCH 136/142] Don't use local type as a template parameter. --- apps/opencs/model/tools/pathgridcheck.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp index 71f596f4f4..8f22cc8cd3 100644 --- a/apps/opencs/model/tools/pathgridcheck.cpp +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -8,6 +8,15 @@ #include "../world/subcellcollection.hpp" #include "../world/pathgrid.hpp" +namespace +{ + struct Point + { + unsigned char mConnectionNum; + std::vector mOtherIndex; + Point() : mConnectionNum(0), mOtherIndex(0) {} + }; +} CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection& pathgrids) : mPathgrids (pathgrids) @@ -35,12 +44,6 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message else if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected")); - struct Point - { - unsigned char mConnectionNum; - std::vector mOtherIndex; - Point() : mConnectionNum(0), mOtherIndex(0) {} - }; std::vector pointList(pathgrid.mPoints.size()); std::vector duplList; From b6878c2e0c02bc6c3c5f8d14b96e991f2cb1f6bd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 27 May 2015 19:45:26 +0200 Subject: [PATCH 137/142] improved error handling in LocalScripts::add --- apps/openmw/mwworld/localscripts.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/localscripts.cpp b/apps/openmw/mwworld/localscripts.cpp index 5be66ccea3..e30246f7cb 100644 --- a/apps/openmw/mwworld/localscripts.cpp +++ b/apps/openmw/mwworld/localscripts.cpp @@ -93,7 +93,7 @@ std::pair MWWorld::LocalScripts::getNext() void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) { - if (const ESM::Script *script = mStore.get().find (scriptName)) + if (const ESM::Script *script = mStore.get().search (scriptName)) { try { @@ -108,6 +108,10 @@ void MWWorld::LocalScripts::add (const std::string& scriptName, const Ptr& ptr) << " because an exception has been thrown: " << exception.what() << std::endl; } } + else + std::cerr + << "failed to add local script " << scriptName + << " because the script does not exist." << std::endl; } void MWWorld::LocalScripts::addCell (CellStore *cell) From 6821cb4133e0456a42ac279a3fd69b312a6b6c5e Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 29 May 2015 05:40:20 +1000 Subject: [PATCH 138/142] Use the tree model rather than a nested proxy for the dialogue only listing (i.e. non table) items. Should resolve Bug #2586. - QDataWidgetMapper requires the rootindex to be set, which was not possible with the nested proxy model. --- apps/opencs/view/world/dialoguesubview.cpp | 39 +++++++++++++--------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 5e2fa29a55..66e8fcb7a2 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -211,8 +211,17 @@ void CSVWorld::DialogueDelegateDispatcher::editorDataCommited(QWidget* editor, void CSVWorld::DialogueDelegateDispatcher::setEditorData (QWidget* editor, const QModelIndex& index) const { - CSMWorld::ColumnBase::Display display = static_cast - (mTable->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); + CSMWorld::ColumnBase::Display display = CSMWorld::ColumnBase::Display_None; + if (index.parent().isValid()) + { + display = static_cast + (static_cast(mTable)->nestedHeaderData (index.parent().column(), index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); + } + else + { + display = static_cast + (mTable->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); + } QLabel* label = qobject_cast(editor); if(label) @@ -523,22 +532,20 @@ void CSVWorld::EditWidget::remake(int row) } else { - mNestedModels.push_back(new CSMWorld::NestedTableProxyModel ( - static_cast(mTable)->index(row, i), - display, static_cast(mTable))); + CSMWorld::IdTree *tree = static_cast(mTable); mNestedTableMapper = new QDataWidgetMapper (this); - mNestedTableMapper->setModel(mNestedModels.back()); + mNestedTableMapper->setModel(tree); // FIXME: lack MIME support? mNestedTableDispatcher = - new DialogueDelegateDispatcher (0/*this*/, mTable, mCommandDispatcher, mDocument, mNestedModels.back()); + new DialogueDelegateDispatcher (0/*this*/, mTable, mCommandDispatcher, mDocument, tree); + mNestedTableMapper->setRootIndex (tree->index(row, i)); mNestedTableMapper->setItemDelegate(mNestedTableDispatcher); - int columnCount = - mTable->columnCount(mTable->getModelIndex (mNestedModels.back()->getParentId(), i)); + int columnCount = tree->columnCount(tree->index(row, i)); for (int col = 0; col < columnCount; ++col) { - int displayRole = mNestedModels.back()->headerData (col, + int displayRole = tree->nestedHeaderData (i, col, Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt(); CSMWorld::ColumnBase::Display display = @@ -548,16 +555,16 @@ void CSVWorld::EditWidget::remake(int row) // FIXME: assumed all columns are editable QWidget* editor = - mNestedTableDispatcher->makeEditor (display, mNestedModels.back()->index (0, col)); + mNestedTableDispatcher->makeEditor (display, tree->index (0, col, tree->index(row, i))); if (editor) { mNestedTableMapper->addMapping (editor, col); - std::string disString = mNestedModels.back()->headerData (col, + std::string disString = tree->nestedHeaderData (i, col, Qt::Horizontal, Qt::DisplayRole).toString().toStdString(); - // Need ot use Qt::DisplayRole in order to get the correct string + // Need to use Qt::DisplayRole in order to get the correct string // from CSMWorld::Columns - QLabel* label = new QLabel (mNestedModels.back()->headerData (col, + QLabel* label = new QLabel (tree->nestedHeaderData (i, col, Qt::Horizontal, Qt::DisplayRole).toString(), mMainWidget); label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); @@ -567,14 +574,14 @@ void CSVWorld::EditWidget::remake(int row) unlockedLayout->addWidget (editor, unlocked, 1); ++unlocked; - if(mNestedModels.back()->index(0, col).data().type() == QVariant::UserType) + if(tree->index(0, col, tree->index(row, i)).data().type() == QVariant::UserType) { editor->setEnabled(false); label->setEnabled(false); } } } - mNestedTableMapper->setCurrentModelIndex(mNestedModels.back()->index(0, 0)); + mNestedTableMapper->setCurrentModelIndex(tree->index(0, 0, tree->index(row, i))); } } } From 9ad69d908529edfecdd830fd970af6ffb3451a88 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 29 May 2015 05:44:35 +1000 Subject: [PATCH 139/142] Allow wheel events in dialogue spin box types only when they have focus. Should resolve Feature #2585. --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/view/world/dialoguespinbox.cpp | 53 ++++++++++++++++++++++ apps/opencs/view/world/dialoguespinbox.hpp | 40 ++++++++++++++++ apps/opencs/view/world/util.cpp | 8 ++-- 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 apps/opencs/view/world/dialoguespinbox.cpp create mode 100644 apps/opencs/view/world/dialoguespinbox.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 78b2deb7a8..7723b15f5e 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -63,6 +63,7 @@ opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator cellcreator referenceablecreator referencecreator scenesubview infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable + dialoguespinbox ) opencs_units_noqt (view/world diff --git a/apps/opencs/view/world/dialoguespinbox.cpp b/apps/opencs/view/world/dialoguespinbox.cpp new file mode 100644 index 0000000000..1228ca0da9 --- /dev/null +++ b/apps/opencs/view/world/dialoguespinbox.cpp @@ -0,0 +1,53 @@ +#include "dialoguespinbox.hpp" + +#include + +CSVWorld::DialogueSpinBox::DialogueSpinBox(QWidget *parent) : QSpinBox(parent) +{ + setFocusPolicy(Qt::StrongFocus); +} + +void CSVWorld::DialogueSpinBox::focusInEvent(QFocusEvent *event) +{ + setFocusPolicy(Qt::WheelFocus); + QSpinBox::focusInEvent(event); +} + +void CSVWorld::DialogueSpinBox::focusOutEvent(QFocusEvent *event) +{ + setFocusPolicy(Qt::StrongFocus); + QSpinBox::focusOutEvent(event); +} + +void CSVWorld::DialogueSpinBox::wheelEvent(QWheelEvent *event) +{ + if (!hasFocus()) + event->ignore(); + else + QSpinBox::wheelEvent(event); +} + +CSVWorld::DialogueDoubleSpinBox::DialogueDoubleSpinBox(QWidget *parent) : QDoubleSpinBox(parent) +{ + setFocusPolicy(Qt::StrongFocus); +} + +void CSVWorld::DialogueDoubleSpinBox::focusInEvent(QFocusEvent *event) +{ + setFocusPolicy(Qt::WheelFocus); + QDoubleSpinBox::focusInEvent(event); +} + +void CSVWorld::DialogueDoubleSpinBox::focusOutEvent(QFocusEvent *event) +{ + setFocusPolicy(Qt::StrongFocus); + QDoubleSpinBox::focusOutEvent(event); +} + +void CSVWorld::DialogueDoubleSpinBox::wheelEvent(QWheelEvent *event) +{ + if (!hasFocus()) + event->ignore(); + else + QDoubleSpinBox::wheelEvent(event); +} diff --git a/apps/opencs/view/world/dialoguespinbox.hpp b/apps/opencs/view/world/dialoguespinbox.hpp new file mode 100644 index 0000000000..a68e0c3148 --- /dev/null +++ b/apps/opencs/view/world/dialoguespinbox.hpp @@ -0,0 +1,40 @@ +#ifndef CSV_WORLD_DIALOGUESPINBOX_H +#define CSV_WORLD_DIALOGUESPINBOX_H + +#include +#include + +namespace CSVWorld +{ + class DialogueSpinBox : public QSpinBox + { + Q_OBJECT + + public: + + DialogueSpinBox (QWidget *parent = 0); + + protected: + + virtual void focusInEvent(QFocusEvent *event); + virtual void focusOutEvent(QFocusEvent *event); + virtual void wheelEvent(QWheelEvent *event); + }; + + class DialogueDoubleSpinBox : public QDoubleSpinBox + { + Q_OBJECT + + public: + + DialogueDoubleSpinBox (QWidget *parent = 0); + + protected: + + virtual void focusInEvent(QFocusEvent *event); + virtual void focusOutEvent(QFocusEvent *event); + virtual void wheelEvent(QWheelEvent *event); + }; +} + +#endif // CSV_WORLD_DIALOGUESPINBOX_H diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index a11b5bdded..5452214ef4 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -9,8 +9,6 @@ #include #include #include -#include -#include #include #include #include @@ -19,7 +17,7 @@ #include "../../model/world/commands.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/commanddispatcher.hpp" - +#include "dialoguespinbox.hpp" #include "scriptedit.hpp" CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) @@ -174,7 +172,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_Integer: { - QSpinBox *sb = new QSpinBox(parent); + DialogueSpinBox *sb = new DialogueSpinBox(parent); sb->setRange(INT_MIN, INT_MAX); return sb; } @@ -185,7 +183,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_Float: { - QDoubleSpinBox *dsb = new QDoubleSpinBox(parent); + DialogueDoubleSpinBox *dsb = new DialogueDoubleSpinBox(parent); dsb->setRange(-FLT_MAX, FLT_MAX); dsb->setSingleStep(0.01f); dsb->setDecimals(3); From 9cbda0ffada698d45e404c02775bc78d09351636 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Fri, 29 May 2015 22:20:43 +1000 Subject: [PATCH 140/142] Allow users to select syntax highlighting colours. Should resolve Feature #2507. --- apps/opencs/model/settings/usersettings.cpp | 36 +++++ apps/opencs/view/world/scriptedit.cpp | 22 ++-- apps/opencs/view/world/scriptedit.hpp | 7 +- apps/opencs/view/world/scripthighlighter.cpp | 132 +++++++++++++++++-- apps/opencs/view/world/scripthighlighter.hpp | 2 + 5 files changed, 182 insertions(+), 17 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index ea002c5edd..5b6e7ab8b7 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -262,6 +262,42 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() Setting *monoFont = createSetting (Type_CheckBox, "mono-font", "Use monospace font"); monoFont->setDefaultValue ("true"); monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview."); + + QString tooltip = + "\n#RGB (each of R, G, and B is a single hex digit)" + "\n#RRGGBB" + "\n#RRRGGGBBB" + "\n#RRRRGGGGBBBB" + "\nA name from the list of colors defined in the list of SVG color keyword names." + "\nX11 color names may also work."; + + Setting *formatInt = createSetting (Type_LineEdit, "colour-int", "Highlight Colour: Int"); + formatInt->setDefaultValues (QStringList() << "Dark magenta"); + formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip); + + Setting *formatFloat = createSetting (Type_LineEdit, "colour-float", "Highlight Colour: Float"); + formatFloat->setDefaultValues (QStringList() << "Magenta"); + formatFloat->setToolTip ("(Default: Magenta) Use one of the following formats:" + tooltip); + + Setting *formatName = createSetting (Type_LineEdit, "colour-name", "Highlight Colour: Name"); + formatName->setDefaultValues (QStringList() << "Gray"); + formatName->setToolTip ("(Default: Gray) Use one of the following formats:" + tooltip); + + Setting *formatKeyword = createSetting (Type_LineEdit, "colour-keyword", "Highlight Colour: Keyword"); + formatKeyword->setDefaultValues (QStringList() << "Red"); + formatKeyword->setToolTip ("(Default: Red) Use one of the following formats:" + tooltip); + + Setting *formatSpecial = createSetting (Type_LineEdit, "colour-special", "Highlight Colour: Special"); + formatSpecial->setDefaultValues (QStringList() << "Dark yellow"); + formatSpecial->setToolTip ("(Default: Dark yellow) Use one of the following formats:" + tooltip); + + Setting *formatComment = createSetting (Type_LineEdit, "colour-comment", "Highlight Colour: Comment"); + formatComment->setDefaultValues (QStringList() << "Green"); + formatComment->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip); + + Setting *formatId = createSetting (Type_LineEdit, "colour-id", "Highlight Colour: Id"); + formatId->setDefaultValues (QStringList() << "Blue"); + formatId->setToolTip ("(Default: Blue) Use one of the following formats:" + tooltip); } { diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp index 2f0d82ae1c..ad2cddbf84 100644 --- a/apps/opencs/view/world/scriptedit.cpp +++ b/apps/opencs/view/world/scriptedit.cpp @@ -31,11 +31,11 @@ bool CSVWorld::ScriptEdit::event (QEvent *event) if (event->type()==QEvent::ShortcutOverride) { QKeyEvent *keyEvent = static_cast (event); - + if (keyEvent->matches (QKeySequence::Undo) || keyEvent->matches (QKeySequence::Redo)) return true; } - + return QPlainTextEdit::event (event); } @@ -92,13 +92,16 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli connect (&mUpdateTimer, SIGNAL (timeout()), this, SLOT (updateHighlighting())); + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + connect (&userSettings, SIGNAL (userSettingUpdated(const QString &, const QStringList &)), + this, SLOT (updateUserSetting (const QString &, const QStringList &))); + mUpdateTimer.setSingleShot (true); // TODO: provide a font selector dialogue mMonoFont.setStyleHint(QFont::TypeWriter); - std::string useMonoFont = - CSMSettings::UserSettings::instance().setting("script-editor/mono-font", "true").toStdString(); - if (useMonoFont == "true") + + if (userSettings.setting("script-editor/mono-font", "true") == "true") setFont(mMonoFont); mLineNumberArea = new LineNumberArea(this); @@ -107,10 +110,13 @@ CSVWorld::ScriptEdit::ScriptEdit (const CSMDoc::Document& document, ScriptHighli connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); - std::string showStatusBar = - CSMSettings::UserSettings::instance().settingValue("script-editor/show-linenum").toStdString(); + showLineNum(userSettings.settingValue("script-editor/show-linenum") == "true"); +} - showLineNum(showStatusBar == "true"); +void CSVWorld::ScriptEdit::updateUserSetting (const QString &name, const QStringList &list) +{ + if (mHighlighter->updateUserSetting (name, list)) + updateHighlighting(); } void CSVWorld::ScriptEdit::showLineNum(bool show) diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp index fb577e60e4..d17abf24ed 100644 --- a/apps/opencs/view/world/scriptedit.hpp +++ b/apps/opencs/view/world/scriptedit.hpp @@ -56,7 +56,7 @@ namespace CSVWorld protected: bool event (QEvent *event); - + public: ScriptEdit (const CSMDoc::Document& document, ScriptHighlighter::Mode mode, @@ -96,7 +96,12 @@ namespace CSVWorld void updateHighlighting(); void updateLineNumberAreaWidth(int newBlockCount); + void updateLineNumberArea(const QRect &, int); + + public slots: + + void updateUserSetting (const QString &name, const QStringList &list); }; class LineNumberArea : public QWidget diff --git a/apps/opencs/view/world/scripthighlighter.cpp b/apps/opencs/view/world/scripthighlighter.cpp index 6dda8d4faf..4923a44d89 100644 --- a/apps/opencs/view/world/scripthighlighter.cpp +++ b/apps/opencs/view/world/scripthighlighter.cpp @@ -6,6 +6,8 @@ #include #include +#include "../../model/settings/usersettings.hpp" + bool CSVWorld::ScriptHighlighter::parseInt (int value, const Compiler::TokenLoc& loc, Compiler::Scanner& scanner) { @@ -78,46 +80,77 @@ CSVWorld::ScriptHighlighter::ScriptHighlighter (const CSMWorld::Data& data, Mode : QSyntaxHighlighter (parent), Compiler::Parser (mErrorHandler, mContext), mContext (data), mMode (mode) { - /// \todo replace this with user settings + CSMSettings::UserSettings &userSettings = CSMSettings::UserSettings::instance(); + + QColor color = QColor(); + { + color.setNamedColor(userSettings.setting("script-editor/colour-int", "Dark magenta")); + if (!color.isValid()) + color = QColor(Qt::darkMagenta); + QTextCharFormat format; - format.setForeground (Qt::darkMagenta); + format.setForeground (color); mScheme.insert (std::make_pair (Type_Int, format)); } { + color.setNamedColor(userSettings.setting ("script-editor/colour-float", "Magenta")); + if (!color.isValid()) + color = QColor(Qt::magenta); + QTextCharFormat format; - format.setForeground (Qt::magenta); + format.setForeground (color); mScheme.insert (std::make_pair (Type_Float, format)); } { + color.setNamedColor(userSettings.setting ("script-editor/colour-name", "Gray")); + if (!color.isValid()) + color = QColor(Qt::gray); + QTextCharFormat format; - format.setForeground (Qt::gray); + format.setForeground (color); mScheme.insert (std::make_pair (Type_Name, format)); } { + color.setNamedColor(userSettings.setting ("script-editor/colour-keyword", "Red")); + if (!color.isValid()) + color = QColor(Qt::red); + QTextCharFormat format; - format.setForeground (Qt::red); + format.setForeground (color); mScheme.insert (std::make_pair (Type_Keyword, format)); } { + color.setNamedColor(userSettings.setting ("script-editor/colour-special", "Dark yellow")); + if (!color.isValid()) + color = QColor(Qt::darkYellow); + QTextCharFormat format; - format.setForeground (Qt::darkYellow); + format.setForeground (color); mScheme.insert (std::make_pair (Type_Special, format)); } { + color.setNamedColor(userSettings.setting ("script-editor/colour-comment", "Green")); + if (!color.isValid()) + color = QColor(Qt::green); + QTextCharFormat format; - format.setForeground (Qt::green); + format.setForeground (color); mScheme.insert (std::make_pair (Type_Comment, format)); } { + color.setNamedColor(userSettings.setting ("script-editor/colour-id", "Blue")); + if (!color.isValid()) + color = QColor(Qt::blue); + QTextCharFormat format; - format.setForeground (Qt::blue); + format.setForeground (color); mScheme.insert (std::make_pair (Type_Id, format)); } @@ -143,3 +176,86 @@ void CSVWorld::ScriptHighlighter::invalidateIds() { mContext.invalidateIds(); } + +bool CSVWorld::ScriptHighlighter::updateUserSetting (const QString &name, const QStringList &list) +{ + if (list.empty()) + return false; + + QColor color = QColor(); + + if (name == "script-editor/colour-int") + { + color.setNamedColor(list.at(0)); + if (!color.isValid()) + return false; + + QTextCharFormat format; + format.setForeground (color); + mScheme[Type_Int] = format; + } + else if (name == "script-editor/colour-float") + { + color.setNamedColor(list.at(0)); + if (!color.isValid()) + return false; + + QTextCharFormat format; + format.setForeground (color); + mScheme[Type_Float] = format; + } + else if (name == "script-editor/colour-name") + { + color.setNamedColor(list.at(0)); + if (!color.isValid()) + return false; + + QTextCharFormat format; + format.setForeground (color); + mScheme[Type_Name] = format; + } + else if (name == "script-editor/colour-keyword") + { + color.setNamedColor(list.at(0)); + if (!color.isValid()) + return false; + + QTextCharFormat format; + format.setForeground (color); + mScheme[Type_Keyword] = format; + } + else if (name == "script-editor/colour-special") + { + color.setNamedColor(list.at(0)); + if (!color.isValid()) + return false; + + QTextCharFormat format; + format.setForeground (color); + mScheme[Type_Special] = format; + } + else if (name == "script-editor/colour-comment") + { + color.setNamedColor(list.at(0)); + if (!color.isValid()) + return false; + + QTextCharFormat format; + format.setForeground (color); + mScheme[Type_Comment] = format; + } + else if (name == "script-editor/colour-id") + { + color.setNamedColor(list.at(0)); + if (!color.isValid()) + return false; + + QTextCharFormat format; + format.setForeground (color); + mScheme[Type_Id] = format; + } + else + return false; + + return true; +} diff --git a/apps/opencs/view/world/scripthighlighter.hpp b/apps/opencs/view/world/scripthighlighter.hpp index 953f2f953a..6f1f58e823 100644 --- a/apps/opencs/view/world/scripthighlighter.hpp +++ b/apps/opencs/view/world/scripthighlighter.hpp @@ -87,6 +87,8 @@ namespace CSVWorld virtual void highlightBlock (const QString& text); void invalidateIds(); + + bool updateUserSetting (const QString &name, const QStringList &list); }; } From 0aaac59cc3cfdd834ed36d3585ffc96b38237f67 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Sat, 30 May 2015 08:37:58 +1000 Subject: [PATCH 141/142] Return to startup dialog when the open/create action is cancelled. Should resolve Bug #2588. --- apps/opencs/editor.cpp | 30 +++++++++++++++++++++++ apps/opencs/editor.hpp | 2 ++ apps/opencs/model/doc/documentmanager.cpp | 5 ++++ apps/opencs/model/doc/documentmanager.hpp | 2 ++ apps/opencs/view/doc/newgame.cpp | 6 +++++ apps/opencs/view/doc/newgame.hpp | 4 +++ 6 files changed, 49 insertions(+) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 53a9e9e838..84849cbbba 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -67,9 +67,11 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) connect (&mFileDialog, SIGNAL(signalCreateNewFile (const boost::filesystem::path&)), this, SLOT(createNewFile (const boost::filesystem::path&))); + connect (&mFileDialog, SIGNAL (rejected()), this, SLOT (cancelFileDialog ())); connect (&mNewGame, SIGNAL (createRequest (const boost::filesystem::path&)), this, SLOT (createNewGame (const boost::filesystem::path&))); + connect (&mNewGame, SIGNAL (cancelCreateGame()), this, SLOT (cancelCreateGame ())); } CS::Editor::~Editor () @@ -176,12 +178,40 @@ void CS::Editor::createGame() mNewGame.activateWindow(); } +void CS::Editor::cancelCreateGame() +{ + if (!mDocumentManager.isEmpty()) + return; + + mNewGame.hide(); + + if (mStartup.isHidden()) + mStartup.show(); + + mStartup.raise(); + mStartup.activateWindow(); +} + void CS::Editor::createAddon() { mStartup.hide(); mFileDialog.showDialog (CSVDoc::ContentAction_New); } +void CS::Editor::cancelFileDialog() +{ + if (!mDocumentManager.isEmpty()) + return; + + mFileDialog.hide(); + + if (mStartup.isHidden()) + mStartup.show(); + + mStartup.raise(); + mStartup.activateWindow(); +} + void CS::Editor::loadDocument() { mStartup.hide(); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 273f0825b8..eb85743a39 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -87,6 +87,8 @@ namespace CS void createGame(); void createAddon(); + void cancelCreateGame(); + void cancelFileDialog(); void loadDocument(); void openFiles (const boost::filesystem::path &path); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 2d444f2451..29d7a8d3a8 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -49,6 +49,11 @@ CSMDoc::DocumentManager::~DocumentManager() delete *iter; } +bool CSMDoc::DocumentManager::isEmpty() +{ + return mDocuments.empty(); +} + void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 0ae73e70c0..f3fcbf8ec6 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -59,6 +59,8 @@ namespace CSMDoc /// Ask OGRE for a list of available resources. void listResources(); + bool isEmpty(); + private: boost::filesystem::path mResDir; diff --git a/apps/opencs/view/doc/newgame.cpp b/apps/opencs/view/doc/newgame.cpp index 98681c499d..32b4837285 100644 --- a/apps/opencs/view/doc/newgame.cpp +++ b/apps/opencs/view/doc/newgame.cpp @@ -66,3 +66,9 @@ void CSVDoc::NewGameDialogue::create() { emit createRequest (mAdjusterWidget->getPath()); } + +void CSVDoc::NewGameDialogue::reject() +{ + emit cancelCreateGame (); + QDialog::reject(); +} diff --git a/apps/opencs/view/doc/newgame.hpp b/apps/opencs/view/doc/newgame.hpp index 9ad7ea1690..70e9d684b0 100644 --- a/apps/opencs/view/doc/newgame.hpp +++ b/apps/opencs/view/doc/newgame.hpp @@ -36,11 +36,15 @@ namespace CSVDoc void createRequest (const boost::filesystem::path& file); + void cancelCreateGame (); + private slots: void stateChanged (bool valid); void create(); + + void reject(); }; } From 88d5aed62d65e2798bf6f21f8e2b053f9af77fd8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 30 May 2015 12:05:35 +0200 Subject: [PATCH 142/142] removed code that interfered with the default window size on Linux (Fixes #2568) --- apps/opencs/view/doc/view.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 5e3df27399..fca9b27157 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -404,11 +404,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to width = std::max(width, 300); height = std::max(height, 300); - // trick to get the window decorations and their sizes - show(); - hide(); - resize (width - (frameGeometry().width() - geometry().width()), - height - (frameGeometry().height() - geometry().height())); + resize (width, height); mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks);