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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 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;