mirror of https://github.com/Leinnan/rpack.git
Bundler
This commit is contained in:
parent
ac277de75b
commit
e4b8406e90
|
|
@ -0,0 +1,49 @@
|
||||||
|
name: Bundle
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
runningSystem:
|
||||||
|
description: "System to run the job on"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
runningSystem:
|
||||||
|
type: choice
|
||||||
|
description: "System to run the job on"
|
||||||
|
required: true
|
||||||
|
options:
|
||||||
|
- ubuntu-latest
|
||||||
|
- windows-latest
|
||||||
|
- macos-15
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ inputs.runningSystem }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- uses: actions/cache@v4
|
||||||
|
continue-on-error: false
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
~/.cache/sccache
|
||||||
|
target/
|
||||||
|
key: ${{ inputs.runningSystem }}-build-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: ${{ inputs.runningSystem }}-build-
|
||||||
|
- uses: extractions/setup-just@v2
|
||||||
|
- name: Install Cargo Bundle
|
||||||
|
run: cargo install --git https://github.com/Leinnan/cargo-bundler
|
||||||
|
- name: Bundle mac
|
||||||
|
if: inputs.bundle == true && startsWith(inputs.runningSystem, 'macos')
|
||||||
|
working-directory: crates/rpack_egui
|
||||||
|
run: |
|
||||||
|
just bundle
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ inputs.runningSystem }}
|
||||||
|
path: target/release/bundle
|
||||||
|
|
@ -58,7 +58,8 @@ js-sys = "0.3"
|
||||||
|
|
||||||
[package.metadata.bundle]
|
[package.metadata.bundle]
|
||||||
name = "Rpack"
|
name = "Rpack"
|
||||||
resources = ["static/resources/*"]
|
icon = ["static/base_icon.png"]
|
||||||
|
resources_mapping = [["static/JetBrains*","./"]]
|
||||||
identifier = "io.github.leinnan.rpack"
|
identifier = "io.github.leinnan.rpack"
|
||||||
osx_url_schemes = ["io.github.leinnan.rpack"]
|
osx_url_schemes = ["io.github.leinnan.rpack"]
|
||||||
short_description = "Tilemap Editor"
|
short_description = "Tilemap Editor"
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,15 @@
|
||||||
|
format_bundle := if os() == "windows" { "--format wxsmsi" } else { if os() == "linux" { "--format appimage" } else { "--format osx" } }
|
||||||
|
|
||||||
_gen_icon size postfix:
|
# list available commands
|
||||||
sips -z {{size}} {{size}} static/base_icon.png --out static/icon.iconset/icon_{{postfix}}.png
|
list:
|
||||||
cp static/icon.iconset/icon_{{postfix}}.png static/resources/{{postfix}}.png
|
just --list
|
||||||
|
|
||||||
make_win_icon:
|
make_win_icon:
|
||||||
convert static/base_icon.png -define icon:auto-resize=16,24,32,48,64,128,256,512 static/icon.ico
|
convert static/base_icon.png -define icon:auto-resize=16,24,32,48,64,128,256,512 static/icon.ico
|
||||||
|
|
||||||
# Build the icon for macOS app
|
create_mac_installer: bundle
|
||||||
make_mac_icon:
|
pkgbuild --install-location /Applications --component ../../target/release/bundle/osx/Rpack.app ../../target/release/bundle/osx/Rpack.pkg
|
||||||
rm -rf static/icon.iconset
|
|
||||||
mkdir -p static/icon.iconset
|
|
||||||
rm -rf static/resources
|
|
||||||
mkdir -p static/resources
|
|
||||||
just _gen_icon 16 "16x16"
|
|
||||||
just _gen_icon 32 "32x32"
|
|
||||||
just _gen_icon 64 "64x64"
|
|
||||||
just _gen_icon 128 "128x128"
|
|
||||||
just _gen_icon 256 "256x256"
|
|
||||||
just _gen_icon 512 "512x512"
|
|
||||||
just _gen_icon 1024 "1024x1024"
|
|
||||||
just _gen_icon 32 "16x16@2x"
|
|
||||||
just _gen_icon 64 "32x32@2x"
|
|
||||||
just _gen_icon 128 "64x64@2x"
|
|
||||||
just _gen_icon 256 "128x128@2x"
|
|
||||||
just _gen_icon 512 "256x256@2x"
|
|
||||||
just _gen_icon 1024 "512x512@2x"
|
|
||||||
|
|
||||||
iconutil -c icns static/icon.iconset
|
# Create the installer using cargo-bundler
|
||||||
rm -rf static/icon.iconset
|
bundle:
|
||||||
mv static/icon.icns static/resources/icon.icns
|
cargo bundler -r
|
||||||
|
|
||||||
# Build the macOS app
|
|
||||||
build_mac_app: make_mac_icon
|
|
||||||
rm -rf Rpack.app
|
|
||||||
cargo build --release
|
|
||||||
mkdir -p Rpack.app
|
|
||||||
mkdir -p Rpack.app/Contents
|
|
||||||
mkdir -p Rpack.app/Contents/MacOS
|
|
||||||
mkdir -p Rpack.app/Contents/Resources
|
|
||||||
cp static/Info.plist Rpack.app/Contents/Info.plist
|
|
||||||
cp static/resources/* Rpack.app/Contents/Resources/
|
|
||||||
cp ../../target/release/rpack_egui Rpack.app/Contents/MacOS/rpack_egui
|
|
||||||
|
|
||||||
create_mac_installer: build_mac_app
|
|
||||||
pkgbuild --install-location /Applications --component Rpack.app RpackInstaller.pkg
|
|
||||||
|
|
||||||
# Create the installer using cargo-bundle
|
|
||||||
create_installer:
|
|
||||||
cargo bundle --release
|
|
||||||
|
|
|
||||||
|
|
@ -360,14 +360,14 @@ impl eframe::App for Application {
|
||||||
/// Called each time the UI needs repainting, which may be many times per second.
|
/// Called each time the UI needs repainting, which may be many times per second.
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
{
|
{
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("handle_undo");
|
puffin::profile_scope!("handle_undo");
|
||||||
self.undoer
|
self.undoer
|
||||||
.feed_state(ctx.input(|input| input.time), &self.data);
|
.feed_state(ctx.input(|input| input.time), &self.data);
|
||||||
}
|
}
|
||||||
if !INPUT_QUEUE.is_empty() {
|
if !INPUT_QUEUE.is_empty() {
|
||||||
let mut rebuild = false;
|
let mut rebuild = false;
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("loading_images");
|
puffin::profile_scope!("loading_images");
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -456,7 +456,7 @@ impl eframe::App for Application {
|
||||||
egui::TopBottomPanel::top("topPanel")
|
egui::TopBottomPanel::top("topPanel")
|
||||||
.frame(egui::Frame::canvas(&ctx.style()))
|
.frame(egui::Frame::canvas(&ctx.style()))
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("top_panel");
|
puffin::profile_scope!("top_panel");
|
||||||
// ui.add_space(TOP_SIDE_MARGIN);
|
// ui.add_space(TOP_SIDE_MARGIN);
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
|
@ -505,7 +505,7 @@ impl eframe::App for Application {
|
||||||
// });
|
// });
|
||||||
});
|
});
|
||||||
ctx.input(|i| {
|
ctx.input(|i| {
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("dropped_files");
|
puffin::profile_scope!("dropped_files");
|
||||||
if i.raw.dropped_files.is_empty() {
|
if i.raw.dropped_files.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
|
@ -555,7 +555,7 @@ impl eframe::App for Application {
|
||||||
egui::TopBottomPanel::bottom("bottom_panel")
|
egui::TopBottomPanel::bottom("bottom_panel")
|
||||||
.frame(egui::Frame::canvas(&ctx.style()))
|
.frame(egui::Frame::canvas(&ctx.style()))
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("bottom_panel");
|
puffin::profile_scope!("bottom_panel");
|
||||||
ui.add_space(5.0);
|
ui.add_space(5.0);
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
|
@ -592,7 +592,7 @@ impl eframe::App for Application {
|
||||||
.id_salt("rightPanel_scroll")
|
.id_salt("rightPanel_scroll")
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui.add_enabled_ui(!self.output.is_building(), |ui| {
|
ui.add_enabled_ui(!self.output.is_building(), |ui| {
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("right_panel");
|
puffin::profile_scope!("right_panel");
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
Grid::new("settings_grid")
|
Grid::new("settings_grid")
|
||||||
|
|
@ -686,7 +686,7 @@ impl eframe::App for Application {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
{
|
{
|
||||||
ui.style_mut().interaction.selectable_labels = false;
|
ui.style_mut().interaction.selectable_labels = false;
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("image_list");
|
puffin::profile_scope!("image_list");
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
|
@ -821,7 +821,7 @@ impl eframe::App for Application {
|
||||||
egui::CentralPanel::default()
|
egui::CentralPanel::default()
|
||||||
.frame(Frame::central_panel(&ctx.style()).inner_margin(16i8))
|
.frame(Frame::central_panel(&ctx.style()).inner_margin(16i8))
|
||||||
.show(ctx, |ui| {
|
.show(ctx, |ui| {
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
puffin::profile_scope!("central_panel");
|
puffin::profile_scope!("central_panel");
|
||||||
if let Some(error) = &self.last_error {
|
if let Some(error) = &self.last_error {
|
||||||
let text = egui::RichText::new(format!("Error: {}", &error))
|
let text = egui::RichText::new(format!("Error: {}", &error))
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub fn setup_custom_fonts(ctx: &egui::Context) {
|
pub fn setup_custom_fonts(ctx: &egui::Context) {
|
||||||
// Start with the default fonts (we will be adding to them rather than replacing them).
|
// Start with the default fonts (we will be adding to them rather than replacing them).
|
||||||
let mut fonts = egui::FontDefinitions::default();
|
let mut fonts = egui::FontDefinitions::default();
|
||||||
|
|
@ -41,26 +43,95 @@ pub fn setup_custom_fonts(ctx: &egui::Context) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(target_arch = "wasm32")]
|
||||||
fn get_fonts() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
fn get_fonts() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
||||||
use std::fs;
|
let regular = include_bytes!("../static/JetBrainsMonoNL-Regular.ttf").to_vec();
|
||||||
|
let semibold = include_bytes!("../static/JetBrainsMono-SemiBold.ttf").to_vec();
|
||||||
let font_path = std::path::Path::new("/System/Library/Fonts");
|
|
||||||
|
|
||||||
let regular = fs::read(font_path.join("SFNSRounded.ttf"))?;
|
|
||||||
let semibold = fs::read(font_path.join("SFCompact.ttf"))?;
|
|
||||||
|
|
||||||
Ok((regular, semibold))
|
Ok((regular, semibold))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn get_fonts() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
fn get_fonts() -> anyhow::Result<(Vec<u8>, Vec<u8>)> {
|
||||||
use std::fs;
|
let Some(regular) =
|
||||||
let app_data = std::env::var("APPDATA")?;
|
try_get_font_from_list(&["JetBrainsMonoNL-Regular", "SFNSRounded", "aptos"])
|
||||||
let font_path = std::path::Path::new(&app_data);
|
else {
|
||||||
|
anyhow::bail!("Failed to find a suitable font");
|
||||||
let regular = fs::read(font_path.join("../Local/Microsoft/Windows/Fonts/aptos.ttf"))?;
|
};
|
||||||
let semibold = fs::read(font_path.join("../Local/Microsoft/Windows/Fonts/aptos-semibold.ttf"))?;
|
let Some(semibold) =
|
||||||
|
try_get_font_from_list(&["JetBrainsMono-SemiBold", "SFNSRounded", "aptos-semibold"])
|
||||||
|
else {
|
||||||
|
anyhow::bail!("Failed to find a suitable font");
|
||||||
|
};
|
||||||
|
|
||||||
Ok((regular, semibold))
|
Ok((regular, semibold))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_font_from_list(font_names: &[&str]) -> Option<Vec<u8>> {
|
||||||
|
for font_name in font_names {
|
||||||
|
if let Some(font) = try_get_font(font_name) {
|
||||||
|
return Some(font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_get_font(font_name: &str) -> Option<Vec<u8>> {
|
||||||
|
for dir in font_dirs() {
|
||||||
|
if let Ok(font) = std::fs::read(Path::new(&dir).join(format!("{}.ttf", font_name))) {
|
||||||
|
return Some(font);
|
||||||
|
}
|
||||||
|
if let Ok(font) = std::fs::read(Path::new(&dir).join(format!("{}.otf", font_name))) {
|
||||||
|
return Some(font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn font_dirs() -> Vec<String> {
|
||||||
|
let mut dirs = Vec::new();
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
dirs.push("/usr/share/fonts".into());
|
||||||
|
dirs.push("/usr/share/fonts/truetype".into());
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::{path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
dirs.push("/System/Library/Fonts".into());
|
||||||
|
if let Some(resources_font_dir) = std::env::current_exe().ok().and_then(|p| {
|
||||||
|
p.ancestors()
|
||||||
|
.nth(2)
|
||||||
|
.map(|p| p.join("Resources/fonts").to_string_lossy().into_owned())
|
||||||
|
}) {
|
||||||
|
eprintln!("{}", &resources_font_dir);
|
||||||
|
dirs.push(resources_font_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(home) =
|
||||||
|
std::env::var_os("HOME").and_then(|s| PathBuf::from_str(&s.to_string_lossy()).ok())
|
||||||
|
{
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
{
|
||||||
|
dirs.push(format!("{}/Library/Fonts", home.display()));
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
dirs.push(format!("{}/.local/share/fonts", home.display()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
if let Ok(dir) = std::env::var("APPDATA") {
|
||||||
|
let font_path = std::path::Path::new(&dir).join("../Local/Microsoft/Windows/Fonts/");
|
||||||
|
dirs.push(font_path.display().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dirs
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ fn start_puffin_server() {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn main() -> eframe::Result<()> {
|
fn main() -> eframe::Result<()> {
|
||||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||||
#[cfg(feature = "profiler")]
|
#[cfg(all(not(target_arch = "wasm32"), feature = "profiler"))]
|
||||||
start_puffin_server();
|
start_puffin_server();
|
||||||
let file_arg: Option<String> = if std::env::args().len() > 1 {
|
let file_arg: Option<String> = if std::env::args().len() > 1 {
|
||||||
std::env::args().skip(1).next()
|
std::env::args().skip(1).next()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue