mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:53:53 +00:00
Merge branch 'what-a-selection-you-have' into 'master'
Feat(CS): Add More Selection Controls See merge request OpenMW/openmw!3674
This commit is contained in:
commit
cb24475662
27 changed files with 381 additions and 5 deletions
|
@ -25,6 +25,7 @@
|
||||||
#include <components/esm3/loadsoun.hpp>
|
#include <components/esm3/loadsoun.hpp>
|
||||||
#include <components/esm3/loadspel.hpp>
|
#include <components/esm3/loadspel.hpp>
|
||||||
#include <components/esm3/loadsscr.hpp>
|
#include <components/esm3/loadsscr.hpp>
|
||||||
|
#include <components/esm3/selectiongroup.hpp>
|
||||||
|
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
@ -52,6 +53,9 @@ CSMDoc::Saving::Saving(Document& document, const std::filesystem::path& projectP
|
||||||
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script>>(
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script>>(
|
||||||
mDocument.getData().getScripts(), mState, CSMWorld::Scope_Project));
|
mDocument.getData().getScripts(), mState, CSMWorld::Scope_Project));
|
||||||
|
|
||||||
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::SelectionGroup>>(
|
||||||
|
mDocument.getData().getSelectionGroups(), mState, CSMWorld::Scope_Project));
|
||||||
|
|
||||||
appendStage(new CloseSaveStage(mState));
|
appendStage(new CloseSaveStage(mState));
|
||||||
|
|
||||||
// save content file
|
// save content file
|
||||||
|
|
|
@ -415,6 +415,29 @@ void CSMPrefs::State::declare()
|
||||||
declareShortcut("scene-focus-toolbar", "Toggle Toolbar Focus", QKeySequence(Qt::Key_T));
|
declareShortcut("scene-focus-toolbar", "Toggle Toolbar Focus", QKeySequence(Qt::Key_T));
|
||||||
declareShortcut("scene-render-stats", "Debug Rendering Stats", QKeySequence(Qt::Key_F3));
|
declareShortcut("scene-render-stats", "Debug Rendering Stats", QKeySequence(Qt::Key_F3));
|
||||||
declareShortcut("scene-duplicate", "Duplicate Instance", QKeySequence(Qt::ShiftModifier | Qt::Key_C));
|
declareShortcut("scene-duplicate", "Duplicate Instance", QKeySequence(Qt::ShiftModifier | Qt::Key_C));
|
||||||
|
declareShortcut("scene-clear-selection", "Clear Selection", QKeySequence(Qt::Key_Space));
|
||||||
|
declareShortcut("scene-unhide-all", "Unhide All Objects", QKeySequence(Qt::AltModifier | Qt::Key_H));
|
||||||
|
declareShortcut("scene-toggle-visibility", "Toggle Selection Visibility", QKeySequence(Qt::Key_H));
|
||||||
|
declareShortcut("scene-group-1", "Select Group 1", QKeySequence(Qt::Key_1));
|
||||||
|
declareShortcut("scene-save-1", "Save Group 1", QKeySequence(Qt::ControlModifier | Qt::Key_1));
|
||||||
|
declareShortcut("scene-group-2", "Select Group 2", QKeySequence(Qt::Key_2));
|
||||||
|
declareShortcut("scene-save-2", "Save Group 2", QKeySequence(Qt::ControlModifier | Qt::Key_2));
|
||||||
|
declareShortcut("scene-group-3", "Select Group 3", QKeySequence(Qt::Key_3));
|
||||||
|
declareShortcut("scene-save-3", "Save Group 3", QKeySequence(Qt::ControlModifier | Qt::Key_3));
|
||||||
|
declareShortcut("scene-group-4", "Select Group 4", QKeySequence(Qt::Key_4));
|
||||||
|
declareShortcut("scene-save-4", "Save Group 4", QKeySequence(Qt::ControlModifier | Qt::Key_4));
|
||||||
|
declareShortcut("scene-group-5", "Selection Group 5", QKeySequence(Qt::Key_5));
|
||||||
|
declareShortcut("scene-save-5", "Save Group 5", QKeySequence(Qt::ControlModifier | Qt::Key_5));
|
||||||
|
declareShortcut("scene-group-6", "Selection Group 6", QKeySequence(Qt::Key_6));
|
||||||
|
declareShortcut("scene-save-6", "Save Group 6", QKeySequence(Qt::ControlModifier | Qt::Key_6));
|
||||||
|
declareShortcut("scene-group-7", "Selection Group 7", QKeySequence(Qt::Key_7));
|
||||||
|
declareShortcut("scene-save-7", "Save Group 7", QKeySequence(Qt::ControlModifier | Qt::Key_7));
|
||||||
|
declareShortcut("scene-group-8", "Selection Group 8", QKeySequence(Qt::Key_8));
|
||||||
|
declareShortcut("scene-save-8", "Save Group 8", QKeySequence(Qt::ControlModifier | Qt::Key_8));
|
||||||
|
declareShortcut("scene-group-9", "Selection Group 9", QKeySequence(Qt::Key_9));
|
||||||
|
declareShortcut("scene-save-9", "Save Group 9", QKeySequence(Qt::ControlModifier | Qt::Key_9));
|
||||||
|
declareShortcut("scene-group-0", "Selection Group 10", QKeySequence(Qt::Key_0));
|
||||||
|
declareShortcut("scene-save-0", "Save Group 10", QKeySequence(Qt::ControlModifier | Qt::Key_0));
|
||||||
|
|
||||||
declareSubcategory("1st/Free Camera");
|
declareSubcategory("1st/Free Camera");
|
||||||
declareShortcut("free-forward", "Forward", QKeySequence(Qt::Key_W));
|
declareShortcut("free-forward", "Forward", QKeySequence(Qt::Key_W));
|
||||||
|
|
|
@ -477,6 +477,29 @@ namespace CSMPrefs
|
||||||
Settings::SettingValue<std::string> mSceneEditAbort{ mIndex, sName, "scene-edit-abort", "Escape" };
|
Settings::SettingValue<std::string> mSceneEditAbort{ mIndex, sName, "scene-edit-abort", "Escape" };
|
||||||
Settings::SettingValue<std::string> mSceneFocusToolbar{ mIndex, sName, "scene-focus-toolbar", "T" };
|
Settings::SettingValue<std::string> mSceneFocusToolbar{ mIndex, sName, "scene-focus-toolbar", "T" };
|
||||||
Settings::SettingValue<std::string> mSceneRenderStats{ mIndex, sName, "scene-render-stats", "F3" };
|
Settings::SettingValue<std::string> mSceneRenderStats{ mIndex, sName, "scene-render-stats", "F3" };
|
||||||
|
Settings::SettingValue<std::string> mSceneClearSelection{ mIndex, sName, "scene-clear-selection", "Space" };
|
||||||
|
Settings::SettingValue<std::string> mSceneUnhideAll{ mIndex, sName, "scene-unhide-all", "Alt+H" };
|
||||||
|
Settings::SettingValue<std::string> mSceneToggleHidden{ mIndex, sName, "scene-toggle-visibility", "H" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup1{ mIndex, sName, "scene-group-1", "1" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup1{ mIndex, sName, "scene-save-1", "Ctrl+1" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup2{ mIndex, sName, "scene-group-2", "2" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup2{ mIndex, sName, "scene-save-2", "Ctrl+2" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup3{ mIndex, sName, "scene-group-3", "3" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup3{ mIndex, sName, "scene-save-3", "Ctrl+3" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup4{ mIndex, sName, "scene-group-4", "4" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup4{ mIndex, sName, "scene-save-4", "Ctrl+4" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup5{ mIndex, sName, "scene-group-5", "5" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup5{ mIndex, sName, "scene-save-5", "Ctrl+5" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup6{ mIndex, sName, "scene-group-6", "6" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup6{ mIndex, sName, "scene-save-6", "Ctrl+6" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup7{ mIndex, sName, "scene-group-7", "7" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup7{ mIndex, sName, "scene-save-7", "Ctrl+7" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup8{ mIndex, sName, "scene-group-8", "8" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup8{ mIndex, sName, "scene-save-8", "Ctrl+8" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup9{ mIndex, sName, "scene-group-9", "9" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup9{ mIndex, sName, "scene-save-9", "Ctrl+9" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSelectGroup10{ mIndex, sName, "scene-group-0", "0" };
|
||||||
|
Settings::SettingValue<std::string> mSceneSaveGroup10{ mIndex, sName, "scene-save-0", "Ctrl+0" };
|
||||||
Settings::SettingValue<std::string> mFreeForward{ mIndex, sName, "free-forward", "W" };
|
Settings::SettingValue<std::string> mFreeForward{ mIndex, sName, "free-forward", "W" };
|
||||||
Settings::SettingValue<std::string> mFreeBackward{ mIndex, sName, "free-backward", "S" };
|
Settings::SettingValue<std::string> mFreeBackward{ mIndex, sName, "free-backward", "S" };
|
||||||
Settings::SettingValue<std::string> mFreeLeft{ mIndex, sName, "free-left", "A" };
|
Settings::SettingValue<std::string> mFreeLeft{ mIndex, sName, "free-left", "A" };
|
||||||
|
|
|
@ -333,6 +333,37 @@ namespace CSMWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectionGroupColumn::SelectionGroupColumn()
|
||||||
|
: Column<ESM::SelectionGroup>(Columns::ColumnId_SelectionGroupObjects, ColumnBase::Display_None)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SelectionGroupColumn::get(const Record<ESM::SelectionGroup>& record) const
|
||||||
|
{
|
||||||
|
QVariant data;
|
||||||
|
QStringList selectionInfo;
|
||||||
|
const std::vector<std::string>& instances = record.get().selectedInstances;
|
||||||
|
|
||||||
|
for (const std::string& instance : instances)
|
||||||
|
selectionInfo << QString::fromStdString(instance);
|
||||||
|
data.setValue(selectionInfo);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectionGroupColumn::set(Record<ESM::SelectionGroup>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
ESM::SelectionGroup record2 = record.get();
|
||||||
|
for (const auto& item : data.toStringList())
|
||||||
|
record2.selectedInstances.push_back(item.toStdString());
|
||||||
|
record.setModified(record2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SelectionGroupColumn::isEditable() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::uint32_t> getSkillIndex(std::string_view value)
|
std::optional<std::uint32_t> getSkillIndex(std::string_view value)
|
||||||
{
|
{
|
||||||
int index = ESM::Skill::refIdToIndex(ESM::RefId::stringRefId(value));
|
int index = ESM::Skill::refIdToIndex(ESM::RefId::stringRefId(value));
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <components/esm3/loadinfo.hpp>
|
#include <components/esm3/loadinfo.hpp>
|
||||||
#include <components/esm3/loadrace.hpp>
|
#include <components/esm3/loadrace.hpp>
|
||||||
#include <components/esm3/loadskil.hpp>
|
#include <components/esm3/loadskil.hpp>
|
||||||
|
#include <components/esm3/selectiongroup.hpp>
|
||||||
#include <components/esm3/variant.hpp>
|
#include <components/esm3/variant.hpp>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -2391,6 +2392,17 @@ namespace CSMWorld
|
||||||
void set(Record<ESM::BodyPart>& record, const QVariant& data) override;
|
void set(Record<ESM::BodyPart>& record, const QVariant& data) override;
|
||||||
bool isEditable() const override;
|
bool isEditable() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SelectionGroupColumn : public Column<ESM::SelectionGroup>
|
||||||
|
{
|
||||||
|
SelectionGroupColumn();
|
||||||
|
|
||||||
|
QVariant get(const Record<ESM::SelectionGroup>& record) const override;
|
||||||
|
|
||||||
|
void set(Record<ESM::SelectionGroup>& record, const QVariant& data) override;
|
||||||
|
|
||||||
|
bool isEditable() const override;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is required to access the type as a QVariant.
|
// This is required to access the type as a QVariant.
|
||||||
|
|
|
@ -347,6 +347,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
ColumnId_LevelledCreatureId = 315,
|
ColumnId_LevelledCreatureId = 315,
|
||||||
|
|
||||||
|
ColumnId_SelectionGroupObjects = 316,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
ColumnId_UseValue1 = 0x10000,
|
ColumnId_UseValue1 = 0x10000,
|
||||||
|
|
|
@ -620,6 +620,10 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
||||||
mDebugProfiles.addColumn(new DescriptionColumn<ESM::DebugProfile>);
|
mDebugProfiles.addColumn(new DescriptionColumn<ESM::DebugProfile>);
|
||||||
mDebugProfiles.addColumn(new ScriptColumn<ESM::DebugProfile>(ScriptColumn<ESM::DebugProfile>::Type_Lines));
|
mDebugProfiles.addColumn(new ScriptColumn<ESM::DebugProfile>(ScriptColumn<ESM::DebugProfile>::Type_Lines));
|
||||||
|
|
||||||
|
mSelectionGroups.addColumn(new StringIdColumn<ESM::SelectionGroup>);
|
||||||
|
mSelectionGroups.addColumn(new RecordStateColumn<ESM::SelectionGroup>);
|
||||||
|
mSelectionGroups.addColumn(new SelectionGroupColumn);
|
||||||
|
|
||||||
mMetaData.appendBlankRecord(ESM::RefId::stringRefId("sys::meta"));
|
mMetaData.appendBlankRecord(ESM::RefId::stringRefId("sys::meta"));
|
||||||
|
|
||||||
mMetaData.addColumn(new StringIdColumn<MetaData>(true));
|
mMetaData.addColumn(new StringIdColumn<MetaData>(true));
|
||||||
|
@ -664,6 +668,7 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
||||||
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Textures)), UniversalId::Type_Texture);
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Textures)), UniversalId::Type_Texture);
|
||||||
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Videos)), UniversalId::Type_Video);
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Videos)), UniversalId::Type_Video);
|
||||||
addModel(new IdTable(&mMetaData), UniversalId::Type_MetaData);
|
addModel(new IdTable(&mMetaData), UniversalId::Type_MetaData);
|
||||||
|
addModel(new IdTable(&mSelectionGroups), UniversalId::Type_SelectionGroup);
|
||||||
|
|
||||||
mActorAdapter = std::make_unique<ActorAdapter>(*this);
|
mActorAdapter = std::make_unique<ActorAdapter>(*this);
|
||||||
|
|
||||||
|
@ -908,6 +913,16 @@ CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles()
|
||||||
return mDebugProfiles;
|
return mDebugProfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMWorld::IdCollection<ESM::SelectionGroup>& CSMWorld::Data::getSelectionGroups()
|
||||||
|
{
|
||||||
|
return mSelectionGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMWorld::IdCollection<ESM::SelectionGroup>& CSMWorld::Data::getSelectionGroups() const
|
||||||
|
{
|
||||||
|
return mSelectionGroups;
|
||||||
|
}
|
||||||
|
|
||||||
const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
|
const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
|
||||||
{
|
{
|
||||||
return mLand;
|
return mLand;
|
||||||
|
@ -1369,6 +1384,17 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
|
||||||
mDebugProfiles.load(*mReader, mBase);
|
mDebugProfiles.load(*mReader, mBase);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ESM::REC_SELG:
|
||||||
|
|
||||||
|
if (!mProject)
|
||||||
|
{
|
||||||
|
unhandledRecord = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSelectionGroups.load(*mReader, mBase);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
unhandledRecord = true;
|
unhandledRecord = true;
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <components/esm3/loadsoun.hpp>
|
#include <components/esm3/loadsoun.hpp>
|
||||||
#include <components/esm3/loadspel.hpp>
|
#include <components/esm3/loadspel.hpp>
|
||||||
#include <components/esm3/loadsscr.hpp>
|
#include <components/esm3/loadsscr.hpp>
|
||||||
|
#include <components/esm3/selectiongroup.hpp>
|
||||||
#include <components/files/multidircollection.hpp>
|
#include <components/files/multidircollection.hpp>
|
||||||
#include <components/misc/algorithm.hpp>
|
#include <components/misc/algorithm.hpp>
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
@ -105,6 +106,7 @@ namespace CSMWorld
|
||||||
IdCollection<ESM::BodyPart> mBodyParts;
|
IdCollection<ESM::BodyPart> mBodyParts;
|
||||||
IdCollection<ESM::MagicEffect> mMagicEffects;
|
IdCollection<ESM::MagicEffect> mMagicEffects;
|
||||||
IdCollection<ESM::DebugProfile> mDebugProfiles;
|
IdCollection<ESM::DebugProfile> mDebugProfiles;
|
||||||
|
IdCollection<ESM::SelectionGroup> mSelectionGroups;
|
||||||
IdCollection<ESM::SoundGenerator> mSoundGens;
|
IdCollection<ESM::SoundGenerator> mSoundGens;
|
||||||
IdCollection<ESM::StartScript> mStartScripts;
|
IdCollection<ESM::StartScript> mStartScripts;
|
||||||
NestedInfoCollection mTopicInfos;
|
NestedInfoCollection mTopicInfos;
|
||||||
|
@ -251,6 +253,10 @@ namespace CSMWorld
|
||||||
|
|
||||||
IdCollection<ESM::DebugProfile>& getDebugProfiles();
|
IdCollection<ESM::DebugProfile>& getDebugProfiles();
|
||||||
|
|
||||||
|
const IdCollection<ESM::SelectionGroup>& getSelectionGroups() const;
|
||||||
|
|
||||||
|
IdCollection<ESM::SelectionGroup>& getSelectionGroups();
|
||||||
|
|
||||||
const IdCollection<CSMWorld::Land>& getLand() const;
|
const IdCollection<CSMWorld::Land>& getLand() const;
|
||||||
|
|
||||||
IdCollection<CSMWorld::Land>& getLand();
|
IdCollection<CSMWorld::Land>& getLand();
|
||||||
|
|
|
@ -68,6 +68,7 @@ namespace
|
||||||
":./resources-video" },
|
":./resources-video" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles",
|
||||||
":./debug-profile.png" },
|
":./debug-profile.png" },
|
||||||
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SelectionGroup, "Selection Groups", "" },
|
||||||
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":./run-log.png" },
|
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run Log", ":./run-log.png" },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators",
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators",
|
||||||
":./sound-generator.png" },
|
":./sound-generator.png" },
|
||||||
|
|
|
@ -133,6 +133,7 @@ namespace CSMWorld
|
||||||
Type_LandTexture,
|
Type_LandTexture,
|
||||||
Type_Pathgrids,
|
Type_Pathgrids,
|
||||||
Type_Pathgrid,
|
Type_Pathgrid,
|
||||||
|
Type_SelectionGroup,
|
||||||
Type_StartScripts,
|
Type_StartScripts,
|
||||||
Type_StartScript,
|
Type_StartScript,
|
||||||
Type_Search,
|
Type_Search,
|
||||||
|
|
|
@ -612,6 +612,30 @@ osg::ref_ptr<CSVRender::TagBase> CSVRender::Cell::getSnapTarget(unsigned int ele
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::selectFromGroup(const std::vector<std::string> group)
|
||||||
|
{
|
||||||
|
for (const auto& [_, object] : mObjects)
|
||||||
|
{
|
||||||
|
for (const auto& objectName : group)
|
||||||
|
{
|
||||||
|
if (objectName == object->getReferenceId())
|
||||||
|
{
|
||||||
|
object->setSelected(true, osg::Vec4f(1, 0, 1, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::unhideAll()
|
||||||
|
{
|
||||||
|
for (const auto& [_, object] : mObjects)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Group> rootNode = object->getRootNode();
|
||||||
|
if (rootNode->getNodeMask() == Mask_Hidden)
|
||||||
|
rootNode->setNodeMask(Mask_Reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::Cell::getSelection(unsigned int elementMask) const
|
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::Cell::getSelection(unsigned int elementMask) const
|
||||||
{
|
{
|
||||||
std::vector<osg::ref_ptr<TagBase>> result;
|
std::vector<osg::ref_ptr<TagBase>> result;
|
||||||
|
|
|
@ -148,6 +148,10 @@ namespace CSVRender
|
||||||
// already selected
|
// already selected
|
||||||
void selectAllWithSameParentId(int elementMask);
|
void selectAllWithSameParentId(int elementMask);
|
||||||
|
|
||||||
|
void selectFromGroup(const std::vector<std::string> group);
|
||||||
|
|
||||||
|
void unhideAll();
|
||||||
|
|
||||||
void handleSelectDrag(Object* object, DragMode dragMode);
|
void handleSelectDrag(Object* object, DragMode dragMode);
|
||||||
|
|
||||||
void selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode);
|
void selectInsideCube(const osg::Vec3d& pointA, const osg::Vec3d& pointB, DragMode dragMode);
|
||||||
|
|
|
@ -186,6 +186,71 @@ osg::Vec3f CSVRender::InstanceMode::getMousePlaneCoords(const QPoint& point, con
|
||||||
return mousePlanePoint;
|
return mousePlanePoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::InstanceMode::saveSelectionGroup(const int group)
|
||||||
|
{
|
||||||
|
QStringList strings;
|
||||||
|
QUndoStack& undoStack = getWorldspaceWidget().getDocument().getUndoStack();
|
||||||
|
QVariant selectionObjects;
|
||||||
|
CSMWorld::CommandMacro macro(undoStack, "Replace Selection Group");
|
||||||
|
std::string groupName = "project::" + std::to_string(group);
|
||||||
|
|
||||||
|
const auto& selection = getWorldspaceWidget().getSelection(Mask_Reference);
|
||||||
|
const int selectionObjectsIndex
|
||||||
|
= mSelectionGroups->findColumnIndex(CSMWorld::Columns::ColumnId_SelectionGroupObjects);
|
||||||
|
|
||||||
|
if (dynamic_cast<CSVRender::PagedWorldspaceWidget*>(&getWorldspaceWidget()))
|
||||||
|
groupName += "-ext";
|
||||||
|
else
|
||||||
|
groupName += "-" + getWorldspaceWidget().getCellId(osg::Vec3f(0, 0, 0));
|
||||||
|
|
||||||
|
CSMWorld::CreateCommand* newGroup = new CSMWorld::CreateCommand(*mSelectionGroups, groupName);
|
||||||
|
|
||||||
|
newGroup->setType(CSMWorld::UniversalId::Type_SelectionGroup);
|
||||||
|
|
||||||
|
for (const auto& object : selection)
|
||||||
|
if (const CSVRender::ObjectTag* objectTag = dynamic_cast<CSVRender::ObjectTag*>(object.get()))
|
||||||
|
strings << QString::fromStdString(objectTag->mObject->getReferenceId());
|
||||||
|
|
||||||
|
selectionObjects.setValue(strings);
|
||||||
|
|
||||||
|
newGroup->addValue(selectionObjectsIndex, selectionObjects);
|
||||||
|
|
||||||
|
if (mSelectionGroups->getModelIndex(groupName, 0).row() != -1)
|
||||||
|
macro.push(new CSMWorld::DeleteCommand(*mSelectionGroups, groupName));
|
||||||
|
|
||||||
|
macro.push(newGroup);
|
||||||
|
|
||||||
|
getWorldspaceWidget().clearSelection(Mask_Reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::InstanceMode::getSelectionGroup(const int group)
|
||||||
|
{
|
||||||
|
std::string groupName = "project::" + std::to_string(group);
|
||||||
|
std::vector<std::string> targets;
|
||||||
|
|
||||||
|
const auto& selection = getWorldspaceWidget().getSelection(Mask_Reference);
|
||||||
|
const int selectionObjectsIndex
|
||||||
|
= mSelectionGroups->findColumnIndex(CSMWorld::Columns::ColumnId_SelectionGroupObjects);
|
||||||
|
|
||||||
|
if (dynamic_cast<CSVRender::PagedWorldspaceWidget*>(&getWorldspaceWidget()))
|
||||||
|
groupName += "-ext";
|
||||||
|
else
|
||||||
|
groupName += "-" + getWorldspaceWidget().getCellId(osg::Vec3f(0, 0, 0));
|
||||||
|
|
||||||
|
const QModelIndex groupSearch = mSelectionGroups->getModelIndex(groupName, selectionObjectsIndex);
|
||||||
|
|
||||||
|
if (groupSearch.row() == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const QString& target : groupSearch.data().toStringList())
|
||||||
|
targets.push_back(target.toStdString());
|
||||||
|
|
||||||
|
if (!selection.empty())
|
||||||
|
getWorldspaceWidget().clearSelection(Mask_Reference);
|
||||||
|
|
||||||
|
getWorldspaceWidget().selectGroup(targets);
|
||||||
|
}
|
||||||
|
|
||||||
CSVRender::InstanceMode::InstanceMode(
|
CSVRender::InstanceMode::InstanceMode(
|
||||||
WorldspaceWidget* worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget* parent)
|
WorldspaceWidget* worldspaceWidget, osg::ref_ptr<osg::Group> parentNode, QWidget* parent)
|
||||||
: EditMode(worldspaceWidget, QIcon(":scenetoolbar/editing-instance"), Mask_Reference | Mask_Terrain,
|
: EditMode(worldspaceWidget, QIcon(":scenetoolbar/editing-instance"), Mask_Reference | Mask_Terrain,
|
||||||
|
@ -199,6 +264,9 @@ CSVRender::InstanceMode::InstanceMode(
|
||||||
, mUnitScaleDist(1)
|
, mUnitScaleDist(1)
|
||||||
, mParentNode(std::move(parentNode))
|
, mParentNode(std::move(parentNode))
|
||||||
{
|
{
|
||||||
|
mSelectionGroups = dynamic_cast<CSMWorld::IdTable*>(
|
||||||
|
worldspaceWidget->getDocument().getData().getTableModel(CSMWorld::UniversalId::Type_SelectionGroup));
|
||||||
|
|
||||||
connect(this, &InstanceMode::requestFocus, worldspaceWidget, &WorldspaceWidget::requestFocus);
|
connect(this, &InstanceMode::requestFocus, worldspaceWidget, &WorldspaceWidget::requestFocus);
|
||||||
|
|
||||||
CSMPrefs::Shortcut* deleteShortcut = new CSMPrefs::Shortcut("scene-delete", worldspaceWidget);
|
CSMPrefs::Shortcut* deleteShortcut = new CSMPrefs::Shortcut("scene-delete", worldspaceWidget);
|
||||||
|
@ -229,6 +297,14 @@ CSVRender::InstanceMode::InstanceMode(
|
||||||
= new CSMPrefs::Shortcut("scene-instance-drop-terrain-separately", worldspaceWidget);
|
= new CSMPrefs::Shortcut("scene-instance-drop-terrain-separately", worldspaceWidget);
|
||||||
connect(dropToTerrainLevelShortcut2, qOverload<>(&CSMPrefs::Shortcut::activated), this,
|
connect(dropToTerrainLevelShortcut2, qOverload<>(&CSMPrefs::Shortcut::activated), this,
|
||||||
&InstanceMode::dropSelectedInstancesToTerrainSeparately);
|
&InstanceMode::dropSelectedInstancesToTerrainSeparately);
|
||||||
|
|
||||||
|
for (short i = 0; i <= 9; i++)
|
||||||
|
{
|
||||||
|
connect(new CSMPrefs::Shortcut("scene-group-" + std::to_string(i), worldspaceWidget),
|
||||||
|
qOverload<>(&CSMPrefs::Shortcut::activated), this, [this, i] { this->getSelectionGroup(i); });
|
||||||
|
connect(new CSMPrefs::Shortcut("scene-save-" + std::to_string(i), worldspaceWidget),
|
||||||
|
qOverload<>(&CSMPrefs::Shortcut::activated), this, [this, i] { this->saveSelectionGroup(i); });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::InstanceMode::activate(CSVWidget::SceneToolbar* toolbar)
|
void CSVRender::InstanceMode::activate(CSVWidget::SceneToolbar* toolbar)
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
#include "editmode.hpp"
|
#include "editmode.hpp"
|
||||||
#include "instancedragmodes.hpp"
|
#include "instancedragmodes.hpp"
|
||||||
|
#include <apps/opencs/model/world/idtable.hpp>
|
||||||
|
#include <components/esm3/selectiongroup.hpp>
|
||||||
|
|
||||||
class QDragEnterEvent;
|
class QDragEnterEvent;
|
||||||
class QDropEvent;
|
class QDropEvent;
|
||||||
|
@ -60,6 +62,7 @@ namespace CSVRender
|
||||||
osg::ref_ptr<osg::Group> mParentNode;
|
osg::ref_ptr<osg::Group> mParentNode;
|
||||||
osg::Vec3 mDragStart;
|
osg::Vec3 mDragStart;
|
||||||
std::vector<osg::Vec3> mObjectsAtDragStart;
|
std::vector<osg::Vec3> mObjectsAtDragStart;
|
||||||
|
CSMWorld::IdTable* mSelectionGroups;
|
||||||
|
|
||||||
int getSubModeFromId(const std::string& id) const;
|
int getSubModeFromId(const std::string& id) const;
|
||||||
|
|
||||||
|
@ -133,6 +136,8 @@ namespace CSVRender
|
||||||
void subModeChanged(const std::string& id);
|
void subModeChanged(const std::string& id);
|
||||||
void deleteSelectedInstances();
|
void deleteSelectedInstances();
|
||||||
void cloneSelectedInstances();
|
void cloneSelectedInstances();
|
||||||
|
void getSelectionGroup(const int group);
|
||||||
|
void saveSelectionGroup(const int group);
|
||||||
void dropSelectedInstancesToCollision();
|
void dropSelectedInstancesToCollision();
|
||||||
void dropSelectedInstancesToTerrain();
|
void dropSelectedInstancesToTerrain();
|
||||||
void dropSelectedInstancesToCollisionSeparately();
|
void dropSelectedInstancesToCollisionSeparately();
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace CSVRender
|
||||||
enum Mask : unsigned int
|
enum Mask : unsigned int
|
||||||
{
|
{
|
||||||
// elements that are part of the actual scene
|
// elements that are part of the actual scene
|
||||||
|
Mask_Hidden = 0x0,
|
||||||
Mask_Reference = 0x2,
|
Mask_Reference = 0x2,
|
||||||
Mask_Pathgrid = 0x4,
|
Mask_Pathgrid = 0x4,
|
||||||
Mask_Water = 0x8,
|
Mask_Water = 0x8,
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <osg/StateAttribute>
|
#include <osg/StateAttribute>
|
||||||
#include <osg/StateSet>
|
#include <osg/StateSet>
|
||||||
#include <osg/Vec3>
|
#include <osg/Vec3>
|
||||||
#include <osg/Vec4f>
|
|
||||||
|
|
||||||
#include <osgFX/Scribe>
|
#include <osgFX/Scribe>
|
||||||
|
|
||||||
|
@ -485,7 +484,7 @@ CSVRender::Object::~Object()
|
||||||
mParentNode->removeChild(mRootNode);
|
mParentNode->removeChild(mRootNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Object::setSelected(bool selected)
|
void CSVRender::Object::setSelected(bool selected, osg::Vec4f color)
|
||||||
{
|
{
|
||||||
mSelected = selected;
|
mSelected = selected;
|
||||||
|
|
||||||
|
@ -499,7 +498,7 @@ void CSVRender::Object::setSelected(bool selected)
|
||||||
mRootNode->removeChild(mBaseNode);
|
mRootNode->removeChild(mBaseNode);
|
||||||
if (selected)
|
if (selected)
|
||||||
{
|
{
|
||||||
mOutline->setWireframeColor(osg::Vec4f(1, 1, 1, 1));
|
mOutline->setWireframeColor(color);
|
||||||
mOutline->addChild(mBaseNode);
|
mOutline->addChild(mBaseNode);
|
||||||
mRootNode->addChild(mOutline);
|
mRootNode->addChild(mOutline);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
#include <osg/Vec4f>
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
#include <components/esm/defs.hpp>
|
#include <components/esm/defs.hpp>
|
||||||
|
@ -138,7 +139,7 @@ namespace CSVRender
|
||||||
~Object();
|
~Object();
|
||||||
|
|
||||||
/// Mark the object as selected, selected objects show an outline effect
|
/// Mark the object as selected, selected objects show an outline effect
|
||||||
void setSelected(bool selected);
|
void setSelected(bool selected, osg::Vec4f color = osg::Vec4f(1, 1, 1, 1));
|
||||||
|
|
||||||
bool getSelected() const;
|
bool getSelected() const;
|
||||||
|
|
||||||
|
|
|
@ -875,6 +875,18 @@ std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::PagedWorldspaceWidget::
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::selectGroup(std::vector<std::string> group) const
|
||||||
|
{
|
||||||
|
for (const auto& [_, cell] : mCells)
|
||||||
|
cell->selectFromGroup(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::unhideAll() const
|
||||||
|
{
|
||||||
|
for (const auto& [_, cell] : mCells)
|
||||||
|
cell->unhideAll();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::PagedWorldspaceWidget::getEdited(
|
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::PagedWorldspaceWidget::getEdited(
|
||||||
unsigned int elementMask) const
|
unsigned int elementMask) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -163,6 +163,10 @@ namespace CSVRender
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<TagBase>> getSelection(unsigned int elementMask) const override;
|
std::vector<osg::ref_ptr<TagBase>> getSelection(unsigned int elementMask) const override;
|
||||||
|
|
||||||
|
void selectGroup(const std::vector<std::string> group) const override;
|
||||||
|
|
||||||
|
void unhideAll() const override;
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<TagBase>> getEdited(unsigned int elementMask) const override;
|
std::vector<osg::ref_ptr<TagBase>> getEdited(unsigned int elementMask) const override;
|
||||||
|
|
||||||
void setSubMode(int subMode, unsigned int elementMask) override;
|
void setSubMode(int subMode, unsigned int elementMask) override;
|
||||||
|
|
|
@ -199,6 +199,16 @@ std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::UnpagedWorldspaceWidget
|
||||||
return mCell->getSelection(elementMask);
|
return mCell->getSelection(elementMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::selectGroup(const std::vector<std::string> group) const
|
||||||
|
{
|
||||||
|
mCell->selectFromGroup(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::UnpagedWorldspaceWidget::unhideAll() const
|
||||||
|
{
|
||||||
|
mCell->unhideAll();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::UnpagedWorldspaceWidget::getEdited(
|
std::vector<osg::ref_ptr<CSVRender::TagBase>> CSVRender::UnpagedWorldspaceWidget::getEdited(
|
||||||
unsigned int elementMask) const
|
unsigned int elementMask) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,6 +93,10 @@ namespace CSVRender
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<TagBase>> getSelection(unsigned int elementMask) const override;
|
std::vector<osg::ref_ptr<TagBase>> getSelection(unsigned int elementMask) const override;
|
||||||
|
|
||||||
|
void selectGroup(const std::vector<std::string> group) const override;
|
||||||
|
|
||||||
|
void unhideAll() const override;
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<TagBase>> getEdited(unsigned int elementMask) const override;
|
std::vector<osg::ref_ptr<TagBase>> getEdited(unsigned int elementMask) const override;
|
||||||
|
|
||||||
void setSubMode(int subMode, unsigned int elementMask) override;
|
void setSubMode(int subMode, unsigned int elementMask) override;
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
|
|
||||||
#include "cameracontroller.hpp"
|
#include "cameracontroller.hpp"
|
||||||
#include "instancemode.hpp"
|
#include "instancemode.hpp"
|
||||||
|
#include "mask.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "pathgridmode.hpp"
|
#include "pathgridmode.hpp"
|
||||||
|
|
||||||
|
@ -135,6 +136,15 @@ CSVRender::WorldspaceWidget::WorldspaceWidget(CSMDoc::Document& document, QWidge
|
||||||
CSMPrefs::Shortcut* abortShortcut = new CSMPrefs::Shortcut("scene-edit-abort", this);
|
CSMPrefs::Shortcut* abortShortcut = new CSMPrefs::Shortcut("scene-edit-abort", this);
|
||||||
connect(abortShortcut, qOverload<>(&CSMPrefs::Shortcut::activated), this, &WorldspaceWidget::abortDrag);
|
connect(abortShortcut, qOverload<>(&CSMPrefs::Shortcut::activated), this, &WorldspaceWidget::abortDrag);
|
||||||
|
|
||||||
|
connect(new CSMPrefs::Shortcut("scene-toggle-visibility", this), qOverload<>(&CSMPrefs::Shortcut::activated), this,
|
||||||
|
&WorldspaceWidget::toggleHiddenInstances);
|
||||||
|
|
||||||
|
connect(new CSMPrefs::Shortcut("scene-unhide-all", this), qOverload<>(&CSMPrefs::Shortcut::activated), this,
|
||||||
|
&WorldspaceWidget::unhideAll);
|
||||||
|
|
||||||
|
connect(new CSMPrefs::Shortcut("scene-clear-selection", this), qOverload<>(&CSMPrefs::Shortcut::activated), this,
|
||||||
|
[this] { this->clearSelection(Mask_Reference); });
|
||||||
|
|
||||||
mInConstructor = false;
|
mInConstructor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,6 +750,23 @@ void CSVRender::WorldspaceWidget::speedMode(bool activate)
|
||||||
mSpeedMode = activate;
|
mSpeedMode = activate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::WorldspaceWidget::toggleHiddenInstances()
|
||||||
|
{
|
||||||
|
const std::vector<osg::ref_ptr<TagBase>> selection = getSelection(Mask_Reference);
|
||||||
|
|
||||||
|
if (selection.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const CSVRender::ObjectTag* firstSelection = dynamic_cast<CSVRender::ObjectTag*>(selection.begin()->get());
|
||||||
|
|
||||||
|
const CSVRender::Mask firstMask
|
||||||
|
= firstSelection->mObject->getRootNode()->getNodeMask() == Mask_Hidden ? Mask_Reference : Mask_Hidden;
|
||||||
|
|
||||||
|
for (const auto& object : selection)
|
||||||
|
if (const auto objectTag = dynamic_cast<CSVRender::ObjectTag*>(object.get()))
|
||||||
|
objectTag->mObject->getRootNode()->setNodeMask(firstMask);
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::WorldspaceWidget::handleInteraction(InteractionType type, bool activate)
|
void CSVRender::WorldspaceWidget::handleInteraction(InteractionType type, bool activate)
|
||||||
{
|
{
|
||||||
if (activate)
|
if (activate)
|
||||||
|
|
|
@ -201,6 +201,10 @@ namespace CSVRender
|
||||||
|
|
||||||
virtual std::vector<osg::ref_ptr<TagBase>> getSelection(unsigned int elementMask) const = 0;
|
virtual std::vector<osg::ref_ptr<TagBase>> getSelection(unsigned int elementMask) const = 0;
|
||||||
|
|
||||||
|
virtual void selectGroup(const std::vector<std::string>) const = 0;
|
||||||
|
|
||||||
|
virtual void unhideAll() const = 0;
|
||||||
|
|
||||||
virtual std::vector<osg::ref_ptr<TagBase>> getEdited(unsigned int elementMask) const = 0;
|
virtual std::vector<osg::ref_ptr<TagBase>> getEdited(unsigned int elementMask) const = 0;
|
||||||
|
|
||||||
virtual void setSubMode(int subMode, unsigned int elementMask) = 0;
|
virtual void setSubMode(int subMode, unsigned int elementMask) = 0;
|
||||||
|
@ -300,6 +304,8 @@ namespace CSVRender
|
||||||
|
|
||||||
void speedMode(bool activate);
|
void speedMode(bool activate);
|
||||||
|
|
||||||
|
void toggleHiddenInstances();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
|
||||||
void elementSelectionChanged();
|
void elementSelectionChanged();
|
||||||
|
|
|
@ -166,7 +166,7 @@ add_component_dir (esm3
|
||||||
inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats
|
inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats
|
||||||
weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
||||||
aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache
|
aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache
|
||||||
infoorder timestamp formatversion landrecorddata
|
infoorder timestamp formatversion landrecorddata selectiongroup
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (esmterrain
|
add_component_dir (esmterrain
|
||||||
|
|
|
@ -170,6 +170,8 @@ namespace ESM
|
||||||
// format 1
|
// format 1
|
||||||
REC_FILT = esm3Recname("FILT"),
|
REC_FILT = esm3Recname("FILT"),
|
||||||
REC_DBGP = esm3Recname("DBGP"), ///< only used in project files
|
REC_DBGP = esm3Recname("DBGP"), ///< only used in project files
|
||||||
|
REC_SELG = esm3Recname("SELG"),
|
||||||
|
|
||||||
REC_LUAL = esm3Recname("LUAL"), // LuaScriptsCfg (only in omwgame or omwaddon)
|
REC_LUAL = esm3Recname("LUAL"), // LuaScriptsCfg (only in omwgame or omwaddon)
|
||||||
|
|
||||||
// format 16 - Lua scripts in saved games
|
// format 16 - Lua scripts in saved games
|
||||||
|
|
38
components/esm3/selectiongroup.cpp
Normal file
38
components/esm3/selectiongroup.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include "selectiongroup.hpp"
|
||||||
|
|
||||||
|
#include "esmreader.hpp"
|
||||||
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
void SelectionGroup::load(ESMReader& esm, bool& isDeleted)
|
||||||
|
{
|
||||||
|
|
||||||
|
while (esm.hasMoreSubs())
|
||||||
|
{
|
||||||
|
esm.getSubName();
|
||||||
|
switch (esm.retSubName().toInt())
|
||||||
|
{
|
||||||
|
case fourCC("SELC"):
|
||||||
|
mId = esm.getRefId();
|
||||||
|
break;
|
||||||
|
case fourCC("SELI"):
|
||||||
|
selectedInstances.push_back(esm.getRefId().getRefIdString());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
esm.fail("Unknown subrecord");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectionGroup::save(ESMWriter& esm, bool isDeleted) const
|
||||||
|
{
|
||||||
|
esm.writeHNCRefId("SELC", mId);
|
||||||
|
for (std::string id : selectedInstances)
|
||||||
|
esm.writeHNCString("SELI", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectionGroup::blank() {}
|
||||||
|
|
||||||
|
}
|
34
components/esm3/selectiongroup.hpp
Normal file
34
components/esm3/selectiongroup.hpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef COMPONENTS_ESM_SELECTIONGROUP_H
|
||||||
|
#define COMPONENTS_ESM_SELECTIONGROUP_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "components/esm/defs.hpp"
|
||||||
|
#include "components/esm/refid.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
|
||||||
|
struct SelectionGroup
|
||||||
|
{
|
||||||
|
constexpr static RecNameInts sRecordId = REC_SELG;
|
||||||
|
|
||||||
|
static constexpr std::string_view getRecordType() { return "SelectionGroup"; }
|
||||||
|
|
||||||
|
uint32_t mRecordFlags = 0;
|
||||||
|
|
||||||
|
RefId mId;
|
||||||
|
|
||||||
|
std::vector<std::string> selectedInstances;
|
||||||
|
|
||||||
|
void load(ESMReader& esm, bool& isDeleted);
|
||||||
|
void save(ESMWriter& esm, bool isDeleted = false) const;
|
||||||
|
|
||||||
|
/// Set record to default state (does not touch the ID).
|
||||||
|
void blank();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue