Unreal Engine Archives Explorer
Go to file
Rob Trame c5bc12e618
fix: address remaining WPF→Avalonia migration gaps (issue #82) (#83)
* fix: address remaining WPF→Avalonia migration gaps (issue #82)

Critical fixes:
- C1: RatioToGridLengthConverter — add missing using Avalonia.Controls
- C2/C3: ApplicationViewModel — remove AdonisUI MessageBox, async ShowDialog,
  IClassicDesktopStyleApplicationLifetime.Shutdown()
- C4: ImageCommand — Avalonia Window, BitmapInterpolationMode, PixelSize
- C5: TabCommand/CopyCommand — Avalonia async clipboard with error logging
- C6: ImGuiController — DPI via screen.PixelDensity
- C7: ClipboardExtensions — Avalonia DataObject with PNG bytes, InvokeAsync

Major fixes:
- M1: Timeclock — full StyledProperty rewrite, UI-thread-safe event handlers
- M2: DictionaryEditor/EndpointEditor — Avalonia Window + AvaloniaEdit
- M3: CommitDownloaderControl — Avalonia UserControl + StyledProperty
- M4: FileButton2/FolderButton2/FolderButton3 — Avalonia XAML, restore
  NumTextures badge and colored separator in FileButton2
- M5: Breadcrumb — Avalonia XAML + pointer events
- M6: CUE4ParseViewModel — Helper.CloseWindow<Window>
- M7: App.xaml.cs — e.RequestCatch replacing e.Handled
- M8: FileContextMenu — Avalonia namespace + IsVisible

Minor/other fixes:
- Enable <Nullable> in csproj
- OnTagDataTemplateSelector stub + SettingsView code-behind template selection
- TiledExplorer/Resources.xaml — full Avalonia rewrite (style selectors,
  WrapPanel, IDataTemplate, attached behaviors, converter-based empty state)
- ListBoxItemBehavior — Avalonia AttachedProperty with 3 behaviors
- TypeDataTemplateSelector — IDataTemplate with FolderContextMenu attachment
- SmoothScroll — Avalonia AttachedProperty + PointerWheelChanged
- Remove dead code-behind from Resources.xaml.cs
- Remove unsupported IsAsync=True from bindings
- Remove duplicate CornerRadius property from Timeclock
- New converters: AssetExtensionToIconConverter, IntGreaterThanZeroConverter,
  IsNullToBoolConverter, ItemsSourceEmptyToBoolConverter
- FolderToGeometryConverter — add bool return for IsVisible bindings

Closes #82

* fix: address PR #83 review comments

- RestartWithWarning: restore user-visible Avalonia dialog before restart
  (matches original WPF MessageBox.Show behavior)
- UpdateProvider: add null guards for nullable AesManager/CUE4Parse
- FolderContextMenu: add .ContinueWith error logging on clipboard write
- SettingsView: replace throwing FindResource with TryFindResource
- SmoothScroll: cache ScrollViewer in ConditionalWeakTable to avoid
  per-event visual tree walks
- ListBoxItemBehavior: replace throwing FindResource with TryFindResource;
  move e.Handled inside success block so it's only set when menu opens

* fix: address correctness review and second round PR comments

- C1: Fix FolderButton3 LinearGradientBrush StartPoint/EndPoint to use
  relative percentage format (0%,0%/0%,100%) instead of absolute pixels
- M1: TypeDataTemplateSelector resolves FolderContextMenu per-control via
  AttachedToVisualTree + TryFindResource instead of shared Application lookup
- M2: Replace 19 unresolvable SystemColors.ControlTextBrushKey references
  with #DAE5F2 in FileContextMenu.xaml and FolderContextMenu.xaml
- M4: RestartWithWarningAsync non-modal fallback awaits dialog.Closed via
  TaskCompletionSource before calling Restart()
- mn1: EndpointEditor adds _isInitialized flag to suppress TextChanged
  during construction (restores WPF IsLoaded guard behavior)
- S1: Timeclock unsubscribes from Source events in OnDetachedFromVisualTree

Second round PR comments:
- Fix SmoothScroll ConditionalWeakTable.AddOrUpdate → Add (API doesn't exist)
- AvoidEmptyGameDirectoryAsync falls back to MainWindow when owner is null
- Remove unused fileName parameter from ClipboardExtensions.SetImage

* Address PR review findings and reviewer comments

Review findings addressed:
- [M1] Wire 5 Settings dialog handlers (OpenCustomVersions, OpenOptions,
  OpenMapStructTypes, OpenAesEndpoint, OpenMappingEndpoint) to actual
  DictionaryEditor/EndpointEditor modal calls instead of no-op stubs
- [M2] Add TODO(P3-perf) comment documenting WrapPanel virtualization tradeoff
- [m1] Add template fallback in SettingsView to clear ContentTemplate on
  failed resource lookup
- [m2] Improve clipboard image format parity by adding PNG and Bitmap formats
- [S1] Replace hardcoded #DAE5F2 icon fills with DynamicResource
  SystemColors.ControlTextBrushKey in both context menus
- [S2] Simplify TypeDataTemplateSelector by removing redundant global guard

PR reviewer comments addressed:
- EndpointEditor: Fix OnTextChanged signature (EventArgs -> TextChangedEventArgs)
- FolderContextMenu: Fix FindAncestor to use GetVisualAncestors() instead of
  unreliable Parent cast chain
- CommitDownloaderControl: Fix button Width binding (.Bounds.Height ->
  .Height) to avoid zero during initial layout
- ApplicationViewModel: Make RestartWithWarningAsync okButton a direct reference
  instead of brittle Children[1] index cast

* Address review findings and PR comments (round 2)

Major fixes:
- M1: ImGuiController now probes Linux font directories (DejaVu Sans,
  Liberation Sans, Noto Sans) instead of hardcoding Windows paths
- M2: ClipboardExtensions.SetImage wraps MemoryStream/Bitmap in using
  statements to prevent native resource leaks
- M3: ImageCommand divides PixelSize by DPI scale for correct HiDPI
  window sizing

Minor fixes:
- m1: Document Timeclock threading contract for CalculateTime
- m2: CommitDownloaderControl uses fixed 32x32 button size instead of
  Bounds-based binding that yields 0 during initial layout
- m3: Resources.xaml reformatted to consistent indentation
- m4: FolderToGeometryConverter adds parentheses for operator precedence

Suggestions applied:
- S1: Extract ClipboardExtensions.SetText helper; update CopyCommand,
  TabCommand, and FolderContextMenu to use it consistently

PR comments addressed:
- FileContextMenu.xaml: Replace fragile $parent[Window].DataContext with
  Opened handler that resolves DataContext from PlacementTarget visual tree
  (new FileContextMenu.xaml.cs code-behind)
- RestartWithWarningAsync: Accept optional Window owner parameter so
  callers (SettingsView) can pass their window for proper modal parenting
- ClipboardExtensions bitmap leak: Fixed (same as M2)

No new build errors introduced (78 pre-existing in unmigrated files).

* fix: address second review findings (M1, M2, m1, m2, S1) and TitleExtra null guard

- Remove [AggressiveInlining] from ResolveFontPaths and cache result
  in static Lazy<> (M1 + S1)
- Remove using disposal on Bitmap/MemoryStream in SetImage to prevent
  ObjectDisposedException on X11 deferred clipboard reads (M2)
- CommitDownloader button now binds Height to sibling grid, restoring
  parent-relative sizing with MinWidth/MinHeight fallback (m1)
- Add Log.Warning when FileContextMenu cannot find Window ancestor (m2)
- Guard TitleExtra against null CurrentDir (unresolved PR comment)

* fix: address third review findings and 3 unresolved PR comments

- ClipboardExtensions.SetImage: dispose MemoryStream after Bitmap
  decoding (Bitmap copies pixel data during construction); keep Bitmap
  alive for X11/Wayland deferred clipboard rendering
- MenuCommand: add null guards for CUE4Parse before dereferencing in
  Directory_Backup, Directory_ArchivesInfo, Views_3dViewer, and
  ToolBox_Collapse_All cases
- CommitDownloaderControl: revert to deterministic Width=32 Height=32
  to avoid Bounds.Height instability during initial layout

* fix: breadcrumb button filter, one-shot context menu, nullable guards

- Breadcrumb: filter PointerReleased by left button only (M2)
- TypeDataTemplateSelector: one-shot AttachedToVisualTree handler (m1)
- DictionaryEditor: initialize properties to empty defaults, null-coalesce
  DeserializeObject results (PR comment)
- Resources.xaml: document SelectionMode mapping (S1)

* fix: CurrentDir NRE guard, discard ExtractAsync, clean up null checks

- ApplicationViewModel: null-safe CurrentDir?.Equals() in AvoidEmptyGameDirectoryAsync (M1)
- ListBoxItemBehavior: explicit discard on fire-and-forget ExtractAsync (S1/PR)
- SettingsView: remove redundant null checks on DictionaryEditor properties (m1)

* fix: add Cancel click handler to DictionaryEditor

Avalonia's IsCancel="True" maps Escape to the button's Click event but
does not auto-close the window like WPF does. Without a handler, the
Cancel button and Escape key left the dialog stuck.
2026-03-16 14:17:00 -06:00
.github feat(images): Migrate BitmapImage/ImageSource to Avalonia.Media.Imaging.Bitmap [P2-011] (#79) 2026-03-15 19:09:04 -06:00
.vscode Set up dev env 2026-03-11 15:51:34 -06:00
CUE4Parse@06fbf1aced chore: point CUE4Parse submodule at r6e/CUE4Parse-Linux (#66) 2026-03-11 19:49:17 -06:00
FModel fix: address remaining WPF→Avalonia migration gaps (issue #82) (#83) 2026-03-16 14:17:00 -06:00
.editorconfig chore: update identity, branding, and CI for FModel Linux fork (#69) 2026-03-12 11:13:00 -06:00
.gitignore Finish setting up env 2026-03-11 17:28:01 -06:00
.gitmodules chore: point CUE4Parse submodule at r6e/CUE4Parse-Linux (#66) 2026-03-11 19:49:17 -06:00
LICENSE Re-add GPL-3 license 2021-05-22 16:33:08 -04:00
NOTICE chore: update identity, branding, and CI for FModel Linux fork (#69) 2026-03-12 11:13:00 -06:00
README.md chore: update identity, branding, and CI for FModel Linux fork (#69) 2026-03-12 11:13:00 -06:00

FModel Linux — Unreal Engine Archives Explorer for Linux

CI Status Latest


This is an unofficial Linux port of FModel, originally created by Asval (4sval) and contributors. It is not affiliated with or endorsed by the upstream project or its maintainers. Please do not report Linux-port-specific issues upstream.

Description

FModel Linux is a Linux port of FModel — an archive explorer for Unreal Engine games. It uses CUE4Parse as its core parsing library, providing robust support for the latest UE4 and UE5 archive formats, along with a comprehensive set of tools for previewing and converting game packages.

This fork replaces the Windows-only WPF UI stack with Avalonia UI and removes other Windows-specific dependencies to enable native Linux support. It is maintained by r6e.

Installation

Installation instructions for the Linux port are available in the project wiki (work in progress).

For the upstream Windows release, refer to the official FModel installation guide.

Supporting the Upstream Project

This fork does not accept donations. If you find FModel valuable, please consider supporting the original FModel project and its contributors.

License

FModel Linux is a derivative work licensed under GPL-3. The original FModel project is copyright © Asval and FModel contributors. Licenses of third-party libraries used are listed in NOTICE.