Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
67b59ce
Initial Macos Support
thesupersonic16 Mar 5, 2025
8c956b4
Initial Macos Support
to-fuu Mar 6, 2025
6f941d9
Add building instructions
to-fuu Mar 6, 2025
409d8a0
Make self contained
to-fuu Mar 7, 2025
70d5b0b
Remove log
to-fuu Mar 7, 2025
6aee6fe
add build command
to-fuu Mar 7, 2025
2a4b84f
remove Dotnet.Bundle dependencies
to-fuu Mar 7, 2025
db07d96
Update icon
to-fuu Mar 7, 2025
e0ed516
Disable detecting UnleashedRecomp
to-fuu Mar 7, 2025
f1e7c13
Update build docs
to-fuu Mar 7, 2025
b8b3adb
Fix menu bar showing Avalonia Application
to-fuu Mar 7, 2025
a2ae2a1
Support URI Schemes
to-fuu Mar 7, 2025
73e5474
Support URI Schemes
to-fuu Mar 7, 2025
2993c29
Fix build command
to-fuu Mar 8, 2025
e758958
change bash to zsh
to-fuu Mar 8, 2025
1d2f7ea
change bash to zsh
to-fuu Mar 8, 2025
9fab194
update the build command
to-fuu Mar 8, 2025
e4bc8ad
change build command ro release
to-fuu Mar 8, 2025
8459403
Merge remote-tracking branch 'origin' into macos-support
to-fuu Mar 20, 2025
466a041
ignore output and idea folder
to-fuu Mar 20, 2025
b88eacd
move .icns file to macos folder
to-fuu Mar 20, 2025
f11c76a
move info.plist out
to-fuu Mar 20, 2025
56f7431
update locating on macos
to-fuu Mar 20, 2025
b6b158e
use the game's ID
to-fuu Mar 20, 2025
9bb00f0
change to macOS
to-fuu Mar 20, 2025
37f9d2d
update docs
to-fuu Mar 20, 2025
bc7f08a
update output folder
to-fuu Mar 20, 2025
dbe4881
fix rebase
to-fuu Mar 20, 2025
a3b7422
remove version requirement
to-fuu Mar 20, 2025
1b08a77
improve build docs
to-fuu Mar 20, 2025
0a3be97
remove version from docs
to-fuu Mar 20, 2025
25decd2
remove empty space
to-fuu Mar 20, 2025
964a1d7
use Executable for root
to-fuu Mar 20, 2025
c456b48
remove empty line
to-fuu Mar 20, 2025
32b4237
update build release
to-fuu Mar 20, 2025
83ace70
revert changes
to-fuu Mar 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ on:
env:
PROJECT_PATH: ./Source/HedgeModManager.UI/HedgeModManager.UI.csproj
FLATPAK_ID: io.github.hedge_dev.hedgemodmanager
MACOS_BUILD_SCRIPT: ./macos/generate-bundle.bash
GENERATOR_URL: https://raw.githubusercontent.com/flatpak/flatpak-builder-tools/refs/heads/master/dotnet/flatpak-dotnet-generator.py
DOTNET_VERSION: 8
DOTNET_CLI_HOME: /tmp/.dotnet
Expand Down Expand Up @@ -82,12 +83,19 @@ jobs:

- name: Build Flatpak Bundle
run: flatpak build-bundle repo ./flatpak/${{env.FLATPAK_ID}}.flatpak ${{env.FLATPAK_ID}}

- name: osx-arm64 Build
run: dotnet publish -p:PublishProfile=osx-arm64 -c Release -p:AssemblyVersion=${{ github.event.inputs.version }} -p:FileVersion=${{ github.event.inputs.version }} -o ./output/macos/osx-arm64 ${{env.PROJECT_PATH}} -p:UseAppHost=true

- name: Build osx-arm64 Bundle
run: /bin/bash ${{env.MACOS_BUILD_SCRIPT}} ${{ github.event.inputs.version }}

- name: Prepare Release
run: |
mkdir -p ./release
mv ./output/win-x64/HedgeModManager.UI.exe ./release/HedgeModManager.exe
mv ./flatpak/${{env.FLATPAK_ID}}.flatpak ./release/${{env.FLATPAK_ID}}.flatpak
mv ./output/macos/HedgeModManager.app ./release/HedgeModManager.app

- name: Create Release
uses: softprops/[email protected]
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,14 @@ bld/
bin/
[Bb]in/
[Oo]bj/
output/

# Visual Studio 2015 cache/options directory
.vs/

Source/.idea


# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
Expand Down Expand Up @@ -215,3 +219,4 @@ _Pvt_Extensions/
ModelManifest.xml

Ignored/
.DS_Store
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ A mod manager for Hedgehog Engine games on PC.
- [Installation](#installation)
- [Windows](#windows)
- [Linux/Steam Deck](#linuxsteam-deck)
- [Building](#building)
- [Frequently Asked Questions](#frequently-asked-questions)
- [Bug/Issue Reporting](#bugissue-reporting)
- [Contribute](#contribute)
Expand Down Expand Up @@ -62,6 +63,9 @@ Flatpak bundles are also available from the [releases page](https://github.com/h
>
> For Heroic, it must be a flatpak install within the home directory.

### Building
For building from source, please check the [building instructions](/docs/BUILDING.md) page.

### Frequently Asked Questions
- Where can I install mods?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
<ProjectReference Include="..\HedgeModManager\HedgeModManager.csproj" />
</ItemGroup>

</Project>
</Project>
3 changes: 2 additions & 1 deletion Source/HedgeModManager.UI/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
xmlns:local="using:HedgeModManager.UI"
xmlns:themes="using:HedgeModManager.UI.Themes"
xmlns:materialIcons="using:Material.Icons.Avalonia"
RequestedThemeVariant="{x:Static themes:Themes.Darker}">
RequestedThemeVariant="{x:Static themes:Themes.Darker}"
Name="Hedge Mod Manager">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->

<Application.Resources>
Expand Down
2 changes: 1 addition & 1 deletion Source/HedgeModManager.UI/HedgeModManager.UI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>
</Project>
23 changes: 23 additions & 0 deletions Source/HedgeModManager.UI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Runtime.Versioning;
using Avalonia.Controls.ApplicationLifetimes;

#if !DEBUG
using System.Diagnostics;
Expand Down Expand Up @@ -176,6 +177,28 @@ static void installToRegistery(string schema, string args)
}
}

[SupportedOSPlatform("macos")]
public static void ListenForUriSchemeMac(Action<List<ICliCommand>> callback)
{
// Use Avalonia IActivatableLifetime to listen for OpenUri events on macOS
if (Application.Current?.TryGetFeature(typeof(IActivatableLifetime)) is { } activatableLifetime)
{
((IActivatableLifetime)activatableLifetime).Activated += async (s, a) =>
{
if (a is ProtocolActivatedEventArgs protocolArgs && protocolArgs.Kind == ActivationKind.OpenUri)
{
var uri = protocolArgs.Uri.ToString();
var args = CommandLine.ParseArguments(["--schema", uri]);
var (_, commands) = CommandLine.ExecuteArguments(args);
if (commands.Count > 0)
{
callback(commands);
}
}
};
}
}

public static string GetFormattedAppVersion()
{
string unstableType = "beta";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>
<PropertyGroup>
<RuntimeIdentifiers>osx-arm64</RuntimeIdentifiers>
<PublishSingleFile>true</PublishSingleFile>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>
<PropertyGroup>
<RuntimeIdentifiers>osx-x64</RuntimeIdentifiers>
<PublishSingleFile>true</PublishSingleFile>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -945,4 +945,4 @@ protected override void OnPropertyChanged(PropertyChangedEventArgs e)
OnPropertyChanged(nameof(IsFullscreen));
base.OnPropertyChanged(e);
}
}
}
6 changes: 5 additions & 1 deletion Source/HedgeModManager.UI/Views/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void LoadGames()
// Select the last selected game or first game
ViewModel.SelectedGame = ViewModel.Games
.FirstOrDefault(x => x != null && Path.Combine(x.Game.Root, x.Game.Executable ?? "")
== ViewModel.Config.LastSelectedPath, ViewModel.Games.FirstOrDefault());
== ViewModel.Config.LastSelectedPath, ViewModel.Games.FirstOrDefault());
}

// Set to true until we create a setup
Expand Down Expand Up @@ -70,6 +70,8 @@ private void Window_Loaded(object? sender, RoutedEventArgs e)

Logger.Information($"Loading URI handlers...");
Program.InstallURIHandler();
if (OperatingSystem.IsMacOS())
Program.ListenForUriSchemeMac((commands) => _ = ViewModel.ProcessCommandsAsync(commands));

LoadGames();

Expand Down Expand Up @@ -148,6 +150,7 @@ private void OnKeyDown(object? sender, KeyEventArgs e)
});
}
}

break;
case Key.F11:
toggleFullscreen = true;
Expand Down Expand Up @@ -207,6 +210,7 @@ private void OnKeyDown(object? sender, KeyEventArgs e)
if (button != Buttons.None)
_ = Dispatcher.UIThread.Invoke(async () => await ViewModel.OnInputDownAsync(button));
}

break;
}

Expand Down
31 changes: 27 additions & 4 deletions Source/HedgeModManager/ModdableGameLocator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
namespace HedgeModManager;

using Foundation;
using HedgeModManager.Epic;
using HedgeModManager.Properties;
Expand All @@ -17,7 +18,7 @@ public class ModdableGameLocator
ID = "SonicGenerations",
ModLoaderName = "HE1ModLoader",
ModLoaderFileName = "d3d9.dll",
ModLoaderIncompatibleFileNames = [ "dinput8.dll" ],
ModLoaderIncompatibleFileNames = ["dinput8.dll"],
ModLoaderDownloadURL = Resources.HE1MLDownloadURL,
Is64Bit = false,
PlatformInfos = new()
Expand All @@ -30,7 +31,7 @@ public class ModdableGameLocator
ID = "SonicLostWorld",
ModLoaderName = "HE1ModLoader",
ModLoaderFileName = "d3d9.dll",
ModLoaderIncompatibleFileNames = [ "dinput8.dll" ],
ModLoaderIncompatibleFileNames = ["dinput8.dll"],
ModLoaderDownloadURL = Resources.HE1MLDownloadURL,
Is64Bit = false,
PlatformInfos = new() { { "Steam", [new ("329440", "slw.exe")] } }
Expand All @@ -40,7 +41,7 @@ public class ModdableGameLocator
ID = "SonicForces",
ModLoaderName = "HE2ModLoader",
ModLoaderFileName = "d3d11.dll",
ModLoaderIncompatibleFileNames = [ "dinput8.dll" ],
ModLoaderIncompatibleFileNames = ["dinput8.dll"],
ModLoaderDownloadURL = Resources.HE2MLDownloadURL,
PlatformInfos = new() { { "Steam", [new ("637100", Path.Combine("build", "main", "projects", "exec", "Sonic Forces.exe"))] } }
},
Expand Down Expand Up @@ -132,7 +133,8 @@ public class ModdableGameLocator
{
{ "Windows", [new(string.Empty, "SOFTWARE\\UnleashedRecomp")] },
{ "Flatpak", [new("io.github.hedge_dev.unleashedrecomp", "unleashedrecomp")] },
{ "Desktop", [new("io.github.hedge_dev.unleashedrecomp", "unleashedrecomp"), new("UnleashedRecomp", "unleashedrecomp")] }
{ "Desktop", [new("io.github.hedge_dev.unleashedrecomp", "unleashedrecomp"), new("UnleashedRecomp", "unleashedrecomp")] },
{ "macOS", [new("io.github.hedge_dev.unleashedrecomp", "unleashedrecomp"), new("UnleashedRecomp", "unleashedrecomp")] }
}
}
];
Expand Down Expand Up @@ -390,6 +392,27 @@ public static List<IModdableGame> LocateGames()
}
}
}
if (OperatingSystem.IsMacOS() && gameInfo.PlatformInfos.TryGetValue("macOS", out var macOsInfo))
{
foreach (var entry in macOsInfo)
{
string root = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"Library", "Application Support", entry.Executable);
if (Directory.Exists(root))
{
var gameSimple = new GameSimple(
"macOS", entry.ID, gameInfo.ID,
root, Path.GetFileName(entry.Executable), "macOS",
null, $"open -a {entry.Executable}", null);
var game = new ModdableGameGeneric(gameSimple)
{
Is64Bit = gameInfo.Is64Bit
};
game.ModDatabase.SupportsCodeCompilation = gameInfo.SupportsCodes;
games.Add(game);
}
}
}
}

return games;
Expand Down
26 changes: 26 additions & 0 deletions docs/BUILDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Building from source

## 1. Clone the repository
```zsh
git clone https://github.com/hedge-dev/HedgeModManager.git
```

## 2. Build the project

### macOS

1. Navigate to the root of the project
2. Run the build command
```zsh
dotnet publish -p:PublishProfile=osx-arm64 -c Release -o ./output/macos/osx-arm64 ./Source/HedgeModManager.UI/HedgeModManager.UI.csproj -p:UseAppHost=true
```
3. Navigate to `macos`
```zsh
cd macos
```
4. Run the following command to create the app bundle.
```zsh
/bin/bash generate-bundle.bash
```
5. Navigate to `../output/macos`
6. Run `HedgeModManager.app`
Binary file added macos/AppIcon.icns
Binary file not shown.
43 changes: 43 additions & 0 deletions macos/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>hedgemmswa</string>
<string>hedgemmgens</string>
<string>hedgemmlw</string>
<string>hedgemmforces</string>
<string>hedgemmtenpex</string>
<string>hedgemmmusashi</string>
<string>hedgemmrainbow</string>
<string>hedgemmhite</string>
<string>hedgemmrangers</string>
<string>hedgemmmillersonic</string>
<string>hedgemmmillershadow</string>
</array>
</dict>
</array>
<key>CFBundleIconFile</key>
<string>AppIcon.icns</string>
<key>CFBundleIdentifier</key>
<string>io.github.hedge_dev.hedgemodmanager</string>
<key>CFBundleName</key>
<string>HedgeModManager</string>
<key>CFBundleVersion</key><string>1.0.0</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
<key>CFBundleExecutable</key>
<string>HedgeModManager.UI</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key><string>1.0.0</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
31 changes: 31 additions & 0 deletions macos/generate-bundle.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
VERSION=${1:-"1.0.0"}

APP_NAME="../output/macos/HedgeModManager.app"
PLIST_PATH="./Info.plist"
PUBLISH_OUTPUT_DIRECTORY="../output/macos/osx-arm64/."

ICON_FILE="./AppIcon.icns"

if [ -d "$APP_NAME" ]
then
rm -rf "$APP_NAME"
fi

mkdir "$APP_NAME"

mkdir "$APP_NAME/Contents"
mkdir "$APP_NAME/Contents/MacOS"
mkdir "$APP_NAME/Contents/Resources"

cp "$ICON_FILE" "$APP_NAME/Contents/Resources/AppIcon.icns"
cp -a "$PUBLISH_OUTPUT_DIRECTORY" "$APP_NAME/Contents/MacOS"
cp -a "$PLIST_PATH" "$APP_NAME/Contents/Info.plist"

PLIST_PATH="$APP_NAME/Contents/Info.plist"

# Update CFBundleShortVersionString using sed
sed -i '' -e "s/<key>CFBundleShortVersionString<\/key>\s*<string>[^<]*<\/string>/<key>CFBundleShortVersionString<\/key><string>${VERSION}<\/string>/g" "$PLIST_PATH"

# Update CFBundleVersion using sed
sed -i '' -e "s/<key>CFBundleVersion<\/key>\s*<string>[^<]*<\/string>/<key>CFBundleVersion<\/key><string>${VERSION}<\/string>/g" "$PLIST_PATH"