From ab7a2bb72b9ee9591049d4ec3c8815d57986bd2c Mon Sep 17 00:00:00 2001 From: shedaniel Date: Sun, 19 Feb 2023 02:05:30 +0800 Subject: Mini Displays Favorites --- .../rei/api/client/entry/region/RegionEntry.java | 10 ++ .../rei/api/client/favorites/FavoriteEntry.java | 7 + .../api/client/favorites/FavoriteEntryType.java | 6 + .../entry/settings/EntryIngredientSetting.java | 2 +- .../crafting/filler/ArmorDyeRecipeFiller.java | 2 +- .../filler/BannerDuplicateRecipeFiller.java | 2 +- .../crafting/filler/BookCloningRecipeFiller.java | 2 +- .../crafting/filler/CraftingRecipeFiller.java | 2 +- .../filler/FireworkRocketRecipeFiller.java | 2 +- .../crafting/filler/MapCloningRecipeFiller.java | 2 +- .../crafting/filler/MapExtendingRecipeFiller.java | 2 +- .../filler/ShieldDecorationRecipeFiller.java | 2 +- .../crafting/filler/ShulkerBoxColoringFiller.java | 2 +- .../filler/SuspiciousStewRecipeFiller.java | 2 +- .../crafting/filler/TippedArrowRecipeFiller.java | 2 +- .../impl/client/config/FavoritesConfigManager.java | 2 +- .../collapsible/CollapsibleConfigManager.java | 2 +- .../DelegatingFavoriteEntryProviderImpl.java | 11 ++ .../client/gui/dragging/CurrentDraggingStack.java | 33 ++-- .../collapsible/CollapsibleEntriesScreen.java | 23 +++ .../screen/collapsible/CollapsibleEntryWidget.java | 23 +++ .../client/gui/widget/DisplayCompositeWidget.java | 80 ++++++++-- .../gui/widget/favorites/FavoritesListWidget.java | 4 +- .../listeners/FavoritesRegionListener.java | 12 ++ .../gui/widget/favorites/panel/FavoritesPanel.java | 5 +- .../panel/rows/FavoritesPanelEntriesRow.java | 7 +- .../gui/widget/region/EntryStacksRegionWidget.java | 96 +++++++++++- .../gui/widget/region/RegionDraggableStack.java | 25 --- .../client/gui/widget/region/RegionListener.java | 13 ++ .../client/util/AbstractIndexedCyclingList.java | 2 +- .../rei/impl/client/util/ClientTickCounter.java | 2 +- .../impl/client/util/ConcatenatedListIterator.java | 2 +- .../rei/impl/client/util/CyclingList.java | 2 +- .../client/util/OriginalRetainingCyclingList.java | 2 +- .../client/runtime/DefaultClientRuntimePlugin.java | 171 ++++++++++++++++++++- runtime/src/test/java/CyclingListTest.java | 2 +- 36 files changed, 476 insertions(+), 90 deletions(-) diff --git a/api/src/main/java/me/shedaniel/rei/api/client/entry/region/RegionEntry.java b/api/src/main/java/me/shedaniel/rei/api/client/entry/region/RegionEntry.java index cf88e5263..d6ed83471 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/entry/region/RegionEntry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/entry/region/RegionEntry.java @@ -25,7 +25,11 @@ package me.shedaniel.rei.api.client.entry.region; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.widgets.Slot; import me.shedaniel.rei.api.common.entry.EntryStack; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Optional; @@ -55,4 +59,10 @@ public interface RegionEntry> { default boolean doAction(int button) { return false; } + + @Nullable + @ApiStatus.Experimental + default DraggableComponent asDraggableComponent(Slot slot) { + return null; + } } diff --git a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java index 2c5293ba5..42a884d0d 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntry.java @@ -28,12 +28,14 @@ import com.mojang.serialization.Lifecycle; import me.shedaniel.rei.api.client.entry.region.RegionEntry; import me.shedaniel.rei.api.client.gui.Renderer; import me.shedaniel.rei.api.client.util.ClientEntryStacks; +import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.impl.ClientInternals; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -73,6 +75,11 @@ public abstract class FavoriteEntry implements RegionEntry { return delegateResult(() -> FavoriteEntryType.registry().get(FavoriteEntryType.ENTRY_STACK).fromArgs(stack), null); } + @ApiStatus.Experimental + public static FavoriteEntry fromDisplay(Display display) { + return delegateResult(() -> FavoriteEntryType.registry().get(FavoriteEntryType.DISPLAY).fromArgs(display), null); + } + @Override public boolean isEntryInvalid() { return isInvalid(); diff --git a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java index 40e1bcf43..62236f22c 100644 --- a/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java +++ b/api/src/main/java/me/shedaniel/rei/api/client/favorites/FavoriteEntryType.java @@ -25,6 +25,7 @@ package me.shedaniel.rei.api.client.favorites; import com.mojang.serialization.DataResult; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.registry.Reloadable; @@ -44,6 +45,11 @@ public interface FavoriteEntryType { * A builtin type of favorites, wrapping a {@link EntryStack}. */ ResourceLocation ENTRY_STACK = new ResourceLocation("roughlyenoughitems", "entry_stack"); + /** + * A builtin type of favorites, wrapping a {@link Display}. + */ + @ApiStatus.Experimental + ResourceLocation DISPLAY = new ResourceLocation("roughlyenoughitems", "display"); static Registry registry() { return PluginManager.getClientInstance().get(FavoriteEntryType.Registry.class); diff --git a/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntryIngredientSetting.java b/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntryIngredientSetting.java index 78f61f446..0a9666ca2 100644 --- a/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntryIngredientSetting.java +++ b/api/src/main/java/me/shedaniel/rei/api/common/entry/settings/EntryIngredientSetting.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ArmorDyeRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ArmorDyeRecipeFiller.java index ab3f38ce7..2582beb51 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ArmorDyeRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ArmorDyeRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BannerDuplicateRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BannerDuplicateRecipeFiller.java index ac37fa0e4..72003af8d 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BannerDuplicateRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BannerDuplicateRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BookCloningRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BookCloningRecipeFiller.java index 25a11cadb..74b3c0101 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BookCloningRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/BookCloningRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/CraftingRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/CraftingRecipeFiller.java index ad4353e52..ac575045b 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/CraftingRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/CraftingRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/FireworkRocketRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/FireworkRocketRecipeFiller.java index 715fd61cf..90357ca88 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/FireworkRocketRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/FireworkRocketRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapCloningRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapCloningRecipeFiller.java index 5e85b41d0..e36a6fd8f 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapCloningRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapCloningRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapExtendingRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapExtendingRecipeFiller.java index 0341f2e2a..34a892e69 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapExtendingRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/MapExtendingRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShieldDecorationRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShieldDecorationRecipeFiller.java index 4af46ffdf..a26c3f14a 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShieldDecorationRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShieldDecorationRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShulkerBoxColoringFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShulkerBoxColoringFiller.java index 4dcbebf7d..1a1240925 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShulkerBoxColoringFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/ShulkerBoxColoringFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/SuspiciousStewRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/SuspiciousStewRecipeFiller.java index 9afc74f26..bfd82e763 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/SuspiciousStewRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/SuspiciousStewRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/TippedArrowRecipeFiller.java b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/TippedArrowRecipeFiller.java index b560c9d7e..e0d62e357 100644 --- a/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/TippedArrowRecipeFiller.java +++ b/default-plugin/src/main/java/me/shedaniel/rei/plugin/client/categories/crafting/filler/TippedArrowRecipeFiller.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/FavoritesConfigManager.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/FavoritesConfigManager.java index b4a73f007..7c10ded8a 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/FavoritesConfigManager.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/FavoritesConfigManager.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/collapsible/CollapsibleConfigManager.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/collapsible/CollapsibleConfigManager.java index edcca423d..1a7781111 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/config/collapsible/CollapsibleConfigManager.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/config/collapsible/CollapsibleConfigManager.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/DelegatingFavoriteEntryProviderImpl.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/DelegatingFavoriteEntryProviderImpl.java index 17d34c12f..e84b9f942 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/DelegatingFavoriteEntryProviderImpl.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/favorites/DelegatingFavoriteEntryProviderImpl.java @@ -27,8 +27,11 @@ import com.mojang.serialization.DataResult; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteMenuEntry; import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.widgets.Slot; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Objects; @@ -93,6 +96,8 @@ public class DelegatingFavoriteEntryProviderImpl extends FavoriteEntry { @Override public FavoriteEntry copy() { + if (value != null && toJson != null) return value.copy(); + if (value != null) return FavoriteEntry.delegateResult(() -> DataResult.success(value.copy()), toJson); return FavoriteEntry.delegateResult(supplier, toJson); } @@ -114,4 +119,10 @@ public class DelegatingFavoriteEntryProviderImpl extends FavoriteEntry { public boolean isSame(FavoriteEntry other) { return getUnwrapped().isSame(other.getUnwrapped()); } + + @Override + @Nullable + public DraggableComponent asDraggableComponent(Slot slot) { + return getUnwrapped().asDraggableComponent(slot); + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java index 838c14516..4e1cbc59f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/dragging/CurrentDraggingStack.java @@ -26,9 +26,7 @@ package me.shedaniel.rei.impl.client.gui.dragging; import com.mojang.blaze3d.vertex.PoseStack; import me.shedaniel.clothconfig2.api.animator.NumberAnimator; import me.shedaniel.clothconfig2.api.animator.ValueAnimator; -import me.shedaniel.math.FloatingRectangle; -import me.shedaniel.math.Point; -import me.shedaniel.math.Rectangle; +import me.shedaniel.math.*; import me.shedaniel.rei.RoughlyEnoughItemsCoreClient; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.gui.drag.DraggableBoundsProvider; @@ -87,13 +85,14 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag if (entry.dragging) { matrices.pushPose(); matrices.translate(0, 0, 600); - entry.bounds.update(delta); + entry.point.update(delta); + entry.dimension.update(delta); int width = entry.component.getWidth(); int height = entry.component.getHeight(); Vec2 mouseStartOffset = entry.mouseStartOffset; - entry.bounds.setTo(new FloatingRectangle(mouseX - width / 2 - mouseStartOffset.x, mouseY - height / 2 - mouseStartOffset.y, width, height), - reducedMotion ? 0 : 30); - entry.component.render(matrices, entry.bounds.value().getBounds(), mouseX, mouseY, delta); + entry.point.setTo(new FloatingPoint(mouseX - mouseStartOffset.x * width, mouseY - mouseStartOffset.y * height), reducedMotion ? 0 : 30); + entry.dimension.setTo(new FloatingDimension(width, height), reducedMotion ? 0 : 700); + entry.component.render(matrices, getCurrentBounds(), mouseX, mouseY, delta); matrices.popPose(); VoxelShape shape = entry.getBoundsProvider().bounds(); @@ -216,16 +215,18 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag public Point getCurrentPosition() { if (!isDraggingComponent()) return null; Vec2 mouseStartOffset = entry.mouseStartOffset; - FloatingRectangle rectangle = entry.bounds.value(); - return new Point(rectangle.getCenterX() + mouseStartOffset.x, rectangle.getCenterY() + mouseStartOffset.y); + FloatingPoint point = entry.point.value(); + FloatingDimension dimension = entry.dimension.value(); + return new Point(point.x + mouseStartOffset.x * dimension.width, point.y + mouseStartOffset.y * dimension.height); } @Override @Nullable public Rectangle getCurrentBounds() { if (!isDraggingComponent()) return null; - FloatingRectangle rectangle = entry.bounds.value(); - return rectangle.getBounds(); + FloatingPoint point = entry.point.value(); + FloatingDimension dimension = entry.dimension.value(); + return new Rectangle(point.x - dimension.width / 2, point.y - dimension.height / 2, dimension.width, dimension.height); } @Override @@ -249,7 +250,8 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag private final DraggableComponent component; private final Point start; private long startDragging = -1; - private final ValueAnimator bounds; + private final ValueAnimator point; + private final ValueAnimator dimension; private final Vec2 mouseStartOffset; private boolean dragging = false; private DraggableBoundsProvider boundsProvider; @@ -257,9 +259,10 @@ public class CurrentDraggingStack extends Widget implements LateRenderable, Drag private DraggableEntry(DraggableComponent component, Point start) { this.component = component; this.start = start; - this.bounds = ValueAnimator.ofFloatingRectangle() - .setAs(component.getOriginBounds(start).getFloatingBounds()); - this.mouseStartOffset = new Vec2((float) (start.x - bounds.value().getCenterX()), (float) (start.y - bounds.value().getCenterY())); + FloatingRectangle floatingBounds = component.getOriginBounds(start).getFloatingBounds(); + this.point = ValueAnimator.ofFloatingPoint().setAs(new FloatingPoint(floatingBounds.getCenterX(), floatingBounds.getCenterY())); + this.dimension = ValueAnimator.ofFloatingDimension().setAs(new FloatingDimension(floatingBounds.width, floatingBounds.height)); + this.mouseStartOffset = new Vec2((float) (start.x - point.value().x) / (float) dimension.value().width, (float) (start.y - point.value().y) / (float) dimension.value().height); } public DraggableBoundsProvider getBoundsProvider() { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntriesScreen.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntriesScreen.java index cb5ff971c..483f37dff 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntriesScreen.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntriesScreen.java @@ -1,3 +1,26 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package me.shedaniel.rei.impl.client.gui.screen.collapsible; import com.google.common.collect.Multimap; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntryWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntryWidget.java index 187313152..1ade1dbeb 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntryWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/screen/collapsible/CollapsibleEntryWidget.java @@ -1,3 +1,26 @@ +/* + * This file is licensed under the MIT License, part of Roughly Enough Items. + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + package me.shedaniel.rei.impl.client.gui.screen.collapsible; import com.mojang.blaze3d.systems.RenderSystem; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayCompositeWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayCompositeWidget.java index 0e040ebf6..a2a1b915f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayCompositeWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/DisplayCompositeWidget.java @@ -27,14 +27,15 @@ import com.mojang.blaze3d.vertex.PoseStack; import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.config.ConfigObject; +import me.shedaniel.rei.api.client.gui.config.RecipeBorderType; import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; import me.shedaniel.rei.api.client.gui.drag.DraggingContext; import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProviderWidget; -import me.shedaniel.rei.api.client.gui.widgets.DelegateWidgetWithBounds; -import me.shedaniel.rei.api.client.gui.widgets.Widget; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.gui.widgets.*; import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.entry.EntryIngredient; +import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesListWidget; import me.shedaniel.rei.impl.display.DisplaySpec; @@ -47,10 +48,12 @@ import java.util.stream.StreamSupport; public class DisplayCompositeWidget extends DelegateWidgetWithBounds implements DraggableComponentProviderWidget { private final DisplaySpec display; + private final List widgets; public DisplayCompositeWidget(DisplaySpec display, List widgets, Rectangle bounds) { super(Widgets.concat(widgets), () -> bounds); this.display = display; + this.widgets = widgets; } @Override @@ -62,7 +65,9 @@ public class DisplayCompositeWidget extends DelegateWidgetWithBounds implements .findFirst() .orElseGet(() -> { if (containsMouse(mouseX, mouseY)) { - return (DraggableComponent) (DraggableComponent) new DisplayDraggableComponent(widget, display.provideInternalDisplay(), getBounds(), getBounds()); + return (DraggableComponent) (DraggableComponent) new DisplayDraggableComponent( + Widgets.concat(CollectionUtils.filterToList(widgets, w -> !(w instanceof Panel))), + display.provideInternalDisplay(), getBounds(), getBounds()); } else { return null; } @@ -114,22 +119,41 @@ public class DisplayCompositeWidget extends DelegateWidgetWithBounds implements private final Display display; private final Rectangle originBounds; private final Rectangle bounds; + private final Panel panel; + private final Slot slot; + public boolean onFavoritesRegion; public DisplayDraggableComponent(Widget widget, Display display, Rectangle originBounds, Rectangle bounds) { this.widget = widget; this.display = display; this.originBounds = originBounds; this.bounds = bounds; + this.panel = Widgets.createRecipeBase(bounds.clone()); + this.slot = Widgets.createSlot(new Rectangle()) + .disableBackground() + .disableHighlight() + .disableTooltips(); + for (EntryIngredient ingredient : display.getOutputEntries()) { + slot.entries(ingredient); + } } @Override public int getWidth() { - return bounds.width; + if (this.onFavoritesRegion) { + return 18; + } + + return bounds.width / 2; } @Override public int getHeight() { - return bounds.height; + if (this.onFavoritesRegion) { + return 18; + } + + return bounds.height / 2; } @Override @@ -139,11 +163,47 @@ public class DisplayCompositeWidget extends DelegateWidgetWithBounds implements @Override public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + if (DraggingContext.getInstance().isDraggingComponent()) { + FavoritesListWidget favorites = ScreenOverlayImpl.getFavoritesListWidget(); + if (favorites != null) { + Rectangle favoritesBounds = favorites.getRegion().getBounds(); + if (!this.onFavoritesRegion && new Rectangle(favoritesBounds.x + 5, favoritesBounds.y + 5, favoritesBounds.width - 10, favoritesBounds.height - 10) + .contains(DraggingContext.getInstance().getCurrentPosition())) { + this.onFavoritesRegion = true; + } else if (this.onFavoritesRegion && !favoritesBounds.contains(DraggingContext.getInstance().getCurrentPosition())) { + this.onFavoritesRegion = false; + } + } else { + this.onFavoritesRegion = false; + } + } else { + this.onFavoritesRegion = false; + } + matrices.pushPose(); - matrices.translate(bounds.getX(), bounds.getY(), 0); - matrices.scale(bounds.width / (float) this.bounds.getWidth(), bounds.height / (float) this.bounds.getHeight(), 1); - matrices.translate(-this.bounds.getX(), -this.bounds.getY(), 0); - widget.render(matrices, -1000, -1000, delta); + if (bounds.width <= Math.max(18, this.bounds.width / 2 - 6) && bounds.height <= Math.max(18, this.bounds.height / 2 - 6) && this.onFavoritesRegion) { + this.panel.yTextureOffset(RecipeBorderType.LIGHTER.getYOffset()); + this.panel.getBounds().setBounds(bounds); + this.panel.render(matrices, mouseX, mouseY, delta); + matrices.pushPose(); + matrices.translate(0, 0.5, 0); + this.slot.getBounds().setBounds(bounds.getCenterX() - 7, bounds.getCenterY() - 7, 14, 14); + this.slot.render(matrices, mouseX, mouseY, delta); + matrices.popPose(); + } else { + this.panel.yTextureOffset(ConfigObject.getInstance().getRecipeBorderType().getYOffset()); + matrices.pushPose(); + matrices.translate(bounds.getX(), bounds.getY(), 1); + matrices.scale(bounds.width / (float) this.bounds.getWidth(), bounds.height / (float) this.bounds.getHeight(), 1); + matrices.translate(-this.bounds.getX(), -this.bounds.getY(), 0); + this.panel.getBounds().setBounds(this.bounds); + this.panel.render(matrices, mouseX, mouseY, delta); + matrices.popPose(); + matrices.translate(bounds.getX(), bounds.getY(), 1); + matrices.scale(bounds.width / (float) this.bounds.getWidth(), bounds.height / (float) this.bounds.getHeight(), 1); + matrices.translate(-this.bounds.getX(), -this.bounds.getY(), 0); + widget.render(matrices, -1000, -1000, delta); + } matrices.popPose(); } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesListWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesListWidget.java index db5a2c9f3..0b285f0f9 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesListWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/FavoritesListWidget.java @@ -126,9 +126,9 @@ public class FavoritesListWidget extends WidgetWithBounds implements DraggableCo @Override @Nullable public DraggableComponent getHovered(DraggingContext context, double mouseX, double mouseY) { - DraggableComponent stack = region.getHoveredStack(context, mouseX, mouseY); + DraggableComponent stack = region.getHovered(context, mouseX, mouseY); if (stack != null) return (DraggableComponent) stack; - stack = systemRegion.getHoveredStack(context, mouseX, mouseY); + stack = systemRegion.getHovered(context, mouseX, mouseY); if (stack != null) return (DraggableComponent) stack; if (favoritePanel.containsMouse(mouseX, mouseY)) { stack = favoritePanel.getHoveredStack(mouseX, mouseY); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/listeners/FavoritesRegionListener.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/listeners/FavoritesRegionListener.java index 078be4703..1e8f9cce8 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/listeners/FavoritesRegionListener.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/listeners/FavoritesRegionListener.java @@ -27,6 +27,8 @@ import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.gui.drag.DraggableStack; import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.common.display.Display; import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesEntriesManager; import me.shedaniel.rei.impl.client.gui.widget.favorites.FavoritesListWidget; import me.shedaniel.rei.impl.client.gui.widget.region.RealRegionEntry; @@ -36,6 +38,7 @@ import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -69,6 +72,15 @@ public class FavoritesRegionListener implements RegionListener { return FavoriteEntry.fromEntryStack(stack.getStack().copy()); } + @Override + @Nullable + public FavoriteEntry convertDraggableComponent(DraggingContext context, DraggableComponent component) { + return component.getIf() + .map(Supplier::get) + .map(FavoriteEntry::fromDisplay) + .orElse(null); + } + @Override public void onSetNewEntries(List> regionEntryListEntries) { favoritesListWidget.setSystemRegionEntries(null); diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/FavoritesPanel.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/FavoritesPanel.java index 21dd3a2f0..c0c0830f5 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/FavoritesPanel.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/FavoritesPanel.java @@ -35,6 +35,7 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.CollectionUtils; @@ -148,10 +149,10 @@ public class FavoritesPanel extends WidgetWithBounds { } @Nullable - public DraggableStack getHoveredStack(double mouseX, double mouseY) { + public DraggableComponent getHoveredStack(double mouseX, double mouseY) { for (FavoritesPanelRow row : rows.get()) { if (row instanceof FavoritesPanelEntriesRow entriesRow) { - DraggableStack hoveredStack = entriesRow.getHoveredStack(mouseX, mouseY); + DraggableComponent hoveredStack = entriesRow.getHoveredStack(mouseX, mouseY); if (hoveredStack != null) { return hoveredStack; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/rows/FavoritesPanelEntriesRow.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/rows/FavoritesPanelEntriesRow.java index 034ae0095..8a55c331f 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/rows/FavoritesPanelEntriesRow.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/favorites/panel/rows/FavoritesPanelEntriesRow.java @@ -31,7 +31,7 @@ import me.shedaniel.math.Point; import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; -import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import me.shedaniel.rei.api.client.gui.widgets.Tooltip; import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; import me.shedaniel.rei.api.client.util.ClientEntryStacks; @@ -39,6 +39,7 @@ import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.impl.client.gui.widget.DisplayedEntryWidget; import me.shedaniel.rei.impl.client.gui.widget.favorites.panel.FavoritesPanel; +import me.shedaniel.rei.impl.client.gui.widget.region.EntryStacksRegionWidget; import me.shedaniel.rei.impl.client.gui.widget.region.RealRegionEntry; import me.shedaniel.rei.impl.client.gui.widget.region.RegionDraggableStack; import net.minecraft.client.gui.components.events.GuiEventListener; @@ -118,12 +119,12 @@ public class FavoritesPanelEntriesRow extends FavoritesPanelRow { } @Nullable - public DraggableStack getHoveredStack(double mouseX, double mouseY) { + public DraggableComponent getHoveredStack(double mouseX, double mouseY) { for (SectionFavoriteWidget widget : widgets) { if (widget.containsMouse(mouseX, mouseY + panel.getScrolledAmount())) { RealRegionEntry entry = new RealRegionEntry<>(panel.getParent().getRegion(), widget.entry.copy(), entrySize()); entry.size.setAs(entrySize() * 100); - return new RegionDraggableStack<>(entry, widget); + return EntryStacksRegionWidget.wrapDraggable(new RegionDraggableStack<>(entry, widget), entry.region, entry); } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/EntryStacksRegionWidget.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/EntryStacksRegionWidget.java index 724735edc..a8903ca37 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/EntryStacksRegionWidget.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/EntryStacksRegionWidget.java @@ -37,7 +37,12 @@ import me.shedaniel.math.Rectangle; import me.shedaniel.rei.api.client.REIRuntime; import me.shedaniel.rei.api.client.config.ConfigObject; import me.shedaniel.rei.api.client.entry.region.RegionEntry; -import me.shedaniel.rei.api.client.gui.drag.*; +import me.shedaniel.rei.api.client.gui.drag.DraggableStack; +import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; +import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProviderWidget; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitorWidget; import me.shedaniel.rei.api.client.gui.widgets.Widget; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.common.entry.EntrySerializer; @@ -62,7 +67,7 @@ import java.util.stream.Stream; import static me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget.entrySize; -public class EntryStacksRegionWidget> extends WidgetWithBounds implements DraggableStackProviderWidget, DraggableStackVisitorWidget { +public class EntryStacksRegionWidget> extends WidgetWithBounds implements DraggableComponentProviderWidget, DraggableComponentVisitorWidget { public final RegionListener listener; protected int blockedCount; private Rectangle bounds = new Rectangle(), innerBounds; @@ -178,17 +183,81 @@ public class EntryStacksRegionWidget> extends WidgetWit @Override @Nullable - public DraggableStack getHoveredStack(DraggingContext context, double mouseX, double mouseY) { + public DraggableComponent getHovered(DraggingContext context, double mouseX, double mouseY) { if (innerBounds.contains(mouseX, mouseY)) { for (RealRegionEntry entry : entries.values()) { if (entry.getWidget().containsMouse(mouseX, mouseY) && listener.canBeDragged(entry)) { - return new RegionDraggableStack<>(entry, null); + DraggableComponent component = listener.convertToDraggableComponent(entry); + return (DraggableComponent) wrapDraggable(component, this, entry); } } } + return null; } + public static > DraggableComponent wrapDraggable(DraggableComponent component, EntryStacksRegionWidget region, RealRegionEntry entry) { + return new DraggableComponent<>() { + private int previousIndex = -1; + + @Override + public T get() { + return component.get(); + } + + @Override + public int getWidth() { + return component.getWidth(); + } + + @Override + public int getHeight() { + return component.getHeight(); + } + + @Override + public void drag() { + if (region.listener.removeOnDrag()) { + previousIndex = region.indexOf(entry); + region.remove(entry, EntryStacksRegionWidget.RemovalMode.MIGRATED); + } + + component.drag(); + } + + @Override + public void release(DraggedAcceptorResult result) { + component.release(result); + + if (result != DraggedAcceptorResult.CONSUMED) { + if (!entry.region.listener.removeOnDrag()) { + DraggingContext.getInstance().renderBack(this, DraggingContext.getInstance().getCurrentPosition(), + () -> entry.pos.value().getLocation()); + } else if (result == DraggedAcceptorResult.ACCEPTED) { + DraggingContext context = DraggingContext.getInstance(); + double x = context.getCurrentPosition().x; + double y = context.getCurrentPosition().y + entry.region.getScrollAmount(); + entry.region.drop(entry, x, y, previousIndex); + } else { + entry.region.drop(entry); + } + } else { + entry.region.listener.onConsumed(entry); + } + } + + @Override + public void render(PoseStack matrices, Point position, int mouseX, int mouseY, float delta) { + component.render(matrices, position, mouseX, mouseY, delta); + } + + @Override + public void render(PoseStack matrices, Rectangle bounds, int mouseX, int mouseY, float delta) { + component.render(matrices, bounds, mouseX, mouseY, delta); + } + }; + } + public EntryStack getFocusedStack() { Point mouse = mouse(); if (innerBounds.contains(mouse)) { @@ -209,6 +278,13 @@ public class EntryStacksRegionWidget> extends WidgetWit } @Override + public DraggedAcceptorResult acceptDragged(DraggingContext context, DraggableComponent component) { + return component.>getIf() + .map(comp -> acceptDraggedStack(context, DraggableStack.from(comp))) + .orElse(innerBounds.contains(context.getCurrentPosition()) && drop(context, component) + ? DraggedAcceptorResult.CONSUMED : DraggedAcceptorResult.PASS); + } + public DraggedAcceptorResult acceptDraggedStack(DraggingContext context, DraggableStack stack) { return checkDraggedStacks(context, stack) .filter(entry -> innerBounds.contains(context.getCurrentPosition())) @@ -223,6 +299,14 @@ public class EntryStacksRegionWidget> extends WidgetWit }).isPresent() ? DraggedAcceptorResult.CONSUMED : DraggedAcceptorResult.PASS; } + public boolean drop(DraggingContext context, DraggableComponent component) { + T regionEntry = listener.convertDraggableComponent(context, component); + if (regionEntry == null) return false; + RealRegionEntry entry = new RealRegionEntry<>(this, regionEntry, entrySize()); + entry.size.setAs(entrySize() * 100); + return drop(entry); + } + public Optional> checkDraggedStacks(DraggingContext context, DraggableStack stack) { EntrySerializer serializer = stack.getStack().getDefinition().getSerializer(); if (serializer != null && (stack instanceof RegionDraggableStack || (serializer.supportReading() && serializer.supportSaving()))) { @@ -348,7 +432,9 @@ public class EntryStacksRegionWidget> extends WidgetWit private int getReleaseIndex(@Nullable Point position) { DraggingContext context = DraggingContext.getInstance(); if (position == null) position = context.getCurrentPosition(); - if (context.isDraggingStack() && bounds.contains(position) && checkDraggedStacks(context.cast(), context.getCurrentStack()).isPresent()) { + boolean draggingStack = context.isDraggingStack() && bounds.contains(position) && checkDraggedStacks(context.cast(), context.getCurrentStack()).isPresent(); + boolean draggingComponent = draggingStack || (context.isDraggingComponent() && bounds.contains(position) && this.listener.convertDraggableComponent(context.cast(), context.getDragged()) != null); + if (draggingStack || draggingComponent) { int entrySize = entrySize(); int width = innerBounds.width / entrySize; int currentX = 0; diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionDraggableStack.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionDraggableStack.java index 5a93c2033..51a94a9d4 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionDraggableStack.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionDraggableStack.java @@ -23,11 +23,9 @@ package me.shedaniel.rei.impl.client.gui.widget.region; -import me.shedaniel.math.Point; import me.shedaniel.rei.api.client.entry.region.RegionEntry; import me.shedaniel.rei.api.client.gui.drag.DraggableStack; import me.shedaniel.rei.api.client.gui.drag.DraggedAcceptorResult; -import me.shedaniel.rei.api.client.gui.drag.DraggingContext; import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds; import me.shedaniel.rei.api.common.entry.EntryStack; @@ -35,7 +33,6 @@ public class RegionDraggableStack> implements Draggable private RealRegionEntry entry; private EntryStack stack; private WidgetWithBounds showcaseWidget; - private int previousIndex = -1; public RegionDraggableStack(RealRegionEntry entry, WidgetWithBounds showcaseWidget) { this.entry = entry; @@ -50,10 +47,6 @@ public class RegionDraggableStack> implements Draggable @Override public void drag() { - if (showcaseWidget == null && entry.region.listener.removeOnDrag()) { - previousIndex = entry.region.indexOf(entry); - entry.region.remove(entry, EntryStacksRegionWidget.RemovalMode.MIGRATED); - } } public RealRegionEntry getEntry() { @@ -62,24 +55,6 @@ public class RegionDraggableStack> implements Draggable @Override public void release(DraggedAcceptorResult result) { - if (result != DraggedAcceptorResult.CONSUMED) { - if (!entry.region.listener.removeOnDrag()) { - DraggingContext.getInstance().renderBackToPosition(this, DraggingContext.getInstance().getCurrentPosition(), - () -> entry.pos.value().getLocation()); - } else if (showcaseWidget != null) { - DraggingContext.getInstance().renderBackToPosition(this, DraggingContext.getInstance().getCurrentPosition(), - () -> new Point(showcaseWidget.getBounds().x, showcaseWidget.getBounds().y)); - } else if (result == DraggedAcceptorResult.ACCEPTED) { - DraggingContext context = DraggingContext.getInstance(); - double x = context.getCurrentPosition().x; - double y = context.getCurrentPosition().y + entry.region.getScrollAmount(); - entry.region.drop(entry, x, y, previousIndex); - } else { - entry.region.drop(entry); - } - } else { - entry.region.listener.onConsumed(entry); - } } public WidgetWithBounds getShowcaseWidget() { diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionListener.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionListener.java index e480348c4..829933230 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionListener.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/gui/widget/region/RegionListener.java @@ -27,6 +27,7 @@ import me.shedaniel.rei.api.client.entry.region.RegionEntry; import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.gui.drag.DraggableStack; import me.shedaniel.rei.api.client.gui.drag.DraggingContext; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import me.shedaniel.rei.impl.client.gui.widget.entrylist.EntryListWidget; import net.minecraft.client.gui.screens.Screen; import org.jetbrains.annotations.Nullable; @@ -42,6 +43,11 @@ public interface RegionListener> { return null; } + @Nullable + default T convertDraggableComponent(DraggingContext context, DraggableComponent component) { + return null; + } + default boolean canAcceptDrop(RealRegionEntry entry) { return true; } @@ -72,4 +78,11 @@ public interface RegionListener> { default boolean notSteppingOnExclusionZones(int left, int top, int width, int height) { return EntryListWidget.notSteppingOnExclusionZones(left, top, width, height); } + + @Nullable + default DraggableComponent convertToDraggableComponent(RealRegionEntry entry) { + DraggableComponent component = entry.getEntry().asDraggableComponent(entry.getWidget()); + if (component != null) return component; + return new RegionDraggableStack<>(entry, null); + } } diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/AbstractIndexedCyclingList.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/AbstractIndexedCyclingList.java index 199afbb29..c22e9662b 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/AbstractIndexedCyclingList.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/AbstractIndexedCyclingList.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ClientTickCounter.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ClientTickCounter.java index 03e2d9de8..4df85beda 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ClientTickCounter.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ClientTickCounter.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ConcatenatedListIterator.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ConcatenatedListIterator.java index eedd2b0cf..73169e421 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ConcatenatedListIterator.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/ConcatenatedListIterator.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/CyclingList.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/CyclingList.java index 2fb060d7a..35f2283e7 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/CyclingList.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/CyclingList.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/OriginalRetainingCyclingList.java b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/OriginalRetainingCyclingList.java index f66e65723..aeb557d45 100644 --- a/runtime/src/main/java/me/shedaniel/rei/impl/client/util/OriginalRetainingCyclingList.java +++ b/runtime/src/main/java/me/shedaniel/rei/impl/client/util/OriginalRetainingCyclingList.java @@ -1,6 +1,6 @@ /* * This file is licensed under the MIT License, part of Roughly Enough Items. - * Copyright (c) 2018, 2019, 2020, 2021, 2022 shedaniel + * Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023 shedaniel * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java index ee5dc388c..cdbec40ac 100644 --- a/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java +++ b/runtime/src/main/java/me/shedaniel/rei/plugin/client/runtime/DefaultClientRuntimePlugin.java @@ -36,13 +36,14 @@ import me.shedaniel.rei.api.client.favorites.FavoriteEntry; import me.shedaniel.rei.api.client.favorites.FavoriteEntryType; import me.shedaniel.rei.api.client.gui.AbstractRenderer; import me.shedaniel.rei.api.client.gui.Renderer; +import me.shedaniel.rei.api.client.gui.config.RecipeBorderType; +import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponent; import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentProviderWidget; import me.shedaniel.rei.api.client.gui.drag.component.DraggableComponentVisitorWidget; -import me.shedaniel.rei.api.client.gui.widgets.Panel; -import me.shedaniel.rei.api.client.gui.widgets.Tooltip; -import me.shedaniel.rei.api.client.gui.widgets.TooltipContext; -import me.shedaniel.rei.api.client.gui.widgets.Widgets; +import me.shedaniel.rei.api.client.gui.widgets.*; import me.shedaniel.rei.api.client.plugins.REIClientPlugin; +import me.shedaniel.rei.api.client.registry.category.CategoryRegistry; +import me.shedaniel.rei.api.client.registry.display.DisplayCategory; import me.shedaniel.rei.api.client.registry.display.DisplayRegistry; import me.shedaniel.rei.api.client.registry.entry.EntryRegistry; import me.shedaniel.rei.api.client.registry.screen.ExclusionZones; @@ -50,18 +51,25 @@ import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry; import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry; import me.shedaniel.rei.api.client.search.method.InputMethodRegistry; import me.shedaniel.rei.api.client.util.ClientEntryStacks; +import me.shedaniel.rei.api.common.category.CategoryIdentifier; +import me.shedaniel.rei.api.common.display.Display; +import me.shedaniel.rei.api.common.display.DisplaySerializerRegistry; +import me.shedaniel.rei.api.common.entry.EntryIngredient; import me.shedaniel.rei.api.common.entry.EntryStack; import me.shedaniel.rei.api.common.plugins.PluginManager; import me.shedaniel.rei.api.common.plugins.REIPlugin; import me.shedaniel.rei.api.common.registry.Reloadable; +import me.shedaniel.rei.api.common.util.CollectionUtils; import me.shedaniel.rei.api.common.util.EntryStacks; import me.shedaniel.rei.impl.client.ClientHelperImpl; import me.shedaniel.rei.impl.client.REIRuntimeImpl; import me.shedaniel.rei.impl.client.gui.ScreenOverlayImpl; import me.shedaniel.rei.impl.client.gui.scr