Merge branch 'mc1.16/dev' of https://github.com/Creators-of-Create/Create into mc1.16/fix-bugs

This commit is contained in:
PepperCode1 2021-05-04 12:18:55 -07:00
commit b0dad3bf79
106 changed files with 4096 additions and 969 deletions

View File

@ -16,6 +16,7 @@ indent_size = 2
[*.java]
indent_style = tab
ij_continuation_indent_size = 8
ij_java_class_count_to_use_import_on_demand = 99
ij_java_names_count_to_use_import_on_demand = 99
ij_java_imports_layout = $*,|,java.**,|,javax.**,|,org.**,|,com.**,|,*
ij_java_imports_layout = $*,|,java.**,|,javax.**,|,org.**,|,com.**,|,*

View File

@ -53,7 +53,7 @@ b59324f051f21d8ce1a48a08f4721a61a3c414d6 assets/create/blockstates/chute.json
e5e3757e99c139d67b2a70288466d8a74d818841 assets/create/blockstates/cogwheel.json
36f54136a7756c97f71bc6b47ef4e8e575e72879 assets/create/blockstates/content_observer.json
cfea7283f0ebd2432d67e80a523f2a12e24c0bd5 assets/create/blockstates/controller_rail.json
2a956df55577ce02384af372a15f41ec626b84b0 assets/create/blockstates/copper_backtank.json
961b615124ea9a5a5735e8a79f81a702de7da2cf assets/create/blockstates/copper_backtank.json
f8eff64c75fc599e9a44a003f54ae9931cd8ce7c assets/create/blockstates/copper_block.json
cabf6b8c59eb0e3d56a0a5a856ca058bb3200882 assets/create/blockstates/copper_casing.json
3355a852cdc717e257ca19b3db836068964733e3 assets/create/blockstates/copper_ore.json
@ -408,20 +408,20 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
a6d814f94926d88764c38862cc4ece9c367e023b assets/create/lang/en_ud.json
80e3112fe5ab12a9bbe7c272ab50904eee351f44 assets/create/lang/en_us.json
9b8c1f501cb57098f3ac67c8fd4532246a0c59bb assets/create/lang/unfinished/de_de.json
9d0482aa7a410bdb9b44bb7c1e24bda0343e1306 assets/create/lang/unfinished/es_es.json
6e401a93ef63da54673d125892893468f04931be assets/create/lang/unfinished/es_mx.json
466fe4336c8c45fab9027e18103f8c7ef5c94fef assets/create/lang/unfinished/fr_fr.json
62d87f787237fbf2ace70eafb536cf5283c4dd16 assets/create/lang/unfinished/it_it.json
e83d8ed48ebf35ce6ba3fac10efff80ce9ffc050 assets/create/lang/unfinished/ja_jp.json
448bdf719bd40bb4cb8f013d29e1c65c1277f4ff assets/create/lang/unfinished/ko_kr.json
a4229b2f23223f31a1b869d5a07ff61128ddd2e8 assets/create/lang/unfinished/nl_nl.json
9d1594172ba55eab5b96bd48f5204b082493e5e8 assets/create/lang/unfinished/pl_pl.json
ba271a34ebf9c23c239fcdf94d71623bfcaaefb1 assets/create/lang/unfinished/pt_br.json
0c78fdaa30db8d54122bb055167ee41e4d1e010c assets/create/lang/unfinished/ru_ru.json
899752fff0af288e71fb1f7c771910395c701477 assets/create/lang/unfinished/zh_cn.json
a7189982351b90b3cde43529a0fbdef696bda22e assets/create/lang/unfinished/zh_tw.json
95f238e0df097f74a7845a58a02d27c3989305ce assets/create/lang/en_us.json
e03638c344f9f80f5cee92c5e4ce4986478e65a5 assets/create/lang/unfinished/de_de.json
dae908c13b54fa5123bad98dd38ba35d58edaaf0 assets/create/lang/unfinished/es_es.json
bf9142028bbd21a4441381c06c3b4557e60e49c5 assets/create/lang/unfinished/es_mx.json
e4f70996f672bc50e8cfeaccd150075c0a07a917 assets/create/lang/unfinished/fr_fr.json
34c1226afddeaf7824fc1aaf65f40505b3811a91 assets/create/lang/unfinished/it_it.json
17a4ed49d461a537ca8e59fc95d12909780105d7 assets/create/lang/unfinished/ja_jp.json
dd1e77bf533b4bf0e7fa358d48ce5643d08b21c3 assets/create/lang/unfinished/ko_kr.json
0faf1940b7c9664be63d02b3685ed0252528a9ce assets/create/lang/unfinished/nl_nl.json
996e1392e3ffcdb6d41a66cf6bd752e301c52b12 assets/create/lang/unfinished/pl_pl.json
49e35e88d59fb49cb1889e960a18371d0616b963 assets/create/lang/unfinished/pt_br.json
af5ee82802fc0e42012c575cd9da1cf36b88b035 assets/create/lang/unfinished/ru_ru.json
63db3153b522775cad4f91eb509e14568bfb0c3c assets/create/lang/unfinished/zh_cn.json
f533c7c7c1cc2b11908377bd807ff006902d5e34 assets/create/lang/unfinished/zh_tw.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -1651,8 +1651,8 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear
866fbb0ce2878a73e0440d1caf6534c8bd7c384f assets/create/models/item/zinc_ingot.json
a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json
b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json
7b73f40a65af0c2288c886928c609ec783c0fc40 assets/create/sounds.json
0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json
3fd540489a0038a78c6b02f81e89d95e53596b2b assets/create/sounds.json
5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json
187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json
0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json
83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json

View File

@ -1,17 +1,32 @@
{
"variants": {
"facing=north": {
"facing=north,waterlogged=false": {
"model": "create:block/copper_backtank/block"
},
"facing=south": {
"facing=south,waterlogged=false": {
"model": "create:block/copper_backtank/block",
"y": 180
},
"facing=west": {
"facing=west,waterlogged=false": {
"model": "create:block/copper_backtank/block",
"y": 270
},
"facing=east": {
"facing=east,waterlogged=false": {
"model": "create:block/copper_backtank/block",
"y": 90
},
"facing=north,waterlogged=true": {
"model": "create:block/copper_backtank/block"
},
"facing=south,waterlogged=true": {
"model": "create:block/copper_backtank/block",
"y": 180
},
"facing=west,waterlogged=true": {
"model": "create:block/copper_backtank/block",
"y": 270
},
"facing=east,waterlogged=true": {
"model": "create:block/copper_backtank/block",
"y": 90
}

View File

@ -1146,6 +1146,7 @@
"create.subtitle.blaze_munch": "Blaze Burner munches",
"create.subtitle.schematicannon_launch_block": "Schematicannon fires",
"create.subtitle.funnel_flap": "Funnel Flaps",
"create.subtitle.copper_armor_equip": "Diving equipment clinks",
"create.subtitle.schematicannon_finish": "Schematicannon dings",
"create.subtitle.scroll_value": "Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "Mechanical Press clangs",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 939",
"_": "Missing Localizations: 940",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "Lohe kaut glücklich",
"create.subtitle.schematicannon_launch_block": "Bauplankanone schießt",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "Bauplankanone endet",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "Mechanische Presse wird aktiviert",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 640",
"_": "Missing Localizations: 641",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "Blaze mastica felizmente",
"create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "Acabados de Schematicannon",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "La Prensa Mecánica se activa",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1263",
"_": "Missing Localizations: 1264",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches",
"create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1191",
"_": "Missing Localizations: 1192",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches",
"create.subtitle.schematicannon_launch_block": "Tir de schémacanon",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "Fin de schémacanon",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "Activation de la presse mechanique",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 657",
"_": "Missing Localizations: 658",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "Il blaze lo gusta felicemente",
"create.subtitle.schematicannon_launch_block": "Tiri del cannoneschematico",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "Finiture cannoneschematico",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "Pressa meccanica attiva",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 21",
"_": "Missing Localizations: 22",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "ブレイズの咀嚼音",
"create.subtitle.schematicannon_launch_block": "概略図砲が発射する",
"create.subtitle.funnel_flap": "ファンネルがはためく",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "概略図砲が作業を終える",
"create.subtitle.scroll_value": "スクロールのカチカチ音",
"create.subtitle.mechanical_press_activation": "メカニカルプレスがガーンと鳴る",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 710",
"_": "Missing Localizations: 711",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "블레이즈가 행복하게 섭취함",
"create.subtitle.schematicannon_launch_block": "청사진 대포가 발포함",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "청사진 대포가 끝남",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "압착기가 가동됨",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1574",
"_": "Missing Localizations: 1575",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches",
"create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 35",
"_": "Missing Localizations: 36",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "Płomyk szczęśliwie przeżuwa",
"create.subtitle.schematicannon_launch_block": "Schematoarmata strzela",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "Schematoarmata skończyła",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "Mechaniczna prasa się uruchamia",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 1626",
"_": "Missing Localizations: 1627",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches",
"create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 554",
"_": "Missing Localizations: 555",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "Всполох радостно жуёт",
"create.subtitle.schematicannon_launch_block": "Выстрелы схематичной пушки",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "Схематичная пушка закончила работу",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "Механический пресс активирован",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 40",
"_": "Missing Localizations: 41",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "烈焰人:咀嚼",
"create.subtitle.schematicannon_launch_block": "蓝图加农炮:发射",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "蓝图加农炮:叮",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "辊压机:工作中",

View File

@ -1,5 +1,5 @@
{
"_": "Missing Localizations: 659",
"_": "Missing Localizations: 660",
"_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "烈焰使者開心地吃著",
"create.subtitle.schematicannon_launch_block": "藍圖大炮發射",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps",
"create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks",
"create.subtitle.schematicannon_finish": "藍圖大炮完成任務",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "液壓機工作",

View File

@ -49,6 +49,15 @@
],
"subtitle": "create.subtitle.contraption_disassemble"
},
"copper_armor_equip": {
"sounds": [
{
"name": "minecraft:item.armor.equip_gold",
"type": "event"
}
],
"subtitle": "create.subtitle.copper_armor_equip"
},
"crafter_click": {
"sounds": [
{

View File

@ -28,8 +28,8 @@
"trigger": "create:bracket_apply",
"conditions": {
"accepted_entries": [
"create:cogwheel",
"create:large_cogwheel"
"create:large_cogwheel",
"create:cogwheel"
]
}
},

View File

@ -100,6 +100,7 @@ public class AllBlockPartials {
EJECTOR_TOP = get("weighted_ejector/top"),
COPPER_BACKTANK_SHAFT = get("copper_backtank/block_shaft_input"),
COPPER_BACKTANK_COGS = get("copper_backtank/block_cogs"),
COUPLING_ATTACHMENT = getEntity("minecart_coupling/attachment"),
COUPLING_RING = getEntity("minecart_coupling/ring"),

View File

@ -1292,6 +1292,7 @@ public class AllBlocks {
REGISTRATE.block("copper_backtank", CopperBacktankBlock::new)
.initialProperties(SharedProperties::softMetal)
.blockstate((c, p) -> p.horizontalBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p)))
.addLayer(() -> RenderType::getCutoutMipped)
.transform(StressConfigDefaults.setImpact(4.0))
.loot((lt, block) -> {
Builder builder = LootTable.builder();

View File

@ -261,23 +261,24 @@ public class AllItems {
REGISTRATE.startSection(CURIOSITIES);
}
public static final ItemEntry<TreeFertilizerItem> TREE_FERTILIZER =
REGISTRATE.item("tree_fertilizer", TreeFertilizerItem::new)
.register();
public static final ItemEntry<? extends CopperArmorItem>
DIVING_HELMET = REGISTRATE.item("diving_helmet", DivingHelmetItem::new)
.register(),
COPPER_BACKTANK = REGISTRATE
COPPER_BACKTANK =
REGISTRATE
.item("copper_backtank", p -> new CopperBacktankItem(p, new BlockItem(AllBlocks.COPPER_BACKTANK.get(), p)))
.model(AssetLookup.<CopperBacktankItem>customGenericItemModel("_", "item"))
.register(),
DIVING_HELMET = REGISTRATE.item("diving_helmet", DivingHelmetItem::new)
.register(),
DIVING_BOOTS = REGISTRATE.item("diving_boots", DivingBootsItem::new)
.register();
public static final ItemEntry<TreeFertilizerItem> TREE_FERTILIZER =
REGISTRATE.item("tree_fertilizer", TreeFertilizerItem::new)
.register();
// Schematics
static {

View File

@ -148,6 +148,11 @@ public class AllSoundEvents {
.category(SoundCategory.BLOCKS)
.build(),
COPPER_ARMOR_EQUIP = create("copper_armor_equip").subtitle("Diving equipment clinks")
.playExisting(SoundEvents.ITEM_ARMOR_EQUIP_GOLD, 1f, 1f)
.category(SoundCategory.PLAYERS)
.build(),
BLAZE_MUNCH = create("blaze_munch").subtitle("Blaze Burner munches")
.playExisting(SoundEvents.ENTITY_GENERIC_EAT, .5f, 1f)
.category(SoundCategory.BLOCKS)
@ -162,6 +167,11 @@ public class AllSoundEvents {
for (SoundEntry entry : entries.values())
entry.register(registry);
}
public static void prepare() {
for (SoundEntry entry : entries.values())
entry.prepare();
}
public static JsonElement provideLangEntries() {
JsonObject object = new JsonObject();
@ -278,6 +288,8 @@ public class AllSoundEvents {
this.category = category;
}
public abstract void prepare();
public abstract void register(IForgeRegistry<SoundEvent> registry);
public abstract void write(JsonObject json);
@ -346,18 +358,23 @@ public class AllSoundEvents {
this.wrappedEvents = wrappedEvents;
compiledEvents = Lists.newArrayList();
}
@Override
public void register(IForgeRegistry<SoundEvent> registry) {
public void prepare() {
for (int i = 0; i < wrappedEvents.size(); i++) {
ResourceLocation location = Create.asResource(getIdOf(i));
SoundEvent sound = new SoundEvent(location).setRegistryName(location);
registry.register(sound);
compiledEvents.add(Pair.of(sound, wrappedEvents.get(i)
.getSecond()));
}
}
@Override
public void register(IForgeRegistry<SoundEvent> registry) {
for (Pair<SoundEvent, Couple<Float>> pair : compiledEvents)
registry.register(pair.getFirst());
}
@Override
public SoundEvent getMainEvent() {
return compiledEvents.get(0)
@ -413,11 +430,16 @@ public class AllSoundEvents {
public CustomSoundEntry(String id, String subtitle, SoundCategory category) {
super(id, subtitle, category);
}
@Override
public void prepare() {
ResourceLocation location = getLocation();
event = new SoundEvent(location).setRegistryName(location);
}
@Override
public void register(IForgeRegistry<SoundEvent> registry) {
ResourceLocation location = getLocation();
registry.register(event = new SoundEvent(location).setRegistryName(location));
registry.register(event);
}
@Override

View File

@ -78,6 +78,7 @@ public class Create {
IEventBus modEventBus = FMLJavaModLoadingContext.get()
.getModEventBus();
AllSoundEvents.prepare();
AllBlocks.register();
AllItems.register();
AllFluids.register();

View File

@ -14,6 +14,7 @@ import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer;
import com.simibubi.create.content.schematics.ClientSchematicLoader;
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
import com.simibubi.create.content.schematics.client.SchematicHandler;
import com.simibubi.create.events.ClientEvents;
import com.simibubi.create.foundation.ResourceReloadHandler;
import com.simibubi.create.foundation.block.render.CustomBlockModels;
import com.simibubi.create.foundation.block.render.SpriteShifter;
@ -82,6 +83,7 @@ public class CreateClient {
modEventBus.addListener(CreateClient::onModelRegistry);
modEventBus.addListener(CreateClient::onTextureStitch);
modEventBus.addListener(AllParticleTypes::registerFactories);
modEventBus.addListener(ClientEvents::loadCompleted);
Backend.init();
OptifineHandler.init();
@ -112,6 +114,7 @@ public class CreateClient {
PonderIndex.registerTags();
UIRenderHelper.init();
UIRenderHelper.enableStencil();
IResourceManager resourceManager = Minecraft.getInstance()
.getResourceManager();

View File

@ -53,7 +53,6 @@ import mezz.jei.api.registration.IGuiHandlerRegistration;
import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration;
import mezz.jei.api.registration.IRecipeRegistration;
import mezz.jei.api.registration.ISubtypeRegistration;
import mezz.jei.api.runtime.IIngredientManager;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;

View File

@ -73,7 +73,7 @@ public class PolishingCategory extends CreateRecipeCategory<SandPaperPolishingRe
tag.put("Polishing", matchingStacks[0].serializeNBT());
tag.putBoolean("JEI", true);
GuiGameElement.of(renderedSandpaper)
.at(getBackground().getWidth() / 2 - 16, 0, 0)
.<GuiGameElement.GuiRenderBuilder>at(getBackground().getWidth() / 2 - 16, 0, 0)
.scale(2)
.render(matrixStack);
}

View File

@ -153,7 +153,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen {
0xffffff);
GuiGameElement.of(renderedItem)
.at(guiLeft + background.width + 10, guiTop + 100, -150)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + background.width + 10, guiTop + 100, -150)
.scale(5)
.render(matrixStack);
}

View File

@ -41,7 +41,7 @@ public class CogwheelBlockItem extends BlockItem {
large = block.isLarge;
placementHelperId = PlacementHelpers.register(large ? new LargeCogHelper() : new SmallCogHelper());
integratedCogHelperId = large ? PlacementHelpers.register(new IntegratedCogHelper()) : -1;
integratedCogHelperId = PlacementHelpers.register(large ? new IntegratedLargeCogHelper() : new IntegratedSmallCogHelper());
}
@Override
@ -93,7 +93,7 @@ public class CogwheelBlockItem extends BlockItem {
for (int offset1 : Iterate.positiveAndNegative) {
for (int offset2 : Iterate.positiveAndNegative) {
BlockPos connectedPos = pos.offset(d1, offset1)
.offset(d2, offset2);
.offset(d2, offset2);
BlockState blockState = world.getBlockState(connectedPos);
if (!(blockState.getBlock() instanceof CogWheelBlock))
continue;
@ -123,7 +123,7 @@ public class CogwheelBlockItem extends BlockItem {
if (!((CogWheelBlock) state.getBlock()).isLarge) {
List<Direction> directions =
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
for (Direction dir : directions) {
BlockPos newPos = pos.offset(dir);
@ -132,8 +132,8 @@ public class CogwheelBlockItem extends BlockItem {
continue;
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
.getMaterial()
.isReplaceable())
continue;
return PlacementOffset.success(newPos, s -> s.with(AXIS, state.get(AXIS)));
@ -162,19 +162,19 @@ public class CogwheelBlockItem extends BlockItem {
if (((CogWheelBlock) state.getBlock()).isLarge) {
Direction side = IPlacementHelper.orderedByDistanceOnlyAxis(pos, ray.getHitVec(), state.get(AXIS))
.get(0);
.get(0);
List<Direction> directions =
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
for (Direction dir : directions) {
BlockPos newPos = pos.offset(dir)
.offset(side);
.offset(side);
if (!CogWheelBlock.isValidCogwheelPosition(true, world, newPos, dir.getAxis()))
continue;
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
.getMaterial()
.isReplaceable())
continue;
return PlacementOffset.success(newPos, s -> s.with(AXIS, dir.getAxis()));
@ -199,16 +199,16 @@ public class CogwheelBlockItem extends BlockItem {
public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
// diagonal gears of different size
Direction closest = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS))
.get(0);
.get(0);
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(),
state.get(AXIS), d -> d.getAxis() != closest.getAxis());
state.get(AXIS), d -> d.getAxis() != closest.getAxis());
for (Direction dir : directions) {
BlockPos newPos = pos.offset(dir)
.offset(closest);
.offset(closest);
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
.getMaterial()
.isReplaceable())
continue;
if (!CogWheelBlock.isValidCogwheelPosition(ICogWheel.isLargeCog(state), world, newPos, state.get(AXIS)))
@ -222,16 +222,16 @@ public class CogwheelBlockItem extends BlockItem {
protected boolean hitOnShaft(BlockState state, BlockRayTraceResult ray) {
return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS))
.getBoundingBox()
.grow(0.001)
.contains(ray.getHitVec()
.subtract(ray.getHitVec()
.align(Iterate.axisSet)));
.getBoundingBox()
.grow(0.001)
.contains(ray.getHitVec()
.subtract(ray.getHitVec()
.align(Iterate.axisSet)));
}
}
@MethodsReturnNonnullByDefault
public static class IntegratedCogHelper implements IPlacementHelper {
public static class IntegratedLargeCogHelper implements IPlacementHelper {
@Override
public Predicate<ItemStack> getItemPredicate() {
@ -250,10 +250,10 @@ public class CogwheelBlockItem extends BlockItem {
if (state.contains(HorizontalKineticBlock.HORIZONTAL_FACING))
newAxis = state.get(HorizontalKineticBlock.HORIZONTAL_FACING)
.getAxis();
.getAxis();
else if (state.contains(DirectionalKineticBlock.FACING))
newAxis = state.get(DirectionalKineticBlock.FACING)
.getAxis();
.getAxis();
else
newAxis = Axis.Y;
@ -261,15 +261,15 @@ public class CogwheelBlockItem extends BlockItem {
return PlacementOffset.fail();
List<Direction> directions =
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), face.getAxis(), newAxis);
IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), face.getAxis(), newAxis);
for (Direction d : directions) {
BlockPos newPos = pos.offset(face)
.offset(d);
.offset(d);
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
.getMaterial()
.isReplaceable())
continue;
if (!CogWheelBlock.isValidCogwheelPosition(false, world, newPos, newAxis))
@ -282,4 +282,57 @@ public class CogwheelBlockItem extends BlockItem {
}
}
@MethodsReturnNonnullByDefault
public static class IntegratedSmallCogHelper implements IPlacementHelper {
@Override
public Predicate<ItemStack> getItemPredicate() {
return ((Predicate<ItemStack>) ICogWheel::isSmallCogItem).and(ICogWheel::isDedicatedCogItem);
}
@Override
public Predicate<BlockState> getStatePredicate() {
return s -> !ICogWheel.isDedicatedCogWheel(s.getBlock()) && ICogWheel.isSmallCog(s);
}
@Override
public PlacementOffset getOffset(PlayerEntity player, World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
Direction face = ray.getFace();
Axis newAxis;
if (state.contains(HorizontalKineticBlock.HORIZONTAL_FACING))
newAxis = state.get(HorizontalKineticBlock.HORIZONTAL_FACING)
.getAxis();
else if (state.contains(DirectionalKineticBlock.FACING))
newAxis = state.get(DirectionalKineticBlock.FACING)
.getAxis();
else
newAxis = Axis.Y;
if (face.getAxis() == newAxis)
return PlacementOffset.fail();
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), newAxis);
for (Direction d : directions) {
BlockPos newPos = pos.offset(d);
if (!world.getBlockState(newPos)
.getMaterial()
.isReplaceable())
continue;
if (!CogWheelBlock.isValidCogwheelPosition(false, world, newPos, newAxis))
return PlacementOffset.fail();
return PlacementOffset.success()
.at(newPos)
.withTransform(s -> s.with(CogWheelBlock.AXIS, newAxis));
}
return PlacementOffset.fail();
}
}
}

View File

@ -20,8 +20,6 @@ import net.minecraft.item.ItemUseContext;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld;
@ -75,7 +73,7 @@ public interface IWrenchable {
default void playRemoveSound(World world, BlockPos pos) {
AllSoundEvents.WRENCH_REMOVE.playOnServer(world, pos, 1, Create.random.nextFloat() * .5f + .5f);
}
default void playRotateSound(World world, BlockPos pos) {
AllSoundEvents.WRENCH_ROTATE.playOnServer(world, pos, 1, Create.random.nextFloat() + .5f);
}

View File

@ -3,21 +3,20 @@ package com.simibubi.create.content.curiosities.armor;
import java.util.function.Supplier;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.IArmorMaterial;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.LazyValue;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.SoundEvents;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public enum AllArmorMaterials implements IArmorMaterial {
COPPER("copper", 7, new int[] { 1, 3, 5, 2 }, 25, SoundEvents.ITEM_ARMOR_EQUIP_GOLD, 0.0F, 0.0F, () -> {
return Ingredient.fromItems(AllItems.COPPER_INGOT.get());
})
COPPER("copper", 7, new int[] { 1, 3, 4, 2 }, 25, AllSoundEvents.COPPER_ARMOR_EQUIP.getMainEvent(), 0.0F, 0.0F,
() -> Ingredient.fromItems(AllItems.COPPER_INGOT.get()))
;

View File

@ -1,13 +1,20 @@
package com.simibubi.create.content.curiosities.armor;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.IRenderTypeBuffer.Impl;
import net.minecraft.client.renderer.RenderType;
@ -19,7 +26,11 @@ import net.minecraft.client.renderer.entity.model.BipedModel;
import net.minecraft.client.renderer.entity.model.EntityModel;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.Pose;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Direction;
import net.minecraft.util.StringUtils;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
public class CopperBacktankArmorLayer<T extends LivingEntity, M extends EntityModel<T>> extends LayerRenderer<T, M> {
@ -49,15 +60,29 @@ public class CopperBacktankArmorLayer<T extends LivingEntity, M extends EntityMo
BipedModel<?> model = (BipedModel<?>) entityModel;
BlockState renderedState = AllBlocks.COPPER_BACKTANK.getDefaultState()
.with(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH);
RenderType renderType = RenderType.getSolid();
RenderType renderType = RenderType.getCutout();
SuperByteBuffer backtank = CreateClient.bufferCache.renderBlock(renderedState);
SuperByteBuffer cogs =
CreateClient.bufferCache.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, renderedState);
model.bipedBody.rotate(ms);
ms.translate(-1 / 2f, 10 / 16f, 1f);
ms.scale(1, -1, -1);
backtank.light(light)
.renderInto(ms, buffer.getBuffer(renderType));
cogs.matrixStacker()
.centre()
.rotateY(180)
.unCentre()
.translate(0, 6.5f / 16, 11f / 16)
.rotate(Direction.EAST, AngleHelper.rad(2 * AnimationTickHolder.getRenderTime(entity.world) % 360))
.translate(0, -6.5f / 16, -11f / 16);
cogs.light(light)
.renderInto(ms, buffer.getBuffer(renderType));
if (buffer instanceof Impl)
((Impl) buffer).draw(renderType);
ms.pop();
@ -78,4 +103,39 @@ public class CopperBacktankArmorLayer<T extends LivingEntity, M extends EntityMo
new CopperBacktankArmorLayer<>((LivingRenderer<?, ?>) entityRenderer);
}
public static void renderRemainingAirOverlay(MatrixStack ms, Impl buffers, int light, int overlay, float pt) {
ClientPlayerEntity player = Minecraft.getInstance().player;
if (player == null)
return;
if (player.isSpectator() || player.isCreative())
return;
if (!player.getPersistentData()
.contains("VisualBacktankAir"))
return;
if (!player.areEyesInFluid(FluidTags.WATER))
return;
int timeLeft = player.getPersistentData()
.getInt("VisualBacktankAir");
ms.push();
MainWindow window = Minecraft.getInstance()
.getWindow();
ms.translate(window.getScaledWidth() / 2 + 90, window.getScaledHeight() - 53, 0);
ITextComponent text = new StringTextComponent(StringUtils.ticksToElapsedTime(timeLeft * 20));
GuiGameElement.of(AllItems.COPPER_BACKTANK.asStack())
.at(0, 0)
.render(ms);
int color = 0xFF_FFFFFF;
if (timeLeft < 60 && timeLeft % 2 == 0) {
color = ColorHelper.mixColors(0xFF_FF0000, color, Math.max(timeLeft / 60f, .25f));
}
Minecraft.getInstance().fontRenderer.drawWithShadow(ms, text, 16, 5, color);
buffers.draw();
ms.pop();
}
}

View File

@ -8,31 +8,74 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.foundation.block.ITE;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.pathfinding.PathType;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer;
public class CopperBacktankBlock extends HorizontalKineticBlock implements ITE<CopperBacktankTileEntity> {
public class CopperBacktankBlock extends HorizontalKineticBlock
implements ITE<CopperBacktankTileEntity>, IWaterLoggable {
public CopperBacktankBlock(Properties properties) {
super(properties);
setDefaultState(super.getDefaultState().with(BlockStateProperties.WATERLOGGED, false));
}
@Override
public FluidState getFluidState(BlockState state) {
return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false)
: Fluids.EMPTY.getDefaultState();
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(BlockStateProperties.WATERLOGGED);
super.fillStateContainer(builder);
}
@Override
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState,
IWorld world, BlockPos pos, BlockPos neighbourPos) {
if (state.get(BlockStateProperties.WATERLOGGED)) {
world.getPendingFluidTicks()
.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
}
return state;
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
FluidState ifluidstate = context.getWorld()
.getFluidState(context.getPos());
return super.getStateForPlacement(context).with(BlockStateProperties.WATERLOGGED,
Boolean.valueOf(ifluidstate.getFluid() == Fluids.WATER));
}
@Override
@ -63,14 +106,20 @@ public class CopperBacktankBlock extends HorizontalKineticBlock implements ITE<C
@Override
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_,
BlockRayTraceResult p_225533_6_) {
if (player == null)
return ActionResultType.PASS;
if (player instanceof FakePlayer)
return ActionResultType.PASS;
if (player.getHeldItemMainhand().getItem() instanceof BlockItem)
if (player.isSneaking())
return ActionResultType.PASS;
if (player.getHeldItemMainhand()
.getItem() instanceof BlockItem)
return ActionResultType.PASS;
if (!player.getItemStackFromSlot(EquipmentSlotType.CHEST)
.isEmpty())
return ActionResultType.PASS;
if (!world.isRemote) {
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, .75f, 1);
player.setItemStackToSlot(EquipmentSlotType.CHEST, getItem(world, pos, state));
world.destroyBlock(pos, false);
}
@ -108,4 +157,9 @@ public class CopperBacktankBlock extends HorizontalKineticBlock implements ITE<C
return CopperBacktankTileEntity.class;
}
@Override
public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) {
return false;
}
}

View File

@ -1,12 +1,19 @@
package com.simibubi.create.content.curiosities.armor;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.util.Direction;
public class CopperBacktankRenderer extends KineticTileEntityRenderer {
@ -14,6 +21,26 @@ public class CopperBacktankRenderer extends KineticTileEntityRenderer {
super(dispatcher);
}
@Override
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light, int overlay) {
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
SuperByteBuffer cogs =
CreateClient.bufferCache.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, te.getBlockState());
cogs.matrixStacker()
.centre()
.rotateY(180 + AngleHelper.horizontalAngle(te.getBlockState()
.get(CopperBacktankBlock.HORIZONTAL_FACING)))
.unCentre()
.translate(0, 6.5f / 16, 11f / 16)
.rotate(Direction.EAST,
AngleHelper.rad(te.getSpeed() / 4f * AnimationTickHolder.getRenderTime(te.getWorld()) % 360))
.translate(0, -6.5f / 16, -11f / 16);
cogs.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
}
@Override
protected SuperByteBuffer getRotatedModel(KineticTileEntity te) {
return PartialBufferer.get(AllBlockPartials.COPPER_BACKTANK_SHAFT, te.getBlockState());

View File

@ -1,6 +1,7 @@
package com.simibubi.create.content.curiosities.armor;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.particle.AirParticleData;
@ -11,6 +12,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.INameable;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d;
@ -37,16 +39,12 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
return;
}
Integer max = AllConfigs.SERVER.curiosities.maxAirInBacktank.get();
int max = getMaxAir();
if (world.isRemote) {
Vector3d centerOf = VecHelper.getCenterOf(pos);
Vector3d v = VecHelper.offsetRandomly(centerOf, Create.random, .65f);
Vector3d m = centerOf.subtract(v);
if (airLevel == max) {
if (Create.random.nextFloat() < 1 / 8f) {
world.addParticle(ParticleTypes.HAPPY_VILLAGER, v.x, v.y, v.z, 0, 0, 0);
}
} else
if (airLevel != max)
world.addParticle(new AirParticleData(1, .05f), v.x, v.y, v.z, m.x, m.y, m.z);
return;
}
@ -62,6 +60,10 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
airLevelTimer = MathHelper.clamp((int) (128f - abs / 5f) - 108, 0, 20);
}
protected int getMaxAir() {
return AllConfigs.SERVER.curiosities.maxAirInBacktank.get();
}
public int getAirLevel() {
return airLevel;
}
@ -91,10 +93,26 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
@Override
protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) {
super.fromTag(state, compound, clientPacket);
int prev = airLevel;
airLevel = compound.getInt("Air");
airLevelTimer = compound.getInt("Timer");
if (compound.contains("CustomName", 8))
this.customName = ITextComponent.Serializer.fromJson(compound.getString("CustomName"));
if (prev != 0 && prev != airLevel && airLevel == getMaxAir() && clientPacket)
playFilledEffect();
}
protected void playFilledEffect() {
AllSoundEvents.CONFIRM.playAt(world, pos, 0.4f, 1, true);
Vector3d baseMotion = new Vector3d(.25, 0.1, 0);
Vector3d baseVec = VecHelper.getCenterOf(pos);
for (int i = 0; i < 360; i += 10) {
Vector3d m = VecHelper.rotate(baseMotion, i, Axis.Y);
Vector3d v = baseVec.add(m.normalize()
.scale(.25f));
world.addParticle(ParticleTypes.SPIT, v.x, v.y, v.z, m.x, m.y, m.z);
}
}
@Override
@ -103,5 +121,10 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
: new TranslationTextComponent(AllItems.COPPER_BACKTANK.get()
.getTranslationKey());
}
@Override
public boolean shouldRenderAsTE() {
return true;
}
}

View File

@ -8,6 +8,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@ -22,18 +23,20 @@ public class DivingHelmetItem extends CopperArmorItem {
@SubscribeEvent
public static void breatheUnderwater(LivingUpdateEvent event) {
LivingEntity entity = event.getEntityLiving();
boolean second = entity.world.getGameTime() % 20 == 0;
World world = entity.world;
boolean second = world.getGameTime() % 20 == 0;
boolean drowning = entity.getAir() == 0;
if (!second && !drowning)
return;
if (world.isRemote)
entity.getPersistentData()
.remove("VisualBacktankAir");
if (!AllItems.DIVING_HELMET.get()
.isWornBy(entity))
return;
if (!entity.isInWater())
return;
ItemStack backtank = ItemStack.EMPTY;
for (ItemStack itemStack : entity.getArmorInventoryList()) {
if (AllItems.COPPER_BACKTANK.isIn(itemStack)) {
@ -41,20 +44,25 @@ public class DivingHelmetItem extends CopperArmorItem {
break;
}
}
if (backtank.isEmpty())
return;
CompoundNBT tag = backtank.getOrCreateTag();
int airRemaining = tag.getInt("Air");
if (airRemaining == 0)
return;
if (drowning)
entity.setAir(10);
if (world.isRemote)
entity.getPersistentData()
.putInt("VisualBacktankAir", airRemaining);
if (!second)
return;
entity.setAir(Math.min(entity.getMaxAir(), entity.getAir() + 10));
entity.addPotionEffect(new EffectInstance(Effects.WATER_BREATHING, 30, 0, true, false, true));
tag.putInt("Air", airRemaining - 1);

View File

@ -96,14 +96,14 @@ public class SymmetryWandScreen extends AbstractSimiScreen {
widgets.add(labelAlign);
widgets.add(areaType);
widgets.add(labelType);
confirmButton = new IconButton(guiLeft + background.width - 33, guiTop + background.height - 24, AllIcons.I_CONFIRM);
widgets.add(confirmButton);
}
private void initAlign(SymmetryMirror element) {
if (areaAlign != null)
if (areaAlign != null)
widgets.remove(areaAlign);
areaAlign = new SelectionScrollInput(guiLeft + 45, guiTop + 43, 109, 18).forOptions(element.getAlignToolTips())
@ -121,10 +121,10 @@ public class SymmetryWandScreen extends AbstractSimiScreen {
textRenderer.draw(matrixStack, wand.getDisplayName(), guiLeft + 11, guiTop + 4, 0x6B3802);
renderBlock(matrixStack);
GuiGameElement.of(wand)
.at(guiLeft + 170, guiTop + 490, -150)
.scale(4)
.rotate(-70, 20, 20)
.render(matrixStack);
.scale(4)
.rotate(-70, 20, 20)
.at(guiLeft + 170, guiTop + 490, -150)
.render(matrixStack);
}
protected void renderBlock(MatrixStack ms) {
@ -150,7 +150,7 @@ public class SymmetryWandScreen extends AbstractSimiScreen {
client.player.setHeldItem(hand, heldItem);
super.removed();
}
@Override
public boolean mouseClicked(double x, double y, int button) {
if (confirmButton.isHovered()) {

View File

@ -135,9 +135,9 @@ public class ZapperScreen extends AbstractSimiScreen {
protected void renderZapper(MatrixStack matrixStack) {
GuiGameElement.of(zapper)
.at((this.width - this.sWidth) / 2 + 220, this.height / 2 - this.sHeight / 4 + 27, -150)
.scale(4)
.render(matrixStack);
.scale(4)
.at((this.width - this.sWidth) / 2 + 220, this.height / 2 - this.sHeight / 4 + 27, -150)
.render(matrixStack);
}
protected void renderBlock(MatrixStack matrixStack) {

View File

@ -97,7 +97,7 @@ public class AdjustableCrateScreen extends AbstractSimiContainerScreen<Adjustabl
}
GuiGameElement.of(renderedItem)
.at(guiLeft + ADJUSTABLE_CRATE.width + 110, guiTop + 70, -150)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + ADJUSTABLE_CRATE.width + 110, guiTop + 70, -150)
.scale(5)
.render(matrixStack);
}

View File

@ -126,7 +126,7 @@ public class StockpileSwitchScreen extends AbstractSimiScreen {
matrixStack.push();
GuiGameElement.of(renderedItem)
.at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250)
.scale(5)
.render(matrixStack);
matrixStack.pop();

View File

@ -69,7 +69,7 @@ public abstract class AbstractFilterScreen<F extends AbstractFilterContainer> ex
textRenderer.draw(ms, I18n.format(container.filterItem.getTranslationKey()), x + 15, y + 3, 0xdedede);
GuiGameElement.of(container.filterItem)
.at(x + background.width, guiTop + background.height - 60)
.<GuiGameElement.GuiRenderBuilder>at(x + background.width, guiTop + background.height - 60)
.scale(5)
.render(ms);

View File

@ -122,7 +122,7 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen<SchematicT
textRenderer.drawWithShadow(matrixStack, noSchematics, mainLeft + 54, mainTop + 26, 0xd3d3d3);
GuiGameElement.of(renderedItem)
.at(mainLeft + 217, mainTop + 50, -150)
.<GuiGameElement.GuiRenderBuilder>at(mainLeft + 217, mainTop + 50, -150)
.scale(3)
.render(matrixStack);

View File

@ -262,7 +262,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
renderBlueprintHighlight(matrixStack);
GuiGameElement.of(renderedItem)
.at(guiLeft + 230, guiTop + 110, -200)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + 230, guiTop + 110, -200)
.scale(5)
.render(matrixStack);
@ -274,7 +274,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen<Schematica
if (te.missingItem != null) {
stringWidth += 15;
GuiGameElement.of(te.missingItem)
.at(guiLeft + 150, guiTop + 46, 100)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + 150, guiTop + 46, 100)
.scale(1)
.render(matrixStack);
}

View File

@ -152,7 +152,7 @@ public class SchematicEditScreen extends AbstractSimiScreen {
x + 93 - textRenderer.getStringWidth(handler.getCurrentSchematicName()) / 2, y + 3, 0xffffff);
GuiGameElement.of(AllItems.SCHEMATIC.asStack())
.at(guiLeft + 200, guiTop + 82, 0)
.<GuiGameElement.GuiRenderBuilder>at(guiLeft + 200, guiTop + 82, 0)
.scale(3)
.render(matrixStack);
}

View File

@ -23,6 +23,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra
import com.simibubi.create.content.contraptions.components.turntable.TurntableHandler;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler;
import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer;
import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler;
import com.simibubi.create.content.curiosities.zapper.ZapperItem;
import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler;
@ -30,6 +31,7 @@ import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperR
import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler;
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
import com.simibubi.create.foundation.fluid.FluidHelper;
import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.item.TooltipHelper;
@ -54,6 +56,7 @@ import com.simibubi.create.foundation.utility.worldWrappers.WrappedClientWorld;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.IRenderTypeBuffer.Impl;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.fluid.Fluid;
@ -79,7 +82,11 @@ import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
@EventBusSubscriber(value = Dist.CLIENT)
public class ClientEvents {
@ -195,12 +202,20 @@ public class ClientEvents {
@SubscribeEvent
public static void onRenderOverlay(RenderGameOverlayEvent.Post event) {
MatrixStack ms = event.getMatrixStack();
Impl buffers = Minecraft.getInstance()
.getBufferBuilders()
.getEntityVertexConsumers();
int light = 0xF000F0;
int overlay = OverlayTexture.DEFAULT_UV;
float pt = event.getPartialTicks();
if (event.getType() == ElementType.AIR)
CopperBacktankArmorLayer.renderRemainingAirOverlay(ms, buffers, light, overlay, pt);
if (event.getType() != ElementType.HOTBAR)
return;
onRenderHotbar(event.getMatrixStack(), Minecraft.getInstance()
.getBufferBuilders()
.getEntityVertexConsumers(), 0xF000F0, OverlayTexture.DEFAULT_UV, event.getPartialTicks());
onRenderHotbar(ms, buffers, light, overlay, pt);
}
public static void onRenderHotbar(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay,
@ -319,4 +334,9 @@ public class ClientEvents {
}
}
public static void loadCompleted(FMLLoadCompleteEvent event) {
ModContainer createContainer = ModList.get().getModContainerById("create").orElseThrow(() -> new IllegalStateException("Create Mod Container missing after loadCompleted"));
createContainer.registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (mc, previousScreen) -> new BaseConfigScreen(previousScreen));
}
}

View File

@ -21,20 +21,22 @@ public class AllCommands {
LiteralCommandNode<CommandSource> util = buildUtilityCommands();
LiteralCommandNode<CommandSource> createRoot = dispatcher.register(Commands.literal("create")
.requires(cs -> cs.hasPermissionLevel(0))
// general purpose
.then(new ToggleExperimentalRenderingCommand().register())
.then(new ToggleDebugCommand().register())
.then(FabulousWarningCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
.then(HighlightCommand.register())
.then(CouplingCommand.register())
.then(CloneCommand.register())
.then(PonderCommand.register())
.requires(cs -> cs.hasPermissionLevel(0))
// general purpose
.then(new ToggleExperimentalRenderingCommand().register())
.then(new ToggleDebugCommand().register())
.then(FabulousWarningCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
.then(HighlightCommand.register())
.then(CouplingCommand.register())
.then(ConfigCommand.register())
.then(PonderCommand.register())
.then(CloneCommand.register())
// utility
.then(util));
// utility
.then(util)
);
createRoot.addChild(buildRedirect("u", util));
@ -50,12 +52,12 @@ public class AllCommands {
private static LiteralCommandNode<CommandSource> buildUtilityCommands() {
return Commands.literal("util")
.then(ReplaceInCommandBlocksCommand.register())
.then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register())
.then(FlySpeedCommand.register())
// .then(KillTPSCommand.register())
.build();
.then(ReplaceInCommandBlocksCommand.register())
.then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register())
.then(FlySpeedCommand.register())
//.then(KillTPSCommand.register())
.build();
}
@ -72,15 +74,15 @@ public class AllCommands {
*
* @return the built node
*/
public static LiteralCommandNode<CommandSource> buildRedirect(final String alias,
final LiteralCommandNode<CommandSource> destination) {
public static LiteralCommandNode<CommandSource> buildRedirect(final String alias, final LiteralCommandNode<CommandSource> destination) {
// Redirects only work for nodes with children, but break the top argument-less command.
// Manually adding the root command after setting the redirect doesn't fix it.
// See https://github.com/Mojang/brigadier/issues/46). Manually clone the node instead.
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder.<CommandSource>literal(alias)
.requires(destination.getRequirement())
.forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork())
.executes(destination.getCommand());
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder
.<CommandSource>literal(alias)
.requires(destination.getRequirement())
.forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork())
.executes(destination.getCommand());
for (CommandNode<CommandSource> child : destination.getChildren()) {
builder.then(child);
}

View File

@ -0,0 +1,27 @@
package com.simibubi.create.foundation.command;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraftforge.fml.network.PacketDistributor;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.simibubi.create.foundation.networking.AllPackets;
public class ConfigCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("config")
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource().asPlayer();
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.configScreen.name(), "")
);
return Command.SINGLE_SUCCESS;
});
}
}

View File

@ -13,16 +13,18 @@ public class FabulousWarningCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("dismissFabulousWarning")
.requires(AllCommands.sourceIsPlayer)
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource()
.asPlayer();
.requires(AllCommands.sourceIsPlayer)
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource()
.asPlayer();
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fabulousWarning.name(), ""));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fabulousWarning.name(), "")
);
return Command.SINGLE_SUCCESS;
});
return Command.SINGLE_SUCCESS;
});
}
}

View File

@ -17,7 +17,7 @@ public class FixLightingCommand {
.executes(ctx -> {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
ctx.getSource()
.sendFeedback(

View File

@ -15,35 +15,32 @@ public class OverlayConfigCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("overlay")
.requires(cs -> cs.hasPermissionLevel(0))
.then(Commands.literal("reset")
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> ConfigureConfigPacket.Actions.overlayReset.performAction(""));
.requires(cs -> cs.hasPermissionLevel(0))
.then(Commands.literal("reset")
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SConfigureConfigPacket.Actions.overlayReset.performAction(""));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER,
() -> () -> AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.overlayReset.name(), "")));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () ->
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.overlayReset.name(), "")));
ctx.getSource()
.sendFeedback(new StringTextComponent("reset overlay offset"), true);
return 1;
}))
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT,
() -> () -> ConfigureConfigPacket.Actions.overlayScreen.performAction(""));
return 1;
})
)
.executes(ctx -> {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> SConfigureConfigPacket.Actions.overlayScreen.performAction(""));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER,
() -> () -> AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.overlayScreen.name(), "")));
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () ->
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.overlayScreen.name(), "")));
ctx.getSource()
.sendFeedback(new StringTextComponent("window opened"), true);
ctx.getSource()
.sendFeedback(new StringTextComponent("window opened"), true);
return 1;
});

View File

@ -21,26 +21,20 @@ import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.network.PacketDistributor;
public class PonderCommand {
public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register(
new ResourceLocation("all_ponders"),
(iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet()
.stream(), builder));
public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register(new ResourceLocation("all_ponders"), (iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet().stream(), builder));
static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("ponder")
.requires(cs -> cs.hasPermissionLevel(0))
.executes(ctx -> openScene("index", ctx.getSource()
.asPlayer()))
.then(Commands.argument("scene", ResourceLocationArgument.resourceLocation())
.suggests(ITEM_PONDERS)
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene")
.toString(),
ctx.getSource()
.asPlayer()))
.then(Commands.argument("targets", EntityArgument.players())
.requires(cs -> cs.hasPermissionLevel(2))
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene")
.toString(), EntityArgument.getPlayers(ctx, "targets")))));
.requires(cs -> cs.hasPermissionLevel(0))
.executes(ctx -> openScene("index", ctx.getSource().asPlayer()))
.then(Commands.argument("scene", ResourceLocationArgument.resourceLocation())
.suggests(ITEM_PONDERS)
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), ctx.getSource().asPlayer()))
.then(Commands.argument("targets", EntityArgument.players())
.requires(cs -> cs.hasPermissionLevel(2))
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), EntityArgument.getPlayers(ctx, "targets")))
)
);
}
@ -53,8 +47,9 @@ public class PonderCommand {
if (player instanceof FakePlayer)
continue;
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.openPonder.name(), sceneId));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.openPonder.name(), sceneId));
}
return Command.SINGLE_SUCCESS;
}

View File

@ -8,6 +8,7 @@ import org.apache.logging.log4j.LogManager;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.ui.BaseConfigScreen;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.ponder.PonderRegistry;
@ -31,17 +32,17 @@ import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent;
public class ConfigureConfigPacket extends SimplePacketBase {
public class SConfigureConfigPacket extends SimplePacketBase {
private final String option;
private final String value;
public ConfigureConfigPacket(String option, String value) {
public SConfigureConfigPacket(String option, String value) {
this.option = option;
this.value = value;
}
public ConfigureConfigPacket(PacketBuffer buffer) {
public SConfigureConfigPacket(PacketBuffer buffer) {
this.option = buffer.readString(32767);
this.value = buffer.readString(32767);
}
@ -69,7 +70,8 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.setPacketHandled(true);
}
enum Actions {
public enum Actions {
configScreen(() -> Actions::configScreen),
rainbowDebug(() -> Actions::rainbowDebug),
overlayScreen(() -> Actions::overlayScreen),
fixLighting(() -> Actions::experimentalLighting),
@ -91,6 +93,11 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.accept(value);
}
@OnlyIn(Dist.CLIENT)
private static void configScreen(String value) {
ScreenOpener.open(new BaseConfigScreen(null));
}
@OnlyIn(Dist.CLIENT)
private static void rainbowDebug(String value) {
ClientPlayerEntity player = Minecraft.getInstance().player;

View File

@ -13,7 +13,9 @@ public class ToggleDebugCommand extends ConfigureConfigCommand {
@Override
protected void sendPacket(ServerPlayerEntity player, String option) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.rainbowDebug.name(), option));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.rainbowDebug.name(), option)
);
}
}

View File

@ -13,7 +13,9 @@ public class ToggleExperimentalRenderingCommand extends ConfigureConfigCommand {
@Override
protected void sendPacket(ServerPlayerEntity player, String option) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.experimentalRendering.name(), option));
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.experimentalRendering.name(), option)
);
}
}

View File

@ -107,8 +107,7 @@ public abstract class ConfigBase {
if (comment.length > 0) {
String[] comments = new String[comment.length + 1];
comments[0] = "";
for (int i = 0; i < comment.length; i++)
comments[i + 1] = comment[i];
System.arraycopy(comment, 0, comments, 1, comment.length);
builder.comment(comments);
} else
builder.comment("");

View File

@ -0,0 +1,59 @@
package com.simibubi.create.foundation.config.ui;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.config.ModConfig;
public class BaseConfigScreen extends ConfigScreen {
BoxWidget clientConfigWidget;
BoxWidget commonConfigWidget;
BoxWidget serverConfigWidget;
public BaseConfigScreen(Screen parent) {
super(parent);
}
@Override
protected void init() {
widgets.clear();
super.init();
TextStencilElement text = new TextStencilElement(client.fontRenderer, new StringTextComponent("Client Settings").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16)
.showingElement(text)
.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification)))
);
text.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget));
TextStencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("World Generation Settings").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16)
.showingElement(text2)
.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification)))
);
text2.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget));
TextStencilElement text3 = new TextStencilElement(client.fontRenderer, new StringTextComponent("Gameplay Settings").formatted(TextFormatting.BOLD)).centered(true, true);
widgets.add(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16)
.showingElement(text3)
);
if (Minecraft.getInstance().world != null) {
serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, AllConfigs.SERVER.specification)));
text3.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget));
} else {
serverConfigWidget.active = false;
serverConfigWidget.updateColorsFromState();
text3.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.BUTTON_DISABLE, true), Theme.i(Theme.Key.BUTTON_DISABLE, false) | 0x40_000000));
}
}
}

View File

@ -0,0 +1,83 @@
package com.simibubi.create.foundation.config.ui;
import java.util.function.Supplier;
import com.simibubi.create.foundation.command.SConfigureConfigPacket;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fml.network.PacketDistributor;
public class CConfigureConfigPacket<T> extends SimplePacketBase {
private String path;
private String value;
public CConfigureConfigPacket(String path, T value) {
this.path = path;
this.value = serialize(value);
}
public CConfigureConfigPacket(PacketBuffer buffer) {
this.path = buffer.readString(32767);
this.value = buffer.readString(32767);
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeString(path);
buffer.writeString(value);
}
@Override
public void handle(Supplier<NetworkEvent.Context> context) {
ServerPlayerEntity sender = context.get().getSender();
if (sender == null || !sender.hasPermissionLevel(2))
return;
ForgeConfigSpec.ValueSpec valueSpec = AllConfigs.SERVER.specification.getRaw(path);
ForgeConfigSpec.ConfigValue<T> configValue = AllConfigs.SERVER.specification.getValues().get(path);
T v = (T) deserialize(configValue.get(), value);
if (!valueSpec.test(v))
return;
configValue.set(v);
}
public String serialize(T value) {
if (value instanceof Boolean)
return Boolean.toString((Boolean) value);
if (value instanceof Enum<?>)
return ((Enum<?>) value).name();
if (value instanceof Integer)
return Integer.toString((Integer) value);
if (value instanceof Float)
return Float.toString((Float) value);
if (value instanceof Double)
return Double.toString((Double) value);
throw new IllegalArgumentException("unknown type " + value + ": " + value.getClass().getSimpleName());
}
public Object deserialize(Object type, String sValue) {
if (type instanceof Boolean)
return Boolean.parseBoolean(sValue);
if (type instanceof Enum<?>)
return Enum.valueOf(((Enum<?>) type).getClass(), sValue);
if (type instanceof Integer)
return Integer.parseInt(sValue);
if (type instanceof Float)
return Float.parseFloat(sValue);
if (type instanceof Double)
return Double.parseDouble(sValue);
throw new IllegalArgumentException("unknown type " + type + ": " + type.getClass().getSimpleName());
}
}

View File

@ -0,0 +1,113 @@
package com.simibubi.create.foundation.config.ui;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.StencilElement;
import com.simibubi.create.foundation.utility.animation.Force;
import com.simibubi.create.foundation.utility.animation.PhysicalFloat;
import net.minecraft.block.BlockState;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.Direction;
public abstract class ConfigScreen extends AbstractSimiScreen {
/*
*
* zelo's list for configUI
*
* reduce number of packets sent to the server when saving a bunch of values
* maybe replace java's awt color with something mutable
* find out why framebuffer blending is incorrect
*
* FIXME
*
* tooltips are hidden underneath the scrollbar, if the bar is near the middle
*
* */
public static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f));
public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().with(CogWheelBlock.AXIS, Direction.Axis.Y);
public static final Map<String, Object> changes = new HashMap<>();
protected final Screen parent;
public ConfigScreen(Screen parent) {
this.parent = parent;
}
@Override
public void tick() {
super.tick();
cogSpin.tick();
}
@Override
public void renderBackground(@Nonnull MatrixStack ms) {
net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.GuiScreenEvent.BackgroundDrawnEvent(this, ms));
}
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
if (this.client != null && this.client.world != null) {
fill(ms, 0, 0, this.width, this.height, 0xb0_282c34);
} else {
fill(ms, 0, 0, this.width, this.height, 0xff_282c34);
}
new StencilElement() {
@Override
protected void renderStencil(MatrixStack ms) {
renderCog(ms, partialTicks);
}
@Override
protected void renderElement(MatrixStack ms) {
fill(ms, -200, -200, 200, 200, 0x60_000000);
}
}.at(width * 0.5f, height * 0.5f, 0).render(ms);
super.renderWindowBackground(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double delta) {
cogSpin.bump(3, -delta * 5);
return super.mouseScrolled(mouseX, mouseY, delta);
}
public static String toHumanReadable(String key) {
String s = key.replaceAll("_", " ");
s = Arrays.stream(StringUtils.splitByCharacterTypeCamelCase(s)).map(StringUtils::capitalize).collect(Collectors.joining(" "));
s = s.replaceAll("\\s\\s+", " ");
return s;
}
protected void renderCog(MatrixStack ms, float partialTicks) {
ms.push();
ms.translate(-100, 100, -100);
ms.scale(200, 200, 1);
GuiGameElement.of(cogwheelState)
.rotateBlock(22.5, cogSpin.getValue(partialTicks), 22.5)
.render(ms);
ms.pop();
}
}

View File

@ -0,0 +1,176 @@
package com.simibubi.create.foundation.config.ui;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.gui.widget.list.ExtendedList;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fml.client.gui.GuiUtils;
public class ConfigScreenList extends ExtendedList<ConfigScreenList.Entry> {
public static TextFieldWidget currentText;
public boolean isForServer = false;
public ConfigScreenList(Minecraft client, int width, int height, int top, int bottom, int elementHeight) {
super(client, width, height, top, bottom, elementHeight);
func_244605_b(false);
func_244606_c(false);
setRenderSelection(false);
currentText = null;
headerHeight = 3;
}
@Override
public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
UIRenderHelper.angledGradient(ms, 90, left + width / 2, top, width, 5, 0x60_000000, 0x0);
UIRenderHelper.angledGradient(ms, -90, left + width / 2, bottom, width, 5, 0x60_000000, 0x0);
UIRenderHelper.angledGradient(ms, 0, left, top + height / 2, height, 5, 0x60_000000, 0x0);
UIRenderHelper.angledGradient(ms, 180, right, top + height / 2, height, 5, 0x60_000000, 0x0);
super.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void renderList(MatrixStack p_238478_1_, int p_238478_2_, int p_238478_3_, int p_238478_4_, int p_238478_5_, float p_238478_6_) {
MainWindow window = Minecraft.getInstance().getWindow();
double d0 = window.getGuiScaleFactor();
RenderSystem.enableScissor((int) (this.left * d0), (int) (window.getFramebufferHeight() - (this.bottom * d0)), (int) (this.width * d0), (int) (this.height * d0));
super.renderList(p_238478_1_, p_238478_2_, p_238478_3_, p_238478_4_, p_238478_5_, p_238478_6_);
RenderSystem.disableScissor();
}
@Override
public boolean mouseClicked(double x, double y, int button) {
children().stream().filter(e -> e instanceof NumberEntry<?>).forEach(e -> e.mouseClicked(x, y, button));
return super.mouseClicked(x, y, button);
}
@Override
public int getRowWidth() {
return width - 16;
}
@Override
protected int getScrollbarPositionX() {
return left + this.width - 6;
}
public void tick() {
for(int i = 0; i < getItemCount(); ++i) {
int top = this.getRowTop(i);
int bot = top + itemHeight;
if (bot >= this.top && top <= this.bottom)
this.getEntry(i).tick();
}
}
public void bumpCog(float force) {
ConfigScreen.cogSpin.bump(3, force);
}
public static abstract class Entry extends ExtendedList.AbstractListEntry<Entry> {
protected List<IGuiEventListener> listeners;
protected Entry() {
listeners = new ArrayList<>();
}
@Override
public boolean mouseClicked(double x, double y, int button) {
return getGuiListeners().stream().anyMatch(l -> l.mouseClicked(x, y, button));
}
@Override
public boolean keyPressed(int code, int keyPressed_2_, int keyPressed_3_) {
return getGuiListeners().stream().anyMatch(l -> l.keyPressed(code, keyPressed_2_, keyPressed_3_));
}
@Override
public boolean charTyped(char ch, int code) {
return getGuiListeners().stream().anyMatch(l -> l.charTyped(ch, code));
}
public void tick() {}
public List<IGuiEventListener> getGuiListeners() {
return listeners;
}
protected void setEditable(boolean b) {}
}
public static class LabeledEntry extends Entry {
protected static final float labelWidthMult = 0.4f;
protected TextStencilElement label;
protected List<ITextComponent> labelTooltip;
protected String unit = null;
public LabeledEntry(String label) {
this.label = new TextStencilElement(Minecraft.getInstance().fontRenderer, label);
this.label.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.TEXT_ACCENT_STRONG)));
labelTooltip = new ArrayList<>();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 6, width, 0xdd_000000);
IFormattableTextComponent component = label.getComponent();
FontRenderer font = Minecraft.getInstance().fontRenderer;
if (font.getWidth(component) > getLabelWidth(width) - 10) {
label.withText(font.trimToWidth(component, getLabelWidth(width) - 15).getString() + "...");
}
if (unit != null) {
int unitWidth = font.getStringWidth(unit);
font.draw(ms, unit, x + getLabelWidth(width) - unitWidth - 5, y + height / 2 + 2, Theme.i(Theme.Key.TEXT_DARKER));
label.at(x + 10, y + height / 2 - 10, 0).render(ms);
} else {
label.at(x + 10, y + height / 2 - 4, 0).render(ms);
}
if (mouseX > x && mouseX < x + getLabelWidth(width) && mouseY > y + 5 && mouseY < y + height - 5) {
List<ITextComponent> tooltip = getLabelTooltip();
if (tooltip.isEmpty())
return;
GL11.glDisable(GL11.GL_SCISSOR_TEST);
Screen screen = Minecraft.getInstance().currentScreen;
ms.push();
ms.translate(0, 0, 400);
GuiUtils.drawHoveringText(ms, tooltip, mouseX, mouseY, screen.width, screen.height, 300, font);
ms.pop();
GL11.glEnable(GL11.GL_SCISSOR_TEST);
}
}
public List<ITextComponent> getLabelTooltip() {
return labelTooltip;
}
protected int getLabelWidth(int totalWidth) {
return totalWidth;
}
}
}

View File

@ -0,0 +1,34 @@
package com.simibubi.create.foundation.config.ui;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.util.text.StringTextComponent;
public class ConfigTextField extends TextFieldWidget {
protected FontRenderer font;
protected String unit;
public ConfigTextField(FontRenderer font, int x, int y, int width, int height, String unit) {
super(font, x, y, width, height, StringTextComponent.EMPTY);
this.font = font;
this.unit = unit;
}
@Override
public void setFocused2(boolean focus) {
super.setFocused2(focus);
if (!focus) {
if (ConfigScreenList.currentText == this)
ConfigScreenList.currentText = null;
return;
}
if (ConfigScreenList.currentText != null && ConfigScreenList.currentText != this)
ConfigScreenList.currentText.setFocused2(false);
ConfigScreenList.currentText = this;
}
}

View File

@ -0,0 +1,345 @@
package com.simibubi.create.foundation.config.ui;
import java.awt.Color;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.lwjgl.glfw.GLFW;
import com.electronwill.nightconfig.core.AbstractConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.entries.BooleanEntry;
import com.simibubi.create.foundation.config.ui.entries.EnumEntry;
import com.simibubi.create.foundation.config.ui.entries.NumberEntry;
import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry;
import com.simibubi.create.foundation.config.ui.entries.ValueEntry;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.ConfirmationScreen;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.util.text.ITextProperties;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.config.ModConfig;
public class SubMenuConfigScreen extends ConfigScreen {
public final ModConfig.Type type;
protected ForgeConfigSpec spec;
protected UnmodifiableConfig configGroup;
protected ConfigScreenList list;
protected BoxWidget resetAll;
protected BoxWidget saveChanges;
protected BoxWidget discardChanges;
protected BoxWidget goBack;
protected BoxWidget serverLocked;
protected int listWidth;
protected String title;
public SubMenuConfigScreen(Screen parent, String title, ModConfig.Type type, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) {
super(parent);
this.type = type;
this.spec = configSpec;
this.title = title;
this.configGroup = configGroup;
}
public SubMenuConfigScreen(Screen parent, ModConfig.Type type, ForgeConfigSpec configSpec) {
super(parent);
this.type = type;
this.spec = configSpec;
this.title = "root";
this.configGroup = configSpec.getValues();
}
protected void clearChanges() {
changes.clear();
list.children()
.stream()
.filter(e -> e instanceof ValueEntry)
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
}
protected void saveChanges() {
UnmodifiableConfig values = spec.getValues();
changes.forEach((path, value) -> {
ForgeConfigSpec.ConfigValue configValue = values.get(path);
configValue.set(value);
if (type == ModConfig.Type.SERVER) {
AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(path, value));
}
});
clearChanges();
}
protected void resetConfig(UnmodifiableConfig values) {
values.valueMap().forEach((key, obj) -> {
if (obj instanceof AbstractConfig) {
resetConfig((UnmodifiableConfig) obj);
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
if (!configValue.get().equals(valueSpec.getDefault()))
changes.put(String.join(".", configValue.getPath()), valueSpec.getDefault());
}
});
list.children()
.stream()
.filter(e -> e instanceof ValueEntry)
.forEach(e -> ((ValueEntry<?>) e).onValueChange());
}
@Override
public void tick() {
super.tick();
list.tick();
}
@Override
protected void init() {
widgets.clear();
super.init();
listWidth = Math.min(width - 80, 300);
int yCenter = height / 2;
int listL = this.width / 2 - listWidth / 2;
int listR = this.width / 2 + listWidth / 2;
resetAll = new BoxWidget(listR + 10, yCenter - 25, 20, 20)
.withPadding(2, 2)
.withCallback((x, y) ->
new ConfirmationScreen()
.at(x, y)
.withText(ITextProperties.plain("You are about to reset all settings for the " + type.toString() + " config. Are you sure?"))
.withAction(success -> {
if (success)
resetConfig(spec.getValues());
})
.open(this)
);
resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll)));
resetAll.getToolTip().add(new StringTextComponent("Reset All"));
resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all configs to their default value.", TextFormatting.GRAY, TextFormatting.GRAY));
saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20)
.withPadding(2, 2)
.withCallback((x, y) -> {
if (changes.isEmpty())
return;
new ConfirmationScreen()
.at(x, y)
.withText(ITextProperties.plain("You are about to change " + changes.size() + " value" + (changes.size() != 1 ? "s" : "") + ". Are you sure?"))
.withAction(success -> {
if (success)
saveChanges();
})
.open(this);
});
saveChanges.showingElement(AllIcons.I_CONFIG_SAVE.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(saveChanges)));
saveChanges.getToolTip().add(new StringTextComponent("Save Changes"));
saveChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to save your current changes.", TextFormatting.GRAY, TextFormatting.GRAY));
discardChanges = new BoxWidget(listL - 30, yCenter + 5, 20, 20)
.withPadding(2, 2)
.withCallback((x, y) -> {
if (changes.isEmpty())
return;
new ConfirmationScreen()
.at(x, y)
.withText(ITextProperties.plain("You are about to discard " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + ". Are you sure?"))
.withAction(success -> {
if (success)
clearChanges();
})
.open(this);
});
discardChanges.showingElement(AllIcons.I_CONFIG_DISCARD.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(discardChanges)));
discardChanges.getToolTip().add(new StringTextComponent("Discard Changes"));
discardChanges.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to discard all the changes you made.", TextFormatting.GRAY, TextFormatting.GRAY));
goBack = new BoxWidget(listL - 30, yCenter + 65, 20, 20)
.withPadding(2, 2)
.withCallback(this::attemptBackstep);
goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(goBack)));
goBack.getToolTip().add(new StringTextComponent("Go Back"));
widgets.add(resetAll);
widgets.add(saveChanges);
widgets.add(discardChanges);
widgets.add(goBack);
list = new ConfigScreenList(client, listWidth, height - 60, 45, height - 15, 40);
list.setLeftPos(this.width / 2 - list.getWidth() / 2);
children.add(list);
configGroup.valueMap().forEach((key, obj) -> {
String humanKey = toHumanReadable(key);
if (obj instanceof AbstractConfig) {
SubMenuEntry entry = new SubMenuEntry(this, humanKey, spec, (UnmodifiableConfig) obj);
list.children().add(entry);
} else if (obj instanceof ForgeConfigSpec.ConfigValue<?>) {
ForgeConfigSpec.ConfigValue<?> configValue = (ForgeConfigSpec.ConfigValue<?>) obj;
ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath());
Object value = configValue.get();
if (value instanceof Boolean) {
BooleanEntry entry = new BooleanEntry(humanKey, (ForgeConfigSpec.ConfigValue<Boolean>) configValue, valueSpec);
list.children().add(entry);
} else if (value instanceof Enum) {
EnumEntry entry = new EnumEntry(humanKey, (ForgeConfigSpec.ConfigValue<Enum<?>>) configValue, valueSpec);
list.children().add(entry);
} else if (value instanceof Number) {
NumberEntry<? extends Number> entry = NumberEntry.create(value, humanKey, configValue, valueSpec);
if (entry != null) {
list.children().add(entry);
} else {
list.children().add(new ConfigScreenList.LabeledEntry("n-" + obj.getClass().getSimpleName() + " " + humanKey + " : " + value));
}
} else {
list.children().add(new ConfigScreenList.LabeledEntry(humanKey + " : " + value));
}
}
});
//extras for server configs
if (type != ModConfig.Type.SERVER)
return;
list.isForServer = true;
boolean canEdit = client != null && client.player != null && client.player.hasPermissionLevel(2);
Couple<Color> red = Theme.p(Theme.Key.BUTTON_FAIL);
Couple<Color> green = Theme.p(Theme.Key.BUTTON_SUCCESS);
DelegatedStencilElement stencil = new DelegatedStencilElement();
serverLocked = new BoxWidget(listR + 10, yCenter + 5, 20, 20)
.withPadding(2, 2)
.showingElement(stencil);
if (!canEdit) {
list.children().forEach(e -> e.setEditable(false));
resetAll.active = false;
stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_LOCKED.draw(ms, 0, 0));
stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, red));
serverLocked.withBorderColors(red);
serverLocked.getToolTip().add(new StringTextComponent("Locked").formatted(TextFormatting.BOLD));
serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You don't have enough permissions to edit the server config. You can still look at the current values here though.", TextFormatting.GRAY, TextFormatting.GRAY));
} else {
stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0));
stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, green));
serverLocked.withBorderColors(green);
serverLocked.getToolTip().add(new StringTextComponent("Unlocked").formatted(TextFormatting.BOLD));
serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You have enough permissions to edit the server config. Changes you make here will be synced with the server when you save them.", TextFormatting.GRAY, TextFormatting.GRAY));
}
widgets.add(serverLocked);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderWindow(ms, mouseX, mouseY, partialTicks);
int x = width/2;
drawCenteredString(ms, client.fontRenderer, "Editing config: " + type.toString() + "@" + title, x, 15, Theme.i(Theme.Key.TEXT));
list.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected void renderWindowForeground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderWindowForeground(ms, mouseX, mouseY, partialTicks);
}
@Override
public void resize(@Nonnull Minecraft client, int width, int height) {
double scroll = list.getScrollAmount();
init(client, width, height);
list.setScrollAmount(scroll);
}
@Nullable
@Override
public IGuiEventListener getFocused() {
if (ConfigScreenList.currentText != null)
return ConfigScreenList.currentText;
return super.getFocused();
}
@Override
public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) {
if (super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_))
return true;
if (code == GLFW.GLFW_KEY_BACKSPACE) {
attemptBackstep();
}
return false;
}
private void attemptBackstep() {
if (!changes.isEmpty() && parent instanceof BaseConfigScreen) {
new ConfirmationScreen()
.centered()
.addText(ITextProperties.plain("You still have " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + " for this config."))
.addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?"))
.withAction(success -> {
if (!success)
return;
changes.clear();
ScreenOpener.open(parent);
})
.open(this);
} else {
ScreenOpener.open(parent);
}
}
@Override
public void onClose() {
if (changes.isEmpty()) {
super.onClose();
return;
}
new ConfirmationScreen()
.centered()
.addText(ITextProperties.plain("You still have " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + " for this config."))
.addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?"))
.withAction(success -> {
if (!success)
return;
changes.clear();
super.onClose();
})
.open(this);
}
}

View File

@ -0,0 +1,66 @@
package com.simibubi.create.foundation.config.ui.entries;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.RenderElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraftforge.common.ForgeConfigSpec;
public class BooleanEntry extends ValueEntry<Boolean> {
RenderElement enabled;
RenderElement disabled;
BoxWidget button;
public BooleanEntry(String label, ForgeConfigSpec.ConfigValue<Boolean> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
enabled = AllIcons.I_CONFIRM.asStencil()
.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.BUTTON_SUCCESS)))
.at(10, 0);
disabled = AllIcons.I_DISABLE.asStencil()
.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.p(Theme.Key.BUTTON_FAIL)))
.at(10, 0);
button = new BoxWidget().showingElement(enabled)
.withCallback(() -> setValue(!getValue()));
listeners.add(button);
onReset();
}
@Override
protected void setEditable(boolean b) {
super.setEditable(b);
button.active = b;
}
@Override
public void tick() {
super.tick();
button.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY,
boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
button.x = x + width - 80 - resetWidth;
button.y = y + 10;
button.setWidth(35);
button.setHeight(height - 20);
button.render(ms, mouseX, mouseY, partialTicks);
}
@Override
public void onValueChange(Boolean newValue) {
super.onValueChange(newValue);
button.showingElement(newValue ? enabled : disabled);
bumpCog(newValue ? 15f : -16f);
}
}

View File

@ -0,0 +1,102 @@
package com.simibubi.create.foundation.config.ui.entries;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraft.client.Minecraft;
import net.minecraftforge.common.ForgeConfigSpec;
public class EnumEntry extends ValueEntry<Enum<?>> {
protected static final int cycleWidth = 34;
protected TextStencilElement valueText;
protected BoxWidget cycleLeft;
protected BoxWidget cycleRight;
public EnumEntry(String label, ForgeConfigSpec.ConfigValue<Enum<?>> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
valueText = new TextStencilElement(Minecraft.getInstance().fontRenderer, "YEP").centered(true, true);
valueText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2,
height, width, Theme.p(Theme.Key.TEXT)));
DelegatedStencilElement l = AllIcons.I_CONFIG_PREV.asStencil();
cycleLeft = new BoxWidget(0, 0, cycleWidth + 8, 16).showingElement(l)
.withCallback(() -> cycleValue(-1));
l.withElementRenderer(BoxWidget.gradientFactory.apply(cycleLeft));
DelegatedStencilElement r = AllIcons.I_CONFIG_NEXT.asStencil();
cycleRight = new BoxWidget(0, 0, cycleWidth + 8, 16).showingElement(r)
.withCallback(() -> cycleValue(1));
r.at(cycleWidth - 8, 0);
r.withElementRenderer(BoxWidget.gradientFactory.apply(cycleRight));
listeners.add(cycleLeft);
listeners.add(cycleRight);
onReset();
}
protected void cycleValue(int direction) {
Enum<?> e = getValue();
Enum<?>[] options = e.getDeclaringClass()
.getEnumConstants();
e = options[Math.floorMod(e.ordinal() + direction, options.length)];
setValue(e);
bumpCog(direction * 15f);
}
@Override
protected void setEditable(boolean b) {
super.setEditable(b);
cycleLeft.active = b;
cycleLeft.animateGradientFromState();
cycleRight.active = b;
cycleRight.animateGradientFromState();
}
@Override
public void tick() {
super.tick();
cycleLeft.tick();
cycleRight.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY,
boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
cycleLeft.x = x + getLabelWidth(width) + 4;
cycleLeft.y = y + 10;
cycleLeft.render(ms, mouseX, mouseY, partialTicks);
valueText.at(cycleLeft.x + cycleWidth - 8, y + 11, 200)
.withBounds(width - getLabelWidth(width) - 2 * cycleWidth - resetWidth - 4, 16)
.render(ms);
cycleRight.x = x + width - cycleWidth * 2 - resetWidth + 10;
cycleRight.y = y + 10;
cycleRight.render(ms, mouseX, mouseY, partialTicks);
new BoxElement()
.withBackground(0)
.flatBorder(0)
.withBounds(10, 10)
.at(cycleLeft.x + cycleWidth + 4, cycleLeft.y + 3)
.render(ms);
}
@Override
public void onValueChange(Enum<?> newValue) {
super.onValueChange(newValue);
valueText.withText(newValue.name());
}
}

View File

@ -0,0 +1,211 @@
package com.simibubi.create.foundation.config.ui.entries;
import java.lang.reflect.Field;
import java.util.function.Function;
import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.ConfigTextField;
import com.simibubi.create.foundation.gui.TextStencilElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.common.ForgeConfigSpec;
public abstract class NumberEntry<T extends Number> extends ValueEntry<T> {
protected int minOffset = 0, maxOffset = 0;
protected TextStencilElement minText = null, maxText = null;
protected TextFieldWidget textField;
@Nullable
public static NumberEntry<? extends Number> create(Object type, String label, ForgeConfigSpec.ConfigValue<?> value, ForgeConfigSpec.ValueSpec spec) {
if (type instanceof Integer) {
return new IntegerEntry(label, (ForgeConfigSpec.ConfigValue<Integer>) value, spec);
} else if (type instanceof Float) {
return new FloatEntry(label, (ForgeConfigSpec.ConfigValue<Float>) value, spec);
} else if (type instanceof Double) {
return new DoubleEntry(label, (ForgeConfigSpec.ConfigValue<Double>) value, spec);
}
return null;
}
public NumberEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
textField = new ConfigTextField(Minecraft.getInstance().fontRenderer, 0, 0, 200, 20, unit);
textField.setText(String.valueOf(getValue()));
textField.setTextColor(Theme.i(Theme.Key.TEXT));
Object range = spec.getRange();
try {
Field minField = range.getClass().getDeclaredField("min");
Field maxField = range.getClass().getDeclaredField("max");
minField.setAccessible(true);
maxField.setAccessible(true);
T min = (T) minField.get(range);
T max = (T) maxField.get(range);
FontRenderer font = Minecraft.getInstance().fontRenderer;
if (min.doubleValue() > getTypeMin().doubleValue()) {
StringTextComponent t = new StringTextComponent(formatBound(min) + " < ");
minText = new TextStencilElement(font, t).centered(true, false);
minText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.p(Theme.Key.TEXT_DARKER)));
minOffset = font.getWidth(t);
}
if (max.doubleValue() < getTypeMax().doubleValue()) {
StringTextComponent t = new StringTextComponent(" < " + formatBound(max));
maxText = new TextStencilElement(font, t).centered(true, false);
maxText.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0 ,0, height/2, height, width, Theme.p(Theme.Key.TEXT_DARKER)));
maxOffset = font.getWidth(t);
}
} catch (NoSuchFieldException | IllegalAccessException | ClassCastException | NullPointerException ignored) {
}
textField.setResponder(s -> {
try {
T number = getParser().apply(s);
if (!spec.test(number))
throw new IllegalArgumentException();
textField.setTextColor(Theme.i(Theme.Key.TEXT));
setValue(number);
} catch (IllegalArgumentException ignored) {
textField.setTextColor(Theme.i(Theme.Key.BUTTON_FAIL));
}
});
listeners.add(textField);
onReset();
}
protected String formatBound(T bound) {
String sci = String.format("%.2E", bound.doubleValue());
String str = String.valueOf(bound);
return sci.length() < str.length() ? sci : str;
}
protected abstract T getTypeMin();
protected abstract T getTypeMax();
protected abstract Function<String, T> getParser();
@Override
protected void setEditable(boolean b) {
super.setEditable(b);
textField.setEnabled(b);
}
@Override
public void onValueChange(T newValue) {
super.onValueChange(newValue);
String newText = String.valueOf(newValue);
if (textField.getText().equals(newText))
return;
textField.setText(newText);
}
@Override
public void tick() {
super.tick();
textField.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
textField.x = x + width - 82 - resetWidth;
textField.y = y + 8;
textField.setWidth(Math.min(width - getLabelWidth(width) - resetWidth - minOffset - maxOffset, 40));
textField.setHeight(20);
textField.render(ms, mouseX, mouseY, partialTicks);
if (minText != null)
minText
.at(textField.x - minOffset, textField.y, 0)
.withBounds(minOffset, textField.unusedGetHeight())
.render(ms);
if (maxText != null)
maxText
.at(textField.x + textField.getWidth(), textField.y, 0)
.withBounds(maxOffset, textField.unusedGetHeight())
.render(ms);
}
public static class IntegerEntry extends NumberEntry<Integer> {
public IntegerEntry(String label, ForgeConfigSpec.ConfigValue<Integer> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Integer getTypeMin() {
return Integer.MIN_VALUE;
}
@Override
protected Integer getTypeMax() {
return Integer.MAX_VALUE;
}
@Override
protected Function<String, Integer> getParser() {
return Integer::parseInt;
}
}
public static class FloatEntry extends NumberEntry<Float> {
public FloatEntry(String label, ForgeConfigSpec.ConfigValue<Float> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Float getTypeMin() {
return -Float.MAX_VALUE;
}
@Override
protected Float getTypeMax() {
return Float.MAX_VALUE;
}
@Override
protected Function<String, Float> getParser() {
return Float::parseFloat;
}
}
public static class DoubleEntry extends NumberEntry<Double> {
public DoubleEntry(String label, ForgeConfigSpec.ConfigValue<Double> value, ForgeConfigSpec.ValueSpec spec) {
super(label, value, spec);
}
@Override
protected Double getTypeMin() {
return (double) -Float.MAX_VALUE;
}
@Override
protected Double getTypeMax() {
return (double) Float.MAX_VALUE;
}
@Override
protected Function<String, Double> getParser() {
return Double::parseDouble;
}
}
}

View File

@ -0,0 +1,49 @@
package com.simibubi.create.foundation.config.ui.entries;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraftforge.common.ForgeConfigSpec;
public class SubMenuEntry extends ConfigScreenList.LabeledEntry {
protected BoxWidget button;
public SubMenuEntry(SubMenuConfigScreen parent, String label, ForgeConfigSpec spec, UnmodifiableConfig config) {
super(label);
button = new BoxWidget(0, 0, 35, 16)
.showingElement(AllIcons.I_CONFIG_OPEN.asStencil().at(10, 0))
.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(parent, label, parent.type, spec, config)));
button.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(button)));
listeners.add(button);
}
@Override
public void tick() {
super.tick();
button.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
button.x = x + width - 108;
button.y = y + 10;
button.setHeight(height - 20);
button.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected int getLabelWidth(int totalWidth) {
return (int) (totalWidth * labelWidthMult) + 30;
}
}

View File

@ -0,0 +1,159 @@
package com.simibubi.create.foundation.config.ui.entries;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.ArrayUtils;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.config.ui.ConfigScreen;
import com.simibubi.create.foundation.config.ui.ConfigScreenList;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.common.ForgeConfigSpec;
public class ValueEntry<T> extends ConfigScreenList.LabeledEntry {
protected static final IFormattableTextComponent modComponent = new StringTextComponent("* ").formatted(TextFormatting.BOLD, TextFormatting.DARK_BLUE).append(StringTextComponent.EMPTY.copy().formatted(TextFormatting.RESET));
protected static final int resetWidth = 28;//including 6px offset on either side
public static final Pattern unitPattern = Pattern.compile("\\[(in .*)]");
protected ForgeConfigSpec.ConfigValue<T> value;
protected ForgeConfigSpec.ValueSpec spec;
protected BoxWidget resetButton;
protected boolean editable = true;
protected String path;
public ValueEntry(String label, ForgeConfigSpec.ConfigValue<T> value, ForgeConfigSpec.ValueSpec spec) {
super(label);
this.value = value;
this.spec = spec;
this.path = String.join(".", value.getPath());
resetButton = new BoxWidget(0, 0, resetWidth - 12, 16)
.showingElement(AllIcons.I_CONFIG_RESET.asStencil())
.withCallback(() -> {
setValue((T) spec.getDefault());
this.onReset();
});
resetButton.modifyElement(e -> ((DelegatedStencilElement) e).withElementRenderer(BoxWidget.gradientFactory.apply(resetButton)));
listeners.add(resetButton);
List<String> path = value.getPath();
labelTooltip.add(new StringTextComponent(path.get(path.size()-1)).formatted(TextFormatting.GRAY));
String comment = spec.getComment();
if (comment == null || comment.isEmpty())
return;
String[] commentLines = comment.split("\n");
//find unit in the comment
for (int i = 0; i < commentLines.length; i++) {
if (commentLines[i].isEmpty()) {
commentLines = ArrayUtils.remove(commentLines, i);
i--;
continue;
}
Matcher matcher = unitPattern.matcher(commentLines[i]);
if (!matcher.matches())
continue;
String u = matcher.group(1);
if (u.equals("in Revolutions per Minute"))
u = "in RPM";
if (u.equals("in Stress Units"))
u = "in SU";
unit = u;
}
//add comment to tooltip
labelTooltip.addAll(Arrays.stream(commentLines).map(StringTextComponent::new).collect(Collectors.toList()));
}
@Override
protected void setEditable(boolean b) {
editable = b;
resetButton.active = editable && !isCurrentValueDefault();
resetButton.animateGradientFromState();
}
@Override
public void tick() {
super.tick();
resetButton.tick();
}
@Override
public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) {
if (isCurrentValueChanged()) {
IFormattableTextComponent original = label.getComponent();
IFormattableTextComponent changed = modComponent.copy().append(original);
label.withText(changed);
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
label.withText(original);
} else {
super.render(ms, index, y, x, width, height, mouseX, mouseY, p_230432_9_, partialTicks);
}
resetButton.x = x + width - resetWidth + 6;
resetButton.y = y + 10;
resetButton.render(ms, mouseX, mouseY, partialTicks);
}
@Override
protected int getLabelWidth(int totalWidth) {
return (int) (totalWidth * labelWidthMult) + 30;
}
public void setValue(@Nonnull T value) {
if (value.equals(this.value.get())) {
ConfigScreen.changes.remove(path);
onValueChange(value);
return;
}
ConfigScreen.changes.put(path, value);
onValueChange(value);
}
@Nonnull
public T getValue() {
//noinspection unchecked
return (T) ConfigScreen.changes.getOrDefault(path, this.value.get());
}
protected boolean isCurrentValueChanged() {
return ConfigScreen.changes.containsKey(path);
}
protected boolean isCurrentValueDefault() {
return spec.getDefault().equals(getValue());
}
public void onReset() {
onValueChange(getValue());
}
public void onValueChange() {
onValueChange(getValue());
}
public void onValueChange(T newValue) {
resetButton.active = editable && !isCurrentValueDefault();
resetButton.animateGradientFromState();
}
protected void bumpCog() {bumpCog(10f);}
protected void bumpCog(float force) {
if (list != null && list instanceof ConfigScreenList)
((ConfigScreenList) list).bumpCog(force);
}
}

View File

@ -69,8 +69,6 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
RenderSystem.disableLighting();
RenderSystem.disableDepthTest();
renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(matrixStack, mouseX, mouseY);
}
@Override
@ -152,9 +150,12 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
if (!widget.isHovered())
continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip()
.isEmpty()) {
renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY);
if (widget instanceof AbstractSimiWidget) {
if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY);
} else {
widget.renderToolTip(matrixStack, mouseX, mouseY);
}
}
}

View File

@ -33,6 +33,13 @@ public abstract class AbstractSimiScreen extends Screen {
guiTop = (this.height - sHeight) / 2;
}
@Override
public void tick() {
super.tick();
widgets.stream().filter(w -> w instanceof AbstractSimiWidget).forEach(w -> ((AbstractSimiWidget) w).tick());
}
@Override
public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
partialTicks = partialTicks == 10 ? 0
@ -46,8 +53,6 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets)
widget.render(ms, mouseX, mouseY, partialTicks);
renderWindowForeground(ms, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(ms, mouseX, mouseY);
ms.pop();
}
@ -62,6 +67,10 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets)
if (widget.mouseClicked(x, y, button))
result = true;
if (!result) {
result = super.mouseClicked(x, y, button);
}
return result;
}
@ -127,9 +136,12 @@ public abstract class AbstractSimiScreen extends Screen {
if (!widget.isHovered())
continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip()
.isEmpty()) {
renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY);
if (widget instanceof AbstractSimiWidget) {
if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY);
} else {
widget.renderToolTip(ms, mouseX, mouseY);
}
}
}

View File

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui;
import java.awt.Color;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.Create;
@ -80,8 +82,8 @@ public enum AllGuiTextures implements IScreenRenderable {
INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6),
INDICATOR_RED("widgets.png", 72, 18, 18, 6),
SPEECH_TOOLTIP("widgets.png", 0, 24, 8, 8),
SPEECH_TOOLTIP_HIGHLIGHT("widgets.png", 8, 24, 8, 8),
SPEECH_TOOLTIP_BACKGROUND("widgets.png", 0, 24, 8, 8),
SPEECH_TOOLTIP_COLOR("widgets.png", 8, 24, 8, 8),
// PlacementIndicator
PLACEMENT_INDICATOR_SHEET("placement_indicator.png", 0, 0, 16, 256);
@ -123,4 +125,9 @@ public enum AllGuiTextures implements IScreenRenderable {
bind();
screen.drawTexture(ms, x, y, startX, startY, width, height);
}
public void draw(MatrixStack ms, int x, int y, Color c) {
bind();
UIRenderHelper.drawColoredTexture(ms, c, x, y, startX, startY, width, height);
}
}

View File

@ -22,45 +22,121 @@ public class AllIcons implements IScreenRenderable {
private int iconX;
private int iconY;
public static final AllIcons I_ADD = newRow(), I_TRASH = next(), I_3x3 = next(), I_TARGET = next(),
I_PRIORITY_VERY_LOW = next(), I_PRIORITY_LOW = next(), I_PRIORITY_HIGH = next(), I_PRIORITY_VERY_HIGH = next(),
I_BLACKLIST = next(), I_WHITELIST = next(), I_WHITELIST_OR = next(), I_WHITELIST_AND = next(),
I_WHITELIST_NOT = next(), I_RESPECT_NBT = next(), I_IGNORE_NBT = next();
public static final AllIcons
I_ADD = newRow(),
I_TRASH = next(),
I_3x3 = next(),
I_TARGET = next(),
I_PRIORITY_VERY_LOW = next(),
I_PRIORITY_LOW = next(),
I_PRIORITY_HIGH = next(),
I_PRIORITY_VERY_HIGH = next(),
I_BLACKLIST = next(),
I_WHITELIST = next(),
I_WHITELIST_OR = next(),
I_WHITELIST_AND = next(),
I_WHITELIST_NOT = next(),
I_RESPECT_NBT = next(),
I_IGNORE_NBT = next();
public static final AllIcons I_CONFIRM = newRow(), I_NONE = next(), I_OPEN_FOLDER = next(), I_REFRESH = next(),
I_ACTIVE = next(), I_PASSIVE = next(), I_ROTATE_PLACE = next(), I_ROTATE_PLACE_RETURNED = next(),
I_ROTATE_NEVER_PLACE = next(), I_MOVE_PLACE = next(), I_MOVE_PLACE_RETURNED = next(),
I_MOVE_NEVER_PLACE = next(), I_CART_ROTATE = next(), I_CART_ROTATE_PAUSED = next(),
public static final AllIcons
I_CONFIRM = newRow(),
I_NONE = next(),
I_OPEN_FOLDER = next(),
I_REFRESH = next(),
I_ACTIVE = next(),
I_PASSIVE = next(),
I_ROTATE_PLACE = next(),
I_ROTATE_PLACE_RETURNED = next(),
I_ROTATE_NEVER_PLACE = next(),
I_MOVE_PLACE = next(),
I_MOVE_PLACE_RETURNED = next(),
I_MOVE_NEVER_PLACE = next(),
I_CART_ROTATE = next(),
I_CART_ROTATE_PAUSED = next(),
I_CART_ROTATE_LOCKED = next();
public static final AllIcons I_DONT_REPLACE = newRow(), I_REPLACE_SOLID = next(), I_REPLACE_ANY = next(),
I_REPLACE_EMPTY = next(), I_CENTERED = next(), I_ATTACHED = next(), I_INSERTED = next(), I_FILL = next(),
I_PLACE = next(), I_REPLACE = next(), I_CLEAR = next(), I_OVERLAY = next(), I_FLATTEN = next(), I_LMB = next(),
I_SCROLL = next(), I_RMB = next();
public static final AllIcons I_TOOL_DEPLOY = newRow(), I_SKIP_MISSING = next(), I_SKIP_TILES = next(),
I_DICE = next(), I_TUNNEL_SPLIT = next(), I_TUNNEL_FORCED_SPLIT = next(), I_TUNNEL_ROUND_ROBIN = next(),
I_TUNNEL_FORCED_ROUND_ROBIN = next(), I_TUNNEL_PREFER_NEAREST = next(), I_TUNNEL_RANDOMIZE = next(),
public static final AllIcons
I_DONT_REPLACE = newRow(),
I_REPLACE_SOLID = next(),
I_REPLACE_ANY = next(),
I_REPLACE_EMPTY = next(),
I_CENTERED = next(),
I_ATTACHED = next(),
I_INSERTED = next(),
I_FILL = next(),
I_PLACE = next(),
I_REPLACE = next(),
I_CLEAR = next(),
I_OVERLAY = next(),
I_FLATTEN = next(),
I_LMB = next(),
I_SCROLL = next(),
I_RMB = next();
public static final AllIcons
I_TOOL_DEPLOY = newRow(),
I_SKIP_MISSING = next(),
I_SKIP_TILES = next(),
I_DICE = next(),
I_TUNNEL_SPLIT = next(),
I_TUNNEL_FORCED_SPLIT = next(),
I_TUNNEL_ROUND_ROBIN = next(),
I_TUNNEL_FORCED_ROUND_ROBIN = next(),
I_TUNNEL_PREFER_NEAREST = next(),
I_TUNNEL_RANDOMIZE = next(),
I_TUNNEL_SYNCHRONIZE = next(),
I_TOOL_MOVE_XZ = newRow(), I_TOOL_MOVE_Y = next(), I_TOOL_ROTATE = next(), I_TOOL_MIRROR = next(),
I_ARM_ROUND_ROBIN = next(), I_ARM_FORCED_ROUND_ROBIN = next(), I_ARM_PREFER_FIRST = next(),
I_ADD_INVERTED_ATTRIBUTE = next(), I_FLIP = next(),
I_PLAY = newRow(), I_PAUSE = next(), I_STOP = next(), I_PLACEMENT_SETTINGS = next(), I_ROTATE_CCW = next(),
I_HOUR_HAND_FIRST = next(), I_MINUTE_HAND_FIRST = next(), I_HOUR_HAND_FIRST_24 = next(),
I_PATTERN_SOLID = newRow(), I_PATTERN_CHECKERED = next(), I_PATTERN_CHECKERED_INVERSED = next(),
I_TOOL_MOVE_XZ = newRow(),
I_TOOL_MOVE_Y = next(),
I_TOOL_ROTATE = next(),
I_TOOL_MIRROR = next(),
I_ARM_ROUND_ROBIN = next(),
I_ARM_FORCED_ROUND_ROBIN = next(),
I_ARM_PREFER_FIRST = next(),
I_ADD_INVERTED_ATTRIBUTE = next(),
I_FLIP = next(),
I_PLAY = newRow(),
I_PAUSE = next(),
I_STOP = next(),
I_PLACEMENT_SETTINGS = next(),
I_ROTATE_CCW = next(),
I_HOUR_HAND_FIRST = next(),
I_MINUTE_HAND_FIRST = next(),
I_HOUR_HAND_FIRST_24 = next(),
I_PATTERN_SOLID = newRow(),
I_PATTERN_CHECKERED = next(),
I_PATTERN_CHECKERED_INVERSED = next(),
I_PATTERN_CHANCE_25 = next(),
I_PATTERN_CHANCE_50 = newRow(), I_PATTERN_CHANCE_75 = next(), I_FOLLOW_DIAGONAL = next(),
I_PATTERN_CHANCE_50 = newRow(),
I_PATTERN_CHANCE_75 = next(),
I_FOLLOW_DIAGONAL = next(),
I_FOLLOW_MATERIAL = next(),
I_SCHEMATIC = newRow(),
I_MTD_LEFT = newRow(), I_MTD_CLOSE = next(), I_MTD_RIGHT = next(), I_MTD_SCAN = next(), I_MTD_REPLAY = next(),
I_MTD_USER_MODE = next(), I_MTD_SLOW_MODE = next();
I_MTD_LEFT = newRow(),
I_MTD_CLOSE = next(),
I_MTD_RIGHT = next(),
I_MTD_SCAN = next(),
I_MTD_REPLAY = next(),
I_MTD_USER_MODE = next(),
I_MTD_SLOW_MODE = next(),
I_CONFIG_UNLOCKED = newRow(),
I_CONFIG_LOCKED = next(),
I_CONFIG_DISCARD = next(),
I_CONFIG_SAVE = next(),
I_CONFIG_RESET = next(),
I_CONFIG_BACK = next(),
I_CONFIG_PREV = next(),
I_CONFIG_NEXT = next(),
I_DISABLE = next(),
I_CONFIG_OPEN = next();
public AllIcons(int x, int y) {
iconX = x * 16;
@ -116,8 +192,12 @@ public class AllIcons implements IScreenRenderable {
}
@OnlyIn(Dist.CLIENT)
private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u,
float v) {
public DelegatedStencilElement asStencil() {
return new DelegatedStencilElement().withStencilRenderer((ms, w, h, alpha) -> this.draw(ms, 0, 0)).withBounds(16, 16);
}
@OnlyIn(Dist.CLIENT)
private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u, float v) {
builder.vertex(peek.getModel(), (float) vec.x, (float) vec.y, (float) vec.z)
.color((float) rgb.x, (float) rgb.y, (float) rgb.z, 1)
.texture(u, v)

View File

@ -0,0 +1,160 @@
package com.simibubi.create.foundation.gui;
import java.awt.Color;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.vector.Matrix4f;
public class BoxElement extends RenderElement {
protected Color background = new Color(0xff000000, true);
protected Color borderTop = new Color(0x40ffeedd, true);
protected Color borderBot = new Color(0x20ffeedd, true);
protected int borderOffset = 2;
public <T extends BoxElement> T withBackground(Color color) {
this.background = color;
//noinspection unchecked
return (T) this;
}
public <T extends BoxElement> T withBackground(int color) {
return withBackground(new Color(color, true));
}
public <T extends BoxElement> T flatBorder(Color color) {
this.borderTop = color;
this.borderBot = color;
//noinspection unchecked
return (T) this;
}
public <T extends BoxElement> T flatBorder(int color) {
return flatBorder(new Color(color, true));
}
public <T extends BoxElement> T gradientBorder(Couple<Color> colors) {
this.borderTop = colors.getFirst();
this.borderBot = colors.getSecond();
//noinspection unchecked
return (T) this;
}
public <T extends BoxElement> T gradientBorder(Color top, Color bot) {
this.borderTop = top;
this.borderBot = bot;
//noinspection unchecked
return (T) this;
}
public <T extends BoxElement> T gradientBorder(int top, int bot) {
return gradientBorder(new Color(top, true), new Color(bot, true));
}
public <T extends BoxElement> T withBorderOffset(int offset) {
this.borderOffset = offset;
//noinspection unchecked
return (T) this;
}
@Override
public void render(MatrixStack ms) {
renderBox(ms);
}
//total box width = 1 * 2 (outer border) + 1 * 2 (inner color border) + 2 * borderOffset + width
//defaults to 2 + 2 + 4 + 16 = 24px
//batch everything together to save a bunch of gl calls over GuiUtils
protected void renderBox(MatrixStack ms) {
/*
* _____________
* _|_____________|_
* | | ___________ | |
* | | | | | | |
* | | | | | | |
* | | |--* | | | |
* | | | h | | |
* | | | --w-+ | | |
* | | | | | |
* | | |_________| | |
* |_|_____________|_|
* |_____________|
*
* */
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.shadeModel(GL11.GL_SMOOTH);
int f = borderOffset;
Color c1 = ColorHelper.applyAlpha(background, alpha);
Color c2 = ColorHelper.applyAlpha(borderTop, alpha);
Color c3 = ColorHelper.applyAlpha(borderBot, alpha);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder b = tessellator.getBuffer();
Matrix4f model = ms.peek().getModel();
b.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
//outer top
b.vertex(model, x - f - 1 , y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y - f - 2 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
//outer left
b.vertex(model, x - f - 2 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x - f - 2 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
//outer bottom
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y + f + 2 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
//outer right
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 2 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 2 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
//inner background - also render behind the inner edges
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c1.getRed(), c1.getGreen(), c1.getBlue(), c1.getAlpha()).endVertex();
tessellator.draw();
b.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
//inner top - includes corners
b.vertex(model, x - f - 1 , y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y - f - 1 , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
//inner left - excludes corners
b.vertex(model, x - f - 1 , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
b.vertex(model, x - f , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
b.vertex(model, x - f , y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
//inner bottom - includes corners
b.vertex(model, x - f - 1 , y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
b.vertex(model, x - f - 1 , y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y + f + 1 + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
//inner right - excludes corners
b.vertex(model, x + f + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
b.vertex(model, x + f + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y + f + height, z).color(c3.getRed(), c3.getGreen(), c3.getBlue(), c3.getAlpha()).endVertex();
b.vertex(model, x + f + 1 + width, y - f , z).color(c2.getRed(), c2.getGreen(), c2.getBlue(), c2.getAlpha()).endVertex();
tessellator.draw();
RenderSystem.shadeModel(GL11.GL_FLAT);
RenderSystem.disableBlend();
RenderSystem.enableTexture();
}
}

View File

@ -0,0 +1,79 @@
package com.simibubi.create.foundation.gui;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
public class CombinedStencilElement extends StencilElement {
private StencilElement element1;
private StencilElement element2;
private ElementMode mode;
private CombinedStencilElement() {}
public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2) {
return of(element1, element2, ElementMode.FIRST);
}
public static CombinedStencilElement of(@Nonnull StencilElement element1, @Nonnull StencilElement element2, ElementMode mode) {
CombinedStencilElement e = new CombinedStencilElement();
e.element1 = element1;
e.element2 = element2;
e.mode = mode;
return e;
}
public <T extends CombinedStencilElement> T withFirst(StencilElement element) {
this.element1 = element;
//noinspection unchecked
return (T) this;
}
public <T extends CombinedStencilElement> T withSecond(StencilElement element) {
this.element2 = element;
//noinspection unchecked
return (T) this;
}
public <T extends CombinedStencilElement> T withMode(ElementMode mode) {
this.mode = mode;
//noinspection unchecked
return (T) this;
}
@Override
protected void renderStencil(MatrixStack ms) {
ms.push();
element1.transform(ms);
element1.withBounds(width, height);
element1.renderStencil(ms);
ms.pop();
ms.push();
element2.transform(ms);
element2.withBounds(width, height);
element2.renderStencil(ms);
ms.pop();
}
@Override
protected void renderElement(MatrixStack ms) {
if (mode.rendersFirst())
element1.<StencilElement>withBounds(width, height).renderElement(ms);
if (mode.rendersSecond())
element2.<StencilElement>withBounds(width, height).renderElement(ms);
}
public enum ElementMode {
FIRST, SECOND, BOTH;
boolean rendersFirst() {
return this == FIRST || this == BOTH;
}
boolean rendersSecond() {
return this == SECOND || this == BOTH;
}
}
}

View File

@ -0,0 +1,194 @@
package com.simibubi.create.foundation.gui;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import org.lwjgl.opengl.GL30;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.text.ITextProperties;
import net.minecraft.util.text.Style;
public class ConfirmationScreen extends AbstractSimiScreen {
private Screen source;
private Consumer<Boolean> action = _success -> {};
private List<ITextProperties> text = new ArrayList<>();
private boolean centered = false;
private int x;
private int y;
private int textWidth;
private int textHeight;
private BoxWidget confirm;
private BoxWidget cancel;
private BoxElement textBackground;
/*
* Removes text lines from the back of the list
* */
public ConfirmationScreen removeTextLines(int amount) {
if (amount > text.size())
return clearText();
text.subList(text.size() - amount, text.size()).clear();
return this;
}
public ConfirmationScreen clearText() {
this.text.clear();
return this;
}
public ConfirmationScreen addText(ITextProperties text) {
this.text.add(text);
return this;
}
public ConfirmationScreen withText(ITextProperties text) {
return clearText().addText(text);
}
public ConfirmationScreen at(int x, int y) {
this.x = Math.max(x, 0);
this.y = Math.max(y, 0);
this.centered = false;
return this;
}
public ConfirmationScreen centered() {
this.centered = true;
return this;
}
public ConfirmationScreen withAction(Consumer<Boolean> action) {
this.action = action;
return this;
}
public void open(@Nonnull Screen source) {
this.source = source;
Minecraft client = source.getMinecraft();
this.init(client, client.getWindow().getScaledWidth(), client.getWindow().getScaledHeight());
this.client.currentScreen = this;
}
@Override
public void tick() {
super.tick();
confirm.tick();
cancel.tick();
}
@Override
protected void init() {
widgets.clear();
ArrayList<ITextProperties> copy = new ArrayList<>(text);
text.clear();
copy.forEach(t -> text.addAll(client.fontRenderer.getTextHandler().wrapLines(t, 300, Style.EMPTY)));
textHeight = text.size() * (client.fontRenderer.FONT_HEIGHT + 1) + 4;
textWidth = 300;
if (x + textWidth > width) {
x = width - textWidth;
}
if (y + textHeight + 30 > height) {
y = height - textHeight - 30;
}
if (centered) {
x = width/2 - textWidth/2 - 2;
y = height/2 - textHeight/2 - 16;
}
TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true);
confirm = new BoxWidget(x + 4, y + textHeight + 2 , textWidth/2 - 10, 20)
.withCallback(() -> accept(true));
confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm)));
TextStencilElement cancelText = new TextStencilElement(client.fontRenderer, "Cancel").centered(true, true);
cancel = new BoxWidget(x + textWidth/2 + 6, y + textHeight + 2, textWidth/2 - 10, 20)
.withCallback(() -> accept(false));
cancel.showingElement(cancelText.withElementRenderer(BoxWidget.gradientFactory.apply(cancel)));
widgets.add(confirm);
widgets.add(cancel);
textBackground = new BoxElement()
.gradientBorder(Theme.p(Theme.Key.BUTTON_DISABLE))
.withBounds(textWidth, textHeight)
.at(x, y);
}
@Override
public void onClose() {
accept(false);
}
private void accept(boolean success) {
client.currentScreen = source;
action.accept(success);
}
@Override
protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
textBackground.render(ms);
int offset = client.fontRenderer.FONT_HEIGHT + 1;
int lineY = y - offset;
ms.push();
ms.translate(0, 0, 200);
for (ITextProperties line : text) {
lineY = lineY + offset;
if (line == null)
continue;
client.fontRenderer.draw(ms, line.getString(), x, lineY, 0xeaeaea);
}
ms.pop();
}
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
ms.push();
UIRenderHelper.framebuffer.bindFramebuffer(true);
source.render(ms, mouseX, mouseY, 10);
UIRenderHelper.framebuffer.unbindFramebuffer();
Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer();
ms.pop();
//fixme replace with glVersioned-backend calls once they are merged from jozu's branch
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, UIRenderHelper.framebuffer.framebufferObject);
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.framebufferObject);
GL30.glBlitFramebuffer(0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, 0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, GL30.GL_COLOR_BUFFER_BIT, GL30.GL_LINEAR);
mainBuffer.bindFramebuffer(true);
this.fillGradient(ms, 0, 0, this.width, this.height, 0x70101010, 0x80101010);
}
@Override
public void resize(@Nonnull Minecraft client, int width, int height) {
super.resize(client, width, height);
source.resize(client, width, height);
}
}

View File

@ -0,0 +1,51 @@
package com.simibubi.create.foundation.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.utility.ColorHelper;
public class DelegatedStencilElement extends StencilElement {
protected static final ElementRenderer EMPTY_RENDERER = (ms, width, height, alpha) -> {};
protected static final ElementRenderer DEFAULT_ELEMENT = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, -3, 5, height+4, width+6, ColorHelper.applyAlpha(0xff_10dd10, alpha), ColorHelper.applyAlpha(0xff_1010dd, alpha));
protected ElementRenderer stencil;
protected ElementRenderer element;
public DelegatedStencilElement() {
stencil = EMPTY_RENDERER;
element = DEFAULT_ELEMENT;
}
public DelegatedStencilElement(ElementRenderer stencil, ElementRenderer element) {
this.stencil = stencil;
this.element = element;
}
public <T extends DelegatedStencilElement> T withStencilRenderer(ElementRenderer renderer) {
stencil = renderer;
//noinspection unchecked
return (T) this;
}
public <T extends DelegatedStencilElement> T withElementRenderer(ElementRenderer renderer) {
element = renderer;
//noinspection unchecked
return (T) this;
}
@Override
protected void renderStencil(MatrixStack ms) {
stencil.render(ms, width, height, 1);
}
@Override
protected void renderElement(MatrixStack ms) {
element.render(ms, width, height, alpha);
}
@FunctionalInterface
public interface ElementRenderer {
void render(MatrixStack ms, int width, int height, float alpha);
}
}

View File

@ -63,31 +63,17 @@ public class GuiGameElement {
.with(FlowingFluidBlock.LEVEL, 0));
}
public static abstract class GuiRenderBuilder {
double xBeforeScale, yBeforeScale, zBeforeScale = 0;
double x, y, z;
public static abstract class GuiRenderBuilder extends RenderElement {
double xLocal, yLocal, zLocal;
double xRot, yRot, zRot;
double scale = 1;
int color = 0xFFFFFF;
Vector3d rotationOffset = Vector3d.ZERO;
public GuiRenderBuilder atLocal(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
return this;
}
public GuiRenderBuilder at(double x, double y) {
this.xBeforeScale = x;
this.yBeforeScale = y;
return this;
}
public GuiRenderBuilder at(double x, double y, double z) {
this.xBeforeScale = x;
this.yBeforeScale = y;
this.zBeforeScale = z;
this.xLocal = x;
this.yLocal = y;
this.zLocal = z;
return this;
}
@ -136,9 +122,9 @@ public class GuiGameElement {
@Deprecated
protected void transform() {
RenderSystem.translated(xBeforeScale, yBeforeScale, 0);
RenderSystem.translated(x, y, 0);
RenderSystem.scaled(scale, scale, scale);
RenderSystem.translated(x, y, z);
RenderSystem.translated(xLocal, yLocal, zLocal);
RenderSystem.scaled(1, -1, 1);
RenderSystem.translated(rotationOffset.x, rotationOffset.y, rotationOffset.z);
RenderSystem.rotatef((float) zRot, 0, 0, 1);
@ -148,9 +134,9 @@ public class GuiGameElement {
}
protected void transformMatrix(MatrixStack matrixStack) {
matrixStack.translate(xBeforeScale, yBeforeScale, zBeforeScale);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(x, y, z);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(xLocal, yLocal, zLocal);
matrixStack.scale(1, -1, 1);
matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z);
matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion((float) zRot));
@ -272,23 +258,10 @@ public class GuiGameElement {
@Override
public void render(MatrixStack matrixStack) {
prepareMatrix(matrixStack);
// matrixStack.translate(0, 80, 0);
transformMatrix(matrixStack);
renderItemIntoGUI(matrixStack, stack);
cleanUpMatrix(matrixStack);
}
/*
* public void render() {
* prepare();
* transform();
* RenderSystem.scaled(1, -1, 1);
* RenderSystem.translated(0, 0, -75);
* Minecraft.getInstance()
* .getItemRenderer()
* .renderItemIntoGUI(stack, 0, 0);
* cleanUp();
* }
*/
public static void renderItemIntoGUI(MatrixStack matrixStack, ItemStack stack) {
ItemRenderer renderer = Minecraft.getInstance()

View File

@ -0,0 +1,92 @@
package com.simibubi.create.foundation.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.gui.AbstractGui;
public abstract class RenderElement implements IScreenRenderable {
public static RenderElement EMPTY = new RenderElement() {@Override public void render(MatrixStack ms) {}};
public static RenderElement of(IScreenRenderable renderable) {
return new SimpleRenderElement(renderable);
}
protected int width = 16, height = 16;
protected float x = 0, y = 0, z = 0;
protected float alpha = 1f;
public <T extends RenderElement> T at(float x, float y) {
this.x = x;
this.y = y;
//noinspection unchecked
return (T) this;
}
public <T extends RenderElement> T at(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
//noinspection unchecked
return (T) this;
}
public <T extends RenderElement> T withBounds(int width, int height) {
this.width = width;
this.height = height;
//noinspection unchecked
return (T) this;
}
public <T extends RenderElement> T withAlpha(float alpha) {
this.alpha = alpha;
//noinspection unchecked
return (T) this;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getZ() {
return z;
}
public abstract void render(MatrixStack ms);
@Override
public void draw(MatrixStack ms, AbstractGui screen, int x, int y) {
this.at(x, y).render(ms);
}
@Override
public void draw(MatrixStack ms, int x, int y) {
this.at(x, y).render(ms);
}
public static class SimpleRenderElement extends RenderElement {
private IScreenRenderable renderable;
public SimpleRenderElement(IScreenRenderable renderable) {
this.renderable = renderable;
}
@Override
public void render(MatrixStack ms) {
renderable.draw(ms, (int) x, (int) y);
}
}
}

View File

@ -65,7 +65,7 @@ public class ScreenOpener {
if (screenHistory.isEmpty())
return false;
Screen previouslyRenderedScreen = screenHistory.get(0);
if (!(previouslyRenderedScreen instanceof AbstractSimiScreen))
if (!(previouslyRenderedScreen instanceof NavigatableSimiScreen))
return false;
if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen))
return false;

View File

@ -0,0 +1,51 @@
package com.simibubi.create.foundation.gui;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
public abstract class StencilElement extends RenderElement {
@Override
public void render(MatrixStack ms) {
ms.push();
transform(ms);
prepareStencil(ms);
renderStencil(ms);
prepareElement(ms);
renderElement(ms);
cleanUp(ms);
ms.pop();
}
protected abstract void renderStencil(MatrixStack ms);
protected abstract void renderElement(MatrixStack ms);
protected void transform(MatrixStack ms) {
ms.translate(x, y, z);
}
protected void prepareStencil(MatrixStack ms) {
GL11.glDisable(GL11.GL_STENCIL_TEST);
RenderSystem.stencilMask(~0);
RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.IS_RUNNING_ON_MAC);
GL11.glEnable(GL11.GL_STENCIL_TEST);
RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP);
RenderSystem.stencilMask(0xFF);
RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF);
}
protected void prepareElement(MatrixStack ms) {
GL11.glEnable(GL11.GL_STENCIL_TEST);
RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP);
RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF);
}
protected void cleanUp(MatrixStack ms) {
GL11.glDisable(GL11.GL_STENCIL_TEST);
}
}

View File

@ -0,0 +1,79 @@
package com.simibubi.create.foundation.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.util.text.IFormattableTextComponent;
import net.minecraft.util.text.StringTextComponent;
public class TextStencilElement extends DelegatedStencilElement {
protected FontRenderer font;
protected IFormattableTextComponent component;
protected boolean centerVertically = false;
protected boolean centerHorizontally = false;
public TextStencilElement(FontRenderer font) {
super();
this.font = font;
height = 10;
}
public TextStencilElement(FontRenderer font, String text) {
this(font);
component = new StringTextComponent(text);
}
public TextStencilElement(FontRenderer font, IFormattableTextComponent component) {
this(font);
this.component = component;
}
public TextStencilElement withText(String text) {
component = new StringTextComponent(text);
return this;
}
public TextStencilElement withText(IFormattableTextComponent component) {
this.component = component;
return this;
}
public TextStencilElement centered(boolean vertical, boolean horizontal) {
this.centerVertically = vertical;
this.centerHorizontally = horizontal;
return this;
}
@Override
protected void renderStencil(MatrixStack ms) {
float x = 0, y = 0;
if (centerHorizontally)
x = width / 2f - font.getWidth(component) / 2f;
if (centerVertically)
y = height / 2f - font.FONT_HEIGHT / 2f;
font.draw(ms, component, x, y, 0xff_000000);
}
@Override
protected void renderElement(MatrixStack ms) {
float x = 0, y = 0;
if (centerHorizontally)
x = width / 2f - font.getWidth(component) / 2f;
if (centerVertically)
y = height / 2f - font.FONT_HEIGHT / 2f;
ms.push();
ms.translate(x, y, 0);
element.render(ms, font.getWidth(component), font.FONT_HEIGHT + 2, alpha);
ms.pop();
}
public IFormattableTextComponent getComponent() {
return component;
}
}

View File

@ -0,0 +1,177 @@
package com.simibubi.create.foundation.gui;
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.simibubi.create.foundation.utility.Couple;
public class Theme {
private static final Theme base = new Theme();
private static Theme custom = null;
public static void setTheme(@Nullable Theme theme) {
custom = theme;
}
private static ColorHolder resolve(String key) {
ColorHolder h = null;
if (custom != null)
h = custom.get(key);
if (h == null)
h = base.get(key);
if (h == null)
h = ColorHolder.missing;
return h;
}
@Nonnull public static Couple<Color> p(@Nonnull Key key) {return p(key.get());}
@Nonnull public static Couple<Color> p(String key) {return resolve(key).asPair();}
@Nonnull public static Color c(@Nonnull Key key, boolean first) {return c(key.get(), first);}
@Nonnull public static Color c(String key, boolean first) {return p(key).get(first);}
public static int i(@Nonnull Key key, boolean first) {return i(key.get(), first);}
public static int i(String key, boolean first) {return p(key).get(first).getRGB();}
@Nonnull public static Color c(@Nonnull Key key) {return c(key.get());}
@Nonnull public static Color c(String key) {return resolve(key).get();}
public static int i(@Nonnull Key key) {return i(key.get());}
public static int i(String key) {return resolve(key).get().getRGB();}
//-----------//
protected final Map<String, ColorHolder> colors;
protected Theme() {
colors = new HashMap<>();
init();
}
protected void init() {
put(Key.BUTTON_IDLE, new Color(0x60_c0c0ff, true), new Color(0x30_c0c0ff, true));
put(Key.BUTTON_HOVER, new Color(0xa0_c0c0ff, true), new Color(0x50_c0c0ff, true));
put(Key.BUTTON_CLICK, new Color(0xff_4b4bff), new Color(0xff_3b3bdd));
put(Key.BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x20_909090, true));
put(Key.BUTTON_SUCCESS, new Color(0xcc_88f788, true), new Color(0xcc_20cc20, true));
put(Key.BUTTON_FAIL, new Color(0xcc_f78888, true), new Color(0xcc_cc2020, true));
put(Key.TEXT, new Color(0xff_eeeeee), new Color(0xff_a3a3a3));
put(Key.TEXT_DARKER, new Color(0xff_a3a3a3), new Color(0xff_808080));
put(Key.TEXT_ACCENT_STRONG, new Color(0xff_7b7ba3), new Color(0xff_616192));
put(Key.TEXT_ACCENT_SLIGHT, new Color(0xff_ddeeff), new Color(0xff_a0b0c0));
put(Key.STREAK, new Color(0x101010, false));
put(Key.PONDER_BACKGROUND_TRANSPARENT, new Color(0xdd_000000, true));
put(Key.PONDER_BACKGROUND_FLAT, new Color(0xff_000000, false));
put(Key.PONDER_IDLE, new Color(0x40ffeedd, true), new Color(0x20ffeedd, true));
put(Key.PONDER_HOVER, new Color(0x70ffffff, true), new Color(0x30ffffff, true));
put(Key.PONDER_HIGHLIGHT, new Color(0xf0ffeedd, true), new Color(0x60ffeedd, true));
put(Key.TEXT_WINDOW_BORDER, new Color(0x607a6000, true), new Color(0x207a6000, true));
put(Key.PONDER_BACK_ARROW, new Color(0x70aa9999, true), new Color(0x30aa9999, true));
put(Key.PONDER_PROGRESSBAR, new Color(0x80ffeedd, true), new Color(0x50ffeedd, true));
put(Key.PONDER_MISSING_CREATE, new Color(0x70_984500, true), new Color(0x70_692400, true));
put(Key.PONDER_MISSING_VANILLA, new Color(0x50_5000ff, true), new Color(0x50_300077, true));
//put(Key., new Color(0x, true), new Color(0x, true));
}
protected void put(String key, Color c) {
colors.put(key, ColorHolder.single(c));
}
protected void put(Key key, Color c) {
put(key.get(), c);
}
protected void put(String key, Color c1, Color c2) {
colors.put(key, ColorHolder.pair(c1, c2));
}
protected void put(Key key, Color c1, Color c2) {
put(key.get(), c1 , c2);
}
@Nullable protected ColorHolder get(String key) {
return colors.get(key);
}
public static class Key {
public static Key BUTTON_IDLE = new Key();
public static Key BUTTON_HOVER = new Key();
public static Key BUTTON_CLICK = new Key();
public static Key BUTTON_DISABLE = new Key();
public static Key BUTTON_SUCCESS = new Key();
public static Key BUTTON_FAIL = new Key();
public static Key TEXT = new Key();
public static Key TEXT_DARKER = new Key();
public static Key TEXT_ACCENT_STRONG = new Key();
public static Key TEXT_ACCENT_SLIGHT = new Key();
public static Key STREAK = new Key();
public static Key PONDER_BACKGROUND_TRANSPARENT = new Key();
public static Key PONDER_BACKGROUND_FLAT = new Key();
public static Key PONDER_IDLE = new Key();
public static Key PONDER_HOVER = new Key();
public static Key PONDER_HIGHLIGHT = new Key();
public static Key TEXT_WINDOW_BORDER = new Key();
public static Key PONDER_BACK_ARROW = new Key();
public static Key PONDER_PROGRESSBAR = new Key();
public static Key PONDER_MISSING_CREATE = new Key();
public static Key PONDER_MISSING_VANILLA = new Key();
private static int index = 0;
private final String s;
protected Key() {
this.s = "_" + index++;
}
protected Key(String s) {
this.s = s;
}
public String get() {
return s;
}
}
private static class ColorHolder {
private static final ColorHolder missing = ColorHolder.single(Color.BLACK);
private Couple<Color> colors;
private static ColorHolder single(Color c) {
ColorHolder h = new ColorHolder();
h.colors = Couple.create(c, c);
return h;
}
private static ColorHolder pair(Color first, Color second) {
ColorHolder h = new ColorHolder();
h.colors = Couple.create(first, second);
return h;
}
private Color get() {
return colors.getFirst();
}
private Couple<Color> asPair() {
return colors;
}
}
}

View File

@ -1,15 +1,21 @@
package com.simibubi.create.foundation.gui;
import java.awt.Color;
import javax.annotation.Nonnull;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.math.vector.Matrix4f;
@ -18,32 +24,26 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
public class UIRenderHelper {
public static void enableStencil() {
RenderSystem.recordRenderCall(() -> Minecraft.getInstance().getFramebuffer().enableStencil());
}
public static Framebuffer framebuffer;
public static void init() {
RenderSystem.recordRenderCall(() -> {
MainWindow mainWindow = Minecraft.getInstance()
.getWindow();
.getWindow();
framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true,
Minecraft.IS_RUNNING_ON_MAC);
Minecraft.IS_RUNNING_ON_MAC);
framebuffer.setFramebufferColor(0, 0, 0, 0);
// framebuffer.deleteFramebuffer();
framebuffer.enableStencil();
});
}
public static void prepFramebufferSize() {
MainWindow window = Minecraft.getInstance()
.getWindow();
if (framebuffer.framebufferWidth != window.getFramebufferWidth()
|| framebuffer.framebufferHeight != window.getFramebufferHeight()) {
framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(),
Minecraft.IS_RUNNING_ON_MAC);
}
}
public static void drawFramebuffer(float alpha) {
MainWindow window = Minecraft.getInstance()
.getWindow();
.getWindow();
float vx = (float) window.getScaledWidth();
float vy = (float) window.getScaledHeight();
@ -51,10 +51,6 @@ public class UIRenderHelper {
float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight;
RenderSystem.enableTexture();
RenderSystem.enableBlend();
RenderSystem.disableLighting();
RenderSystem.disableAlphaTest();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest();
framebuffer.bindFramebufferTexture();
@ -63,33 +59,21 @@ public class UIRenderHelper {
BufferBuilder bufferbuilder = tessellator.getBuffer();
bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE);
bufferbuilder.vertex(0, vy, 0)
.color(1, 1, 1, alpha)
.texture(0, 0)
.endVertex();
bufferbuilder.vertex(vx, vy, 0)
.color(1, 1, 1, alpha)
.texture(tx, 0)
.endVertex();
bufferbuilder.vertex(vx, 0, 0)
.color(1, 1, 1, alpha)
.texture(tx, ty)
.endVertex();
bufferbuilder.vertex(0, 0, 0)
.color(1, 1, 1, alpha)
.texture(0, ty)
.endVertex();
bufferbuilder.vertex(0, vy, 0).color(1, 1, 1, alpha).texture(0, 0).endVertex();
bufferbuilder.vertex(vx, vy, 0).color(1, 1, 1, alpha).texture(tx, 0).endVertex();
bufferbuilder.vertex(vx, 0, 0).color(1, 1, 1, alpha).texture(tx, ty).endVertex();
bufferbuilder.vertex(0, 0, 0).color(1, 1, 1, alpha).texture(0, ty).endVertex();
tessellator.draw();
framebuffer.unbindFramebufferTexture();
RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
}
public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length) {streak(ms, angle, x, y, breadth, length, Theme.i(Theme.Key.STREAK));}
// angle in degrees; 0° -> fading to the right
// x and y specify the middle point of the starting edge
// width is the total width of the streak
public static void streak(MatrixStack ms, float angle, int x, int y, int width, int length, int color) {
// breadth is the total width of the streak
public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length, int color) {
int a1 = 0xa0 << 24;
int a2 = 0x80 << 24;
int a3 = 0x10 << 24;
@ -105,7 +89,7 @@ public class UIRenderHelper {
ms.translate(x, y, 0);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90));
streak(ms, width / 2, length, c1, c2, c3, c4);
streak(ms, breadth / 2, length, c1, c2, c3, c4);
ms.pop();
}
@ -113,16 +97,59 @@ public class UIRenderHelper {
private static void streak(MatrixStack ms, int width, int height, int c1, int c2, int c3, int c4) {
double split1 = .5;
double split2 = .75;
Matrix4f model = ms.peek()
.getModel();
Matrix4f model = ms.peek().getModel();
RenderSystem.disableAlphaTest();
GuiUtils.drawGradientRect(model, 0, -width, 0, width, (int) (split1 * height), c1, c2);
GuiUtils.drawGradientRect(model, 0, -width, (int) (split1 * height), width, (int) (split2 * height), c2, c3);
GuiUtils.drawGradientRect(model, 0, -width, (int) (split2 * height), width, height, c3, c4);
RenderSystem.enableAlphaTest();
}
/**
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int)
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int breadth, int length, Couple<Color> c) {
angledGradient(ms, angle, x, y, 0, breadth, length, c);
}
/**
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int)
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int z, int breadth, int length, Couple<Color> c) {
angledGradient(ms, angle, x, y, z, breadth, length, c.getFirst().getRGB(), c.getSecond().getRGB());
}
/**
* @see #angledGradient(MatrixStack, float, int, int, int, int, int, int, int)
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int breadth, int length, int color1, int color2) {
angledGradient(ms, angle, x, y, 0, breadth, length, color1, color2);
}
/**
* x and y specify the middle point of the starting edge
*
* @param angle the angle of the gradient in degrees; 0° means from left to right
* @param color1 the color at the starting edge
* @param color2 the color at the ending edge
* @param breadth the total width of the gradient
*/
public static void angledGradient(@Nonnull MatrixStack ms, float angle, int x, int y, int z, int breadth, int length, int color1, int color2) {
ms.push();
ms.translate(x, y, z);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90));
Matrix4f model = ms.peek().getModel();
int w = breadth / 2;
GuiUtils.drawGradientRect(model, 0, -w, 0, w, length, color1, color2);
ms.pop();
}
public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, Couple<Color> colors) {breadcrumbArrow(matrixStack, x, y, z, width, height, indent, colors.getFirst().getRGB(), colors.getSecond().getRGB());}
// draws a wide chevron-style breadcrumb arrow pointing left
public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent,
int startColor, int endColor) {
public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, int startColor, int endColor) {
matrixStack.push();
matrixStack.translate(x - indent, y, z);
@ -134,13 +161,13 @@ public class UIRenderHelper {
private static void breadcrumbArrow(MatrixStack ms, int width, int height, int indent, int c1, int c2) {
/*
* 0,0 x1,y1 ********************* x4,y4 ***** x7,y7
* **** ****
* **** ****
* x0,y0 x2,y2 x5,y5
* **** ****
* **** ****
* x3,y3 ********************* x6,y6 ***** x8,y8
* 0,0 x1,y1 ********************* x4,y4 ***** x7,y7
* **** ****
* **** ****
* x0,y0 x2,y2 x5,y5
* **** ****
* **** ****
* x3,y3 ********************* x6,y6 ***** x8,y8
*
*/
@ -170,69 +197,32 @@ public class UIRenderHelper {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
Matrix4f model = ms.peek()
.getModel();
Matrix4f model = ms.peek().getModel();
bufferbuilder.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR);
bufferbuilder.vertex(model, x0, y0, 0)
.color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x1, y1, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x2, y2, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x0, y0, 0).color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x1, y1, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x2, y2, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x0, y0, 0)
.color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x2, y2, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x3, y3, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x0, y0, 0).color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x2, y2, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x3, y3, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x1, y1, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x4, y4, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x1, y1, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x3, y3, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x4, y4, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x6, y6, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x6, y6, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x5, y5, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x4, y4, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x7, y7, 0)
.color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x5, y5, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x7, y7, 0).color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x6, y6, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x5, y5, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x8, y8, 0)
.color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x6, y6, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x5, y5, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
bufferbuilder.vertex(model, x8, y8, 0).color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 24 & 0xFF).endVertex();
tessellator.draw();
RenderSystem.shadeModel(GL11.GL_FLAT);
@ -241,4 +231,30 @@ public class UIRenderHelper {
RenderSystem.enableAlphaTest();
RenderSystem.enableTexture();
}
//just like AbstractGui#drawTexture, but with a color at every vertex
public static void drawColoredTexture(MatrixStack ms, Color c, int x, int y, int tex_left, int tex_top, int width, int height) {
drawColoredTexture(ms, c, x, y, 0, (float) tex_left, (float) tex_top, width, height, 256, 256);
}
public static void drawColoredTexture(MatrixStack ms, Color c, int x, int y, int z, float tex_left, float tex_top, int width, int height, int sheet_width, int sheet_height) {
drawColoredTexture(ms, c, x, x + width, y, y + height, z, width, height, tex_left, tex_top, sheet_width, sheet_height);
}
private static void drawColoredTexture(MatrixStack ms, Color c, int left, int right, int top, int bot, int z, int tex_width, int tex_height, float tex_left, float tex_top, int sheet_width, int sheet_height) {
drawTexturedQuad(ms.peek().getModel(), c, left, right, top, bot, z, (tex_left + 0.0F) / (float) sheet_width, (tex_left + (float) tex_width) / (float) sheet_width, (tex_top + 0.0F) / (float) sheet_height, (tex_top + (float) tex_height) / (float) sheet_height);
}
private static void drawTexturedQuad(Matrix4f m, Color c, int left, int right, int top, int bot, int z, float u1, float u2, float v1, float v2) {
RenderSystem.enableBlend();
BufferBuilder bufferbuilder = Tessellator.getInstance().getBuffer();
bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE);
bufferbuilder.vertex(m, (float) left , (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u1, v2).endVertex();
bufferbuilder.vertex(m, (float) right, (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u2, v2).endVertex();
bufferbuilder.vertex(m, (float) right, (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u2, v1).endVertex();
bufferbuilder.vertex(m, (float) left , (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).texture(u1, v1).endVertex();
bufferbuilder.finishDrawing();
RenderSystem.enableAlphaTest();
WorldVertexBufferUploader.draw(bufferbuilder);
}
}

View File

@ -2,6 +2,9 @@ package com.simibubi.create.foundation.gui.widgets;
import java.util.LinkedList;
import java.util.List;
import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
@ -11,19 +14,78 @@ import net.minecraft.util.text.StringTextComponent;
public abstract class AbstractSimiWidget extends Widget {
protected List<ITextComponent> toolTip;
public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) {
super(xIn, yIn, widthIn, heightIn, StringTextComponent.EMPTY);
toolTip = new LinkedList<>();
protected float z;
protected boolean wasHovered = false;
protected List<ITextComponent> toolTip = new LinkedList<>();
protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {};
protected AbstractSimiWidget() {
this(0, 0);
}
protected AbstractSimiWidget(int x, int y) {
this(x, y, 16, 16);
}
protected AbstractSimiWidget(int x, int y, int width, int height) {
super(x, y, width, height, StringTextComponent.EMPTY);
}
public <T extends AbstractSimiWidget> T withCallback(BiConsumer<Integer, Integer> cb) {
this.onClick = cb;
//noinspection unchecked
return (T) this;
}
public <T extends AbstractSimiWidget> T withCallback(Runnable cb) {
return withCallback((_$, _$$) -> cb.run());
}
public <T extends AbstractSimiWidget> T atZLevel(float z) {
this.z = z;
//noinspection unchecked
return (T) this;
}
public List<ITextComponent> getToolTip() {
return toolTip;
}
public void tick() {}
@Override
public void renderButton(MatrixStack matrixStack, int p_renderButton_1_, int p_renderButton_2_, float p_renderButton_3_) {
public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
if (visible) {
hovered = isMouseOver(mouseX, mouseY);
beforeRender(ms, mouseX, mouseY, partialTicks);
renderButton(ms, mouseX, mouseY, partialTicks);
afterRender(ms, mouseX, mouseY, partialTicks);
wasHovered = isHovered();
}
}
@Override
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {}
@Override
protected boolean clicked(double mouseX, double mouseY) {
return active && visible && isMouseOver(mouseX, mouseY);
}
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
ms.push();
}
protected void afterRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
ms.pop();
}
public void runCallback(double mouseX, double mouseY) {
onClick.accept((int) mouseX, (int) mouseY);
}
@Override
public void onClick(double mouseX, double mouseY) {
runCallback(mouseX, mouseY);
}
}

View File

@ -0,0 +1,197 @@
package com.simibubi.create.foundation.gui.widgets;
import java.awt.Color;
import java.util.function.Function;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.DelegatedStencilElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
public class BoxWidget extends ElementWidget {
public static final Function<BoxWidget, DelegatedStencilElement.ElementRenderer> gradientFactory = (box) -> (ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, w/2, -2, w + 4, h + 4, box.gradientColor1.getRGB(), box.gradientColor2.getRGB());
protected BoxElement box;
protected Color customBorderTop;
protected Color customBorderBot;
protected boolean animateColors = true;
protected LerpedFloat colorAnimation = LerpedFloat.linear();
protected Color gradientColor1, gradientColor2;
private Color colorTarget1 = Theme.c(Theme.Key.BUTTON_IDLE, true), colorTarget2 = Theme.c(Theme.Key.BUTTON_IDLE, false);
private Color previousColor1, previousColor2;
public BoxWidget() {
this(0, 0);
}
public BoxWidget(int x, int y) {
this(x, y, 16, 16);
}
public BoxWidget(int x, int y, int width, int height) {
super(x, y, width, height);
box = new BoxElement()
.at(x, y)
.withBounds(width, height);
gradientColor1 = colorTarget1;
gradientColor2 = colorTarget2;
}
public <T extends BoxWidget> T withBounds(int width, int height) {
this.width = width;
this.height = height;
//noinspection unchecked
return (T) this;
}
public <T extends BoxWidget> T withBorderColors(Couple<Color> colors) {
this.customBorderTop = colors.getFirst();
this.customBorderBot = colors.getSecond();
updateColorsFromState();
//noinspection unchecked
return (T) this;
}
public <T extends BoxWidget> T withBorderColors(Color top, Color bot) {
this.customBorderTop = top;
this.customBorderBot = bot;
updateColorsFromState();
//noinspection unchecked
return (T) this;
}
public <T extends BoxWidget> T animateColors(boolean b) {
this.animateColors = b;
//noinspection unchecked
return (T) this;
}
@Override
public void tick() {
super.tick();
colorAnimation.tickChaser();
}
@Override
public void onClick(double x, double y) {
super.onClick(x, y);
gradientColor1 = Theme.c(Theme.Key.BUTTON_CLICK, true);
gradientColor2 = Theme.c(Theme.Key.BUTTON_CLICK, true);
startGradientAnimation(getColorForState(true), getColorForState(false), true, 0.15);
}
@Override
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.beforeRender(ms, mouseX, mouseY, partialTicks);
if (hovered != wasHovered) {
startGradientAnimation(
getColorForState(true),
getColorForState(false),
hovered
);
}
if (colorAnimation.settled()) {
gradientColor1 = colorTarget1;
gradientColor2 = colorTarget2;
} else {
float animationValue = 1 - Math.abs(colorAnimation.getValue(partialTicks));
gradientColor1 = ColorHelper.mixColors(previousColor1, colorTarget1, animationValue);
gradientColor2 = ColorHelper.mixColors(previousColor2, colorTarget2, animationValue);
}
}
@Override
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
float fadeValue = fade.getValue(partialTicks);
if (fadeValue < .1f)
return;
box.withAlpha(fadeValue);
box.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_TRANSPARENT))
.gradientBorder(gradientColor1, gradientColor2)
.at(x, y, z)
.withBounds(width, height)
.render(ms);
super.renderButton(ms, mouseX, mouseY, partialTicks);
wasHovered = hovered;
}
@Override
public boolean isMouseOver(double mX, double mY) {
if (!active || !visible)
return false;
return
x - 4 <= mX &&
y - 4 <= mY &&
mX <= x + 4 + width &&
mY <= y + 4 + height;
}
public BoxElement getBox() {
return box;
}
public void updateColorsFromState() {
colorTarget1 = getColorForState(true);
colorTarget2 = getColorForState(false);
}
public void animateGradientFromState() {
startGradientAnimation(
getColorForState(true),
getColorForState(false),
true
);
}
private void startGradientAnimation(Color c1, Color c2, boolean positive, double expSpeed) {
if (!animateColors)
return;
colorAnimation.startWithValue(positive ? 1 : -1);
colorAnimation.chase(0, expSpeed, LerpedFloat.Chaser.EXP);
colorAnimation.tickChaser();
previousColor1 = gradientColor1;
previousColor2 = gradientColor2;
colorTarget1 = c1;
colorTarget2 = c2;
}
private void startGradientAnimation(Color c1, Color c2, boolean positive) {
startGradientAnimation(c1, c2, positive, 0.3);
}
private Color getColorForState(boolean first) {
if (!active)
return Theme.p(Theme.Key.BUTTON_DISABLE).get(first);
if (hovered) {
if (first)
return customBorderTop != null ? customBorderTop.darker() : Theme.c(Theme.Key.BUTTON_HOVER, true);
else
return customBorderBot != null ? customBorderBot.darker() : Theme.c(Theme.Key.BUTTON_HOVER, false);
}
if (first)
return customBorderTop != null ? customBorderTop : Theme.c(Theme.Key.BUTTON_IDLE, true);
else
return customBorderBot != null ? customBorderBot : Theme.c(Theme.Key.BUTTON_IDLE, false);
}
}

View File

@ -0,0 +1,144 @@
package com.simibubi.create.foundation.gui.widgets;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.RenderElement;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
public class ElementWidget extends AbstractSimiWidget {
protected RenderElement element = RenderElement.EMPTY;
protected boolean usesFade = false;
protected int fadeModX;
protected int fadeModY;
protected LerpedFloat fade = LerpedFloat.linear().startWithValue(1);
protected boolean rescaleElement = false;
protected float rescaleSizeX;
protected float rescaleSizeY;
protected float paddingX = 0;
protected float paddingY = 0;
public ElementWidget(int x, int y) {
super(x, y);
}
public ElementWidget(int x, int y, int width, int height) {
super(x, y, width, height);
}
public <T extends ElementWidget> T showingElement(RenderElement element) {
this.element = element;
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T showing(IScreenRenderable renderable) {
return this.showingElement(RenderElement.of(renderable));
}
public <T extends ElementWidget> T modifyElement(Consumer<RenderElement> consumer) {
if (element != null)
consumer.accept(element);
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T mapElement(UnaryOperator<RenderElement> function) {
if (element != null)
element = function.apply(element);
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T withPadding(float paddingX, float paddingY) {
this.paddingX = paddingX;
this.paddingY = paddingY;
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T enableFade(int fadeModifierX, int fadeModifierY) {
this.fade.startWithValue(0);
this.usesFade = true;
this.fadeModX = fadeModifierX;
this.fadeModY = fadeModifierY;
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T disableFade() {
this.fade.startWithValue(1);
this.usesFade = false;
//noinspection unchecked
return (T) this;
}
public LerpedFloat fade() {
return fade;
}
public <T extends ElementWidget> T fade(float target) {
fade.chase(target, 0.1, LerpedFloat.Chaser.EXP);
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T rescaleElement(float rescaleSizeX, float rescaleSizeY) {
this.rescaleElement = true;
this.rescaleSizeX = rescaleSizeX;
this.rescaleSizeY = rescaleSizeY;
//noinspection unchecked
return (T) this;
}
public <T extends ElementWidget> T disableRescale() {
this.rescaleElement = false;
//noinspection unchecked
return (T) this;
}
@Override
public void tick() {
super.tick();
fade.tickChaser();
}
@Override
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.beforeRender(ms, mouseX, mouseY, partialTicks);
float fadeValue = fade.getValue(partialTicks);
element.withAlpha(fadeValue);
if (fadeValue < 1) {
ms.translate((1 - fadeValue) * fadeModX, (1 - fadeValue) * fadeModY, 0);
}
}
@Override
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
ms.push();
ms.translate(x + paddingX, y + paddingY, z);
float innerWidth = width - 2 * paddingX;
float innerHeight = height - 2 * paddingY;
if (rescaleElement) {
float xScale = innerWidth / rescaleSizeX;
float yScale = innerHeight / rescaleSizeY;
ms.scale(xScale, yScale, 1);
element.at(element.getX() / xScale, element.getY() / yScale);
}
element.withBounds((int) innerWidth, (int) innerHeight).render(ms);
ms.pop();
}
public RenderElement getRenderElement() {
return element;
}
}

View File

@ -7,6 +7,8 @@ import com.simibubi.create.foundation.gui.AllIcons;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
public class IconButton extends AbstractSimiWidget {
private AllIcons icon;
@ -18,7 +20,7 @@ public class IconButton extends AbstractSimiWidget {
}
@Override
public void renderButton(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
public void renderButton(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
if (this.visible) {
this.hovered =
mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;

View File

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllGuiTextures;
@ -22,7 +24,7 @@ public class Indicator extends AbstractSimiWidget {
}
@Override
public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks ) {
public void render(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks ) {
AllGuiTextures toDraw;
switch(state) {
case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break;

View File

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
@ -69,7 +71,7 @@ public class Label extends AbstractSimiWidget {
}
@Override
public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
public void render(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
if (!visible)
return;
if (text == null || text.getString().isEmpty())

View File

@ -0,0 +1,29 @@
package com.simibubi.create.foundation.mixin;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@Mixin(Minecraft.class)
public class WindowResizeMixin {
@Shadow @Final private MainWindow mainWindow;
@Inject(at = @At("TAIL"), method = "updateWindowSize")
private void updateWindowSize(CallbackInfo ci) {
if (UIRenderHelper.framebuffer != null)
UIRenderHelper.framebuffer.func_216491_a(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC);
}
}

View File

@ -38,8 +38,9 @@ import com.simibubi.create.content.schematics.packet.InstantSchematicPacket;
import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
import com.simibubi.create.foundation.command.ConfigureConfigPacket;
import com.simibubi.create.foundation.command.SConfigureConfigPacket;
import com.simibubi.create.foundation.command.HighlightPacket;
import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
@ -80,12 +81,13 @@ public enum AllPackets {
PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER),
TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER),
EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::new, PLAY_TO_SERVER),
C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER),
// Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::new, PLAY_TO_CLIENT),
CONFIGURE_CONFIG(ConfigureConfigPacket.class, ConfigureConfigPacket::new, PLAY_TO_CLIENT),
S_CONFIGURE_CONFIG(SConfigureConfigPacket.class, SConfigureConfigPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::new, PLAY_TO_CLIENT),

View File

@ -9,9 +9,11 @@ import org.apache.commons.lang3.mutable.MutableInt;
import org.lwjgl.glfw.GLFW;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.content.PonderTagScreen;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
@ -76,9 +78,9 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
if (screen instanceof PonderTagScreen)
icon = ((PonderTagScreen) screen).getTag();
widgets.add(backTrack = new PonderButton(31, height - 31 - PonderButton.SIZE, () -> {
ScreenOpener.openPreviousScreen(this, Optional.empty());
}).fade(0, -1));
widgets.add(backTrack = new PonderButton(31, height - 31 - 20)
.enableFade(0, 5)
.withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty())));
backTrack.fade(1);
if (icon != null)
@ -97,7 +99,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.push();
ms.translate(0, 0, 500);
if (backTrack.isHovered()) {
textRenderer.draw(ms, Lang.translate(THINK_BACK), 15, height - 16, 0xffa3a3a3);
textRenderer.draw(ms, Lang.translate(THINK_BACK), 15, height - 16, Theme.i(Theme.Key.TEXT_DARKER));
if (MathHelper.epsilonEquals(arrowAnimation.getValue(), arrowAnimation.getChaseTarget())) {
arrowAnimation.setValue(1);
arrowAnimation.setValue(1);// called twice to also set the previous value to 1
@ -108,7 +110,18 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
@Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
if (transition.getChaseTarget() == 0) {
if (backTrack != null) {
int x = (int) MathHelper.lerp(arrowAnimation.getValue(partialTicks), -9, 21);
int maxX = backTrack.x + backTrack.getWidth();
if (x + 30 < backTrack.x)
UIRenderHelper.breadcrumbArrow(ms, x + 30, height - 51, 0, maxX - (x + 30), 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW));
UIRenderHelper.breadcrumbArrow(ms, x, height - 51, 0, 30, 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW));
UIRenderHelper.breadcrumbArrow(ms, x - 30, height - 51, 0, 30, 20, 5, Theme.p(Theme.Key.PONDER_BACK_ARROW));
}
if (transition.getChaseTarget() == 0 || transition.settled()) {
renderBackground(ms);
return;
}
@ -121,14 +134,14 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
// draw last screen into buffer
if (lastScreen != null && lastScreen != this && !transition.settled()) {
ms.push();// 1
ms.push();
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
UIRenderHelper.prepFramebufferSize();
ms.push();// 2
ms.translate(0, 0, -1000);
UIRenderHelper.framebuffer.bindFramebuffer(true);
lastScreen.render(ms, mouseX, mouseY, 10);
ms.pop();// 2
lastScreen.render(ms, mouseX, mouseY, partialTicks);
ms.pop();
ms.push();
// use the buffer texture
Minecraft.getInstance()
@ -144,32 +157,23 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
dpy = ((NavigatableSimiScreen) lastScreen).depthPointY;
}
// transitionV is 1/-1 when the older screen is hidden
// transitionV is 0 when the older screen is still fully visible
ms.translate(dpx, dpy, 0);
ms.scale((float) scale, (float) scale, 1);
ms.scale(scale, scale, 1);
ms.translate(-dpx, -dpy, 0);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.disableAlphaTest();
UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue));
ms.pop();// 1
RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
ms.pop();
}
// modify current screen as well
scale = transitionValue > 0 ? 1 - 0.5f * (1 - transitionValue) : 1 + .5f * (1 + transitionValue);
ms.translate(depthPointX, depthPointY, 0);
ms.scale((float) scale, (float) scale, 1);
ms.scale(scale, scale, 1);
ms.translate(-depthPointX, -depthPointY, 0);
if (backTrack != null) {
int x = (int) MathHelper.lerp(arrowAnimation.getValue(partialTicks), -9, 21);
int maxX = backTrack.x + backTrack.getWidth();
if (x + 30 < backTrack.x)
UIRenderHelper.breadcrumbArrow(ms, x + 30, height - 51, 0, maxX - (x + 30), 20, 5, 0x40aa9999,
0x10aa9999);
UIRenderHelper.breadcrumbArrow(ms, x, height - 51, 0, 30, 20, 5, 0x40aa9999, 0x10aa9999);
UIRenderHelper.breadcrumbArrow(ms, x - 30, height - 51, 0, 30, 20, 5, 0x40aa9999, 0x10aa9999);
}
}
@Override

View File

@ -1,9 +1,11 @@
package com.simibubi.create.foundation.ponder;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import it.unimi.dsi.fastutil.ints.IntList;
@ -15,7 +17,6 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
public class PonderProgressBar extends AbstractSimiWidget {
LerpedFloat progress;
LerpedFloat flash;
PonderUI ponder;
@ -24,35 +25,20 @@ public class PonderProgressBar extends AbstractSimiWidget {
this.ponder = ponder;
progress = LerpedFloat.linear()
.startWithValue(0);
flash = LerpedFloat.linear()
.startWithValue(0);
.startWithValue(0);
}
public void tick() {
progress.chase(ponder.getActiveScene()
.getSceneProgress(), .5f, LerpedFloat.Chaser.EXP);
.getSceneProgress(), .5f, LerpedFloat.Chaser.EXP);
progress.tickChaser();
if (hovered)
flash();
}
public void flash() {
float value = flash.getValue();
flash.setValue(value + (1 - value) * .2f);
}
public void dim() {
float value = flash.getValue();
flash.setValue(value * .5f);
}
@Override
protected boolean clicked(double mouseX, double mouseY) {
return this.active && this.visible && !ponder.getActiveScene().keyframeTimes.isEmpty()
&& mouseX >= (double) this.x && mouseX < (double) (this.x + this.width + 4) && mouseY >= (double) this.y - 3
&& mouseY < (double) (this.y + this.height + 20);
&& mouseX >= (double) this.x && mouseX < (double) (this.x + this.width + 4) && mouseY >= (double) this.y - 3
&& mouseY < (double) (this.y + this.height + 20);
}
@Override
@ -102,58 +88,46 @@ public class PonderProgressBar extends AbstractSimiWidget {
}
@Override
public void renderButton(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
hovered = clicked(mouseX, mouseY);
ms.push();
ms.translate(0, 0, 250);
/*
* ponderButtons are at z+400
* renderBox is at z+100
* gradients have to be in front of the box so z>+100
*/
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(x, y, 250)
.withBounds(width, height)
.render(ms);
ms.push();
PonderUI.renderBox(ms, x, y, width, height, false);
ms.pop();
ms.push();
ms.translate(x - 2, y - 2, 0);
ms.translate(x - 2, y - 2, 150);
ms.push();
ms.scale((width + 4) * progress.getValue(partialTicks), 1, 1);
GuiUtils.drawGradientRect(ms.peek()
.getModel(), 110, 0, 3, 1, 4, 0x80ffeedd, 0x80ffeedd);
GuiUtils.drawGradientRect(ms.peek()
.getModel(), 110, 0, 4, 1, 5, 0x50ffeedd, 0x50ffeedd);
int c1 = Theme.i(Theme.Key.PONDER_PROGRESSBAR, true);
int c2 = Theme.i(Theme.Key.PONDER_PROGRESSBAR, false);
GuiUtils.drawGradientRect(ms.peek().getModel(), 110, 0, 3, 1, 4, c1, c1);
GuiUtils.drawGradientRect(ms.peek().getModel(), 110, 0, 4, 1, 5, c2, c2);
ms.pop();
renderKeyframes(ms, mouseX, partialTicks);
ms.pop();
ms.pop();
}
private void renderKeyframes(MatrixStack ms, int mouseX, float partialTicks) {
PonderScene activeScene = ponder.getActiveScene();
int hoverStartColor;
int hoverEndColor;
int hoverStartColor = Theme.i(Theme.Key.PONDER_HOVER, true) | 0xa0_000000;
int hoverEndColor = Theme.i(Theme.Key.PONDER_HOVER, false) | 0xa0_000000;
int idleStartColor = Theme.i(Theme.Key.PONDER_IDLE, true) | 0x40_000000;
int idleEndColor = Theme.i(Theme.Key.PONDER_IDLE, false) | 0x40_000000;
int hoverIndex;
if (hovered) {
hoverIndex = getHoveredKeyframeIndex(activeScene, mouseX);
float flashValue = flash.getValue(partialTicks) * 3
+ (float) Math.sin((AnimationTickHolder.getTicks() + partialTicks) / 6);
hoverEndColor = ColorHelper.applyAlpha(0x70ffffff, flashValue);
hoverStartColor = ColorHelper.applyAlpha(0x30ffffff, flashValue);
} else {
hoverIndex = -2;
hoverEndColor = 0;
hoverStartColor = 0;
}
IntList keyframeTimes = activeScene.keyframeTimes;
@ -167,8 +141,8 @@ public class PonderProgressBar extends AbstractSimiWidget {
int keyframePos = (int) (((float) keyframeTime) / ((float) activeScene.totalTime) * (width + 4));
boolean selected = i == hoverIndex;
int startColor = selected ? hoverStartColor : 0x30ffeedd;
int endColor = selected ? hoverEndColor : 0x60ffeedd;
int startColor = selected ? hoverStartColor : idleStartColor;
int endColor = selected ? hoverEndColor : idleEndColor;
int height = selected ? 8 : 4;
drawKeyframe(ms, activeScene, selected, keyframeTime, keyframePos, startColor, endColor, height);
@ -176,12 +150,11 @@ public class PonderProgressBar extends AbstractSimiWidget {
}
}
private void drawKeyframe(MatrixStack ms, PonderScene activeScene, boolean selected, int keyframeTime,
int keyframePos, int startColor, int endColor, int height) {
private void drawKeyframe(MatrixStack ms, PonderScene activeScene, boolean selected, int keyframeTime, int keyframePos, int startColor, int endColor, int height) {
if (selected) {
FontRenderer font = Minecraft.getInstance().fontRenderer;
GuiUtils.drawGradientRect(ms.peek()
.getModel(), 100, keyframePos, 10, keyframePos + 1, 10 + height, endColor, startColor);
.getModel(), 100, keyframePos, 10, keyframePos + 1, 10 + height, endColor, startColor);
ms.push();
ms.translate(0, 0, 100);
String text;
@ -198,7 +171,7 @@ public class PonderProgressBar extends AbstractSimiWidget {
}
GuiUtils.drawGradientRect(ms.peek()
.getModel(), 500, keyframePos, -1, keyframePos + 1, 2 + height, startColor, endColor);
.getModel(), 500, keyframePos, -1, keyframePos + 1, 2 + height, startColor, endColor);
}
@Override

View File

@ -2,13 +2,13 @@ package com.simibubi.create.foundation.ponder;
import static com.simibubi.create.foundation.ponder.PonderLocalization.LANG_PREFIX;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.stream.IntStream;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack;
@ -16,8 +16,10 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.PonderScene.SceneTransform;
import com.simibubi.create.foundation.ponder.content.DebugScenes;
@ -29,6 +31,7 @@ import com.simibubi.create.foundation.ponder.elements.TextWindowElement;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.FontHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -43,14 +46,12 @@ import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.MutableBoundingBox;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
import net.minecraft.util.text.IFormattableTextComponent;
@ -166,13 +167,16 @@ public class PonderUI extends NavigatableSimiScreen {
int i = tagButtons.size();
int x = 31;
int y = 81 + i * 30;
PonderButton b = new PonderButton(x, y, (mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(new PonderTagScreen(t));
}).showing(t);
widgets.add(b);
tagButtons.add(b);
PonderButton b2 = new PonderButton(x, y)
.showing(t)
.withCallback((mX, mY) -> {
centerScalingOn(mX, mY);
ScreenOpener.transitionTo(new PonderTagScreen(t));
});
widgets.add(b2);
tagButtons.add(b2);
LerpedFloat chase = LerpedFloat.linear()
.startWithValue(0)
@ -181,10 +185,10 @@ public class PonderUI extends NavigatableSimiScreen {
});
if (chapter != null) {
/*if (chapter != null) {
widgets.add(chap = new PonderButton(width - 31 - 24, 31, () -> {
}).showing(chapter));
}
}*/
GameSettings bindings = client.gameSettings;
int spacing = 8;
@ -193,53 +197,63 @@ public class PonderUI extends NavigatableSimiScreen {
{
int pX = (width / 2) - 110;
int pY = bY + PonderButton.SIZE + 4;
int pY = bY + 20 + 4;
int pW = width - 2 * pX;
widgets.add(progressBar = new PonderProgressBar(this, pX, pY, pW, 1));
}
widgets.add(scan = new PonderButton(bX, bY, () -> {
identifyMode = !identifyMode;
if (!identifyMode)
scenes.get(index)
.deselect();
else
ponderPartialTicksPaused = client.getRenderPartialTicks();
}).showing(AllIcons.I_MTD_SCAN)
.shortcut(bindings.keyBindDrop)
.fade(0, -1));
widgets.add(scan = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindDrop)
.showing(AllIcons.I_MTD_SCAN)
.enableFade(0, 5)
.withCallback(() -> {
identifyMode = !identifyMode;
if (!identifyMode)
scenes.get(index)
.deselect();
else
ponderPartialTicksPaused = client.getRenderPartialTicks();
}));
widgets.add(slowMode = new PonderButton(width - 20 - 31, bY, () -> {
setComfyReadingEnabled(!isComfyReadingEnabled());
}).showing(AllIcons.I_MTD_SLOW_MODE)
.fade(0, -1));
widgets.add(slowMode = new PonderButton(width - 20 - 31, bY)
.showing(AllIcons.I_MTD_SLOW_MODE)
.enableFade(0, 5)
.withCallback(() -> setComfyReadingEnabled(!isComfyReadingEnabled())));
if (PonderIndex.EDITOR_MODE) {
widgets.add(userMode = new PonderButton(width - 50 - 31, bY, () -> {
userViewMode = !userViewMode;
}).showing(AllIcons.I_MTD_USER_MODE)
.fade(0, -1));
widgets.add(userMode = new PonderButton(width - 50 - 31, bY)
.showing(AllIcons.I_MTD_USER_MODE)
.enableFade(0, 5)
.withCallback(() -> userViewMode = !userViewMode));
}
bX += 50 + spacing;
widgets.add(left = new PonderButton(bX, bY, () -> this.scroll(false)).showing(AllIcons.I_MTD_LEFT)
.shortcut(bindings.keyBindLeft)
.fade(0, -1));
widgets.add(left = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindLeft)
.showing(AllIcons.I_MTD_LEFT)
.enableFade(0, 5)
.withCallback(() -> this.scroll(false)));
bX += 20 + spacing;
widgets.add(close = new PonderButton(bX, bY, this::onClose).showing(AllIcons.I_MTD_CLOSE)
.shortcut(bindings.keyBindInventory)
.fade(0, -1));
widgets.add(close = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindInventory)
.showing(AllIcons.I_MTD_CLOSE)
.enableFade(0, 5)
.withCallback(this::onClose));
bX += 20 + spacing;
widgets.add(right = new PonderButton(bX, bY, () -> this.scroll(true)).showing(AllIcons.I_MTD_RIGHT)
.shortcut(bindings.keyBindRight)
.fade(0, -1));
widgets.add(right = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindRight)
.showing(AllIcons.I_MTD_RIGHT)
.enableFade(0, 5)
.withCallback(() -> this.scroll(true)));
bX += 50 + spacing;
widgets.add(replay = new PonderButton(bX, bY, this::replay).showing(AllIcons.I_MTD_REPLAY)
.shortcut(bindings.keyBindBack)
.fade(0, -1));
widgets.add(replay = new PonderButton(bX, bY)
.withShortcut(bindings.keyBindBack)
.showing(AllIcons.I_MTD_REPLAY)
.enableFade(0, 5)
.withCallback(this::replay));
}
@Override
@ -429,7 +443,6 @@ public class PonderUI extends NavigatableSimiScreen {
MutableBoundingBox bounds = story.getBounds();
ms.push();
// ms.peek().getModel().multiply(ms.peek().getModel());
// kool shadow fx
{
@ -527,17 +540,16 @@ public class PonderUI extends NavigatableSimiScreen {
float lazyIndexValue = lazyIndex.getValue(partialTicks);
float indexDiff = Math.abs(lazyIndexValue - index);
PonderScene activeScene = scenes.get(index);
int textColor = 0xeeeeee;
boolean noWidgetsHovered = true;
for (Widget widget : widgets)
noWidgetsHovered &= !widget.isMouseOver(mouseX, mouseY);
int tooltipColor = 0xffa3a3a3;
int tooltipColor = Theme.i(Theme.Key.TEXT_DARKER);
{
// Chapter title
ms.push();
ms.translate(0, 0, 300);
ms.translate(0, 0, 100);
int x = 31 + 20 + 8;
int y = 31;
@ -545,36 +557,40 @@ public class PonderUI extends NavigatableSimiScreen {
int wordWrappedHeight = textRenderer.getWordWrappedHeight(title, left.x - 51);
int streakHeight = 35 - 9 + wordWrappedHeight;
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade), 0x101010);
UIRenderHelper.streak(ms, 180, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (30 * fade), 0x101010);
renderBox(ms, 21, 21, 30, 30, false);
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade));
UIRenderHelper.streak(ms, 180, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (30 * fade));
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(21, 21, 100)
.withBounds(30, 30)
.render(ms);
GuiGameElement.of(stack)
.at(x - 39, y - 11)
.scale(2)
.render(ms);
.scale(2)
.at(x - 39, y - 11)
.render(ms);
textRenderer.draw(ms, Lang.translate(PONDERING), x, y - 6, tooltipColor);
y += 8;
x += 0;
// ms.translate(0, 3 * (indexDiff), 0);
ms.translate(x, y, 0);
ms.multiply(Vector3f.NEGATIVE_X.getDegreesQuaternion(indexDiff * -75));
ms.translate(0, 0, 5);
FontHelper.drawSplitString(ms, textRenderer, title, 0, 0, left.x - 51,
ColorHelper.applyAlpha(textColor, 1 - indexDiff));
ColorHelper.applyAlpha(Theme.i(Theme.Key.TEXT), 1 - indexDiff));
ms.pop();
if (chapter != null) {
ms.push();
ms.translate(chap.x - 4 - 4, chap.y, 0);
UIRenderHelper.streak(ms, 180, 4, 10, 26, (int) (150 * fade), 0x101010);
UIRenderHelper.streak(ms, 180, 4, 10, 26, (int) (150 * fade));
drawRightAlignedString(textRenderer, ms, Lang.translate(IN_CHAPTER)
.getString(), 0, 0, tooltipColor);
drawRightAlignedString(textRenderer, ms, Lang.translate(LANG_PREFIX + "chapter." + chapter.getId())
.getString(), 0, 12, 0xffeeeeee);
drawRightAlignedString(textRenderer, ms, Lang.translate(IN_CHAPTER).getString(), 0, 0, tooltipColor);
drawRightAlignedString(textRenderer, ms,
Lang.translate(LANG_PREFIX + "chapter." + chapter.getId()).getString(), 0, 12, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -590,29 +606,24 @@ public class PonderUI extends NavigatableSimiScreen {
ms.push();
ms.translate(mouseX, mouseY, 100);
if (hoveredTooltipItem.isEmpty()) {
IFormattableTextComponent text = Lang
.translate(IDENTIFY_MODE,
((IFormattableTextComponent) client.gameSettings.keyBindDrop.getBoundKeyLocalizedText())
.formatted(TextFormatting.WHITE))
.formatted(TextFormatting.GRAY);
IFormattableTextComponent text = Lang.translate(
IDENTIFY_MODE,
((IFormattableTextComponent) client.gameSettings.keyBindDrop.getBoundKeyLocalizedText()).formatted(TextFormatting.WHITE)
).formatted(TextFormatting.GRAY);
// renderOrderedTooltip(ms, textRenderer.wrapLines(text, width / 3), 0, 0);
renderWrappedToolTip(ms, textRenderer.getTextHandler()
.wrapLines(text, width / 3, Style.EMPTY), 0, 0, textRenderer);
/*
* String tooltip = Lang
* .createTranslationTextComponent(IDENTIFY_MODE, client.gameSettings.keyBindDrop.getBoundKeyLocalizedText().applyTextStyle(TextFormatting.WHITE))
* .applyTextStyle(TextFormatting.GRAY)
* .getFormattedText();
* renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0);
*/
//renderOrderedTooltip(ms, textRenderer.wrapLines(text, width / 3), 0, 0);
renderWrappedToolTip(ms, textRenderer.getTextHandler().wrapLines(text, width / 3, Style.EMPTY), 0, 0, textRenderer);
/*String tooltip = Lang
.createTranslationTextComponent(IDENTIFY_MODE, client.gameSettings.keyBindDrop.getBoundKeyLocalizedText().applyTextStyle(TextFormatting.WHITE))
.applyTextStyle(TextFormatting.GRAY)
.getFormattedText();
renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0);*/
} else
renderTooltip(ms, hoveredTooltipItem, 0, 0);
if (hoveredBlockPos != null && PonderIndex.EDITOR_MODE && !userViewMode) {
ms.translate(0, -15, 0);
boolean copied = copiedBlockPos != null && hoveredBlockPos.equals(copiedBlockPos);
IFormattableTextComponent coords = new StringTextComponent(
hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ())
IFormattableTextComponent coords = new StringTextComponent(hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ())
.formatted(copied ? TextFormatting.GREEN : TextFormatting.GOLD);
renderTooltip(ms, coords, 0, 0);
}
@ -649,15 +660,14 @@ public class PonderUI extends NavigatableSimiScreen {
// Widgets
widgets.forEach(w -> {
if (w instanceof PonderButton) {
PonderButton mtdButton = (PonderButton) w;
mtdButton.fade(fade);
((PonderButton) w).fade().startWithValue(fade);
}
});
if (index == 0 || index == 1 && lazyIndexValue < index)
left.fade(lazyIndexValue);
left.fade().startWithValue(lazyIndexValue);
if (index == scenes.size() - 1 || index == scenes.size() - 2 && lazyIndexValue > index)
right.fade(scenes.size() - lazyIndexValue - 1);
right.fade().startWithValue(scenes.size() - lazyIndexValue - 1);
boolean finished = activeScene.isFinished();
if (finished)
@ -693,14 +703,14 @@ public class PonderUI extends NavigatableSimiScreen {
ms.translate(x, y + 5 * (1 - fade), 800);
float fadedWidth = 200 * chase.getValue(partialTicks);
UIRenderHelper.streak(ms, 0, 0, 12, 26, (int) fadedWidth, 0x101010);
UIRenderHelper.streak(ms, 0, 0, 12, 26, (int) fadedWidth);
GL11.glScissor((int) (x * s), 0, (int) (fadedWidth * s), (int) (height * s));
GL11.glEnable(GL11.GL_SCISSOR_TEST);
String tagName = this.tags.get(i)
.getTitle();
textRenderer.draw(ms, tagName, 3, 8, 0xffeedd);
textRenderer.draw(ms, tagName, 3, 8, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
GL11.glDisable(GL11.GL_SCISSOR_TEST);
@ -727,24 +737,6 @@ public class PonderUI extends NavigatableSimiScreen {
ms.pop();
}
protected void lowerButtonGroup(MatrixStack ms, int index, int mouseX, int mouseY, float fade, AllIcons icon,
KeyBinding key) {
int bWidth = 20;
int bHeight = 20;
int bX = (width - bWidth) / 2 + (index - 1) * (bWidth + 8);
int bY = height - bHeight - 31;
ms.push();
if (fade < fadeIn.getChaseTarget())
ms.translate(0, (1 - fade) * 5, 0);
boolean hovered = isMouseOver(mouseX, mouseY, bX, bY, bWidth, bHeight);
renderBox(ms, bX, bY, bWidth, bHeight, hovered);
icon.draw(ms, bX + 2, bY + 2);
drawCenteredText(ms, textRenderer, key.getBoundKeyLocalizedText(), bX + bWidth / 2 + 8, bY + bHeight - 6,
0xff606060);
ms.pop();
}
private void renderOverlay(MatrixStack ms, int i, float partialTicks) {
if (identifyMode)
return;
@ -756,23 +748,6 @@ public class PonderUI extends NavigatableSimiScreen {
@Override
public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> {
if (handled.booleanValue())
return;
if (!w.isMouseOver(x, y))
return;
if (w instanceof PonderButton) {
PonderButton mtdButton = (PonderButton) w;
mtdButton.runCallback(x, y);
handled.setTrue();
return;
}
});
if (handled.booleanValue())
return true;
if (identifyMode && hoveredBlockPos != null && PonderIndex.EDITOR_MODE) {
long handle = client.getWindow()
.getHandle();
@ -843,8 +818,8 @@ public class PonderUI extends NavigatableSimiScreen {
.getString();
return stack.getItem()
.getName()
.getString();
.getName()
.getString();
}
public FontRenderer getFontRenderer() {
@ -857,13 +832,8 @@ public class PonderUI extends NavigatableSimiScreen {
return hovered;
}
public static void renderBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted) {
renderBox(ms, x, y, w, h, 0xff000000, highlighted ? 0xf0ffeedd : 0x40ffeedd,
highlighted ? 0x60ffeedd : 0x20ffeedd);
}
public static void renderSpeechBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted,
Pointing pointing, boolean returnWithLocalTransform) {
public static void renderSpeechBox(MatrixStack ms, int x, int y, int w, int h, boolean highlighted, Pointing pointing,
boolean returnWithLocalTransform) {
if (!returnWithLocalTransform)
ms.push();
@ -875,6 +845,8 @@ public class PonderUI extends NavigatableSimiScreen {
int divotSize = 8;
int distance = 1;
int divotRadius = divotSize / 2;
Couple<Color> borderColors = Theme.p(highlighted ? Theme.Key.PONDER_HIGHLIGHT : Theme.Key.PONDER_IDLE);
Color c;
switch (pointing) {
default:
@ -884,6 +856,7 @@ public class PonderUI extends NavigatableSimiScreen {
boxY -= h + divotSize + 1 + distance;
divotX -= divotRadius;
divotY -= divotSize + distance;
c = borderColors.getSecond();
break;
case LEFT:
divotRotation = 90;
@ -891,6 +864,7 @@ public class PonderUI extends NavigatableSimiScreen {
boxY -= h / 2;
divotX += distance;
divotY -= divotRadius;
c = ColorHelper.mixColors(borderColors, 0.5f);
break;
case RIGHT:
divotRotation = 270;
@ -898,6 +872,7 @@ public class PonderUI extends NavigatableSimiScreen {
boxY -= h / 2;
divotX -= divotSize + distance;
divotY -= divotRadius;
c = ColorHelper.mixColors(borderColors, 0.5f);
break;
case UP:
divotRotation = 180;
@ -905,17 +880,23 @@ public class PonderUI extends NavigatableSimiScreen {
boxY += divotSize + 1 + distance;
divotX -= divotRadius;
divotY += distance;
c = borderColors.getFirst();
break;
}
renderBox(ms, boxX, boxY, w, h, highlighted);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(borderColors)
.at(boxX, boxY, 100)
.withBounds(w, h)
.render(ms);
ms.push();
AllGuiTextures toRender = highlighted ? AllGuiTextures.SPEECH_TOOLTIP_HIGHLIGHT : AllGuiTextures.SPEECH_TOOLTIP;
ms.translate(divotX + divotRadius, divotY + divotRadius, 10);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(divotRotation));
ms.translate(-divotRadius, -divotRadius, 0);
toRender.draw(ms, 0, 0);
AllGuiTextures.SPEECH_TOOLTIP_BACKGROUND.draw(ms, 0, 0);
AllGuiTextures.SPEECH_TOOLTIP_COLOR.draw(ms, 0, 0, c);
ms.pop();
if (returnWithLocalTransform) {
@ -927,24 +908,6 @@ public class PonderUI extends NavigatableSimiScreen {
}
public static void renderBox(MatrixStack ms, int x, int y, int w, int h, int backgroundColor, int borderColorStart,
int borderColorEnd) {
int z = 100;
Matrix4f model = ms.peek()
.getModel();
GuiUtils.drawGradientRect(model, z, x - 3, y - 4, x + w + 3, y - 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 3, y + h + 3, x + w + 3, y + h + 4, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 3, y - 3, x + w + 3, y + h + 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 4, y - 3, x - 3, y + h + 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x + w + 3, y - 3, x + w + 4, y + h + 3, backgroundColor, backgroundColor);
GuiUtils.drawGradientRect(model, z, x - 3, y - 3 + 1, x - 3 + 1, y + h + 3 - 1, borderColorStart,
borderColorEnd);
GuiUtils.drawGradientRect(model, z, x + w + 2, y - 3 + 1, x + w + 3, y + h + 3 - 1, borderColorStart,
borderColorEnd);
GuiUtils.drawGradientRect(model, z, x - 3, y - 3, x + w + 3, y - 3 + 1, borderColorStart, borderColorStart);
GuiUtils.drawGradientRect(model, z, x - 3, y + h + 2, x + w + 3, y + h + 3, borderColorEnd, borderColorEnd);
}
public ItemStack getHoveredTooltipItem() {
return hoveredTooltipItem;
}
@ -1011,4 +974,4 @@ public class PonderUI extends NavigatableSimiScreen {
AllConfigs.CLIENT.comfyReading.set(slowTextMode);
}
}
}

View File

@ -10,6 +10,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderRegistry;
@ -106,17 +107,17 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
int itemCenterY = (int) (height * itemYmult);
for (Item item : items) {
PonderButton button =
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return;
PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
.showing(new ItemStack(item))
.withCallback((x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return;
centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
}).showing(new ItemStack(item));
centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
});
button.fade(1);
widgets.add(button);
widgets.add(b);
layout.next();
}
@ -158,8 +159,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010);
textRenderer.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, 0xffddeeff);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -170,8 +171,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220, 0x101010);
textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, 0xffddeeff);
UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -189,7 +190,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.pop();
}
@Override
/*@Override
public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> {
@ -207,7 +208,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
if (handled.booleanValue())
return true;
return super.mouseClicked(x, y, button);
}
}*/
@Override
public boolean isEquivalentTo(NavigatableSimiScreen other) {

View File

@ -9,7 +9,9 @@ import org.apache.commons.lang3.mutable.MutableBoolean;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderLocalization;
@ -84,24 +86,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int itemCenterY = getItemsY();
for (Item i : items) {
final boolean canClick = PonderRegistry.all.containsKey(i.getRegistryName());
PonderButton button =
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (mouseX, mouseY) -> {
if (!canClick)
return;
PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
.showing(new ItemStack(i));
if (PonderRegistry.all.containsKey(i.getRegistryName())) {
b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag));
}).showing(new ItemStack(i));
if (!canClick)
});
} else {
if (i.getRegistryName()
.getNamespace()
.equals(Create.ID))
button.customColors(0x70984500, 0x70692400);
.getNamespace()
.equals(Create.ID))
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else
button.customColors(0x505000FF, 0x50300077);
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1);
widgets.add(button);
widgets.add(b);
layout.next();
}
@ -109,23 +113,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ResourceLocation registryName = tag.getMainItem()
.getItem()
.getRegistryName();
final boolean canClick = PonderRegistry.all.containsKey(registryName);
PonderButton button =
new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10, (mouseX, mouseY) -> {
if (!canClick)
return;
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag));
}).showing(tag.getMainItem());
if (!canClick)
PonderButton b = new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10)
.showing(tag.getMainItem());
if (PonderRegistry.all.containsKey(registryName)) {
b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag));
});
} else {
if (registryName.getNamespace()
.equals(Create.ID))
button.customColors(0x70984500, 0x70692400);
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else
button.customColors(0x505000FF, 0x50300077);
b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1);
widgets.add(button);
widgets.add(b);
}
// chapters
@ -187,15 +194,21 @@ public class PonderTagScreen extends NavigatableSimiScreen {
String title = tag.getTitle();
int streakHeight = 35;
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240, 0x101010);
PonderUI.renderBox(ms, 21, 21, 30, 30, false);
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240);
//PonderUI.renderBox(ms, 21, 21, 30, 30, false);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(21, 21, 100)
.withBounds(30, 30)
.render(ms);
textRenderer.draw(ms, Lang.translate(PonderUI.PONDERING), x, y - 6, 0xffa3a3a3);
textRenderer.draw(ms, Lang.translate(PonderUI.PONDERING), x, y - 6, Theme.i(Theme.Key.TEXT_DARKER));
y += 8;
x += 0;
ms.translate(x, y, 0);
ms.translate(0, 0, 5);
textRenderer.draw(ms, title, 0, 0, 0xeeeeee);
textRenderer.draw(ms, title, 0, 0, Theme.i(Theme.Key.TEXT));
ms.pop();
ms.push();
@ -214,9 +227,16 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int h = textRenderer.getWordWrappedHeight(desc, w);
PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false);
//PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at(x - 3, y - 3, 90)
.withBounds(w + 6, h + 6)
.render(ms);
ms.translate(0, 0, 100);
FontHelper.drawSplitString(ms, textRenderer, desc, x, y, w, 0xeeeeee);
FontHelper.drawSplitString(ms, textRenderer, desc, x, y, w, Theme.i(Theme.Key.TEXT));
ms.pop();
}
@ -232,16 +252,23 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(x, y, 0);
PonderUI.renderBox(ms, (sWidth - stringWidth) / 2 - 5, itemArea.getY() - 21, stringWidth + 10, 10, false);
//PonderUI.renderBox(ms, (sWidth - stringWidth) / 2 - 5, itemArea.getY() - 21, stringWidth + 10, 10, false);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.PONDER_IDLE))
.at((sWidth - stringWidth) / 2f - 5, itemArea.getY() - 21, 100)
.withBounds(stringWidth + 10, 10)
.render(ms);
ms.translate(0, 0, 200);
// UIRenderHelper.streak(0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 180, 0x101010);
drawCenteredString(ms, textRenderer, relatedTitle, sWidth / 2, itemArea.getY() - 20, 0xeeeeee);
drawCenteredString(ms, textRenderer, relatedTitle, sWidth / 2, itemArea.getY() - 20, Theme.i(Theme.Key.TEXT));
ms.translate(0,0, -200);
UIRenderHelper.streak(ms, 0, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75, 0x101010);
UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75, 0x101010);
UIRenderHelper.streak(ms, 0, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75);
UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75);
ms.pop();
@ -261,8 +288,8 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push();
ms.translate(chapterX, chapterY, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010);
textRenderer.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, 0xffddeeff);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
ms.pop();
}
@ -291,7 +318,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
return hoveredItem;
}
@Override
/*@Override
public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> {
@ -310,7 +337,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
if (handled.booleanValue())
return true;
return super.mouseClicked(x, y, button);
}
}*/
@Override
public boolean isEquivalentTo(NavigatableSimiScreen other) {

View File

@ -136,7 +136,7 @@ public class InputWindowElement extends AnimatedOverlayElement {
if (hasItem) {
GuiGameElement.of(item)
.at(keyWidth + (hasIcon ? 24 : 0), 0)
.<GuiGameElement.GuiRenderBuilder>at(keyWidth + (hasIcon ? 24 : 0), 0)
.scale(1.5)
.render(ms);
RenderSystem.disableDepthTest();

View File

@ -4,6 +4,8 @@ import java.util.List;
import java.util.function.Supplier;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.BoxElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.ponder.PonderLocalization;
import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.PonderUI;
@ -110,7 +112,14 @@ public class TextWindowElement extends AnimatedOverlayElement {
ms.push();
ms.translate(0, sceneToScreen.y, 400);
PonderUI.renderBox(ms, targetX - 10, 3, boxWidth, boxHeight - 1, 0xaa000000, 0x30eebb00, 0x10eebb00);
new BoxElement()
.withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT))
.gradientBorder(Theme.p(Theme.Key.TEXT_WINDOW_BORDER))
.at(targetX - 10, 3, 100)
.withBounds(boxWidth, boxHeight - 1)
.render(ms);
//PonderUI.renderBox(ms, targetX - 10, 3, boxWidth, boxHeight - 1, 0xaa000000, 0x30eebb00, 0x10eebb00);
int brighterColor = ColorHelper.mixAlphaColors(color, 0xFFffffdd, 1 / 2f);
if (vec != null) {

View File

@ -5,6 +5,7 @@ import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.ponder.content.PonderChapter;
@ -20,17 +21,18 @@ public class ChapterLabel extends AbstractSimiWidget {
public ChapterLabel(PonderChapter chapter, int x, int y, BiConsumer<Integer, Integer> onClick) {
super(x, y, 175, 38);
this.button = new PonderButton(x + 4, y + 4, onClick, 30, 30).showing(chapter);
this.button.fade(1);
this.button = new PonderButton(x + 4, y + 4, 30, 30)
.showing(chapter)
.withCallback(onClick);
this.chapter = chapter;
}
@Override
public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 2, width, 0x101010);
UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 2, width);
Minecraft.getInstance().fontRenderer.draw(ms, Lang.translate("ponder.chapter." + chapter.getId()), x + 50,
y + 20, 0xffddeeff);
y + 20, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
button.renderButton(ms, mouseX, mouseY, partialTicks);
super.render(ms, mouseX, mouseY, partialTicks);

View File

@ -1,175 +1,105 @@
package com.simibubi.create.foundation.ponder.ui;
import java.util.function.BiConsumer;
import java.awt.Color;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.ponder.PonderUI;
import com.simibubi.create.foundation.gui.RenderElement;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.widgets.BoxWidget;
import com.simibubi.create.foundation.gui.widgets.ElementWidget;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
public class PonderButton extends AbstractSimiWidget {
public class PonderButton extends BoxWidget {
private IScreenRenderable icon;
private ItemStack item;
protected boolean pressed;
private BiConsumer<Integer, Integer> onClick;
private int xFadeModifier;
private int yFadeModifier;
private float fade;
private KeyBinding shortcut;
private LerpedFloat flash;
private Couple<Integer> customPassiveBorder;
protected ItemStack item;
protected KeyBinding shortcut;
protected LerpedFloat flash = LerpedFloat.linear().startWithValue(0).chase(0, 0.1f, LerpedFloat.Chaser.EXP);
public static final int SIZE = 20;
public PonderButton(int x, int y) {
this(x, y, 20, 20);
}
public PonderButton(int x, int y, BiConsumer<Integer, Integer> onClick, int width, int height) {
public PonderButton(int x, int y, int width, int height) {
super(x, y, width, height);
this.onClick = onClick;
flash = LerpedFloat.linear()
.startWithValue(0);
z = 400;
paddingX = 2;
paddingY = 2;
}
public PonderButton(int x, int y, BiConsumer<Integer, Integer> onClick) {
this(x, y, onClick, SIZE, SIZE);
}
public PonderButton(int x, int y, Runnable onClick) {
this(x, y, ($, $$) -> onClick.run());
}
public PonderButton showing(IScreenRenderable icon) {
this.icon = icon;
return this;
}
public PonderButton showing(ItemStack item) {
this.item = item;
return this;
}
public PonderButton customColors(int start, int end) {
this.customPassiveBorder = Couple.create(start, end);
return this;
}
public PonderButton shortcut(KeyBinding key) {
public <T extends PonderButton> T withShortcut(KeyBinding key) {
this.shortcut = key;
return this;
//noinspection unchecked
return (T) this;
}
public PonderButton fade(int xModifier, int yModifier) {
this.xFadeModifier = xModifier;
this.yFadeModifier = yModifier;
return this;
public <T extends PonderButton> T showing(ItemStack item) {
this.item = item;
return super.showingElement(GuiGameElement.of(item)
.scale(1.5f)
.at(-4, -4));
}
public void fade(float fade) {
this.fade = fade;
@Override
public <T extends ElementWidget> T showingElement(RenderElement element) {
return super.showingElement(element);
}
public void flash() {
float value = flash.getValue();
flash.setValue(value + (1 - value) * .2f);
flash.updateChaseTarget(1);
}
public void dim() {
float value = flash.getValue();
flash.setValue(value * .5f);
flash.updateChaseTarget(0);
}
@Override
public void renderButton(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
if (!visible)
return;
if (fade < .1f)
return;
public void tick() {
super.tick();
flash.tickChaser();
}
hovered = isMouseOver(mouseX, mouseY) && fade > .75f;
ms.push();
RenderSystem.disableDepthTest();
if (fade < 1)
ms.translate((1 - fade) * -5 * xFadeModifier, (1 - fade) * -5 * yFadeModifier, 0);
@Override
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.beforeRender(ms, mouseX, mouseY, partialTicks);
float flashValue = flash.getValue(partialTicks);
if (flashValue > .1f)
fade *= 3 * flashValue + Math.sin((PonderUI.ponderTicks + partialTicks) / 6);
int backgroundColor = ColorHelper.applyAlpha(0xdd000000, fade);
int borderColorStart = customPassiveBorder != null ? customPassiveBorder.getFirst() : hovered ? 0x70ffffff : 0x40aa9999;
int borderColorEnd = customPassiveBorder != null ? customPassiveBorder.getSecond() : hovered ? 0x30ffffff : 0x20aa9999;
borderColorStart = ColorHelper.applyAlpha(borderColorStart, fade);
borderColorEnd = ColorHelper.applyAlpha(borderColorEnd, fade);
ms.translate(0, 0, 400);
PonderUI.renderBox(ms, x, y, width, height, backgroundColor, borderColorStart, borderColorEnd);
ms.translate(0, 0, 100);
if (icon != null) {
RenderSystem.enableBlend();
RenderSystem.color4f(1, 1, 1, fade);
ms.push();
ms.translate(x + 2, y + 2, 0);
ms.scale((width - 4) / 16f, (height - 4) / 16f, 1);
icon.draw(ms, this, 0, 0);
ms.pop();
if (flashValue > .1f) {
float sin = 0.5f + 0.5f * MathHelper.sin((AnimationTickHolder.getTicks(true) + partialTicks) / 6f);
sin *= flashValue;
Color c1 = gradientColor1;
Color c2 = gradientColor2;
Color nc1 = new Color(c1.getRed(), c1.getGreen(), c1.getBlue(), MathHelper.clamp(c1.getAlpha() + 50, 0, 255));
Color nc2 = new Color(c2.getRed(), c2.getGreen(), c2.getBlue(), MathHelper.clamp(c2.getAlpha() + 50, 0, 255));
gradientColor1 = ColorHelper.mixColors(c1, nc1, sin);
gradientColor2 = ColorHelper.mixColors(c2, nc2, sin);
}
if (item != null) {
ms.push();
ms.translate(0, 0, -100);
GuiGameElement.of(item)
.at(x - 2, y - 2)
.scale(1.5f)
.render(ms);
ms.pop();
}
if (shortcut != null)
drawCenteredText(ms, Minecraft.getInstance().fontRenderer, shortcut.getBoundKeyLocalizedText(), x + width / 2 + 8,
y + height - 6, ColorHelper.applyAlpha(0xff606060, fade));
ms.pop();
}
public void runCallback(double mouseX, double mouseY) {
onClick.accept((int) mouseX, (int) mouseY);
}
@Override
public void onClick(double p_onClick_1_, double p_onClick_3_) {
super.onClick(p_onClick_1_, p_onClick_3_);
this.pressed = true;
}
public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.renderButton(ms, mouseX, mouseY, partialTicks);
float fadeValue = fade.getValue();
@Override
public void onRelease(double p_onRelease_1_, double p_onRelease_3_) {
super.onRelease(p_onRelease_1_, p_onRelease_3_);
this.pressed = false;
}
if (fadeValue < .1f)
return;
/*public void setToolTip(String text) {
toolTip.clear();
toolTip.add(text);
}*/
if (shortcut != null) {
ms.translate(0, 0, z+50);
drawCenteredText(ms, Minecraft.getInstance().fontRenderer, shortcut.getBoundKeyLocalizedText(), x + width / 2 + 8, y + height - 6, ColorHelper.applyAlpha(Theme.i(Theme.Key.TEXT_DARKER), fadeValue));
}
}
public ItemStack getItem() {
return item;
}
@Override
public boolean isMouseOver(double x, double y) {
double m = 4;
x = Math.floor(x);
y = Math.floor(y);
return active && visible
&& !(x < this.x - m || x > this.x + width + m - 1 || y < this.y - m || y > this.y + height + m - 1);
}
}

View File

@ -10,20 +10,28 @@ import net.minecraft.world.IWorld;
public class AnimationTickHolder {
private static int ticks;
private static int paused_ticks;
public static void reset() {
ticks = 0;
paused_ticks = 0;
}
public static void tick() {
if (!Minecraft.getInstance()
.isGamePaused()) {
ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision
} else {
paused_ticks = (paused_ticks + 1) % 1_728_000;
}
}
public static int getTicks() {
return ticks;
return getTicks(false);
}
public static int getTicks(boolean includePaused) {
return includePaused ? ticks + paused_ticks : ticks;
}
public static float getRenderTime() {

View File

@ -1,7 +1,10 @@
package com.simibubi.create.foundation.utility;
import java.awt.Color;
import java.util.UUID;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.math.MathHelper;
@ -39,6 +42,10 @@ public class ColorHelper {
return (color & 0xFFFFFF) | alphaChannel << 24;
}
public static Color applyAlpha(Color c, float alpha) {
return new Color(applyAlpha(c.getRGB(), alpha), true);
}
public static int mixColors(int color1, int color2, float w) {
int r1 = (color1 >> 16);
int g1 = (color1 >> 8) & 0xFF;
@ -52,6 +59,23 @@ public class ColorHelper {
return color;
}
@Nonnull
public static Color mixColors(@Nonnull Color c1, @Nonnull Color c2, float w) {
float[] cmp1 = c1.getRGBComponents(null);
float[] cmp2 = c2.getRGBComponents(null);
return new Color(
cmp1[0] + (cmp2[0] - cmp1[0]) * w,
cmp1[1] + (cmp2[1] - cmp1[1]) * w,
cmp1[2] + (cmp2[2] - cmp1[2]) * w,
cmp1[3] + (cmp2[3] - cmp1[3]) * w
);
}
@Nonnull
public static Color mixColors(@Nonnull Couple<Color> colors, float w) {
return mixColors(colors.getFirst(), colors.getSecond(), w);
}
public static int mixAlphaColors(int color1, int color2, float w) {
int a1 = (color1 >> 24);
int r1 = (color1 >> 16) & 0xFF;

Some files were not shown because too many files have changed in this diff Show More