Autocomplete plugin filenames and Bash Tags in editor

Bash Tags are hardcoded in the game settings. They could be
sourced from the masterlist, but while that would be more
flexible, they don't change often and hardcoding them avoids
having to make a change to masterlist syntax.
This commit is contained in:
Oliver Hamlet
2016-07-06 20:35:39 +01:00
parent 65afed18e5
commit 5c5670d52f
10 changed files with 364 additions and 9 deletions
+2 -1
View File
@@ -33,6 +33,7 @@
"Jed": "SlexAxton/Jed#a9d03e1bbca9211a8b29a93a298a7ee9ddb353f0",
"jed-gettext-parser": "^1.0.0",
"marked": "^0.3.2",
"lodash": "^4.3.0"
"lodash": "^4.3.0",
"paper-autocomplete": "loot/paper-autocomplete#master"
}
}
+154
View File
@@ -54,6 +54,73 @@ namespace loot {
_masterFile = "Oblivion.esm";
_repositoryURL = "https://github.com/loot/oblivion.git";
_repositoryBranch = "v0.8";
bashTags = {
"Actors.ACBS",
"Actors.AIData",
"Actors.AIPackages",
"Actors.AIPackagesForceAdd",
"Actors.Animations",
"Actors.CombatStyle",
"Actors.DeathItem",
"Actors.Skeleton",
"Actors.Spells",
"Actors.SpellsForceAdd",
"Actors.Stats",
"Body-F",
"Body-M",
"Body-Size-F",
"Body-Size-M",
"C.Climate",
"C.Light",
"C.Music",
"C.Name",
"C.Owner",
"C.RecordFlags",
"C.Water",
"Creatures.Blood",
"Deactivate",
"Delev",
"Eyes",
"Factions",
"Filter",
"Graphics",
"Hair",
"IIM",
"Invent",
"InventOnly",
"Merge",
"MustBeActiveIfImported",
"Names",
"NoMerge",
"NpcFaces",
"NpcFacesForceFullImport",
"NPC.Class",
"Npc.EyesOnly",
"Npc.HairOnly",
"NPC.Race",
"Relations",
"Relev",
"Roads",
"R.AddSpells",
"R.Attributes-F",
"R.Attributes-M",
"R.ChangeSpells",
"R.Description",
"R.Ears",
"R.Head",
"R.Mouth",
"R.Relations",
"R.Skills",
"R.Teeth",
"ScriptContents",
"Scripts",
"Sound",
"SpellStats",
"Stats",
"Voice-F",
"Voice-M",
};
}
else if (Id() == GameSettings::tes5) {
_name = "TES V: Skyrim";
@@ -62,6 +129,78 @@ namespace loot {
_masterFile = "Skyrim.esm";
_repositoryURL = "https://github.com/loot/skyrim.git";
_repositoryBranch = "v0.8";
bashTags = {
"Actors.ACBS",
"Actors.AIData",
"Actors.AIPackages",
"Actors.AIPackagesForceAdd",
"Actors.Animations",
"Actors.CombatStyle",
"Actors.DeathItem",
"Actors.Skeleton",
"Actors.Spells",
"Actors.SpellsForceAdd",
"Actors.Stats",
"Body-F",
"Body-M",
"Body-Size-F",
"Body-Size-M",
"C.Acoustic",
"C.Climate",
"C.ImageSpace",
"C.Light",
"C.Location",
"C.Music",
"C.Name",
"C.Owner",
"C.RecordFlags",
"C.Regions",
"C.SkyLighting",
"C.Water",
"Creatures.Blood",
"Deactivate",
"Delev",
"Eyes",
"Factions",
"Filter",
"Graphics",
"Hair",
"IIM",
"Invent",
"InventOnly",
"Merge",
"MustBeActiveIfImported",
"Names",
"NoMerge",
"NpcFaces",
"NpcFacesForceFullImport",
"NPC.Class",
"Npc.EyesOnly",
"Npc.HairOnly",
"NPC.Race",
"Relations",
"Relev",
"Roads",
"R.AddSpells",
"R.Attributes-F",
"R.Attributes-M",
"R.ChangeSpells",
"R.Description",
"R.Ears",
"R.Head",
"R.Mouth",
"R.Relations",
"R.Skills",
"R.Teeth",
"ScriptContents",
"Scripts",
"Sound",
"SpellStats",
"Stats",
"Voice-F",
"Voice-M",
};
}
else if (Id() == GameSettings::fo3) {
_name = "Fallout 3";
@@ -70,6 +209,11 @@ namespace loot {
_masterFile = "Fallout3.esm";
_repositoryURL = "https://github.com/loot/fallout3.git";
_repositoryBranch = "v0.8";
bashTags = {
"Deflst",
"Destructible",
};
}
else if (Id() == GameSettings::fonv) {
_name = "Fallout: New Vegas";
@@ -78,6 +222,12 @@ namespace loot {
_masterFile = "FalloutNV.esm";
_repositoryURL = "https://github.com/loot/falloutnv.git";
_repositoryBranch = "v0.8";
bashTags = {
"Deflst",
"Destructible",
"WeaponMods",
};
}
else if (Id() == GameSettings::fo4) {
_name = "Fallout 4";
@@ -191,6 +341,10 @@ namespace loot {
return LootPaths::getLootDataPath() / _lootFolderName / "userlist.yaml";
}
std::vector<std::string> GameSettings::getSupportedBashTags() const {
return bashTags;
}
GameSettings& GameSettings::SetName(const std::string& name) {
BOOST_LOG_TRIVIAL(trace) << "Setting \"" << _name << "\" name to: " << name;
_name = name;
+4
View File
@@ -59,6 +59,8 @@ namespace loot {
boost::filesystem::path MasterlistPath() const;
boost::filesystem::path UserlistPath() const;
std::vector<std::string> getSupportedBashTags() const;
GameSettings& SetName(const std::string& name);
GameSettings& SetMaster(const std::string& masterFile);
GameSettings& SetRegistryKey(const std::string& registry);
@@ -84,6 +86,8 @@ namespace loot {
std::string _repositoryBranch;
boost::filesystem::path _gamePath; //Path to the game's folder.
std::vector<std::string> bashTags;
};
}
+2
View File
@@ -701,6 +701,8 @@ namespace loot {
// Now store global messages.
gameNode["globalMessages"] = GetGeneralMessages();
gameNode["bashTags"] = _lootState.CurrentGame().getSupportedBashTags();
// Now store plugin data.
for (const auto& plugin : installed) {
/* Each plugin has members while hold its raw masterlist and userlist data for
+6 -5
View File
@@ -2,6 +2,7 @@
<link rel="import" href="../../../../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../../../../bower_components/paper-autocomplete/paper-autocomplete.html">
<link rel="import" href="../../../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../../../../bower_components/paper-input/paper-input.html">
<link rel="import" href="../../../../bower_components/paper-input/paper-textarea.html">
@@ -12,7 +13,7 @@
<template id="fileRow">
<tr>
<td><paper-input error-message="A filename is required." class="name" required auto-validate no-label-float></paper-input></td>
<td><paper-autocomplete error-message="A filename is required." class="name" required auto-validate no-label-float></paper-autocomplete></td>
<td><paper-input class="display" no-label-float></paper-input></td>
<td><paper-input class="condition" no-label-float></paper-input></td>
<td>
@@ -55,7 +56,7 @@
<paper-item value="remove">Remove</paper-item>
</loot-dropdown-menu>
</td>
<td><paper-input error-message="A name is required." class="name" required auto-validate no-label-float></paper-input></td>
<td><paper-autocomplete error-message="A name is required." class="name" required auto-validate no-label-float></paper-autocomplete></td>
<td><paper-input class="condition" no-label-float></paper-input></td>
<td>
<span>
@@ -240,7 +241,7 @@
if (trash.length > 0 && (!writableOnly || !trash[0].disabled)) {
const rowData = {};
const inputs = rows[i].querySelectorAll('paper-input, paper-textarea, loot-dropdown-menu');
const inputs = rows[i].querySelectorAll('paper-autocomplete, paper-input, paper-textarea, loot-dropdown-menu');
for (let j = 0; j < inputs.length; ++j) {
rowData[inputs[j].className] = inputs[j].value;
}
@@ -264,7 +265,7 @@
trash.disabled = readOnly;
}
const inputs = row.querySelectorAll('paper-input, paper-textarea, loot-dropdown-menu');
const inputs = row.querySelectorAll('paper-autocomplete, paper-input, paper-textarea, loot-dropdown-menu');
for (let i = 0; i < inputs.length; ++i) {
if (classMask) {
for (let j = 0; j < classMask.length; ++j) {
@@ -337,7 +338,7 @@
},
validate() {
const inputs = this.querySelectorAll('paper-input, paper-textarea');
const inputs = this.querySelectorAll('paper-autocomplete, paper-input, paper-textarea');
for (let i = 0; i < inputs.length; ++i) {
if (!inputs[i].validate()) {
return false;
+8
View File
@@ -235,5 +235,13 @@
static onSearchChangeSelection(evt) {
document.getElementById('pluginCardList').scrollToIndex(evt.detail.selection);
}
static initialiseAutocompleteFilenames(filenames) {
getElementInTableRowTemplate('fileRow', 'name').setAttribute('source', JSON.stringify(filenames));
}
static initialiseAutocompleteBashTags(tags) {
getElementInTableRowTemplate('tagRow', 'name').setAttribute('source', JSON.stringify(tags));
}
};
}));
+1 -2
View File
@@ -59,8 +59,7 @@ function onChangeGame(evt) {
const gameInfo = JSON.parse(result, loot.Plugin.fromJson);
loot.game = new loot.Game(gameInfo, loot.l10n);
/* Re-initialise conflicts filter plugin list. */
loot.Filters.fillConflictsFilterList(loot.game.plugins);
loot.game.initialiseUI(loot.DOM, loot.Filters);
/* Now update virtual lists. */
if (loot.filters.areAnyFiltersActive()) {
+10
View File
@@ -15,6 +15,7 @@
this.globalMessages = obj.globalMessages || [];
this.masterlist = obj.masterlist || {};
this.plugins = obj.plugins || [];
this.bashTags = obj.bashTags || [];
this.oldLoadOrder = undefined;
@@ -330,6 +331,15 @@
});
}
initialiseUI(DOM, Filters) {
/* Re-initialise autocomplete suggestions. */
DOM.initialiseAutocompleteFilenames(this.getPluginNames());
DOM.initialiseAutocompleteBashTags(this.bashTags);
/* Re-initialise conflicts filter plugin list. */
Filters.fillConflictsFilterList(this.plugins);
}
static onPluginsChange(evt) {
if (!evt.detail.valuesAreTotals) {
evt.detail.totalMessageNo += parseInt(document.getElementById('totalMessageNo').textContent, 10);
+1 -1
View File
@@ -176,7 +176,7 @@
const game = JSON.parse(result, Plugin.fromJson);
appData.game = new Game(game, appData.l10n);
appData.Filters.fillConflictsFilterList(appData.game.plugins);
appData.game.initialiseUI(dom, appData.Filters);
appData.filters.load(appData.settings.filters);
/* Initialise the lists before checking if any filters need to be applied.
+176
View File
@@ -59,6 +59,8 @@ namespace loot {
EXPECT_EQ("", game.DataPath());
EXPECT_EQ("", game.MasterlistPath());
EXPECT_EQ("", game.UserlistPath());
EXPECT_TRUE(game.getSupportedBashTags().empty());
}
TEST_P(GameSettingsTest, idConstructorShouldInitialiseSettingsToDefaultsForThatGame) {
@@ -87,6 +89,180 @@ namespace loot {
EXPECT_EQ(LootPaths::getLootDataPath() / "folder" / "userlist.yaml", game.UserlistPath());
}
TEST_P(GameSettingsTest, idConstructorShouldSetCorrectBashTagsForTES4) {
game = GameSettings(GameSettings::tes4);
std::vector<std::string> expectedBashTags = {
"Actors.ACBS",
"Actors.AIData",
"Actors.AIPackages",
"Actors.AIPackagesForceAdd",
"Actors.Animations",
"Actors.CombatStyle",
"Actors.DeathItem",
"Actors.Skeleton",
"Actors.Spells",
"Actors.SpellsForceAdd",
"Actors.Stats",
"Body-F",
"Body-M",
"Body-Size-F",
"Body-Size-M",
"C.Climate",
"C.Light",
"C.Music",
"C.Name",
"C.Owner",
"C.RecordFlags",
"C.Water",
"Creatures.Blood",
"Deactivate",
"Delev",
"Eyes",
"Factions",
"Filter",
"Graphics",
"Hair",
"IIM",
"Invent",
"InventOnly",
"Merge",
"MustBeActiveIfImported",
"Names",
"NoMerge",
"NpcFaces",
"NpcFacesForceFullImport",
"NPC.Class",
"Npc.EyesOnly",
"Npc.HairOnly",
"NPC.Race",
"Relations",
"Relev",
"Roads",
"R.AddSpells",
"R.Attributes-F",
"R.Attributes-M",
"R.ChangeSpells",
"R.Description",
"R.Ears",
"R.Head",
"R.Mouth",
"R.Relations",
"R.Skills",
"R.Teeth",
"ScriptContents",
"Scripts",
"Sound",
"SpellStats",
"Stats",
"Voice-F",
"Voice-M",
};
EXPECT_EQ(expectedBashTags, game.getSupportedBashTags());
}
TEST_P(GameSettingsTest, idConstructorShouldSetCorrectBashTagsForTES5) {
game = GameSettings(GameSettings::tes5);
std::vector<std::string> expectedBashTags = {
"Actors.ACBS",
"Actors.AIData",
"Actors.AIPackages",
"Actors.AIPackagesForceAdd",
"Actors.Animations",
"Actors.CombatStyle",
"Actors.DeathItem",
"Actors.Skeleton",
"Actors.Spells",
"Actors.SpellsForceAdd",
"Actors.Stats",
"Body-F",
"Body-M",
"Body-Size-F",
"Body-Size-M",
"C.Acoustic",
"C.Climate",
"C.ImageSpace",
"C.Light",
"C.Location",
"C.Music",
"C.Name",
"C.Owner",
"C.RecordFlags",
"C.Regions",
"C.SkyLighting",
"C.Water",
"Creatures.Blood",
"Deactivate",
"Delev",
"Eyes",
"Factions",
"Filter",
"Graphics",
"Hair",
"IIM",
"Invent",
"InventOnly",
"Merge",
"MustBeActiveIfImported",
"Names",
"NoMerge",
"NpcFaces",
"NpcFacesForceFullImport",
"NPC.Class",
"Npc.EyesOnly",
"Npc.HairOnly",
"NPC.Race",
"Relations",
"Relev",
"Roads",
"R.AddSpells",
"R.Attributes-F",
"R.Attributes-M",
"R.ChangeSpells",
"R.Description",
"R.Ears",
"R.Head",
"R.Mouth",
"R.Relations",
"R.Skills",
"R.Teeth",
"ScriptContents",
"Scripts",
"Sound",
"SpellStats",
"Stats",
"Voice-F",
"Voice-M",
};
EXPECT_EQ(expectedBashTags, game.getSupportedBashTags());
}
TEST_P(GameSettingsTest, idConstructorShouldSetNoBashTagsForFO3) {
game = GameSettings(GameSettings::fo3);
std::vector<std::string> expectedBashTags = {
"Deflst",
"Destructible",
};
EXPECT_EQ(expectedBashTags, game.getSupportedBashTags());
}
TEST_P(GameSettingsTest, idConstructorShouldSetNoBashTagsForFONV) {
game = GameSettings(GameSettings::fonv);
std::vector<std::string> expectedBashTags = {
"Deflst",
"Destructible",
"WeaponMods",
};
EXPECT_EQ(expectedBashTags, game.getSupportedBashTags());
}
TEST_P(GameSettingsTest, idConstructorShouldSetNoBashTagsForFO4) {
EXPECT_TRUE(GameSettings(GameSettings::fo4).getSupportedBashTags().empty());
}
TEST_P(GameSettingsTest, isInstalledShouldBeFalseIfGamePathIsNotSet) {
GameSettings game;
EXPECT_FALSE(game.IsInstalled());