Commit Graph

1682 Commits

Author SHA1 Message Date
Rob Trame
c33d5f58f2
[P2-007] Migrate Magnifier adorner system to Avalonia (#74)
* feat(P2-007): migrate Magnifier adorner system to Avalonia (#20)

Magnifier.cs:
- System.Windows.Controls.Control → Avalonia TemplatedControl
- DependencyProperty → StyledProperty<T> with AddClassHandler callbacks
- Target property type UIElement → Control (Avalonia uses Control as the
  visual-tree base)
- ZoomFactor / ZoomFactorOnMouseWheel: validation callback replaced with
  validate: parameter on Register (Avalonia 11 API)
- OverrideMetadata for Width/Height → OverrideDefaultValue<T>
- SizeChanged event → BoundsProperty.Changed class handler
- IsInitialized guard → Bounds.Width/Height > 0 guard
- Remove PART_VisualBrush TemplateBinding lookup: Magnifier now renders
  itself via Render(DrawingContext) instead of relying on a ControlTemplate
  in Resources.xaml (which is not yet migrated). Circle/Rectangle shapes
  are drawn directly via DrawingContext.DrawEllipse / DrawRectangle using
  a VisualBrush whose SourceControl points at the Target; SourceRect
  carries the viewport (equivalent to WPF VisualBrush.Viewbox / Absolute
  ViewboxUnits). Brush is rebuilt in RebuildBrush whenever Target changes.
- Avalonia.Data using removed (unused after DependencyProperty removal)

MagnifierAdorner.cs:
- WPF Adorner subclass replaced by Canvas-based adorner control; the
  canvas is placed in the AdornerLayer via AdornerLayer.SetAdornment
  (called by MagnifierManager).
- AddVisualChild(_magnifier) / ArrangeOverride replaced by Canvas.Children
  plus Canvas.SetLeft/SetTop for positioning.
- InputManager.Current.PostProcessInput replaced by
  PointerMoved on the adorned element; position is obtained via
  e.GetPosition(this) relative to the adorner canvas.
- VisualTreeHelper.GetOffset → Control.TranslatePoint to get the
  Target's offset within the adorned element's coordinate space.
- Detach() method added to allow clean unsubscription on removal.

MagnifierManager.cs:
- DependencyObject with RegisterAttached → plain class with
  AvaloniaProperty.RegisterAttached; change handler wired via
  MagnifierProperty.Changed.Subscribe.
- MouseLeftButtonDown/Up → PointerPressed/Released events.
- MouseWheel → PointerWheelChanged; WPF Delta sign convention:
  Delta < 0 = scroll down = zoom out; Avalonia Delta.Y < 0 = scroll
  down — same directional mapping applied.
- AdornerLayer.GetAdornerLayer + layer.Add → AdornerLayer.GetAdornerLayer
  + AdornerLayer.SetAdornment (Avalonia 11 API).
- Visibility.Visible/Collapsed → IsVisible bool.

ImagePopout.xaml:
- AdonisWindow + WPF namespace → Avalonia Window.
- MagnifierManager.Magnifier inline object-element syntax removed;
  Magnifier is now attached in code-behind (XAML object-valued attached
  property on a different element is not supported in Avalonia).
- DockPanel given x:Name="RootPanel" for code-behind access.
- UseLayoutRounding removed (Avalonia default).

ImagePopout.xaml.cs:
- Added : Window base class and using Avalonia.Markup.Xaml.
- Magnifier attached in OnAttachedToVisualTree to avoid running before
  the adorner layer is available.

Closes #20

* Add untracked file

* fix(magnifier): address PR #74 review findings

C1/C2 (Magnifier.cs)
- BoundsProperty.Changed.AddClassHandler moved from instance ctor to
  static ctor; now also calls InvalidateVisual() (C1: was registering N
  handlers for N instances)
- TargetProperty.Changed.AddClassHandler added to static ctor so
  RebuildBrush fires whenever Target is reassigned (C2 / PR-4)
- Remove unused 'using Avalonia.Data' (m1 / PR-5)

C3/M2 (MagnifierAdorner.cs)
- Track _currentElementPosition (element-relative) alongside
  _currentPointerPosition (adorner-relative); both captured from the
  same PointerEventArgs so no PointToScreen/PointToClient round-trip
  is needed (C3)
- CalculateViewBoxLocation now uses _currentElementPosition; the old
  PointToClient(PointToScreen(...)) call is removed
- Subscribe to adornedElement.PointerPressed alongside PointerMoved;
  both route through a shared HandlePointerEvent() so the magnifier is
  pre-positioned before the first render frame (M2 / PR-3)
- Detach() now unsubscribes both PointerPressed and PointerMoved (PR-2)
- Remove unused 'using Avalonia.VisualTree' (PR-6)

M1/PR-1/PR-2 (MagnifierManager.cs)
- e.NewValue.GetValueOrDefault() replaces unsafe e.NewValue.Value
  access (PR-1)
- ConditionalWeakTable<Control, MagnifierManager> lets OnMagnifierChanged
  detach the old manager when the attached property is changed or cleared
- AttachToMagnifier subscribes element.DetachedFromVisualTree so the
  adorner is detached when the host element leaves the tree (M1 / PR-2)
- New Detach() instance method: unsubscribes all element events,
  calls adorner.Detach(), hides and nulls the adorner

ImagePopout.xaml.cs
- Remove unused 'using Avalonia.Markup.Xaml' (PR-7)
- Use compiler-generated RootPanel field directly instead of
  this.FindControl<DockPanel>("RootPanel") (m2)

* fix(magnifier): address review findings from PR #74

C1: Stretch.Fill in RebuildBrush — restores 1/ZoomFactor magnification
    ratio; Stretch.None was painting source at 1:1 with no zoom effect.

C2: Wire SetMagnifier in ImagePopout constructor, not OnAttachedToVisualTree.
    Window is the visual root so AttachedToVisualTree never fires on it;
    constructor wiring matches WPF parse-time property assignment timing.

M1: Filter PointerPressed/Released to left button only via PointerUpdateKind,
    matching WPF MouseLeftButtonDown/MouseLeftButtonUp routing event semantics.

M2: Remove dead OnApplyTemplate override; no ControlTheme is registered for
    Magnifier so the override could never be called.

S1: Change base class from TemplatedControl to Control; declare Background,
    BorderBrush and BorderThickness as local StyledProperty fields. Makes
    the template-less rendering path explicit at the type-system level.

Min1: Subscribe PointerMoved dynamically via OnPropertyChanged(IsVisibleProperty)
      so the handler is only live while the magnifier is visible, matching the
      WPF Loaded/Unloaded-gated InputManager.PostProcessInput subscription.

Min2: Guard BoundsProperty.Changed with an oldBounds.Size == newBounds.Size
      short-circuit to skip redundant UpdateViewBox calls on position-only
      changes (e.g. PositionMagnifier calling Canvas.SetLeft/SetTop).

Closes review findings from PR #74 / issue #20.

* fix(magnifier): address two unresolved PR review comments

MagnifierManager.OnElementDetached: call full Detach() + _managers.Remove()
  instead of only _adorner.Detach(). The partial cleanup left PointerPressed,
  PointerReleased, PointerWheelChanged and DetachedFromVisualTree subscriptions
  live on the element, causing stale handlers if the control re-entered the
  visual tree. Full teardown ensures a clean slate for any future re-attachment.

Magnifier.UpdateViewBox: fall back to Width/Height styled properties (default
  100px) when Bounds are still zero (pre-first-layout). This ensures ViewBox.Size
  is non-zero on the very first PointerPressed, so CalculateViewBoxLocation()
  correctly centers the viewport under the cursor before the initial measure pass
  has completed.

* fix(magnifier): address final review findings

Min1: Remove adorner from AdornerLayer on Detach() via SetAdornment(element, null)
  so the control is not left as an invisible orphan child in the layer for the
  lifetime of the host window. HideAdorner() call removed as redundant — layer
  removal is a stronger cleanup than a visibility toggle.

S1: Remove redundant InvalidateVisual() call in BoundsProperty.Changed handler.
  UpdateViewBox() already calls InvalidateVisual() at its end; the direct call
  in the handler was scheduling the same dirty-flag set twice per size change.

* fix(magnifier): address four unresolved PR review comments

MagnifierAdorner ctor: set IsVisible=false so the first ShowAdorner() call
  triggers a false→true transition on IsVisibleProperty, firing OnPropertyChanged
  and subscribing PointerMoved. Previously, IsVisible defaulted to true, so
  the first ShowAdorner() was a no-op and PointerMoved was never subscribed
  until after the first hide/show cycle.

MagnifierManager.Detach(): replace 'AdornerLayer.GetAdornerLayer + layer?.SetAdornment'
  with a direct 'AdornerLayer.SetAdornment(_element, null)' static call. In
  Avalonia 11 SetAdornment is static; calling it via an instance reference made
  the null-conditional '?.' meaningless and was inconsistent with VerifyAdornerLayer
  which correctly uses the static API. Add/remove are now symmetrical.

ImagePopout.xaml: remove unused xmlns:controls namespace alias. The magnifier
  wiring was moved to code-behind; no XAML element in this file references the
  alias, eliminating a linter warning.
2026-03-14 21:15:49 -06:00
Rob Trame
2081c8af7d
feat(P2-006): migrate HotkeyTextBox, FilterableComboBox, and Hotkey to Avalonia (#73)
* feat(P2-006): migrate HotkeyTextBox, FilterableComboBox, and Hotkey to Avalonia (#19)

Hotkey.cs (Framework):
- Replace System.Windows.Input (Key, ModifierKeys, Keyboard.Modifiers)
  with Avalonia.Input (Key, KeyModifiers)
- ModifierKeys.Windows → KeyModifiers.Meta
- IsTriggered(Key) → IsTriggered(Key, KeyModifiers): receives explicit
  modifiers from the caller's KeyEventArgs instead of the WPF global
  Keyboard.Modifiers static (which does not exist in Avalonia)

UserSettings.cs (Settings):
- Replace using System.Windows / System.Windows.Input with
  Avalonia.Controls / Avalonia.Input
- ModifierKeys.Control → KeyModifiers.Control on the three default
  hotkey values (AssetAddTab, AssetRemoveTab, AddAudio)

HotkeyTextBox.cs:
- WPF TextBox / DependencyProperty / FrameworkPropertyMetadata replaced
  by Avalonia TextBox / StyledProperty<Hotkey> with BindingMode.TwoWay
- Changed property-changed hook to AddClassHandler static ctor pattern
- OnPreviewKeyDown → OnKeyDown; Keyboard.Modifiers → e.KeyModifiers
- Key.System / e.SystemKey handling removed (not applicable on Linux
  X11/Wayland; Alt key arrives directly via e.Key in Avalonia)
- Key.OemClear removed (not in Avalonia.Input.Key enum)
- Key.DeadCharProcessed removed (not in Avalonia.Input.Key enum)
- IsReadOnlyCaretVisible / IsUndoEnabled removed (no Avalonia equivalent)
- ContextMenu set to null instead of collapsed (no default ContextMenu)

FilterableComboBox.cs:
- WPF ComboBox / DependencyProperty / CollectionViewSource replaced by
  Avalonia ComboBox / StyledProperty / manual filter-list pattern
- CollectionViewSource.GetDefaultView().Filter → store original
  IEnumerable, rebuild filtered List<object> in ApplyFilter() on each
  text change; _isUpdatingItems flag prevents recursion
- OnPreviewKeyDown → OnKeyDown
- OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs) →
  OnLostFocus + TopLevel.FocusManager check to avoid false commits when
  focus moves between ComboBox and its own TextBox
- GetTemplateChild in Loaded handler → OnApplyTemplate NameScope.Find
- TextBoxBaseUserChangeTracker: PreviewTextInput→TextInput,
  PreviewKeyDown→KeyDown, PreviewKeyUp→KeyUp; SelectionLength replaced
  with SelectionEnd - SelectionStart (Avalonia TextBox API)
- StaysOpenOnEdit / IsTextSearchEnabled removed (not in Avalonia ComboBox)

MainWindow.xaml.cs:
- Update 7 IsTriggered(e.Key) call sites to IsTriggered(e.Key, e.KeyModifiers)

Closes #19

* fix(P2-006): address #19 review findings and PR comments

Hotkey.cs:
- [M1] IsTriggered: modifiers.HasFlag(Modifiers) → modifiers == Modifiers
  (HasFlag(None) is always true, so any key combo with no modifiers
  requirement would incorrectly fire for every key press with modifiers)
- [S1] Add [JsonConverter(typeof(StringEnumConverter))] on Key and
  Modifiers properties so they serialise as strings rather than integers;
  Avalonia.Input.Key integer values differ from System.Windows.Input.Key
  values (e.g. Key.A: WPF=44, Avalonia=65), so integer serialisation
  would load wrong keys from existing AppSettings.json on first launch

HotkeyTextBox.cs:
- [C1]/PR-1 Move e.Handled = true into capturing cases only (Delete/Back/
  Escape clears hotkey; default captures new hotkey). Modifier-only keys,
  Tab/Enter/Space without modifiers now propagate unhandled so Tab focus
  navigation works correctly. (OnPreviewKeyDown does not exist as a
  virtual override in Avalonia TextBox; OnKeyDown is correct.)
- [m1] Remove dead HasKeyChar method (never called)

FilterableComboBox.cs:
- [M2] OnLostFocus: replace reference equality to _editableTextBox with
  IsVisualAncestorOf(focused) (covers all template parts including the
  dropdown popup, not just the TextBox part)
- [M3] AttachSourceFilter: reset _currentFilter = string.Empty before
  ApplyFilter() so a stale filter is not applied to a new source
- [m2]/PR-6 Remove dead FilterItem method
- [m3] FreezeTextBoxState: wrap action() in try/finally so _textBoxFrozen
  is always reset even if action() throws
- PR-3 Subscribe to INotifyCollectionChanged on the new _originalSource
  in AttachSourceFilter; unsubscribe from the old one in OnPropertyChanged
  before replacing _originalSource. This keeps the filtered ItemsSource
  live when items are added/removed in the bound collection (e.g.
  GameSelectorViewModel.DetectedDirectories).
- PR-4 Normalize tb.Text to string.Empty in OnUserTextChanged before
  Length/Substring to avoid NullReferenceException on empty TextBox
- PR-5 Use string.Contains(filter, StringComparison.OrdinalIgnoreCase)
  in ApplyFilter instead of ToLower().Contains(); removes per-item
  allocations and makes matching locale-independent
- Store _currentFilter without lower-casing (OrdinalIgnoreCase does not
  need pre-normalised input)

AudioPlayer.xaml.cs:
- PR-2 Update 4× IsTriggered(e.Key) → IsTriggered(e.Key, e.KeyModifiers)
  (missed call sites from original migration; old 1-arg overload removed)

* fix(P2-006): address second-pass #19 review findings

FilterableComboBox.cs:
- [M1] Add OnDetachedFromVisualTree: unsubscribe from
  INotifyCollectionChanged.CollectionChanged when the control is
  removed from the visual tree. Without this, a long-lived source
  collection (e.g. GameSelectorViewModel.DetectedDirectories) would
  hold a strong reference to the FilterableComboBox instance via the
  event delegate, preventing GC of the control after removal.
- [m2] Remove dead/inverted _lastText == currentText clause from
  TextBoxUserChangeTracker.TextChanged handler. TextChanged never fires
  with equal text in Avalonia, so the clause never executed; removing
  it eliminates confusing dead code (the equality check was logically
  inverted relative to its intended meaning).

Hotkey.cs:
- [S1] Add comment documenting StringEnumConverter round-trip behaviour
  for [Flags] KeyModifiers values (Newtonsoft serialises them as
  comma-separated strings, e.g. "Control, Shift", and round-trips
  correctly through the same format).

* fix(P2-006): address third-pass #19 review findings

FilterableComboBox.cs:
- [m1] Remove dead _lastText field and its two assignment sites
  (constructor init + TextChanged update). The field became unreachable
  after the [m2] fix removed the only read site (_lastText == text
  predicate). No behavioral change.

Hotkey.cs:
- Fix typo in comment: "combinationsthrough" → "combinations through"

* fix(P2-006): use SetCurrentValue in ApplyFilter to preserve XAML binding

FilterableComboBox.cs:
- ApplyFilter previously called ItemsSource = ... which invokes SetValue
  at LocalValue priority, clearing any XAML binding on ItemsSource. If
  the bound ViewModel property is later updated (e.g. the VM replaces
  DetectedDirectories), the severed binding means OnPropertyChanged
  never fires and the new source is never captured.
- Switch to SetCurrentValue(ItemsSourceProperty, filtered) which writes
  the filtered list at LocalValue priority without removing the binding,
  so ViewModel-driven ItemsSource replacements continue to flow through
  normally after filtering has been applied.
2026-03-14 17:32:55 -06:00
Rob Trame
bc74c35dc1
feat(P2-005): migrate CustomRichTextBox (FLogger) and CustomScrollViewer to Avalonia (#72)
* feat(P2-005): migrate CustomRichTextBox (FLogger) and CustomScrollViewer to Avalonia (#18)

CustomRichTextBox:
- Replace WPF RichTextBox / FlowDocument / Hyperlink with AvaloniaEdit.TextEditor
- FLogger converted to static class; removes ITextFormatter / BrushConverter / _previous offset
- Per-segment colouring implemented via LogColorizer : DocumentColorizingTransformer
- LogSegment record tracks offset, length, IBrush, and optional link URL
- Append/Text/Link methods marshal to Dispatcher.UIThread.InvokeAsync (DispatcherPriority.Background)
- Link click handler stubs TODO(P4-001) (OS file manager integration)
- GetBrush() caches parsed Color.Parse(hexString) -> SolidColorBrush per hex string

CustomScrollViewer:
- Replace WPF DependencyProperty / FrameworkPropertyMetadata with Avalonia AttachedProperty<double>
- Changed from ScrollViewer subclass to static helper class
- VerticalOffsetProperty uses AvaloniaProperty.RegisterAttached + Changed.AddClassHandler
- Offset set via ScrollViewer.Offset.WithY(); two-way sync via ScrollChanged event
- Formatter-clean GetVerticalOffset/SetVerticalOffset accessors added

Package updates (FModel.csproj):
- Replace deprecated AvaloniaEdit 0.10.12 with Avalonia.AvaloniaEdit 11.3.0
  (old package unlisted on NuGet; new namespace is AvaloniaEdit.* not ICSharpCode.AvalonEdit.*)
- Serilog 4.3.0 -> 4.3.1 (patch)

Closes #18

* fix(P2-005): address post-review findings in CustomRichTextBox and CustomScrollViewer

CustomScrollViewer:
- Register VerticalOffsetProperty with BindingMode.TwoWay so bare {Binding ScrollPosition}
  in XAML preserves tab scroll-position across tab switches (matches WPF BindsTwoWayByDefault)
- Replace null! with null in _subscribed.Add (no nullable context; operator was semantic no-op)

CustomRichTextBox:
- Move ScrollToEnd() call to end of Append dispatch lambda so it fires once per log event
  rather than once per Text()/Link() segment (n calls per exception → 1 call per Append)
- Replace dead guard Document.LineCount > 0 with Document.TextLength > 0 in ScrollToEnd()
  (TextDocument always has LineCount >= 1; the old guard was never false)

* fix(P2-005): fix CustomScrollViewer subscription and CWT null marker

- Move ScrollChanged subscription before the epsilon guard so viewers
  starting at offset 0.0 still subscribe on their first property set;
  previously the early return prevented subscription entirely in the
  common initial case where bound value == viewer.Offset.Y == 0.0
- Replace null with a static readonly _marker object as the
  ConditionalWeakTable value; null is technically accepted on .NET 8
  but a non-null sentinel is clearer and avoids platform ambiguity
2026-03-14 16:47:43 -06:00
Rob Trame
c6d7a1b148
Re-add missing files 2026-03-14 15:49:23 -06:00
Rob Trame
1506c71665
feat(P2-004): migrate all 26 IValueConverter/IMultiValueConverter implementations to Avalonia (#71)
* feat(P2-004): migrate all 19 converters from WPF to Avalonia (#17)

Migrates every converter in FModel/Views/Resources/Converters/ off
System.Windows.Data / System.Windows.Markup / System.Windows.Shell
and onto Avalonia.Data.Converters equivalents.

Changes by converter:

Simple using-swap only (IValueConverter interface unchanged):
  AnyItemMeetsConditionConverter, CommitMessageConverter,
  DateTimeToDateConverter, FolderToSeparatorTagConverter,
  GameFileMeetsConditionConverter, InvertBooleanConverter,
  IsNullToBoolReversedConverter, RelativeDateTimeConverter,
  StringToGameConverter, TrimRightToLeftConverter

BoolToRenderModeConverter:
  System.Windows.Media.BitmapScalingMode → Avalonia.Media.Imaging.BitmapInterpolationMode
  (NearestNeighbor → None, Linear → HighQuality);
  typed helper method return type updated accordingly.

BorderThicknessToStrokeThicknessConverter:
  System.Windows.Thickness → Avalonia.Thickness (same properties).

InvertBoolToVisibilityConverter:
  Visibility.Visible/Collapsed/Hidden → bool; Avalonia uses IsVisible (bool).
  Hidden concept does not exist on Avalonia — both Collapsed and Hidden map to false.

RatioConverter:
  Removed MarkupExtension base class (PresentationFramework — Windows-only).
  Added Instance singleton; use {x:Static converters:RatioConverter.Instance} in XAML.

RatioToGridLengthConverter:
  System.Windows.GridLength/GridUnitType → Avalonia.GridLength/GridUnitType.
  IMultiValueConverter signature: object[] → IList<object?>, ConvertBack removed.

StatusToTaskbarStateConverter:
  Stubbed out — System.Windows.Shell.TaskbarItemProgressState has no cross-platform
  Avalonia equivalent. Returns null; tracked by TODO(P2-015).
  MarkupExtension removed; added Instance singleton.

TabSizeConverter:
  System.Windows.Controls.TabControl → Avalonia.Controls.TabControl.
  ActualWidth → Bounds.Width; Items.Count → ItemCount.
  IMultiValueConverter: object[] → IList<object?>, ConvertBack removed.

FileToGeometryConverter:
  System.Windows.Media.{Geometry,Brush} → Avalonia.Media.{Geometry,IBrush}.
  Application.Current.FindResource → Application.Current.TryGetResource(key, null, out var r).
  IMultiValueConverter: object[] → IList<object?>, ConvertBack removed.

FolderToGeometryConverter:
  Same Geometry/IBrush/TryGetResource changes as FileToGeometryConverter.

Already migrated (no changes):
  BoolToToggleConverter, CaseInsensitiveStringEqualsConverter,
  EndpointToTypeConverter, EnumToStringConverter, IsNotZeroConverter,
  MultiParameterConverter, SizeToStringConverter

Build: 1266 errors baseline → 1174 after this commit (92 fewer).
Zero errors introduced in Converters/.

* fix(P2-004): address PR #71 review findings

M1 (PR comment): FolderToGeometryConverter — remove duplicate if condition
  (copy-paste artifact: identical guard appeared twice consecutively)

M2 (PR comment): TabSizeConverter — two fixes
  - divisor guard: return 0 when ItemCount == 0 to prevent divide-by-zero
  - double.Parse now uses CultureInfo.InvariantCulture (XAML ConverterParameter
    values are always invariant-culture strings; avoids FormatException on
    locales that use comma as decimal separator)

PR comment: BoolToRenderModeConverter — typed helper Convert(bool) now
  implements the mapping directly instead of delegating to the interface
  method with null culture; eliminates fragile null-culture call chain

m2: StatusToTaskbarStateConverter — reverted from IMultiValueConverter back
  to IValueConverter to match the original WPF single-value binding contract
  (EStatusKind → TaskbarItemProgressState was always a single-value binding);
  also removed unused System.Collections.Generic using

m1: Aligned all ten 'simple-swap' IValueConverter implementations to use
  Avalonia-idiomatic nullable signatures (object? value, object? parameter,
  object? return) matching the Avalonia interface definition; previously these
  retained the non-nullable WPF-era signatures which were inconsistent with the
  nine converters already updated in the same commit

S1: Renamed InvertBoolToVisibilityConverter class → InvertBoolConverter to
  reflect that it returns bool (for IsVisible) not WPF Visibility;
  file rename is deferred pending terminal access
2026-03-14 15:40:56 -06:00
Rob Trame
24c6a68cce
[P2-003] Migrate all 10 dialog Windows from WPF/AdonisUI to Avalonia (#70)
* feat(P2-003): migrate all 10 dialog Windows from WPF/AdonisUI to Avalonia

Resolves #16 [P2-003] Migrate all 11 XAML view windows to Avalonia Window.

Views migrated (XAML + code-behind):
- About: root Window, AdonisUI namespace/styles removed
- AesManager: root Window, BoolToVisibility→IsVisible, ListView→DataGrid
- AudioPlayer: root Window, CSCore TODO stubs, OpenFileDialog TODO stub
- BackupManager: root Window, IsNotZeroConverter for IsEnabled binding
- CustomDir: root Window, AdonisUI removals
- DirectorySelector: root Window, AdonisUI removals, Visibility→IsVisible
- ImageMerger: root Window, BitmapImage→Avalonia Bitmap, WPF dialogs→TODO stubs
- SearchView: root Window, ListView+GridView→DataGrid x2, ContextMenus
- SettingsView: root Window, DataTriggers→IsVisible/HyperlinkButton/converters,
  SelectedItemChanged→SelectionChanged, VistaFolderBrowserDialog→TODO stub
- UpdateView: root Window, adonisControls:SplitButton→SplitButton+MenuFlyout

Support:
- FModel.csproj: add Avalonia.Controls.DataGrid v11.3.12
- Add IsNotZeroConverter (Avalonia.Data.Converters IValueConverter)

* chore(P2-003): apply post-push refinements to migrated view files

* fix: address review findings from Avalonia migration code review

Critical:
- MainWindow.xaml.cs: unsubscribe all PropertyChanged handlers in OnClosing to
  prevent memory leak and use-after-free on restart (C2)
- MainWindow.xaml.cs: remove ConfigureAwait(false) from async void OnLoaded —
  continuation must stay on Avalonia UI thread (C1)

Major:
- MainWindow.xaml: replace WPF KeyboardNavigation.TabNavigation with
  Avalonia IsTabStop="False" on the feature-preview CheckBox (M3)
- MainWindow.xaml.cs: guard PixelDensity against zero in OnLoaded (m2)
- MainWindow.xaml.cs: add _syncingSelection re-entrancy guard to SyncSelection
  to prevent infinite SelectionChanged event loop (m4)
- App.xaml.cs: add try/catch inside ShowErrorDialog async lambda to prevent
  silent exception swallowing; add TaskScheduler.UnobservedTaskException
  handler in OnFrameworkInitializationCompleted (M1, S1)
- App.xaml.cs: remove redundant Environment.Exit(0) from AppExit handler (m1)
- Helper.cs: null-guard GetWindow<T> return value; add comment re: Show() race (S2)

Views (review fixes):
- SettingsView.xaml.cs: replace TryBrowse/OnBrowseMappings stubs with real
  StorageProvider implementations (OpenFolderPickerAsync, OpenFilePickerAsync)
- ImageMerger.xaml.cs: fix async void + MemoryStream disposal in OnExport
- UpdateView.xaml: fix Grid nesting of ItemsControl + empty-state TextBlock;
  add IsNotZeroConverter-based empty-state visibility
- CustomDir.xaml/cs, DirectorySelector.xaml/cs: cancel button handlers
- Converters: migrate System.Windows.Data IValueConverter usings to
  Avalonia.Data.Converters for BoolToToggleConverter, EndpointToTypeConverter,
  EnumToStringConverter, IsNotZeroConverter, SizeToStringConverter

* fix: address second-round review findings

C1 - SettingsView.xaml.cs: replace WPF editor ShowDialog() calls with
  async void stubs + TODO(P2-016) comments; DictionaryEditor and
  EndpointEditor are not yet migrated to Avalonia so these used the
  WPF synchronous ShowDialog() which is unavailable and returns the
  wrong type

C2 - UpdateView.xaml: add TODO noting CommitsView is still a WPF
  System.Windows.Data.ListCollectionView; once UpdateViewModel is
  migrated the Count binding should be replaced with a dedicated
  HasNoCommits bool property for reliable INPC notification

M1+S1 - Helper.cs: null-guard GetOpenedWindow result in OpenWindow<T>
  to prevent NRE if the window deregisters between IsWindowOpen and
  the dereference

M2 - MainWindow.xaml.cs: add TODO tech-debt comment on the double
  UpdateStatusLabel dispatch when Kind changes; note consolidation
  into a single UpdateStatusUI() for a later pass

M3 - ImageMerger.xaml.cs: replace ContinueWith(..., FromCurrentSync-
  Context()) with try/finally after await Task.Run; eliminates the
  synchronization-context capture hazard when called via ConfigureAwait

m1 - App.xaml.cs: UnobservedTaskException now calls ShowErrorDialog
  for unexpected faults; silently absorbs OperationCanceledException;
  SetObserved() moved before the early-return guard

m2 - IsNotZeroConverter.cs: fix 2-space indentation to 4-space to
  match rest of codebase

m3 - EndpointToTypeConverter.cs: replace misleading NotImplemented-
  Exception with ArgumentException carrying a descriptive message

* fix: address third-round review findings

- App.xaml.cs: check all InnerExceptions for OperationCanceledException,
  not just InnerException[0], so a mixed AggregateException is never
  silently absorbed (m1)
- Helper.cs: add Dispatcher.UIThread.RunJobs() between Show() and the
  window-registry lookup in GetWindow<T> to close the registration race
  on first open (S1); also add missing System.Collections.Generic using
  that caused a pre-existing IEnumerable<> CS0246 error
- SettingsView.xaml.cs: clarify EndpointEditor TODO comments — original
  WPF code used ShowDialog() (modal), so migration target is
  ShowDialog(this), not Show() (m2)

* fix: add missing System.Linq using in App.xaml.cs

InnerExceptions.All() is a LINQ extension method. The project has no
implicit usings, so the explicit using was required. The build check
after the previous commit only grepped for Helper.cs errors, so the
CS1061 on App.xaml.cs was not caught until the follow-up review.

* fix: address PR reviewer findings across six view files

C1 - AudioPlayer.xaml: replace undeclared adonisUi:Brushes.ForegroundBrush
     DynamicResource (compile error) with Fill="White", consistent with all
     other icon paths in the file.

C2 - SettingsView.xaml.cs: fix OnBrowseMappings storing into non-existent
     UserSettings.Default.MappingsPath; now sets
     _applicationView.SettingsView.MappingEndpoint.FilePath which is the
     property the XAML TextBox is bound to (compile error + silent data loss).

C3 - UpdateView.xaml: remove WPF-only ItemsControl.GroupStyle / GroupStyle /
     GroupItem / HeaderStringFormat block (XAML parse failure on Avalonia).
     Date grouping will be re-added alongside the CommitsView ViewModel
     migration (see existing TODO). Also fix FallbackValue=False → 0 so
     IsNotZeroConverter receives the expected int type when the binding
     target can't be resolved.

M1 - ImageMerger.xaml.cs (UpButton case): remove spurious
     SelectedItems.Add(indices) call which was adding the raw int[] to the
     selected-items collection. Items are already marked IsSelected=true
     inside the move loop; the Add call was a no-op at best and a runtime
     inconsistency at worst.

M2 - DirectorySelector.xaml: remove self-referential
     Width={Binding ActualWidth, ElementName=OkGuysButWhoFuckingAsked}
     (control binding its own width to itself — produces binding warnings
     and has no useful effect; layout is determined by content/padding).

m1 - SearchView.xaml.cs: restore WPF DataTrigger behavior — subscribe to
     PropertyChanged on each SearchViewModel and update the corresponding
     TextBox.Watermark when HasRegexEnabled toggles, giving 'Write your
     regex pattern...' vs 'Write your pattern...' hint text.

* fix: unsubscribe PropertyChanged handlers in SearchView on close

SearchVm and RefVm are application-lifetime singletons. Subscribing
anonymous lambdas capturing 'this' (the window's TextBox fields)
meant each closed-and-reopened SearchView was kept permanently
alive by the singletons' PropertyChanged invocation lists.

Fix: promote the handlers to named local functions, cache the VM
references at construction time, and unsubscribe both handlers in
the Closed event so the window becomes eligible for GC immediately
after it is closed.

Also adds the required 'using System.ComponentModel' for the
PropertyChangedEventArgs parameter type.

* fix: migrate WPF converters to Avalonia.Data.Converters interfaces

CaseInsensitiveStringEqualsConverter: replace System.Windows.Data.IValueConverter
with Avalonia.Data.Converters.IValueConverter. Avalonia cannot call WPF converter
implementations, so any SettingsView.xaml binding using this converter would fail
silently at runtime. Also null-guards value/parameter before calling .ToString()
to avoid NREs on binding fallback values.

MultiParameterConverter: replace System.Windows.Data.IMultiValueConverter with
Avalonia.Data.Converters.IMultiValueConverter. The Avalonia interface takes
IList<object?> rather than object[], so update the signature accordingly. Return
values.ToArray() to preserve the same object[] snapshot that the WPF
values.Clone() call produced, keeping CommandParameter multi-binding callers in
SearchView.xaml working. Avalonia's IMultiValueConverter has no ConvertBack, so
that method is removed.
2026-03-14 15:02:31 -06:00
Rob Trame
7e66c44f90
chore: update identity, branding, and CI for FModel Linux fork (#69)
* chore: update identity, branding, and CI for FModel Linux fork

- README.md: complete rewrite with fork identity disclaimer, upstream
  attribution, updated links, and removal of sponsorship section
- NOTICE: add upstream FModel GPL-3 attribution; update library list
  (add Avalonia/AvaloniaEdit/Svg.Skia/Twizzle.ImGui-Bundle.NET, remove
  AdonisUI/AutoUpdater.NET/CSCore/ImGui.NET/Ookii.Dialogs.Wpf)
- Constants.cs: update ISSUE_LINK and GH_REPO to r6e/FModel-Linux;
  clear DISCORD_LINK pending app registration
- FModel.csproj: add opt-in USE_FMODEL_API build flag
  (-p:UseFModelApi=true) for upstream api.fmodel.app integration
- FModelApiEndpoint.cs: gate all api.fmodel.app calls behind
  #if USE_FMODEL_API; rewrite CheckForUpdatesAsync to use GitHub
  Releases API and return GitHubRelease? for caller-side notification
- GitHubApiEndpoint.cs: add GetLatestReleaseAsync() for /releases/latest
- GitHubResponse.cs: add TagName/HtmlUrl/Body to GitHubRelease; replace
  AutoUpdater.DownloadUpdate with Process.Start(UseShellExecute=true)
- MainWindow.xaml.cs: surface update availability via FLogger [WRN] entry
  at startup when a newer GitHub release is found
- DiscordService.cs: disable RPC (empty APP_ID, early-return guard)
  pending Discord application registration for the fork
- About.xaml: version label reads 'FModel Linux {0}'; dual credit lines
  for Asval (original) and Rob Trame (Linux port)
- AboutViewModel.cs: update description, contributors, and references
  list to reflect current Avalonia-based dependency set
- .github/workflows: target ubuntu-latest, linux-x64, net8.0; remove
  fmodel.app deploy steps; rename artifact to FModel-Linux.zip
- .github/ISSUE_TEMPLATE: update assignee and remove Discord link
- .github/FUNDING.yml: note donation link points to upstream project

* Fix whitespace issues

* chore: address PR review feedback

- NOTICE: remove orphaned MS-PL and BSD 3-Clause license texts; the
  index already lists only MIT and Apache 2.0, and no current dependency
  uses either of those licenses
- GitHubResponse.cs: guard against null Asset/BrowserDownloadUrl in
  Download(); log a warning via Serilog instead of NullReferenceException
  or re-throwing InvalidOperationException
- MainWindow.xaml.cs: run update check in a background Task.Run to
  avoid blocking startup; post FLogger notification back on
  Dispatcher.UIThread; swallow exceptions so a failed check never
  impacts startup
- FModelApiEndpoint.cs: log a warning when the current application
  version string cannot be parsed, matching the existing behaviour for
  an unparseable latest-release tag
- .github/workflows: add `permissions: contents: write` to both
  main.yml and qa.yml (GitHub Advanced Security finding)

* chore: address second round of PR review feedback

- NOTICE: add missing direct NuGet dependencies —
  EpicManifestParser.ZlibngDotNetDecompressor, Serilog.Sinks.Console,
  Serilog.Sinks.File, and SkiaSharp.HarfBuzz — each with their
  respective copyright notice and license (MIT / Apache 2.0)
- FModelApiEndpoint.cs: remove now-unused _applicationView property
  (CheckForUpdatesAsync was refactored to use GitHubApi directly;
  _applicationView is dead code outside of #if USE_FMODEL_API blocks)
- DiscordService.cs: fix DiscordRpcClient being constructed at
  field-init time with an empty APP_ID string; make _client nullable
  and only instantiate when APP_ID is non-empty; update all call sites
  to use null-safe pattern matching (_client is not { IsInitialized:
  true }) so callers are safe without runtime client construction

* chore: address third round of PR review feedback

- MenuCommand.cs: guard Help_Discord action against empty DISCORD_LINK;
  Process.Start with an empty FileName throws at runtime, so the action
  is now a no-op when no Discord server URL is configured
- qa.yml: zip the full publish output directory (./FModel/bin/Publish/)
  rather than just the single executable; --no-self-contained publishes
  companion files (*.deps.json, *.runtimeconfig.json) that are required
  at runtime alongside the PublishSingleFile output
- main.yml: same fix — zip ./FModel/bin/Publish/ so the release artifact
  includes all required publish outputs, not just the executable

* Update FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-12 11:13:00 -06:00
Rob Trame
3afea6c9fd
feat(#15): migrate MainWindow.xaml + MainWindow.xaml.cs to Avalonia Window (#68)
* feat(#15): migrate MainWindow.xaml + MainWindow.xaml.cs to Avalonia Window

- Replace AdonisWindow root with Avalonia Window, remove all adonisUi xmlns
- Remove TaskbarItemInfo XAML block (guarded stub in code-behind)
- Replace StatusBar/StatusBarItem + WPF Style.Triggers with Border+DockPanel
- Replace Border.Triggers Storyboard with Avalonia Transitions + :pointerover
- Replace ToggleButton WPF trigger style with Avalonia selector style
- Rewrite MainWindow.xaml.cs: remove WPF CommandBindings/RoutedCommand,
  update event handler signatures, add PropertyChanged-based status bar
  color updates and window title updates (replacing WPF DataTrigger logic)
- Add OnLoaded screen sizing via Screens.Primary.WorkingArea
- Add [SupportedOSPlatform(windows)] InitTaskbarInfo stub
- Helper.cs: replace Application.Current.Windows with
  IClassicDesktopStyleApplicationLifetime.Windows, remove Activate()
- App.xaml.cs: wire desktop.MainWindow = new MainWindow()

* fix(#15): remove double UpdateStatusLabel invocation per SetStatus call

OnStatusKindChanged Kind branch now only calls UpdateStatusBarColor().
UpdateStatusLabel() is driven exclusively by the Label branch, which
always fires immediately after Kind during SetStatus() because distinct
enum states always produce distinct label strings — so SetProperty on
Label always raises PropertyChanged, guaranteeing the Label branch runs.
This eliminates the redundant double-invoke without any behavioral change.

* Address review feedback
2026-03-11 21:36:29 -06:00
Rob Trame
4d82992237
phase2: migrate App.xaml + App.xaml.cs to Avalonia bootstrap (#14) (#67)
* feat(#14): migrate App.xaml + App.xaml.cs to Avalonia bootstrap

- App.xaml: replace WPF/AdonisUI xmlns with Avalonia xmlns=https://github.com/avaloniaui; add FluentTheme; remove AdonisUI MergedDictionaries and BooleanToVisibilityConverter (Views/Resources/* will be re-added as they are migrated in later issues)
- App.xaml.cs: inherit Avalonia.Application; OnFrameworkInitializationCompleted replaces OnStartup; AppExit wired via IClassicDesktopStyleApplicationLifetime.Exit; AdonisUI MessageBox replaced with inline Avalonia Window dialog; P/Invokes guarded with OperatingSystem.IsWindows(); GetRegistryValue guarded for Linux (P3-006 will replace fully)
- Program.cs (new): Avalonia entry point with BuildAvaloniaApp + Main; AppDomain.UnhandledException registered to drive ShowErrorDialog
- AssemblyInfo.cs: remove WPF ThemeInfoAttribute (no Avalonia equivalent)
- FModel.csproj: StartupObject -> FModel.Program; add Serilog.Sinks.Console 6.1.1 (needed for AnsiConsoleTheme in debug logger); exclude Properties/Resources.resx + Designer.cs (WPF boilerplate, unreferenced)

Closes #14

* fix(#14): address code review findings in App bootstrap

[C1] Replace AppDomain.UnhandledException with Dispatcher.UIThread
     .UnhandledExceptionFilter — fires on UI thread, allows Handled=true
[C2] Wrap dialog.Show() fallback in try/catch; return early if app is
     shutting down to avoid silent crash
[M1] Add TODO(#15) comment for desktop.MainWindow assignment
[M2] Change Dispatcher.UIThread.Post → InvokeAsync; restructure
     ShowErrorDialog to only use tcs.Task in the modeless path
[M3] Restore Environment.Exit(0) in AppExit to preserve original
     termination behaviour until proper cancellation is in place
[m2] Add SolidColorBrush resources (AccentColorBrush, AlertColorBrush,
     ErrorColorBrush) alongside Color resources in App.xaml

* fix(#14): address second-pass review findings

[m1/s1] Move Dispatcher.UIThread.UnhandledExceptionFilter subscription
        to after Log.Logger is configured; Log.Error calls inside the
        handler were no-ops when exceptions occurred during the ~80-line
        init block (settings load, directory creation)
[m2]    Attach .ContinueWith(OnlyOnFaulted) to the InvokeAsync task in
        ShowErrorDialog so secondary exceptions in the error-handling
        path (UserSettings.Delete, Restart) are logged rather than
        silently swallowed as unobserved task faults

* Address review feedback
2026-03-11 20:32:20 -06:00
Rob Trame
21183927e8
chore: point CUE4Parse submodule at r6e/CUE4Parse-Linux (#66)
Update .gitmodules URL from FabianFG/CUE4Parse to
r6e/CUE4Parse-Linux and pin to commit 06fbf1ac which adds
Linux-compatible libdetex.so and libtegra_swizzle_x64.so
alongside the Windows DLLs, with RID-aware loading in
DetexHelper and PlatformDeswizzlers.

Closes #10
2026-03-11 19:49:17 -06:00
Rob Trame
51b05e2ffa
chore: remove Autoupdater.NET.Official (WPF-only auto-updater) (#65)
Autoupdater.NET.Official requires WPF for its built-in download dialog
and cannot be used on Linux. Cross-platform replacement is tracked
in #51 (P4-005).

Closes #9 in r6e/FModel-Linux
2026-03-11 18:04:03 -06:00
Rob Trame
72cb906da6
chore: remove VirtualizingWrapPanel (WPF-only panel) (#64)
VirtualizingWrapPanel is a WPF-only third-party panel control.
Replacement with Avalonia's built-in WrapPanel or a community
virtualized panel is tracked in Phase 2 UI migration work.

Closes #6 in r6e/FModel-Linux
2026-03-11 18:01:50 -06:00
Rob Trame
23960d1266
chore: remove CSCore (Windows-only audio engine) (#63)
CSCore uses WASAPI, DirectSound and MediaFoundation APIs that are
unavailable on Linux. Call-site replacement with a cross-platform
audio backend (OpenTK.Audio.OpenAL) is tracked in #40 (P3-013).

Closes #13 in r6e/FModel-Linux
2026-03-11 17:59:11 -06:00
Rob Trame
77431d8c1b
chore: remove Ookii.Dialogs.Wpf (WPF-only folder dialog) (#62)
Ookii.Dialogs.Wpf depends on PresentationFramework and cannot be
restored on Linux. Call-site replacement with Avalonia StorageProvider
is tracked in #48 (P4-004).

Closes #11 in r6e/FModel-Linux
2026-03-11 17:56:18 -06:00
Rob Trame
471bb22b13
chore: replace AvalonEdit with AvaloniaEdit (#61)
- Remove AvalonEdit 6.3.1.120 (WPF-only text editor)
- Add AvaloniaEdit 0.10.12 (Avalonia port, API-compatible)

Existing .xshd syntax definition files (Changelog.xshd, Cpp.xshd,
Ini.xshd, etc.) are format-compatible with AvaloniaEdit and require
no changes at this stage.

Closes #12 in r6e/FModel-Linux
2026-03-11 17:52:44 -06:00
Rob Trame
903aad35c9
[P1-002] Replace AdonisUI with Avalonia UI packages (#60)
* chore: replace AdonisUI with Avalonia UI packages

- Remove AdonisUI 1.17.1 (WPF-only)
- Remove AdonisUI.ClassicTheme 1.17.1 (WPF-only)
- Add Avalonia 11.3.12 (core framework)
- Add Avalonia.Desktop 11.3.12 (desktop host)
- Add Avalonia.Themes.Fluent 11.3.12 (cross-platform theme)

Closes #8 in r6e/FModel-Linux

* chore: add Avalonia.Fonts.Inter for consistent Linux font rendering

Without this package, Avalonia falls back to the system fontconfig font
on Linux, which varies by distro and can produce missing glyphs on
minimal CI runners. Inter gives a consistent cross-platform baseline.
2026-03-11 17:48:21 -06:00
Rob Trame
a8966ae9c1
chore: migrate TFM from net8.0-windows to net8.0 (#59)
- Change TargetFramework from net8.0-windows to net8.0
- Remove UseWPF (not used by Avalonia)
- Change OutputType from WinExe to Exe (cross-platform)
- Remove hardcoded RuntimeIdentifier win-x64 (supply at publish time)

Closes #7 in r6e/FModel-Linux
2026-03-11 17:38:48 -06:00
Rob Trame
ec0bb2b43b
Finish setting up env 2026-03-11 17:28:01 -06:00
Rob Trame
62a0d846f9
Set up dev env 2026-03-11 15:51:34 -06:00
Masusder
c9542f1a91 Aion 2, Crystal of Atlan, Fate Trigger, WuWa and The First Descendant updates
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2026-03-06 11:56:16 +01:00
Asval
d2fe259adc bump c4p + a few settings changes + fix #647
Some checks failed
FModel QA Builder / build (push) Has been cancelled
export raw data is now disabled by default (see settings)
2026-03-01 17:20:05 +01:00
Masusder
fd4eb0a418
Borderlands 3 audio (#649)
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2026-02-25 16:24:43 +01:00
LongerWarrior
7fab3e2ead Titan Quest 2 update, Windrose support
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2026-02-22 16:47:06 +02:00
LongerWarrior
83b5330d1e Fix issue with animation RateScale
Co-authored-by: Asval <asval.contactme@gmail.com>
2026-02-22 16:36:48 +02:00
Masusder
500fa59f85
Option for bulk audio conversion (#646)
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2026-02-18 17:40:15 +01:00
LongerWarrior
1c48a27f8e InitOodle update, High on Life 2 and Borderlands 4 Audio support
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2026-02-17 01:51:22 +02:00
Masusder
6b3a4ae785
Borderlands 4 - GbxAudio support (#645)
Some checks are pending
FModel QA Builder / build (push) Waiting to run
2026-02-16 02:05:52 +02:00
ᴅᴊʟᴏʀ3xᴢᴏ
40ed646dcd
Fix HTML tags in some Quests DisplayName. (#640)
Some checks failed
FModel QA Builder / build (push) Has been cancelled
* Fix HTML tags in some Quests DisplayName.

* New Backups & Hotfixes API

* fix backups being null

---------

Co-authored-by: GhostScissors <79089473+GhostScissors@users.noreply.github.com>
2026-02-11 20:33:50 +05:30
Marlon
bd2e924925
Merge pull request #643 from Krowe-moh/patch-1
Some checks are pending
FModel QA Builder / build (push) Waiting to run
2026-02-11 14:04:30 +01:00
Krowe Moh
dee4ecab9c
Prevents ImGui assert from AddFontFromFileTTF 2026-02-11 23:57:59 +11:00
LongerWarrior
e47b3ac6bb
WWise refactor and Wuthering Waves, Neverness To Everness update
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2026-02-10 01:28:43 +02:00
LongerWarrior
87fe6ed09d bump cue4parse 2026-02-10 01:10:24 +02:00
Masusder
508dcb4c7a Wwise media assets + .adx fallback 2026-02-08 12:49:50 +01:00
LongerWarrior
40996973eb Code Vein 2, Infinity Nikki update
Some checks failed
FModel QA Builder / build (push) Has been cancelled
Ashes of Creation dbc extraction
2026-02-03 00:35:13 +02:00
Marlon
14e05da2e0
fixed line endings to lf to match editorconfig
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2026-01-27 14:17:43 +01:00
Marlon
892dd8cdef
latest oodle dl 2026-01-27 14:10:13 +01:00
Marlon
1e2b1b1e3e
support for .UONDEMANDTOC files 2026-01-26 15:09:30 +01:00
Masusder
ef906084fb Bump CUE4Parse
I forgot
2026-01-25 18:06:48 +01:00
Masusder
669b07f807
Overall improvements (#633) 2026-01-25 17:49:44 +01:00
Fabian
31d426f795
Merge pull request #635 from LeleDerGrasshalmi/fix-bp-decompiling-disabled
Allow "decompile bp" for other bp types
2026-01-25 17:32:10 +01:00
Lele
667e5ef7b9
Fix "decompile bp" being disabled (typo) 2026-01-25 14:52:27 +01:00
Marlon
b4a5e05c8a
cue4parse update 2026-01-24 19:33:09 +01:00
Marlon
aae182d8e4
wwise fix 2026-01-24 19:30:47 +01:00
Marlon
3eb4c0d4be
update fn engine version 2026-01-24 18:36:31 +01:00
Masusder
b9315cc298
'The Dark Pictures Anthology: House of Ashes' Wwise support (#632)
* 'The Dark Pictures Anthology: House of Ashes' Wwise support

* AnyItemMeetsConditionConverter.ConditionMode

---------

Co-authored-by: Asval <asval.contactme@gmail.com>
2026-01-19 20:33:32 +01:00
LongerWarrior
86ec2a931e Assault Fire Future support
Ace Combat 7 wwise fixes
2026-01-19 19:21:58 +02:00
LongerWarrior
8de4402032 The Finals, Styx Blades of Steel, Palia, StarRupture, Octopath Traveler CoTC support
Dune Awakening, GrayZoneWarfare update
2026-01-13 22:52:22 +02:00
Asval
fe4529908e some post update fixes
Some checks failed
FModel QA Builder / build (push) Has been cancelled
2025-12-22 00:02:37 +01:00
LongerWarrior
2415c50698 PUBG Black Budget support
Valorant mappings endpoint
2025-12-22 01:00:24 +02:00
Masusder
8b95b403bb
New Explorer System (#619)
Some checks failed
FModel QA Builder / build (push) Has been cancelled
+ filter by types, find by references (UE5+), and a lot of other improvements

Co-authored-by: Asval <asval.contactme@gmail.com>
Co-authored-by: LongerWarrior <LongerWarrior@gmail.com>
2025-12-19 18:34:33 +01:00