Unreal Engine Archives Explorer
Go to file
Rob Trame 4c233f9947
feat(images): Migrate BitmapImage/ImageSource to Avalonia.Media.Imaging.Bitmap [P2-011] (#79)
* feat(images): Migrate BitmapImage/ImageSource to Avalonia.Media.Imaging.Bitmap [P2-011]

Replace WPF image types in the three affected ViewModels with their
Avalonia.Media.Imaging.Bitmap equivalents. Closes #24.

TabControlViewModel.cs (TabImage):
- Remove 'using System.Windows' and 'using System.Windows.Media.Imaging'
- Add 'using Avalonia.Media.Imaging'
- BitmapImage _image / public BitmapImage Image -> Bitmap
- Both SetImage overloads (SKBitmap and CTexture): replace
  BeginInit/CacheOption/StreamSource/EndInit/Freeze pattern
  with 'Image = new Bitmap(stream)'. Bitmap reads the stream
  into an internal buffer at construction; disposing the
  MemoryStream after is safe.

GameFileViewModel.cs:
- Remove 'using System.Windows', '.Windows.Media',
  '.Windows.Media.Imaging'
- Add 'using Avalonia.Media.Imaging', 'using Avalonia.Threading'
- ImageSource _previewImage / public ImageSource PreviewImage -> Bitmap
- SetPreviewImage: replace WPF BitmapImage construction +
  Application.Current.Dispatcher.InvokeAsync with
  new Bitmap(stream) + Dispatcher.UIThread.Post. Bitmap is
  immutable and not UI-thread-affine; constructing on the
  background Thread and posting the property assignment is safe.

CustomDirectoriesViewModel.cs:
- Remove 'using System.Windows', '.Windows.Controls',
  '.Windows.Media.Imaging'
- Add 'using Avalonia.Controls', 'using Avalonia.Layout',
  'using Avalonia.Media.Imaging', 'using Avalonia.Platform'
- MenuItem/Image/Separator/Control -> Avalonia equivalents
  (same class names, different namespaces)
- BitmapImage(new Uri('/FModel;component/Resources/xxx.png'))
  -> new Bitmap(AssetLoader.Open(new Uri('avares://FModel/...')))
  for the four directory-icon menu items

* fix(images): Address PR #79 review findings [P2-011]

FModel.csproj [C1]:
- Change <Resource> to <AvaloniaResource> for the four directory icon
  PNGs (add_directory, delete, edit, go_to_directory). WPF <Resource>
  items are not processed into Avalonia's avares resource manifest,
  so AssetLoader.Open would have thrown at runtime on every app startup.

GameFileViewModel.cs [m1 + PR comment]:
- Remove redundant 'ms.Position = 0' in SetPreviewImage: MemoryStream
  initializes to position 0, making the reset a no-op.
- Fix 'Resolved |= ~EResolveCompute.Preview' to 'Resolved &= ~...'.
  The bitwise-NOT operator on an enum value produces a large negative
  int, ORing in undefined bits; ORing never clears bits, so the intent
  (undo the premature Preview flag set at the top of
  ResolveByExtensionAsync) required &= ~, not |= ~.

CustomDirectoriesViewModel.cs [PR comment]:
- Extract private static LoadIcon(string filename) helper to wrap each
  AssetLoader.Open call in a using, ensuring the stream returned by
  AssetLoader.Open is disposed after Bitmap copies its data.

[m2] (Bitmap disposal in Image/PreviewImage setters) is intentionally
deferred: disposing the old Bitmap in the setter while the Avalonia
render thread may still hold it for the current frame risks a crash.

* fix(magnifier): Address review findings [M1, m1, m2, S1]

MagnifierManager.cs [M1]:
- Replace AdornerLayer.SetAdornment(element, adorner) / SetAdornment(element, null)
  with AdornerLayer.SetAdornedElement + layer.Children.Add in VerifyAdornerLayer
  and Parent-cast + Children.Remove in Detach().  SetAdornment is a single-slot
  API that silently evicts any other adornment on the same element; the collection
  API matches WPF's AdornerLayer.Add/Remove semantics and allows co-existing
  adorners.

MagnifierManager.cs [S1]:
- Set e.Handled = true after a zoom change when the adorner is visible so that
  a parent ScrollViewer does not also scroll while the user is zooming the
  magnifier.
- Adjust the zoom-out floor from 0 to ZoomFactorOnMouseWheel now that the
  ZoomFactor validator rejects values <= 0.
- Only call UpdateViewBox when the adorner is visible (no-op otherwise).

Magnifier.cs [m1]:
- Change ZoomFactor validate: v >= 0 -> v > 0.  ZoomFactor = 0 produced a
  zero-sized SourceRect on the VisualBrush which rendered undefined content.
  The minimum meaningful zoom is any positive value.

MagnifierAdorner.cs [m2]:
- Return early from HandlePointerEvent when Bounds.Width and Bounds.Height are
  both 0: the first PointerPressed arrives before the adorner canvas has been
  through a layout pass, so GetPosition(this) returns meaningless coordinates.
  The subsequent PointerMoved fires after layout and picks up correct values.

* Fix reviewer to stop it getting confused
2026-03-15 19:09:04 -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 feat(images): Migrate BitmapImage/ImageSource to Avalonia.Media.Imaging.Bitmap [P2-011] (#79) 2026-03-15 19:09:04 -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.