diff --git a/Source/Data/AchievementSet.cs b/Source/Data/AchievementSet.cs
index 721ce46a..4c699d48 100644
--- a/Source/Data/AchievementSet.cs
+++ b/Source/Data/AchievementSet.cs
@@ -9,5 +9,10 @@ public class AchievementSet : AssetBase
/// Gets or sets the type classification of the achievement set.
///
public AchievementSetType Type { get; set; }
+
+ ///
+ /// Gets the name of the badge for the achievement set.
+ ///
+ public string BadgeName { get; set; }
}
}
diff --git a/Source/Data/Leaderboard.cs b/Source/Data/Leaderboard.cs
index 11544a64..caa26180 100644
--- a/Source/Data/Leaderboard.cs
+++ b/Source/Data/Leaderboard.cs
@@ -241,7 +241,12 @@ public enum ValueFormat
Value,
///
- /// Generic value followed by "Points" - %06d Points
+ /// Generic unsigned value - %01u
+ ///
+ Unsigned,
+
+ ///
+ /// Generic value padded with 0s to 6 digits - %06d Points
///
Score,
diff --git a/Source/Parser/PublishedAssets.cs b/Source/Parser/PublishedAssets.cs
index b97d5d6a..3229f363 100644
--- a/Source/Parser/PublishedAssets.cs
+++ b/Source/Parser/PublishedAssets.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Linq;
namespace RATools.Parser
@@ -129,6 +130,7 @@ private void Read()
OwnerGameId = GameId,
Title = Title,
Type = AchievementSetType.Core,
+ BadgeName = ExtractBadgeName(publishedData.GetField("ImageIconUrl").StringValue),
});
var publishedAchievements = publishedData.GetField("Achievements");
@@ -168,6 +170,16 @@ private static AchievementSetType ConvertType(string type)
}
}
+ private static string ExtractBadgeName(string url)
+ {
+ if (url == null)
+ return null;
+
+ var index = url.LastIndexOf('/');
+ var filename = url.Substring(index + 1);
+ return Path.GetFileNameWithoutExtension(filename);
+ }
+
private void ReadSets(JsonField sets)
{
foreach (var set in sets.ObjectArrayValue)
@@ -182,6 +194,7 @@ private void ReadSets(JsonField sets)
OwnerGameId = gameId,
Title = set.GetField("Title").StringValue ?? Title,
Type = ConvertType(set.GetField("Type").StringValue),
+ BadgeName = ExtractBadgeName(set.GetField("ImageIconUrl").StringValue),
});
var publishedAchievements = set.GetField("Achievements");
diff --git a/Source/ViewModels/AchievementViewModel.cs b/Source/ViewModels/AchievementViewModel.cs
index 27aa4b1b..950056c1 100644
--- a/Source/ViewModels/AchievementViewModel.cs
+++ b/Source/ViewModels/AchievementViewModel.cs
@@ -184,5 +184,13 @@ private static string GetMeasuredTarget(IEnumerable requirements)
return null;
}
+
+ public bool BelongsToSet(AchievementSet achievementSet)
+ {
+ if (OwnerSetId == 0)
+ return (achievementSet == null || achievementSet.Type == AchievementSetType.Core);
+
+ return (achievementSet == null || achievementSet.Id == OwnerSetId);
+ }
}
}
diff --git a/Source/ViewModels/AchievementsListViewModel.cs b/Source/ViewModels/AchievementsListViewModel.cs
new file mode 100644
index 00000000..6a30675a
--- /dev/null
+++ b/Source/ViewModels/AchievementsListViewModel.cs
@@ -0,0 +1,183 @@
+using Jamiras.Commands;
+using Jamiras.DataModels;
+using Jamiras.ViewModels;
+using RATools.Data;
+using RATools.ViewModels.Navigation;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace RATools.ViewModels
+{
+ public class AchievementsListViewModel : ViewerViewModelBase
+ {
+ public AchievementsListViewModel(GameViewModel owner, AchievementSet achievementSet, IEnumerable navigationNodes)
+ : base(owner)
+ {
+ AchievementViewModel[] achievements;
+
+ if (navigationNodes != null)
+ {
+ achievements = navigationNodes.OfType()
+ .Select(vm => vm.Editor as AchievementViewModel).ToArray();
+ }
+ else
+ {
+ achievements = owner.Editors.OfType()
+ .Where(a => a.BelongsToSet(achievementSet)).ToArray();
+ }
+
+ Achievements = achievements;
+
+ Title = achievementSet.Title;
+ CountAchievements(achievements);
+ _badgeName = achievementSet?.BadgeName ?? owner.BadgeName;
+
+ _id = (achievementSet != null) ? achievementSet.Id : 0;
+
+ ExportCommand = new DelegateCommand(Export);
+ }
+
+ private readonly int _id;
+
+ private void CountAchievements(AchievementViewModel[] achievements)
+ {
+ var description = new StringBuilder();
+ description.AppendFormat("{0} achievements", achievements.Length);
+ var initialDescriptionLength = description.Length;
+ description.Append(" (");
+
+ var points = new StringBuilder();
+ points.AppendFormat("{0} points", achievements.Sum(a => a.Points));
+ var initialPointsLength = points.Length;
+ points.Append(" (");
+
+ var published = achievements.Where(a => !a.Published?.Asset?.IsUnofficial ?? false);
+ if (published.Any())
+ {
+ description.AppendFormat("{0} published, ", published.Count());
+ points.AppendFormat("{0} published, ", published.Sum(a => a.Points));
+ }
+
+ var unpublished = achievements.Where(a => a.Published?.Asset?.IsUnofficial ?? false);
+ if (unpublished.Any())
+ {
+ description.AppendFormat("{0} unpublished, ", unpublished.Count());
+ points.AppendFormat("{0} unpublished, ", unpublished.Sum(a => a.Points));
+ }
+
+ var local = achievements.Where(a => a.Published?.Asset == null);
+ if (local.Any())
+ {
+ description.AppendFormat("{0} local, ", local.Count());
+ points.AppendFormat("{0} local, ", local.Sum(a => a.Points));
+ }
+
+ description.Length -= 2;
+ description.Append(')');
+
+ points.Length -= 2;
+ points.Append(')');
+
+ bool hasComma = false;
+ for (int i = initialDescriptionLength; i < description.Length; i++)
+ {
+ if (description[i] == ',')
+ {
+ hasComma = true;
+ break;
+ }
+ }
+ if (!hasComma)
+ {
+ description.Length = initialDescriptionLength;
+ points.Length = initialPointsLength;
+ }
+
+ Description = description.ToString();
+ PointsSummary = points.ToString();
+ }
+
+ private readonly string _badgeName;
+
+ public override string ViewerType => "AchievementList";
+
+ public override int ViewerId { get { return _id; } }
+
+ public static readonly ModelProperty BadgeProperty = ModelProperty.RegisterDependant(typeof(AchievementsListViewModel), "Badge", typeof(ImageSource), new ModelProperty[0], GetBadge);
+ public ImageSource Badge
+ {
+ get { return (ImageSource)GetValue(BadgeProperty); }
+ }
+
+ private static ImageSource GetBadge(ModelBase model)
+ {
+ var vm = (AchievementsListViewModel)model;
+ if (!String.IsNullOrEmpty(vm._badgeName) && vm._badgeName != "0")
+ {
+ if (String.IsNullOrEmpty(vm._owner.RACacheDirectory))
+ return null;
+
+ var name = "i" + vm._badgeName;
+ if (Path.GetExtension(name) == "")
+ name += ".png";
+ var path = Path.Combine(Path.Combine(vm._owner.RACacheDirectory, "..\\Badge"), name);
+ if (File.Exists(path))
+ {
+ var image = new BitmapImage(new Uri(path));
+ image.Freeze();
+ return image;
+ }
+ }
+
+ return null;
+ }
+
+ public static readonly ModelProperty PointsSummaryProperty = ModelProperty.Register(typeof(AchievementsListViewModel), "PointsSummary", typeof(string), String.Empty);
+ public string PointsSummary
+ {
+ get { return (string)GetValue(PointsSummaryProperty); }
+ protected set { SetValue(PointsSummaryProperty, value); }
+ }
+
+ ///
+ /// Gets the list of achievements.
+ ///
+ public IEnumerable Achievements { get; private set; }
+
+ public int Points { get { return Achievements.Sum(a => a.Points); } }
+
+ public CommandBase ExportCommand { get; private set; }
+
+ private void Export()
+ {
+ var filename = Path.GetFileNameWithoutExtension(_owner.Script.Filename) ?? "achievements";
+
+ var vm = new FileDialogViewModel();
+ vm.DialogTitle = "Export achievement information";
+ vm.Filters["CSV file"] = "*.csv";
+ vm.FileNames = new[] { filename + ".csv" };
+ vm.OverwritePrompt = true;
+
+ if (vm.ShowSaveFileDialog() == DialogResult.Ok)
+ {
+ using (var file = File.CreateText(vm.FileNames[0]))
+ {
+ file.WriteLine("Id,Title,Description,Points");
+
+ foreach (var achievement in Achievements)
+ {
+ file.Write("{0},\"{1}\",", achievement.Id, achievement.Title.Replace("\"", "\\\""));
+ file.Write("\"{0}\",", achievement.Description.Replace("\"", "\\\""));
+ file.Write("{0}", achievement.Points);
+ file.WriteLine();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Source/ViewModels/AssetViewModelBase.cs b/Source/ViewModels/AssetViewModelBase.cs
index 03401d77..115eb65d 100644
--- a/Source/ViewModels/AssetViewModelBase.cs
+++ b/Source/ViewModels/AssetViewModelBase.cs
@@ -36,6 +36,8 @@ public AssetViewModelBase(GameViewModel owner)
}
}
+ public override int ViewerId { get { return this.Id; } }
+
///
/// The asset generated by the script.
///
diff --git a/Source/ViewModels/GameViewModel.cs b/Source/ViewModels/GameViewModel.cs
index 86eb3518..d8dba841 100644
--- a/Source/ViewModels/GameViewModel.cs
+++ b/Source/ViewModels/GameViewModel.cs
@@ -134,20 +134,7 @@ public void NavigateBack()
private void NavigateTo(NavigationItem item)
{
- ViewerViewModelBase editor = null;
- foreach (var scan in Editors)
- {
- if (scan.ViewerType != item.EditorType)
- continue;
-
- var assetEditor = scan as AssetViewModelBase;
- if (assetEditor != null && assetEditor.Id != item.EditorId)
- continue;
-
- editor = scan;
- break;
- }
-
+ ViewerViewModelBase editor = FindEditor(NavigationNodes, item);
if (editor == null)
return;
@@ -199,10 +186,7 @@ public void CaptureNavigationLocation()
private static NavigationItem CaptureNavigationItem(ViewerViewModelBase editor)
{
- var item = new NavigationItem { EditorType = editor.ViewerType };
- var assetEditor = editor as AssetViewModelBase;
- if (assetEditor != null)
- item.EditorId = assetEditor.Id;
+ var item = new NavigationItem { EditorType = editor.ViewerType, EditorId = editor.ViewerId };
var scriptEditor = editor as ScriptViewModel;
if (scriptEditor != null)
@@ -211,6 +195,28 @@ private static NavigationItem CaptureNavigationItem(ViewerViewModelBase editor)
return item;
}
+ private static ViewerViewModelBase FindEditor(IEnumerable nodes, NavigationItem item)
+ {
+ foreach (var node in nodes.OfType())
+ {
+ var editor = node.Editor;
+ if (editor.ViewerType == item.EditorType && editor.ViewerId == item.EditorId)
+ return editor;
+ }
+
+ foreach (var node in nodes)
+ {
+ if (node.Children != null && node.Children.Count > 0)
+ {
+ var child = FindEditor(node.Children, item);
+ if (child != null)
+ return child;
+ }
+ }
+
+ return null;
+ }
+
internal void PopulateEditorList(AchievementScriptInterpreter interpreter)
{
if (interpreter != null)
@@ -227,9 +233,48 @@ internal void PopulateEditorList(AchievementScriptInterpreter interpreter)
var navigation = new NavigationListViewModel(this, _publishedAssets, _localAssets, _editors);
NavigationNodes = navigation.Merge(interpreter);
- SelectedNavigationNode = FindEditorNavigationNode(NavigationNodes, SelectedEditor);
+ UpdateSelectedNavigationNode(SelectedNavigationNode);
}
+ internal void UpdateSelectedNavigationNode(NavigationViewModelBase searchNode)
+ {
+ var newNode = searchNode != null
+ ? FindNavigationNode(NavigationNodes, searchNode)
+ : FindEditorNavigationNode(NavigationNodes, Script);
+ if (!ReferenceEquals(searchNode, newNode))
+ {
+ SelectedNavigationNode = newNode;
+
+ if (newNode != null)
+ newNode.IsSelected = true;
+
+ if (searchNode != null)
+ searchNode.IsSelected = false;
+ }
+ }
+
+ internal static NavigationViewModelBase FindNavigationNode(IEnumerable nodes, NavigationViewModelBase searchNode)
+ {
+ foreach (var node in nodes)
+ {
+ if (node == searchNode)
+ return node;
+ }
+
+ foreach (var node in nodes)
+ {
+ if (node.Children != null && node.Children.Count > 0)
+ {
+ var child = FindNavigationNode(node.Children, searchNode);
+ if (child != null)
+ return child;
+ }
+ }
+
+ return null;
+ }
+
+
public int CompileProgress { get; internal set; }
public int CompileProgressLine { get; internal set; }
@@ -264,7 +309,7 @@ public NavigationViewModelBase SelectedNavigationNode
private static void OnSelectedNavigationNodeChanged(object sender, ModelPropertyChangedEventArgs e)
{
- var editorNavigationViewModel = e.NewValue as EditorNavigationViewModelBase;
+ var editorNavigationViewModel = e.NewValue as IEditorNavigationViewModel;
if (editorNavigationViewModel != null)
((GameViewModel)sender).SelectedEditor = editorNavigationViewModel.Editor;
}
@@ -307,10 +352,10 @@ private static void OnSelectedEditorChanged(object sender, ModelPropertyChangedE
private static NavigationViewModelBase FindEditorNavigationNode(IEnumerable nodes, ViewerViewModelBase editor)
{
- foreach (var node in nodes.OfType())
+ foreach (var node in nodes.OfType())
{
if (ReferenceEquals(node.Editor, editor))
- return node;
+ return (NavigationViewModelBase)node;
}
foreach (var node in nodes)
@@ -522,13 +567,20 @@ private void HandleLocalAssetChange(AssetBase asset, LocalAssets.LocalAssetChang
}
}
- public static readonly ModelProperty TitleProperty = ModelProperty.Register(typeof(MainWindowViewModel), "Title", typeof(string), String.Empty);
+ public static readonly ModelProperty TitleProperty = ModelProperty.Register(typeof(GameViewModel), "Title", typeof(string), String.Empty);
public string Title
{
get { return (string)GetValue(TitleProperty); }
private set { SetValue(TitleProperty, value); }
}
+ public static readonly ModelProperty BadgeNameProperty = ModelProperty.Register(typeof(GameViewModel), "BadgeName", typeof(string), String.Empty);
+ public string BadgeName
+ {
+ get { return (string)GetValue(BadgeNameProperty); }
+ set { SetValue(BadgeNameProperty, value); }
+ }
+
public IEnumerable PublishedSets
{
get
@@ -537,49 +589,49 @@ public IEnumerable PublishedSets
}
}
- public static readonly ModelProperty GeneratedAchievementCountProperty = ModelProperty.Register(typeof(MainWindowViewModel), "GeneratedAchievementCount", typeof(int), 0);
+ public static readonly ModelProperty GeneratedAchievementCountProperty = ModelProperty.Register(typeof(GameViewModel), "GeneratedAchievementCount", typeof(int), 0);
public int GeneratedAchievementCount
{
get { return (int)GetValue(GeneratedAchievementCountProperty); }
private set { SetValue(GeneratedAchievementCountProperty, value); }
}
- public static readonly ModelProperty CoreAchievementCountProperty = ModelProperty.Register(typeof(MainWindowViewModel), "CoreAchievementCount", typeof(int), 0);
+ public static readonly ModelProperty CoreAchievementCountProperty = ModelProperty.Register(typeof(GameViewModel), "CoreAchievementCount", typeof(int), 0);
public int CoreAchievementCount
{
get { return (int)GetValue(CoreAchievementCountProperty); }
private set { SetValue(CoreAchievementCountProperty, value); }
}
- public static readonly ModelProperty CoreAchievementPointsProperty = ModelProperty.Register(typeof(MainWindowViewModel), "CoreAchievementPoints", typeof(int), 0);
+ public static readonly ModelProperty CoreAchievementPointsProperty = ModelProperty.Register(typeof(GameViewModel), "CoreAchievementPoints", typeof(int), 0);
public int CoreAchievementPoints
{
get { return (int)GetValue(CoreAchievementPointsProperty); }
private set { SetValue(CoreAchievementPointsProperty, value); }
}
- public static readonly ModelProperty UnofficialAchievementCountProperty = ModelProperty.Register(typeof(MainWindowViewModel), "UnofficialAchievementCount", typeof(int), 0);
+ public static readonly ModelProperty UnofficialAchievementCountProperty = ModelProperty.Register(typeof(GameViewModel), "UnofficialAchievementCount", typeof(int), 0);
public int UnofficialAchievementCount
{
get { return (int)GetValue(UnofficialAchievementCountProperty); }
private set { SetValue(UnofficialAchievementCountProperty, value); }
}
- public static readonly ModelProperty UnofficialAchievementPointsProperty = ModelProperty.Register(typeof(MainWindowViewModel), "UnofficialAchievementPoints", typeof(int), 0);
+ public static readonly ModelProperty UnofficialAchievementPointsProperty = ModelProperty.Register(typeof(GameViewModel), "UnofficialAchievementPoints", typeof(int), 0);
public int UnofficialAchievementPoints
{
get { return (int)GetValue(UnofficialAchievementPointsProperty); }
private set { SetValue(UnofficialAchievementPointsProperty, value); }
}
- public static readonly ModelProperty LocalAchievementCountProperty = ModelProperty.Register(typeof(MainWindowViewModel), "LocalAchievementCount", typeof(int), 0);
+ public static readonly ModelProperty LocalAchievementCountProperty = ModelProperty.Register(typeof(GameViewModel), "LocalAchievementCount", typeof(int), 0);
public int LocalAchievementCount
{
get { return (int)GetValue(LocalAchievementCountProperty); }
private set { SetValue(LocalAchievementCountProperty, value); }
}
- public static readonly ModelProperty LocalAchievementPointsProperty = ModelProperty.Register(typeof(MainWindowViewModel), "LocalAchievementPoints", typeof(int), 0);
+ public static readonly ModelProperty LocalAchievementPointsProperty = ModelProperty.Register(typeof(GameViewModel), "LocalAchievementPoints", typeof(int), 0);
public int LocalAchievementPoints
{
get { return (int)GetValue(LocalAchievementPointsProperty); }
diff --git a/Source/ViewModels/MainWindowViewModel.cs b/Source/ViewModels/MainWindowViewModel.cs
index deb00b03..7ff3143b 100644
--- a/Source/ViewModels/MainWindowViewModel.cs
+++ b/Source/ViewModels/MainWindowViewModel.cs
@@ -4,12 +4,14 @@
using Jamiras.Services;
using Jamiras.ViewModels;
using RATools.Services;
+using RATools.ViewModels.Navigation;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
+using System.Xml.Linq;
namespace RATools.ViewModels
{
@@ -28,7 +30,6 @@ public MainWindowViewModel()
DragDropScriptCommand = new DelegateCommand(DragDropFile, CanDragDropFile);
UpdateLocalCommand = DisabledCommand.Instance;
- ViewAchievementsCommand = DisabledCommand.Instance;
GameBadgesCommand = new DelegateCommand(GameBadges);
GameStatsCommand = new DelegateCommand(GameStats);
@@ -154,12 +155,10 @@ private static void OnGameChanged(object sender, ModelPropertyChangedEventArgs e
vm.SaveScriptAsCommand = new DelegateCommand(() => vm.SaveScriptAs());
vm.RefreshScriptCommand = new DelegateCommand(vm.RefreshScript);
vm.UpdateLocalCommand = new DelegateCommand(vm.UpdateLocal);
- vm.ViewAchievementsCommand = new DelegateCommand(vm.ViewAchievements);
vm.OnPropertyChanged(() => vm.SaveScriptCommand);
vm.OnPropertyChanged(() => vm.SaveScriptAsCommand);
vm.OnPropertyChanged(() => vm.RefreshScriptCommand);
vm.OnPropertyChanged(() => vm.UpdateLocalCommand);
- vm.OnPropertyChanged(() => vm.ViewAchievementsCommand);
}
}
@@ -214,7 +213,7 @@ private void OpenFile(string filename)
int line = 1;
int column = 1;
- string selectedEditor = null;
+ NavigationViewModelBase selectedNavigationNode = null;
if (Game != null && Game.Script.Filename == filename)
{
if (Game.Script.CompareState == GeneratedCompareState.LocalDiffers)
@@ -226,8 +225,7 @@ private void OpenFile(string filename)
// capture current location so we can restore it after refreshing
line = Game.Script.Editor.CursorLine;
column = Game.Script.Editor.CursorColumn;
- if (Game.SelectedEditor != null)
- selectedEditor = Game.SelectedEditor.Title;
+ selectedNavigationNode = Game.SelectedNavigationNode;
}
else if (!CloseEditor())
{
@@ -359,7 +357,7 @@ private void OpenFile(string filename)
existingViewModel.Script.SetContent(content);
viewModel = existingViewModel;
- existingViewModel.SelectedEditor = existingViewModel.Editors.FirstOrDefault(e => e.Title == selectedEditor);
+ existingViewModel.UpdateSelectedNavigationNode(selectedNavigationNode);
existingViewModel.Script.Editor.MoveCursorTo(line, column, Jamiras.ViewModels.CodeEditor.CodeEditorViewModel.MoveCursorFlags.None);
}
else
@@ -483,20 +481,6 @@ private void UpdateLocal()
dialog.ShowDialog();
}
- public CommandBase ViewAchievementsCommand { get; private set; }
- private void ViewAchievements()
- {
- var game = Game;
- if (game == null)
- {
- TaskDialogViewModel.ShowErrorMessage("No game loaded", "Cannot view achievements if game not loaded.");
- return;
- }
-
- var dialog = new ViewAchievementsViewModel(game);
- dialog.ShowDialog();
- }
-
public static readonly ModelProperty ShowHexValuesProperty = ModelProperty.Register(typeof(MainWindowViewModel), "ShowHexValues", typeof(bool), false, OnShowHexValuesChanged);
public bool ShowHexValues
{
diff --git a/Source/ViewModels/Navigation/AchievementSetFolderNavigationViewModel.cs b/Source/ViewModels/Navigation/AchievementSetFolderNavigationViewModel.cs
index 7d0144a1..7ce16830 100644
--- a/Source/ViewModels/Navigation/AchievementSetFolderNavigationViewModel.cs
+++ b/Source/ViewModels/Navigation/AchievementSetFolderNavigationViewModel.cs
@@ -11,5 +11,16 @@ public AchievementSetFolderNavigationViewModel(AchievementSet achievementSet)
}
public AchievementSet AchievementSet { get; private set; }
+
+ public override bool Equals(object obj)
+ {
+ var that = obj as AchievementSetFolderNavigationViewModel;
+ return (that != null && this.AchievementSet.Id == that.AchievementSet.Id);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
}
}
diff --git a/Source/ViewModels/Navigation/AchievementsFolderNavigationViewModel.cs b/Source/ViewModels/Navigation/AchievementsFolderNavigationViewModel.cs
new file mode 100644
index 00000000..763b2a50
--- /dev/null
+++ b/Source/ViewModels/Navigation/AchievementsFolderNavigationViewModel.cs
@@ -0,0 +1,28 @@
+using RATools.Data;
+using System.Linq;
+
+namespace RATools.ViewModels.Navigation
+{
+ internal class AchievementsFolderNavigationViewModel : AssetFolderNavigationViewModel, IEditorNavigationViewModel
+ {
+ public AchievementsFolderNavigationViewModel(GameViewModel game, AchievementSet achievementSet)
+ : base("Achievements")
+ {
+ _game = game;
+ _achievementSet = achievementSet;
+ }
+
+ private readonly GameViewModel _game;
+ private readonly AchievementSet _achievementSet;
+ private AchievementsListViewModel _editor;
+
+ public ViewerViewModelBase Editor
+ {
+ get
+ {
+ _editor ??= new AchievementsListViewModel(_game, _achievementSet, Children.OfType());
+ return _editor;
+ }
+ }
+ }
+}
diff --git a/Source/ViewModels/Navigation/EditorNavigationViewModelBase.cs b/Source/ViewModels/Navigation/EditorNavigationViewModelBase.cs
index 6310df6f..1faf10f1 100644
--- a/Source/ViewModels/Navigation/EditorNavigationViewModelBase.cs
+++ b/Source/ViewModels/Navigation/EditorNavigationViewModelBase.cs
@@ -7,7 +7,7 @@
namespace RATools.ViewModels.Navigation
{
- public abstract class EditorNavigationViewModelBase : NavigationViewModelBase
+ public abstract class EditorNavigationViewModelBase : NavigationViewModelBase, IEditorNavigationViewModel
{
public EditorNavigationViewModelBase()
{
@@ -125,5 +125,28 @@ public bool IsNodeFor(AssetViewModelBase editor)
return false;
}
+ public override bool Equals(object obj)
+ {
+ var that = obj as EditorNavigationViewModelBase;
+ if (that == null || this.Editor?.ViewerType != that.Editor?.ViewerType)
+ return false;
+
+ var assetEditorViewModel = this.Editor as AssetViewModelBase;
+ if (assetEditorViewModel != null)
+ return assetEditorViewModel.Id == ((AssetViewModelBase)that.Editor).Id;
+
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+
+ public interface IEditorNavigationViewModel
+ {
+ public ViewerViewModelBase Editor { get; }
}
+
}
diff --git a/Source/ViewModels/Navigation/NavigationListViewModel.cs b/Source/ViewModels/Navigation/NavigationListViewModel.cs
index 014f2b19..1ee060a6 100644
--- a/Source/ViewModels/Navigation/NavigationListViewModel.cs
+++ b/Source/ViewModels/Navigation/NavigationListViewModel.cs
@@ -363,7 +363,7 @@ private void UpdateNavigationNodes(IEnumerable navigati
bool hasSubsets = false;
foreach (var achievementSetNode in navigationNodes.OfType())
{
- var achievementsFolder = achievementSetNode.Children.OfType().First(n => n.Label == "Achievements");
+ var achievementsFolder = achievementSetNode.Children.OfType().First();
var leaderboardsFolder = achievementSetNode.Children.OfType().First(n => n.Label == "Leaderboards");
UpdateAchievementSetNodes(achievementsFolder, leaderboardsFolder, achievementSetNode.AchievementSet);
hasSubsets = true;
@@ -371,7 +371,7 @@ private void UpdateNavigationNodes(IEnumerable navigati
if (!hasSubsets)
{
- var achievementsFolder = navigationNodes.OfType().First(n => n.Label == "Achievements");
+ var achievementsFolder = navigationNodes.OfType().First();
var leaderboardsFolder = navigationNodes.OfType().First(n => n.Label == "Leaderboards");
UpdateAchievementSetNodes(achievementsFolder, leaderboardsFolder, null);
}
@@ -382,11 +382,8 @@ private void UpdateAchievementSetNodes(AssetFolderNavigationViewModel achievemen
var achievementNodes = achievementsFolder.Children.OfType().ToList();
foreach (var achievement in _editors.OfType())
{
- if (achievementSet != null && achievement.OwnerSetId != achievementSet.Id)
- {
- if (achievement.OwnerSetId != 0 || achievementSet.Type != AchievementSetType.Core)
- continue;
- }
+ if (!achievement.BelongsToSet(achievementSet))
+ continue;
if (achievement.Generated.Asset == null && achievement.Local.Asset == null && achievement.Published.Asset == null)
{
@@ -513,7 +510,7 @@ public IEnumerable Merge(AchievementScriptInterpreter i
if (sets.Count < 2)
{
- newNavigationNodes.Add(new AssetFolderNavigationViewModel("Achievements"));
+ newNavigationNodes.Add(new AchievementsFolderNavigationViewModel(_gameViewModel, sets[0]));
newNavigationNodes.Add(new AssetFolderNavigationViewModel("Leaderboards"));
}
else
@@ -521,7 +518,7 @@ public IEnumerable Merge(AchievementScriptInterpreter i
foreach (var achievementSet in sets)
{
var setFolderNode = new AchievementSetFolderNavigationViewModel(achievementSet);
- setFolderNode.AddChild(new AssetFolderNavigationViewModel("Achievements"));
+ setFolderNode.AddChild(new AchievementsFolderNavigationViewModel(_gameViewModel, achievementSet));
setFolderNode.AddChild(new AssetFolderNavigationViewModel("Leaderboards"));
newNavigationNodes.Add(setFolderNode);
}
@@ -539,11 +536,13 @@ public IEnumerable Merge(AchievementScriptInterpreter i
MergePublished();
}
- if (_localAssets != null)
- MergeLocal();
-
if (interpreter != null)
+ {
+ if (_localAssets != null)
+ MergeLocal();
+
MergeGenerated(interpreter);
+ }
UpdateTemporaryIds();
diff --git a/Source/ViewModels/Navigation/NavigationViewModelBase.cs b/Source/ViewModels/Navigation/NavigationViewModelBase.cs
index 9ca2d11b..e332ba64 100644
--- a/Source/ViewModels/Navigation/NavigationViewModelBase.cs
+++ b/Source/ViewModels/Navigation/NavigationViewModelBase.cs
@@ -96,6 +96,13 @@ internal void UpdateCompareState()
CompareState = compareState;
}
+ public static readonly ModelProperty IsSelectedProperty = ModelProperty.Register(typeof(NavigationViewModelBase), "IsSelected", typeof(bool), false);
+ public bool IsSelected
+ {
+ get { return (bool)GetValue(IsSelectedProperty); }
+ set { SetValue(IsSelectedProperty, value); }
+ }
+
public static readonly ModelProperty IsExpandedProperty = ModelProperty.Register(typeof(NavigationViewModelBase), "IsExpanded", typeof(bool), true);
public bool IsExpanded
{
@@ -122,5 +129,37 @@ public void AddChild(NavigationViewModelBase child)
}
public IEnumerable ContextMenu { get; protected set; }
+
+ public static bool operator ==(NavigationViewModelBase left, NavigationViewModelBase right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+ if (left is null || right is null)
+ return false;
+
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(NavigationViewModelBase left, NavigationViewModelBase right)
+ {
+ if (ReferenceEquals(left, right))
+ return false;
+ if (left is null || right is null)
+ return true;
+
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ var that = obj as NavigationViewModelBase;
+
+ return that != null && this.ImageName == that.ImageName && this.Label == that.Label;
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
}
}
diff --git a/Source/ViewModels/ViewAchievementsViewModel.cs b/Source/ViewModels/ViewAchievementsViewModel.cs
deleted file mode 100644
index 52fb2eea..00000000
--- a/Source/ViewModels/ViewAchievementsViewModel.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using Jamiras.Commands;
-using Jamiras.ViewModels;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace RATools.ViewModels
-{
- public class ViewAchievementsViewModel : DialogViewModelBase
- {
- public ViewAchievementsViewModel(GameViewModel game)
- {
- _game = game;
-
- DialogTitle = "Achievements - " + game.Title;
- CanClose = true;
- CancelButtonText = null;
- ExtraButtonCommand = new DelegateCommand(Export);
-
- Achievements = game.Editors.OfType().ToArray();
- }
-
- private readonly GameViewModel _game;
-
- ///
- /// Gets the list of achievements.
- ///
- public IEnumerable Achievements { get; private set; }
-
- public string ExtraButtonText { get { return "Export"; } }
- public CommandBase ExtraButtonCommand { get; private set; }
-
- private void Export()
- {
- var filename = Path.GetFileNameWithoutExtension(_game.Script.Filename) ?? "achievements";
-
- var vm = new FileDialogViewModel();
- vm.DialogTitle = "Export achievement information";
- vm.Filters["CSV file"] = "*.csv";
- vm.FileNames = new[] { filename + ".csv" };
- vm.OverwritePrompt = true;
-
- if (vm.ShowSaveFileDialog() == DialogResult.Ok)
- {
- using (var file = File.CreateText(vm.FileNames[0]))
- {
- file.WriteLine("Id,Title,Description,Points");
-
- foreach (var achievement in Achievements)
- {
- file.Write("{0},\"{1}\",", achievement.Id, achievement.Title.Replace("\"", "\\\""));
- file.Write("\"{0}\",", achievement.Description.Replace("\"", "\\\""));
- file.Write("{0}", achievement.Points);
- file.WriteLine();
- }
- }
- }
- }
- }
-}
diff --git a/Source/ViewModels/ViewerViewModelBase.cs b/Source/ViewModels/ViewerViewModelBase.cs
index 727b5f09..a868855b 100644
--- a/Source/ViewModels/ViewerViewModelBase.cs
+++ b/Source/ViewModels/ViewerViewModelBase.cs
@@ -23,6 +23,8 @@ public virtual string ViewerImage
get { return String.Format("/RATools;component/Resources/{0}.png", ViewerType.ToLower()); }
}
+ public virtual int ViewerId { get { return 0; } }
+
public CommandBase UpdateLocalCommand { get; protected set; }
internal int SortOrder { get; set; }
diff --git a/Source/Views/AchievementsListViewer.xaml b/Source/Views/AchievementsListViewer.xaml
new file mode 100644
index 00000000..94199289
--- /dev/null
+++ b/Source/Views/AchievementsListViewer.xaml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Views/GameViewer.xaml b/Source/Views/GameViewer.xaml
index f3394b9b..35b79cd9 100644
--- a/Source/Views/GameViewer.xaml
+++ b/Source/Views/GameViewer.xaml
@@ -5,6 +5,7 @@
+
@@ -156,6 +157,7 @@
+
diff --git a/Source/Views/MainWindow.xaml b/Source/Views/MainWindow.xaml
index 059034fc..5a353afd 100644
--- a/Source/Views/MainWindow.xaml
+++ b/Source/Views/MainWindow.xaml
@@ -54,8 +54,6 @@