diff --git a/Source/Data/Achievement.cs b/Source/Data/Achievement.cs index 6623ae36..205390f1 100644 --- a/Source/Data/Achievement.cs +++ b/Source/Data/Achievement.cs @@ -31,6 +31,18 @@ public Achievement() /// public string BadgeName { get; set; } + public static bool IsValidBadgeName(string badgeName) + { + if (String.IsNullOrEmpty(badgeName)) + return false; + if (badgeName == "0") + return false; + if (badgeName == "00000") + return false; + + return true; + } + /// /// Gets the trigger for the achievement. /// diff --git a/Source/Parser/Functions/AchievementFunction.cs b/Source/Parser/Functions/AchievementFunction.cs index b9dff5d6..deb74bdc 100644 --- a/Source/Parser/Functions/AchievementFunction.cs +++ b/Source/Parser/Functions/AchievementFunction.cs @@ -25,7 +25,7 @@ public AchievementFunction() Parameters.Add(new VariableDefinitionExpression("modified")); DefaultParameters["modified"] = new StringConstantExpression(""); Parameters.Add(new VariableDefinitionExpression("badge")); - DefaultParameters["badge"] = new StringConstantExpression("0"); + DefaultParameters["badge"] = new StringConstantExpression("00000"); Parameters.Add(new VariableDefinitionExpression("type")); DefaultParameters["type"] = new StringConstantExpression(""); diff --git a/Source/ViewModels/AchievementViewModel.cs b/Source/ViewModels/AchievementViewModel.cs index 950056c1..611634d6 100644 --- a/Source/ViewModels/AchievementViewModel.cs +++ b/Source/ViewModels/AchievementViewModel.cs @@ -2,10 +2,12 @@ using Jamiras.Components; using Jamiras.DataModels; using Jamiras.Services; +using Jamiras.ViewModels; using RATools.Data; using RATools.Services; using System; using System.Collections.Generic; +using System.IO; using System.Text; namespace RATools.ViewModels @@ -16,6 +18,7 @@ public AchievementViewModel(GameViewModel owner) : base(owner) { CopyDefinitionToClipboardCommand = new DelegateCommand(CopyDefinitionToClipboard); + ChangeImageCommand = new DelegateCommand(ChangeImage); } public override string ViewerType @@ -37,7 +40,13 @@ public override void Refresh() else if (localAsset != null) AchievementType = localAsset.Type; - if (String.IsNullOrEmpty(BadgeName)) + if (generatedAsset != null && Achievement.IsValidBadgeName(generatedAsset.BadgeName)) + BadgeName = generatedAsset.BadgeName; + else if (localAsset != null && Achievement.IsValidBadgeName(localAsset.BadgeName)) + BadgeName = localAsset.BadgeName; + else if (coreAsset != null && Achievement.IsValidBadgeName(coreAsset.BadgeName)) + BadgeName = coreAsset.BadgeName; + else BadgeName = "00000"; } @@ -79,6 +88,7 @@ public string TypeImage protected override bool AreAssetSpecificPropertiesModified(AssetSourceViewModel left, AssetSourceViewModel right) { IsPointsModified = (left.Points.Value != right.Points.Value); + bool badgeModified = left.BadgeName != right.BadgeName; var leftAchievement = left.Asset as Achievement; var rightAchievement = right.Asset as Achievement; @@ -86,7 +96,7 @@ protected override bool AreAssetSpecificPropertiesModified(AssetSourceViewModel var rightAchievementType = rightAchievement?.Type ?? AchievementType.Standard; IsAchievementTypeModified = leftAchievementType != rightAchievementType; - return IsPointsModified || IsAchievementTypeModified; + return IsPointsModified || IsAchievementTypeModified || badgeModified; } internal override IEnumerable BuildTriggerList(AssetSourceViewModel assetViewModel) @@ -114,7 +124,7 @@ protected override void UpdateLocal(AssetBase asset, AssetBase localAsset, Strin if (achievement != null) { - if (String.IsNullOrEmpty(achievement.BadgeName) || achievement.BadgeName == "0") + if (!Achievement.IsValidBadgeName(achievement.BadgeName)) achievement.BadgeName = BadgeName; } @@ -136,6 +146,67 @@ private void CopyDefinitionToClipboard() } } + public DelegateCommand ChangeImageCommand { get; private set; } + + private void ChangeImage() + { + var vm = new FileDialogViewModel(); + vm.DialogTitle = "Select badge image"; + vm.Filters["Image file"] = "*.png;*.gif;*.jpg;*.jpeg"; + vm.CheckFileExists = true; + + if (vm.ShowOpenFileDialog() != DialogResult.Ok) + return; + + var bValid = false; + var bytes = File.ReadAllBytes(vm.FileNames[0]); + var sExtension = Path.GetExtension(vm.FileNames[0]).Substring(1).ToLower(); + switch (sExtension) + { + case "png": + bValid = bytes[1] == 'P' && bytes[2] == 'N' && bytes[3] == 'G'; + break; + + case "gif": + bValid = bytes[0] == 'G' && bytes[1] == 'I' && bytes[2] == 'F' && bytes[3] == '8'; + break; + + case "jpg": + case "jpeg": + bValid = bytes[6] == 'J' && bytes[7] == 'F' && bytes[8] == 'I' && bytes[9] == 'F'; + break; + } + + if (!bValid) + { + MessageBoxViewModel.ShowMessage("File does not appear to be a valid " + sExtension + " image."); + return; + } + + var achievement = Generated.Asset as Achievement; + if (achievement == null) + achievement = Published.Asset as Achievement; + + if (achievement != null) + { + var md5 = Convert.ToHexString(System.Security.Cryptography.MD5.HashData(bytes)).ToLower(); + var localFolder = Path.Combine(_owner.RACacheDirectory, "..", "Badge", "local"); + if (!Directory.Exists(localFolder)) + Directory.CreateDirectory(localFolder); + var localFilename = Path.Combine(localFolder, String.Format("{0}-{1}.{2}", _owner.GameId, md5, sExtension)); + if (!File.Exists(localFilename)) + File.Copy(vm.FileNames[0], localFilename); + + achievement.BadgeName = localFilename.Substring(localFilename.LastIndexOf("local")); + if (ReferenceEquals(Generated.Asset, achievement)) + Generated.BadgeName = achievement.BadgeName; + else + Published.BadgeName = achievement.BadgeName; + + Refresh(); + } + } + public string MeasuredTarget { get diff --git a/Source/ViewModels/AssetViewModelBase.cs b/Source/ViewModels/AssetViewModelBase.cs index 115eb65d..f8182077 100644 --- a/Source/ViewModels/AssetViewModelBase.cs +++ b/Source/ViewModels/AssetViewModelBase.cs @@ -425,14 +425,14 @@ internal string BadgeName private static ImageSource GetBadge(ModelBase model) { var vm = (AssetViewModelBase)model; - if (IsValidBadgeName(vm.Generated.BadgeName)) + if (Achievement.IsValidBadgeName(vm.Generated.BadgeName)) return vm.Generated.Badge; - if (IsValidBadgeName(vm.Local.BadgeName)) + if (Achievement.IsValidBadgeName(vm.Local.BadgeName)) return vm.Local.Badge; - if (IsValidBadgeName(vm.Published.BadgeName)) + if (Achievement.IsValidBadgeName(vm.Published.BadgeName)) return vm.Published.Badge; - if (IsValidBadgeName(vm.BadgeName)) + if (Achievement.IsValidBadgeName(vm.BadgeName)) { vm.Local.BadgeName = vm.BadgeName; return vm.Local.Badge; @@ -441,18 +441,6 @@ private static ImageSource GetBadge(ModelBase model) return null; } - private static bool IsValidBadgeName(string badgeName) - { - if (String.IsNullOrEmpty(badgeName)) - return false; - if (badgeName == "0") - return false; - if (badgeName == "00000") - return false; - - return true; - } - public override void Refresh() { var generatedAsset = Generated.Asset; @@ -484,11 +472,11 @@ public override void Refresh() else Id = Published.Id; - if (IsValidBadgeName(Generated.BadgeName)) + if (Achievement.IsValidBadgeName(Generated.BadgeName)) BadgeName = Generated.BadgeName; - else if (IsValidBadgeName(Local.BadgeName)) + else if (Achievement.IsValidBadgeName(Local.BadgeName)) BadgeName = Local.BadgeName; - else if (IsValidBadgeName(Published.BadgeName)) + else if (Achievement.IsValidBadgeName(Published.BadgeName)) BadgeName = Published.BadgeName; else BadgeName = null; diff --git a/Source/ViewModels/Navigation/NavigationListViewModel.cs b/Source/ViewModels/Navigation/NavigationListViewModel.cs index 1ee060a6..431ab698 100644 --- a/Source/ViewModels/Navigation/NavigationListViewModel.cs +++ b/Source/ViewModels/Navigation/NavigationListViewModel.cs @@ -72,9 +72,28 @@ private void MergeGenerated(AchievementScriptInterpreter interpreter) MergeAndPruneAssets(interpreter.Achievements, 10000, (vm, a) => { + var generatedAchievement = a as Achievement; + if (generatedAchievement != null) + { + vm.SourceLine = interpreter.GetSourceLine(generatedAchievement); + + if (!Achievement.IsValidBadgeName(generatedAchievement.BadgeName)) + { + var localAchievement = vm.Local.Asset as Achievement; + if (localAchievement != null && Achievement.IsValidBadgeName(localAchievement.BadgeName)) + { + generatedAchievement.BadgeName = localAchievement.BadgeName; + } + else + { + var publishedAchievement = vm.Published.Asset as Achievement; + if (publishedAchievement != null && Achievement.IsValidBadgeName(publishedAchievement.BadgeName)) + generatedAchievement.BadgeName = publishedAchievement.BadgeName; + } + } + } + vm.Generated.Asset = a; - if (a != null) - vm.SourceLine = interpreter.GetSourceLine((Achievement)a); }, (vm) => vm.Generated.Asset); MergeAndPruneAssets(interpreter.Leaderboards, 10000, (vm, a) => diff --git a/Source/Views/AchievementViewer.xaml b/Source/Views/AchievementViewer.xaml index 074764b1..c1de9641 100644 --- a/Source/Views/AchievementViewer.xaml +++ b/Source/Views/AchievementViewer.xaml @@ -40,7 +40,14 @@ - + + + + + + + + diff --git a/Source/Views/AchievementsListViewer.xaml b/Source/Views/AchievementsListViewer.xaml index 94199289..e5874050 100644 --- a/Source/Views/AchievementsListViewer.xaml +++ b/Source/Views/AchievementsListViewer.xaml @@ -48,19 +48,27 @@ - - - - - - + + + + + + + + + + + + + + diff --git a/Tests/Parser/AchievementScriptInterpreterTests.cs b/Tests/Parser/AchievementScriptInterpreterTests.cs index 7b0b94fa..d3261e4d 100644 --- a/Tests/Parser/AchievementScriptInterpreterTests.cs +++ b/Tests/Parser/AchievementScriptInterpreterTests.cs @@ -1103,7 +1103,7 @@ public void TestDefaultParameterPassthrough() // calling achievement() directly without a badge or id var achievement = parser.Achievements.ElementAt(0); Assert.That(achievement.Id, Is.EqualTo(0)); - Assert.That(achievement.BadgeName, Is.EqualTo("0")); + Assert.That(achievement.BadgeName, Is.EqualTo("00000")); // calling achievement() indirectly without a badge or id achievement = parser.Achievements.ElementAt(1); diff --git a/Tests/Parser/Functions/AchievementFunctionTests.cs b/Tests/Parser/Functions/AchievementFunctionTests.cs index a5beae26..6f50e056 100644 --- a/Tests/Parser/Functions/AchievementFunctionTests.cs +++ b/Tests/Parser/Functions/AchievementFunctionTests.cs @@ -36,7 +36,7 @@ public void TestDefinition() Assert.That(def.DefaultParameters["modified"], Is.InstanceOf()); Assert.That(((StringConstantExpression)def.DefaultParameters["modified"]).Value, Is.EqualTo("")); Assert.That(def.DefaultParameters["badge"], Is.InstanceOf()); - Assert.That(((StringConstantExpression)def.DefaultParameters["badge"]).Value, Is.EqualTo("0")); + Assert.That(((StringConstantExpression)def.DefaultParameters["badge"]).Value, Is.EqualTo("00000")); Assert.That(def.DefaultParameters["type"], Is.InstanceOf()); Assert.That(((StringConstantExpression)def.DefaultParameters["type"]).Value, Is.EqualTo("")); Assert.That(def.DefaultParameters["set"], Is.InstanceOf());