diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d5250022 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,164 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +# C# files +[*.cs] +indent_size = 4 +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_within_query_expression_clauses = true + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current + +# avoid this. unless absolutely necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# only use var when it's obvious what the variable type is +csharp_style_var_for_built_in_types = false:none +csharp_style_var_when_type_is_apparent = false:none +csharp_style_var_elsewhere = false:suggestion + +# use language keywords instead of BCL types +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# name all constant fields using PascalCase +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style + +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const + +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style + +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal + +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# Code style defaults +dotnet_sort_system_directives_first = true +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion + +# Expression-bodied members +csharp_style_expression_bodied_methods = false:none +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_operators = false:none +csharp_style_expression_bodied_properties = true:none +csharp_style_expression_bodied_indexers = true:none +csharp_style_expression_bodied_accessors = true:none + +# Pattern matching +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +# Null checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Space preferences +csharp_space_after_cast = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +[*.{asm,inc}] +indent_size = 8 + +# Visual Studio Solution Files +[*.sln] +indent_style = tab + +# Visual Studio XML Project Files +[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# XML Configuration Files +[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] +indent_size = 2 + +[CMakeLists.txt] +indent_size = 2 + +# Makefiles +[Makefile] +indent_style = tab + +# Batch Files +[*.{cmd,bat}] +indent_size = 2 +end_of_line = crlf + +# Bash Files +[*.sh] +end_of_line = lf + +# Web Files +[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,pcss,svg,vue}] +indent_size = 2 + +# Markdown Files +[*.md] +trim_trailing_whitespace = false + +# JSON Files +[*.{json,json5,webmanifest}] +indent_size = 2 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a56c0d4d..6e9a4217 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: run: dotnet restore FModel - name: .NET Publish - run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net5.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false -p:AssemblyVersion=${{ github.event.inputs.appVersion }} -p:FileVersion=${{ github.event.inputs.appVersion }} + run: dotnet publish FModel -c Release --no-self-contained -r win-x64 -f net6.0-windows -o "./FModel/bin/Publish/" -p:PublishReadyToRun=false -p:PublishSingleFile=true -p:DebugType=None -p:GenerateDocumentationFile=false -p:DebugSymbols=false -p:AssemblyVersion=${{ github.event.inputs.appVersion }} -p:FileVersion=${{ github.event.inputs.appVersion }} - name: ZIP File uses: papeloto/action-zip@v1 @@ -45,4 +45,4 @@ jobs: automatic_release_tag: ${{ github.event.inputs.appVersion }} repo_token: ${{ secrets.GITHUB_TOKEN }} prerelease: false - files: FModel.zip \ No newline at end of file + files: FModel.zip diff --git a/CUE4Parse b/CUE4Parse index 6d911668..d2163de3 160000 --- a/CUE4Parse +++ b/CUE4Parse @@ -1 +1 @@ -Subproject commit 6d911668e730b3f4c1eab0b3f7e9a99bc3dde943 +Subproject commit d2163de354e97a0e62222221b96666a678255884 diff --git a/FModel/App.xaml.cs b/FModel/App.xaml.cs index 7c485483..16ad94dc 100644 --- a/FModel/App.xaml.cs +++ b/FModel/App.xaml.cs @@ -25,7 +25,7 @@ namespace FModel { [DllImport("kernel32.dll")] private static extern bool AttachConsole(int dwProcessId); - + protected override void OnStartup(StartupEventArgs e) { #if DEBUG @@ -98,7 +98,7 @@ namespace FModel { if ((EErrorKind) messageBox.ButtonPressed.Id == EErrorKind.ResetSettings) UserSettings.Default = new UserSettings(); - + ApplicationService.ApplicationView.Restart(); } @@ -123,7 +123,7 @@ namespace FModel return $"{productName} ({(Environment.Is64BitOperatingSystem ? "64" : "32")}-bit)"; } - private string GetRegistryValue(string path, string name = null, RegistryHive root = RegistryHive.CurrentUser) + public static string GetRegistryValue(string path, string name = null, RegistryHive root = RegistryHive.CurrentUser) { using var rk = RegistryKey.OpenBaseKey(root, RegistryView.Default).OpenSubKey(path); if (rk != null) @@ -131,4 +131,4 @@ namespace FModel return string.Empty; } } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseCommunity.cs b/FModel/Creator/Bases/FN/BaseCommunity.cs index 78c2fe30..d0066e94 100644 --- a/FModel/Creator/Bases/FN/BaseCommunity.cs +++ b/FModel/Creator/Bases/FN/BaseCommunity.cs @@ -30,12 +30,12 @@ namespace FModel.Creator.Bases.FN public override void ParseForInfo() { - ParseForReward(UserSettings.Default.CosmeticDisplayAsset == EEnabledDisabled.Enabled); + ParseForReward(UserSettings.Default.CosmeticDisplayAsset); if (Object.TryGetValue(out FPackageIndex series, "Series") && Utils.TryGetPackageIndexExport(series, out UObject export)) _rarityName = export.Name; else - _rarityName = GetRarityName(Object.GetOrDefault("Rarity")); + _rarityName = Object.GetOrDefault("Rarity", EFortRarity.Uncommon).GetDescription(); if (Object.TryGetValue(out FGameplayTagContainer gameplayTags, "GameplayTags")) CheckGameplayTags(gameplayTags); @@ -108,44 +108,6 @@ namespace FModel.Creator.Bases.FN return number > 10 ? $"C{number / 10 + 1} S{s[^1..]}" : $"C1 S{s}"; } - private string GetRarityName(FName r) - { - var rarity = EFortRarity.Uncommon; - switch (r.Text) - { - case "EFortRarity::Common": - case "EFortRarity::Handmade": - rarity = EFortRarity.Common; - break; - case "EFortRarity::Rare": - case "EFortRarity::Sturdy": - rarity = EFortRarity.Rare; - break; - case "EFortRarity::Epic": - case "EFortRarity::Quality": - rarity = EFortRarity.Epic; - break; - case "EFortRarity::Legendary": - case "EFortRarity::Fine": - rarity = EFortRarity.Legendary; - break; - case "EFortRarity::Mythic": - case "EFortRarity::Elegant": - rarity = EFortRarity.Mythic; - break; - case "EFortRarity::Transcendent": - case "EFortRarity::Masterwork": - rarity = EFortRarity.Transcendent; - break; - case "EFortRarity::Unattainable": - case "EFortRarity::Badass": - rarity = EFortRarity.Unattainable; - break; - } - - return rarity.GetDescription(); - } - private new void DrawBackground(SKCanvas c) { if (_design.Rarities.TryGetValue(_rarityName, out var rarity)) @@ -302,4 +264,4 @@ namespace FModel.Creator.Bases.FN } } } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseIcon.cs b/FModel/Creator/Bases/FN/BaseIcon.cs index 6ecfce2b..a58a0aa0 100644 --- a/FModel/Creator/Bases/FN/BaseIcon.cs +++ b/FModel/Creator/Bases/FN/BaseIcon.cs @@ -33,14 +33,14 @@ namespace FModel.Creator.Bases.FN { // rarity if (Object.TryGetValue(out FPackageIndex series, "Series")) GetSeries(series); - else GetRarity(Object.GetOrDefault("Rarity")); // default is uncommon + else GetRarity(Object.GetOrDefault("Rarity", EFortRarity.Uncommon)); // default is uncommon // preview if (isUsingDisplayAsset && Utils.TryGetDisplayAsset(Object, out var preview)) Preview = preview; else if (Object.TryGetValue(out FPackageIndex itemDefinition, "HeroDefinition", "WeaponDefinition")) Preview = Utils.GetBitmap(itemDefinition); - else if (Object.TryGetValue(out FSoftObjectPath largePreview, "LargePreviewImage", "SidePanelIcon", "EntryListIcon", "SmallPreviewImage", "ItemDisplayAsset", "LargeIcon", "ToastIcon", "SmallIcon")) + else if (Object.TryGetValue(out FSoftObjectPath largePreview, "LargePreviewImage", "EntryListIcon", "SmallPreviewImage", "ItemDisplayAsset", "LargeIcon", "ToastIcon", "SmallIcon")) Preview = Utils.GetBitmap(largePreview); else if (Object.TryGetValue(out string s, "LargePreviewImage") && !string.IsNullOrEmpty(s)) Preview = Utils.GetBitmap(s); @@ -78,7 +78,7 @@ namespace FModel.Creator.Bases.FN public override void ParseForInfo() { - ParseForReward(UserSettings.Default.CosmeticDisplayAsset == EEnabledDisabled.Enabled); + ParseForReward(UserSettings.Default.CosmeticDisplayAsset); if (Object.TryGetValue(out FGameplayTagContainer gameplayTags, "GameplayTags")) CheckGameplayTags(gameplayTags); @@ -165,44 +165,11 @@ namespace FModel.Creator.Bases.FN } } - private void GetRarity(FName r) + private void GetRarity(EFortRarity r) { if (!Utils.TryLoadObject("FortniteGame/Content/Balance/RarityData.RarityData", out UObject export)) return; - var rarity = EFortRarity.Uncommon; - switch (r.Text) - { - case "EFortRarity::Common": - case "EFortRarity::Handmade": - rarity = EFortRarity.Common; - break; - case "EFortRarity::Rare": - case "EFortRarity::Sturdy": - rarity = EFortRarity.Rare; - break; - case "EFortRarity::Epic": - case "EFortRarity::Quality": - rarity = EFortRarity.Epic; - break; - case "EFortRarity::Legendary": - case "EFortRarity::Fine": - rarity = EFortRarity.Legendary; - break; - case "EFortRarity::Mythic": - case "EFortRarity::Elegant": - rarity = EFortRarity.Mythic; - break; - case "EFortRarity::Transcendent": - case "EFortRarity::Masterwork": - rarity = EFortRarity.Transcendent; - break; - case "EFortRarity::Unattainable": - case "EFortRarity::Badass": - rarity = EFortRarity.Unattainable; - break; - } - - if (export.GetByIndex((int) rarity) is { } data && + if (export.GetByIndex((int) r) is { } data && data.TryGetValue(out FLinearColor color1, "Color1") && data.TryGetValue(out FLinearColor color2, "Color2") && data.TryGetValue(out FLinearColor color3, "Color3")) @@ -308,4 +275,4 @@ namespace FModel.Creator.Bases.FN } } } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseIconStats.cs b/FModel/Creator/Bases/FN/BaseIconStats.cs index b1c44508..706d0dd0 100644 --- a/FModel/Creator/Bases/FN/BaseIconStats.cs +++ b/FModel/Creator/Bases/FN/BaseIconStats.cs @@ -114,7 +114,7 @@ namespace FModel.Creator.Bases.FN weaponRowValue.TryGetValue(out UDataTable durabilityTable, "Durability") && weaponRowValue.TryGetValue(out FName durabilityRowName, "DurabilityRowName") && durabilityTable.TryGetDataTableRow(durabilityRowName.Text, StringComparison.OrdinalIgnoreCase, out var durability) && - durability.TryGetValue(out int duraByRarity, GetRarityName(Object.GetOrDefault("Rarity")))) + durability.TryGetValue(out int duraByRarity, Object.GetOrDefault("Rarity", EFortRarity.Uncommon).GetDescription())) { _statistics.Add(new IconStat(Utils.GetLocalizedResource("", "6FA2882140CB69DE32FD73A392F0585B", "Durability"), duraByRarity, 20)); } @@ -145,7 +145,7 @@ namespace FModel.Creator.Bases.FN curveTable.TryGetCurveTableRow(rowName.Text, StringComparison.OrdinalIgnoreCase, out var rowValue) && rowValue.TryGetValue(out FSimpleCurveKey[] keys, "Keys") && keys.Length > 0) { - statValue = keys[0].KeyValue; + statValue = keys[0].Value; return true; } @@ -153,44 +153,6 @@ namespace FModel.Creator.Bases.FN return false; } - private string GetRarityName(FName r) - { - var rarity = EFortRarity.Uncommon; - switch (r.Text) - { - case "EFortRarity::Common": - case "EFortRarity::Handmade": - rarity = EFortRarity.Common; - break; - case "EFortRarity::Rare": - case "EFortRarity::Sturdy": - rarity = EFortRarity.Rare; - break; - case "EFortRarity::Epic": - case "EFortRarity::Quality": - rarity = EFortRarity.Epic; - break; - case "EFortRarity::Legendary": - case "EFortRarity::Fine": - rarity = EFortRarity.Legendary; - break; - case "EFortRarity::Mythic": - case "EFortRarity::Elegant": - rarity = EFortRarity.Mythic; - break; - case "EFortRarity::Transcendent": - case "EFortRarity::Masterwork": - rarity = EFortRarity.Transcendent; - break; - case "EFortRarity::Unattainable": - case "EFortRarity::Badass": - rarity = EFortRarity.Unattainable; - break; - } - - return rarity.GetDescription(); - } - private readonly SKPaint _informationPaint = new() { IsAntialias = true, FilterQuality = SKFilterQuality.High, @@ -293,7 +255,7 @@ namespace FModel.Creator.Bases.FN public void Draw(SKCanvas c, SKColor sliderColor, int width, int height, ref float y) { - while (_statPaint.MeasureText(_statName) > height * 2) + while (_statPaint.MeasureText(_statName) > height * 2 - 40) { _statPaint.TextSize -= 1; } @@ -316,4 +278,4 @@ namespace FModel.Creator.Bases.FN c.DrawRect(new SKRect(height * 2, y, Math.Min(height * 2 + sliderWidth, sliderRight), y + 5), _statPaint); } } -} \ No newline at end of file +} diff --git a/FModel/Creator/Bases/FN/BaseQuest.cs b/FModel/Creator/Bases/FN/BaseQuest.cs index b4a1df51..b194dc37 100644 --- a/FModel/Creator/Bases/FN/BaseQuest.cs +++ b/FModel/Creator/Bases/FN/BaseQuest.cs @@ -2,6 +2,8 @@ using System.Linq; using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Assets.Exports.Engine; +using CUE4Parse.UE4.Assets.Exports.Material; +using CUE4Parse.UE4.Assets.Exports.Texture; using CUE4Parse.UE4.Assets.Objects; using CUE4Parse.UE4.Objects.Core.i18N; using CUE4Parse.UE4.Objects.UObject; @@ -72,9 +74,15 @@ namespace FModel.Creator.Bases.FN Description += "\n" + completionText.Text; if (Object.TryGetValue(out FSoftObjectPath tandemCharacterData, "TandemCharacterData") && Utils.TryLoadObject(tandemCharacterData.AssetPathName.Text, out UObject uObject) && - uObject.TryGetValue(out FSoftObjectPath tandemIcon, "SidePanelIcon", "EntryListIcon", "ToastIcon")) + uObject.TryGetValue(out FSoftObjectPath tandemIcon, "EntryListIcon", "ToastIcon") && + Utils.TryLoadObject(tandemIcon.AssetPathName.Text, out UObject iconObject)) { - Preview = Utils.GetBitmap(tandemIcon); + Preview = iconObject switch + { + UTexture2D text => Utils.GetBitmap(text), + UMaterialInstanceConstant mat => Utils.GetBitmap(mat), + _ => Preview + }; } } diff --git a/FModel/Creator/Utils.cs b/FModel/Creator/Utils.cs index 9a6fd51b..a4975b28 100644 --- a/FModel/Creator/Utils.cs +++ b/FModel/Creator/Utils.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -46,7 +46,7 @@ namespace FModel.Creator var path = $"/Game/Catalog/MI_OfferImages/MI_{uObject.Name.Replace("Athena_Commando_", string.Empty)}"; if (!TryLoadObject(path, out UMaterialInstanceConstant material)) // non-obfuscated item definition { - if (!TryLoadObject($"{path[..path.LastIndexOf('_')]}_{path.SubstringAfterLast('_').ToLower()}", out material)) // Try to get MI with lowercase obfuscation + if (!TryLoadObject($"{path[..path.LastIndexOf('_')]}_{path.SubstringAfterLast('_').ToLower()}", out material)) // Try to get MI with lowercase obfuscation TryLoadObject(path[..path.LastIndexOf('_')], out material); // hopefully gets obfuscated item definition } @@ -93,6 +93,7 @@ namespace FModel.Creator case "TextureB": case "OfferImage": case "KeyArtTexture": + case "NPC-Portrait": { return GetBitmap(texture); } @@ -122,11 +123,11 @@ namespace FModel.Creator me.ScalePixels(pixmap, SKFilterQuality.Medium); return bmp; } - - public static void ClearToTransparent(this SKBitmap me) { + + public static void ClearToTransparent(this SKBitmap me, SKColor colorToDelete) { var colors = me.Pixels; for (var n = 0; n < colors.Length; n++) { - if (colors[n] != SKColors.Black) continue; + if (colors[n] != colorToDelete) continue; colors[n] = SKColors.Transparent; } me.Pixels = colors; @@ -274,4 +275,4 @@ namespace FModel.Creator return ret; } } -} \ No newline at end of file +} diff --git a/FModel/Enums.cs b/FModel/Enums.cs index 58dca396..2e63af22 100644 --- a/FModel/Enums.cs +++ b/FModel/Enums.cs @@ -51,14 +51,6 @@ namespace FModel Never } - public enum EEnabledDisabled - { - [Description("Disabled")] - Disabled, - [Description("Enabled")] - Enabled - } - public enum FGame { [Description("Unknown")] @@ -90,7 +82,13 @@ namespace FModel [Description("Core")] Platform, [Description("Days Gone")] - BendGame + BendGame, + [Description("PLAYERUNKNOWN'S BATTLEGROUNDS")] + TslGame, + [Description("Splitgate")] + PortalWars, + [Description("GTA: The Trilogy - Definitive Edition")] + Gameface } public enum ELoadingMode @@ -138,4 +136,4 @@ namespace FModel // [Description("Community")] // CommunityMade } -} \ No newline at end of file +} diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index a081481e..28e1b01b 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -2,12 +2,12 @@ WinExe - net5.0-windows + net6.0-windows true FModel.ico 4.0.0 - 4.0.1.1 - 4.0.1.1 + 4.0.2.0 + 4.0.2.0 false true win-x64 @@ -102,20 +102,20 @@ - - + + - - - + + + - + - - + + @@ -186,6 +186,7 @@ + diff --git a/FModel/FModel.sln b/FModel/FModel.sln index a53a4881..7de93e7b 100644 --- a/FModel/FModel.sln +++ b/FModel/FModel.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30804.86 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31912.275 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FModel", "FModel.csproj", "{B1F494EA-90A6-4C24-800E-2F724A1884CA}" EndProject diff --git a/FModel/Framework/NavigationList.cs b/FModel/Framework/NavigationList.cs new file mode 100644 index 00000000..7e32beea --- /dev/null +++ b/FModel/Framework/NavigationList.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace FModel.Framework +{ + public class NavigationList : List + { + private int _currentIndex = 0; + public int CurrentIndex + { + get + { + if (_currentIndex > Count - 1) { _currentIndex = Count - 1; } + if (_currentIndex < 0) { _currentIndex = 0; } + return _currentIndex; + } + set { _currentIndex = value; } + } + + public T MoveNext + { + get { _currentIndex++; return this[CurrentIndex]; } + } + + public T MovePrevious + { + get { _currentIndex--; return this[CurrentIndex]; } + } + + public T Current + { + get { return this[CurrentIndex]; } + } + } +} diff --git a/FModel/Helper.cs b/FModel/Helper.cs index ddee04f2..f300e538 100644 --- a/FModel/Helper.cs +++ b/FModel/Helper.cs @@ -85,4 +85,4 @@ namespace FModel return -d < n && d > n; } } -} \ No newline at end of file +} diff --git a/FModel/MainWindow.xaml b/FModel/MainWindow.xaml index c926fc3c..be4aa554 100644 --- a/FModel/MainWindow.xaml +++ b/FModel/MainWindow.xaml @@ -64,6 +64,15 @@ + + + + + + + + + @@ -147,18 +156,15 @@ - - + @@ -333,14 +339,14 @@ - + - + @@ -448,7 +454,7 @@ - + @@ -472,7 +478,7 @@ - + @@ -500,11 +506,11 @@ - + - - + + @@ -634,7 +640,7 @@ - + @@ -664,7 +670,7 @@ - + @@ -673,7 +679,7 @@ - +