From dc5921b98827b84a92f2e7e95e1b6c75f7b6f1dc Mon Sep 17 00:00:00 2001 From: ItsKirby69 <117233443+ItsKirby69@users.noreply.github.com> Date: Sat, 10 Jan 2026 21:53:42 -0500 Subject: [PATCH] Editor Favoriting Blocks (#11538) * Add system for block favorites * Favorite custom sound * Update sounds * Use one sound for favorites * Sound changes * Last sound changes i promise * Use get/putJson for favorite blocks * Give favoriting blocks a more unique sound effect --- core/assets/contributors | 3 +- core/assets/sounds/ui/uiFavorite.ogg | Bin 0 -> 8176 bytes .../mindustry/ui/fragments/HudFragment.java | 96 +++++++++++++++++- 3 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 core/assets/sounds/ui/uiFavorite.ogg diff --git a/core/assets/contributors b/core/assets/contributors index f93506c9d8..3906467e94 100644 --- a/core/assets/contributors +++ b/core/assets/contributors @@ -187,4 +187,5 @@ Iniquit DSFdsfWxp Someone's Shadow buj -Agzam4 \ No newline at end of file +Agzam4 +ItsKirby69 \ No newline at end of file diff --git a/core/assets/sounds/ui/uiFavorite.ogg b/core/assets/sounds/ui/uiFavorite.ogg new file mode 100644 index 0000000000000000000000000000000000000000..14736e09e37c7272b3972c3ad9afa4f49921157c GIT binary patch literal 8176 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 literal 0 HcmV?d00001 diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index b7f06e0cb0..9881c6f648 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -14,6 +14,7 @@ import arc.scene.ui.ImageButton.*; import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; +import arc.input.*; import mindustry.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; @@ -54,6 +55,9 @@ public class HudFragment{ private Seq blocksOut = new Seq<>(); private Table hudLabel; + private static ObjectSet favoriteBlocks = new ObjectSet<>(); + private static String lastFavorited = null; + private void addBlockSelection(Table cont){ Table blockSelection = new Table(); var pane = new ScrollPane(blockSelection, Styles.smallPane); @@ -100,12 +104,53 @@ public class HudFragment{ rebuildBlockSelection(blockSelection, ""); } + private static void loadFavorites(){ + favoriteBlocks = Core.settings.getJson("editor-block-favorites", ObjectSet.class, String.class, ObjectSet::new); + } + + private static void saveFavorites(){ + Core.settings.putJson("editor-block-favorites", String.class, favoriteBlocks); + } + + private static boolean isFavorite(Block block){ + return favoriteBlocks.contains(block.name); + } + + private static void toggleFavorite(Block block){ + boolean isFav = favoriteBlocks.contains(block.name); + if(isFav){ + favoriteBlocks.remove(block.name); + Sounds.uiFavorite.play(0.35f, 0.67f, 0f); + }else{ + favoriteBlocks.add(block.name); + lastFavorited = block.name; + Sounds.uiFavorite.play(0.6f, 2.0f, 0f); + } + saveFavorites(); + } + private void rebuildBlockSelection(Table blockSelection, String searchText){ blockSelection.clear(); blocksOut.clear(); - blocksOut.addAll(Vars.content.blocks()); + // Favorites first + for(Block block : Vars.content.blocks()){ + if(isFavorite(block)){ + blocksOut.add(block); + } + } + + for(Block block : Vars.content.blocks()){ + if(!isFavorite(block)){ + blocksOut.add(block); + } + } blocksOut.sort((b1, b2) -> { + // These two block should stay at the top + if(b1 == Blocks.removeOre || b1 == Blocks.removeWall) return -1; + if(b2 == Blocks.removeOre || b2 == Blocks.removeWall) return 1; + int fav = Boolean.compare(isFavorite(b2), isFavorite(b1)); + if(fav != 0) return fav; int synth = Boolean.compare(b1.synthetic(), b2.synthetic()); if(synth != 0) return synth; int ore = Boolean.compare(b1 instanceof OverlayFloor && b1 != Blocks.removeOre, b2 instanceof OverlayFloor && b2 != Blocks.removeOre); @@ -128,9 +173,54 @@ public class HudFragment{ ImageButton button = new ImageButton(Tex.whiteui, Styles.clearNoneTogglei); button.getStyle().imageUp = new TextureRegionDrawable(region); button.clicked(() -> control.input.block = block); + // Pc input for favorites + button.clicked(KeyCode.mouseRight, () -> { + if(block == Blocks.removeOre || block == Blocks.removeWall) return; + toggleFavorite(block); + rebuildBlockSelection(blockSelection, searchText); + control.input.block = block; + }); + // Mobile double-click for favorites + button.addListener(new ClickListener(){ + @Override + public void clicked(InputEvent event, float x, float y){ + if(mobile && getTapCount() == 2){ + if(block == Blocks.removeOre || block == Blocks.removeWall) return; + toggleFavorite(block); + rebuildBlockSelection(blockSelection, searchText); + control.input.block = block; + } + } + }); button.resizeImage(8 * 4f); button.update(() -> button.setChecked(control.input.block == block)); - blockSelection.add(button).size(48f).tooltip(block.localizedName); + + Stack stack = new Stack(); + stack.add(button); + if(isFavorite(block)){ + Image favIcon = new Image(Icon.star); + favIcon.setColor(Color.gold); + favIcon.setOrigin(Align.center); + + if(block.name.equals(lastFavorited)){ + favIcon.color.a = 0f; + favIcon.setScale(0f); + favIcon.addAction(Actions.parallel( + Actions.scaleTo(0.7f, 0.7f, 0.2f), + Actions.alpha(1f, 0.2f), + Actions.run(() -> lastFavorited = null) + )); + }else{ + favIcon.setScale(0.7f); + } + + Table overlay = new Table().align(Align.topRight); + overlay.touchable = Touchable.disabled; + overlay.add(favIcon).size(2f).pad(12f); + + stack.add(overlay); + } + blockSelection.add(stack).size(48f).tooltip(block.localizedName); if(++i % 6 == 0){ blockSelection.row(); @@ -143,7 +233,7 @@ public class HudFragment{ } public void build(Group parent){ - + loadFavorites(); //warn about guardian/boss waves Events.on(WaveEvent.class, e -> { int max = 10;