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] [*.java]
indent_style = tab indent_style = tab
ij_continuation_indent_size = 8
ij_java_class_count_to_use_import_on_demand = 99 ij_java_class_count_to_use_import_on_demand = 99
ij_java_names_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 e5e3757e99c139d67b2a70288466d8a74d818841 assets/create/blockstates/cogwheel.json
36f54136a7756c97f71bc6b47ef4e8e575e72879 assets/create/blockstates/content_observer.json 36f54136a7756c97f71bc6b47ef4e8e575e72879 assets/create/blockstates/content_observer.json
cfea7283f0ebd2432d67e80a523f2a12e24c0bd5 assets/create/blockstates/controller_rail.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 f8eff64c75fc599e9a44a003f54ae9931cd8ce7c assets/create/blockstates/copper_block.json
cabf6b8c59eb0e3d56a0a5a856ca058bb3200882 assets/create/blockstates/copper_casing.json cabf6b8c59eb0e3d56a0a5a856ca058bb3200882 assets/create/blockstates/copper_casing.json
3355a852cdc717e257ca19b3db836068964733e3 assets/create/blockstates/copper_ore.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 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
a6d814f94926d88764c38862cc4ece9c367e023b assets/create/lang/en_ud.json a6d814f94926d88764c38862cc4ece9c367e023b assets/create/lang/en_ud.json
80e3112fe5ab12a9bbe7c272ab50904eee351f44 assets/create/lang/en_us.json 95f238e0df097f74a7845a58a02d27c3989305ce assets/create/lang/en_us.json
9b8c1f501cb57098f3ac67c8fd4532246a0c59bb assets/create/lang/unfinished/de_de.json e03638c344f9f80f5cee92c5e4ce4986478e65a5 assets/create/lang/unfinished/de_de.json
9d0482aa7a410bdb9b44bb7c1e24bda0343e1306 assets/create/lang/unfinished/es_es.json dae908c13b54fa5123bad98dd38ba35d58edaaf0 assets/create/lang/unfinished/es_es.json
6e401a93ef63da54673d125892893468f04931be assets/create/lang/unfinished/es_mx.json bf9142028bbd21a4441381c06c3b4557e60e49c5 assets/create/lang/unfinished/es_mx.json
466fe4336c8c45fab9027e18103f8c7ef5c94fef assets/create/lang/unfinished/fr_fr.json e4f70996f672bc50e8cfeaccd150075c0a07a917 assets/create/lang/unfinished/fr_fr.json
62d87f787237fbf2ace70eafb536cf5283c4dd16 assets/create/lang/unfinished/it_it.json 34c1226afddeaf7824fc1aaf65f40505b3811a91 assets/create/lang/unfinished/it_it.json
e83d8ed48ebf35ce6ba3fac10efff80ce9ffc050 assets/create/lang/unfinished/ja_jp.json 17a4ed49d461a537ca8e59fc95d12909780105d7 assets/create/lang/unfinished/ja_jp.json
448bdf719bd40bb4cb8f013d29e1c65c1277f4ff assets/create/lang/unfinished/ko_kr.json dd1e77bf533b4bf0e7fa358d48ce5643d08b21c3 assets/create/lang/unfinished/ko_kr.json
a4229b2f23223f31a1b869d5a07ff61128ddd2e8 assets/create/lang/unfinished/nl_nl.json 0faf1940b7c9664be63d02b3685ed0252528a9ce assets/create/lang/unfinished/nl_nl.json
9d1594172ba55eab5b96bd48f5204b082493e5e8 assets/create/lang/unfinished/pl_pl.json 996e1392e3ffcdb6d41a66cf6bd752e301c52b12 assets/create/lang/unfinished/pl_pl.json
ba271a34ebf9c23c239fcdf94d71623bfcaaefb1 assets/create/lang/unfinished/pt_br.json 49e35e88d59fb49cb1889e960a18371d0616b963 assets/create/lang/unfinished/pt_br.json
0c78fdaa30db8d54122bb055167ee41e4d1e010c assets/create/lang/unfinished/ru_ru.json af5ee82802fc0e42012c575cd9da1cf36b88b035 assets/create/lang/unfinished/ru_ru.json
899752fff0af288e71fb1f7c771910395c701477 assets/create/lang/unfinished/zh_cn.json 63db3153b522775cad4f91eb509e14568bfb0c3c assets/create/lang/unfinished/zh_cn.json
a7189982351b90b3cde43529a0fbdef696bda22e assets/create/lang/unfinished/zh_tw.json f533c7c7c1cc2b11908377bd807ff006902d5e34 assets/create/lang/unfinished/zh_tw.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.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 866fbb0ce2878a73e0440d1caf6534c8bd7c384f assets/create/models/item/zinc_ingot.json
a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json
b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json
7b73f40a65af0c2288c886928c609ec783c0fc40 assets/create/sounds.json 3fd540489a0038a78c6b02f81e89d95e53596b2b assets/create/sounds.json
0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json 5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json
187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json 187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json
0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json 0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json
83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json 83c046bd200623933545c9e4326f782fb02c87fa data/create/advancements/arm_blaze_burner.json

View file

@ -1,17 +1,32 @@
{ {
"variants": { "variants": {
"facing=north": { "facing=north,waterlogged=false": {
"model": "create:block/copper_backtank/block" "model": "create:block/copper_backtank/block"
}, },
"facing=south": { "facing=south,waterlogged=false": {
"model": "create:block/copper_backtank/block", "model": "create:block/copper_backtank/block",
"y": 180 "y": 180
}, },
"facing=west": { "facing=west,waterlogged=false": {
"model": "create:block/copper_backtank/block", "model": "create:block/copper_backtank/block",
"y": 270 "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", "model": "create:block/copper_backtank/block",
"y": 90 "y": 90
} }

View file

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

View file

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

View file

@ -1,5 +1,5 @@
{ {
"_": "Missing Localizations: 640", "_": "Missing Localizations: 641",
"_": "->------------------------] Game Elements [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "Blaze mastica felizmente", "create.subtitle.blaze_munch": "Blaze mastica felizmente",
"create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon", "create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", "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.schematicannon_finish": "Acabados de Schematicannon",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "La Prensa Mecánica se activa", "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 [------------------------<-", "_": "->------------------------] Game Elements [------------------------<-",
@ -1147,6 +1147,7 @@
"create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches",
"create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires", "create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires",
"create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", "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.schematicannon_finish": "UNLOCALIZED: Schematicannon dings",
"create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks",
"create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs", "create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -49,6 +49,15 @@
], ],
"subtitle": "create.subtitle.contraption_disassemble" "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": { "crafter_click": {
"sounds": [ "sounds": [
{ {

View file

@ -28,8 +28,8 @@
"trigger": "create:bracket_apply", "trigger": "create:bracket_apply",
"conditions": { "conditions": {
"accepted_entries": [ "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"), EJECTOR_TOP = get("weighted_ejector/top"),
COPPER_BACKTANK_SHAFT = get("copper_backtank/block_shaft_input"), COPPER_BACKTANK_SHAFT = get("copper_backtank/block_shaft_input"),
COPPER_BACKTANK_COGS = get("copper_backtank/block_cogs"),
COUPLING_ATTACHMENT = getEntity("minecart_coupling/attachment"), COUPLING_ATTACHMENT = getEntity("minecart_coupling/attachment"),
COUPLING_RING = getEntity("minecart_coupling/ring"), COUPLING_RING = getEntity("minecart_coupling/ring"),

View file

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

View file

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

View file

@ -148,6 +148,11 @@ public class AllSoundEvents {
.category(SoundCategory.BLOCKS) .category(SoundCategory.BLOCKS)
.build(), .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") BLAZE_MUNCH = create("blaze_munch").subtitle("Blaze Burner munches")
.playExisting(SoundEvents.ENTITY_GENERIC_EAT, .5f, 1f) .playExisting(SoundEvents.ENTITY_GENERIC_EAT, .5f, 1f)
.category(SoundCategory.BLOCKS) .category(SoundCategory.BLOCKS)
@ -163,6 +168,11 @@ public class AllSoundEvents {
entry.register(registry); entry.register(registry);
} }
public static void prepare() {
for (SoundEntry entry : entries.values())
entry.prepare();
}
public static JsonElement provideLangEntries() { public static JsonElement provideLangEntries() {
JsonObject object = new JsonObject(); JsonObject object = new JsonObject();
for (SoundEntry entry : entries.values()) for (SoundEntry entry : entries.values())
@ -278,6 +288,8 @@ public class AllSoundEvents {
this.category = category; this.category = category;
} }
public abstract void prepare();
public abstract void register(IForgeRegistry<SoundEvent> registry); public abstract void register(IForgeRegistry<SoundEvent> registry);
public abstract void write(JsonObject json); public abstract void write(JsonObject json);
@ -348,16 +360,21 @@ public class AllSoundEvents {
} }
@Override @Override
public void register(IForgeRegistry<SoundEvent> registry) { public void prepare() {
for (int i = 0; i < wrappedEvents.size(); i++) { for (int i = 0; i < wrappedEvents.size(); i++) {
ResourceLocation location = Create.asResource(getIdOf(i)); ResourceLocation location = Create.asResource(getIdOf(i));
SoundEvent sound = new SoundEvent(location).setRegistryName(location); SoundEvent sound = new SoundEvent(location).setRegistryName(location);
registry.register(sound);
compiledEvents.add(Pair.of(sound, wrappedEvents.get(i) compiledEvents.add(Pair.of(sound, wrappedEvents.get(i)
.getSecond())); .getSecond()));
} }
} }
@Override
public void register(IForgeRegistry<SoundEvent> registry) {
for (Pair<SoundEvent, Couple<Float>> pair : compiledEvents)
registry.register(pair.getFirst());
}
@Override @Override
public SoundEvent getMainEvent() { public SoundEvent getMainEvent() {
return compiledEvents.get(0) return compiledEvents.get(0)
@ -415,9 +432,14 @@ public class AllSoundEvents {
} }
@Override @Override
public void register(IForgeRegistry<SoundEvent> registry) { public void prepare() {
ResourceLocation location = getLocation(); ResourceLocation location = getLocation();
registry.register(event = new SoundEvent(location).setRegistryName(location)); event = new SoundEvent(location).setRegistryName(location);
}
@Override
public void register(IForgeRegistry<SoundEvent> registry) {
registry.register(event);
} }
@Override @Override

View file

@ -78,6 +78,7 @@ public class Create {
IEventBus modEventBus = FMLJavaModLoadingContext.get() IEventBus modEventBus = FMLJavaModLoadingContext.get()
.getModEventBus(); .getModEventBus();
AllSoundEvents.prepare();
AllBlocks.register(); AllBlocks.register();
AllItems.register(); AllItems.register();
AllFluids.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.ClientSchematicLoader;
import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler; import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler;
import com.simibubi.create.content.schematics.client.SchematicHandler; 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.ResourceReloadHandler;
import com.simibubi.create.foundation.block.render.CustomBlockModels; import com.simibubi.create.foundation.block.render.CustomBlockModels;
import com.simibubi.create.foundation.block.render.SpriteShifter; import com.simibubi.create.foundation.block.render.SpriteShifter;
@ -82,6 +83,7 @@ public class CreateClient {
modEventBus.addListener(CreateClient::onModelRegistry); modEventBus.addListener(CreateClient::onModelRegistry);
modEventBus.addListener(CreateClient::onTextureStitch); modEventBus.addListener(CreateClient::onTextureStitch);
modEventBus.addListener(AllParticleTypes::registerFactories); modEventBus.addListener(AllParticleTypes::registerFactories);
modEventBus.addListener(ClientEvents::loadCompleted);
Backend.init(); Backend.init();
OptifineHandler.init(); OptifineHandler.init();
@ -112,6 +114,7 @@ public class CreateClient {
PonderIndex.registerTags(); PonderIndex.registerTags();
UIRenderHelper.init(); UIRenderHelper.init();
UIRenderHelper.enableStencil();
IResourceManager resourceManager = Minecraft.getInstance() IResourceManager resourceManager = Minecraft.getInstance()
.getResourceManager(); .getResourceManager();

View file

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

View file

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

View file

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

View file

@ -41,7 +41,7 @@ public class CogwheelBlockItem extends BlockItem {
large = block.isLarge; large = block.isLarge;
placementHelperId = PlacementHelpers.register(large ? new LargeCogHelper() : new SmallCogHelper()); placementHelperId = PlacementHelpers.register(large ? new LargeCogHelper() : new SmallCogHelper());
integratedCogHelperId = large ? PlacementHelpers.register(new IntegratedCogHelper()) : -1; integratedCogHelperId = PlacementHelpers.register(large ? new IntegratedLargeCogHelper() : new IntegratedSmallCogHelper());
} }
@Override @Override
@ -231,7 +231,7 @@ public class CogwheelBlockItem extends BlockItem {
} }
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
public static class IntegratedCogHelper implements IPlacementHelper { public static class IntegratedLargeCogHelper implements IPlacementHelper {
@Override @Override
public Predicate<ItemStack> getItemPredicate() { public Predicate<ItemStack> getItemPredicate() {
@ -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.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;

View file

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

View file

@ -1,13 +1,20 @@
package com.simibubi.create.content.curiosities.armor; package com.simibubi.create.content.curiosities.armor;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.render.SuperByteBuffer; 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.block.BlockState;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.IRenderTypeBuffer.Impl; import net.minecraft.client.renderer.IRenderTypeBuffer.Impl;
import net.minecraft.client.renderer.RenderType; 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.client.renderer.entity.model.EntityModel;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.Pose; import net.minecraft.entity.Pose;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Direction; 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> { 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; BipedModel<?> model = (BipedModel<?>) entityModel;
BlockState renderedState = AllBlocks.COPPER_BACKTANK.getDefaultState() BlockState renderedState = AllBlocks.COPPER_BACKTANK.getDefaultState()
.with(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); .with(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH);
RenderType renderType = RenderType.getSolid(); RenderType renderType = RenderType.getCutout();
SuperByteBuffer backtank = CreateClient.bufferCache.renderBlock(renderedState); SuperByteBuffer backtank = CreateClient.bufferCache.renderBlock(renderedState);
SuperByteBuffer cogs =
CreateClient.bufferCache.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, renderedState);
model.bipedBody.rotate(ms); model.bipedBody.rotate(ms);
ms.translate(-1 / 2f, 10 / 16f, 1f); ms.translate(-1 / 2f, 10 / 16f, 1f);
ms.scale(1, -1, -1); ms.scale(1, -1, -1);
backtank.light(light) backtank.light(light)
.renderInto(ms, buffer.getBuffer(renderType)); .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) if (buffer instanceof Impl)
((Impl) buffer).draw(renderType); ((Impl) buffer).draw(renderType);
ms.pop(); ms.pop();
@ -78,4 +103,39 @@ public class CopperBacktankArmorLayer<T extends LivingEntity, M extends EntityMo
new CopperBacktankArmorLayer<>((LivingRenderer<?, ?>) entityRenderer); 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.content.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ITE;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.FluidState;
import net.minecraft.fluid.Fluids;
import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; 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.tileentity.TileEntity;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand; 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.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.FakePlayer; 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) { public CopperBacktankBlock(Properties properties) {
super(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 @Override
@ -63,14 +106,20 @@ public class CopperBacktankBlock extends HorizontalKineticBlock implements ITE<C
@Override @Override
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_, public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand p_225533_5_,
BlockRayTraceResult p_225533_6_) { BlockRayTraceResult p_225533_6_) {
if (player == null)
return ActionResultType.PASS;
if (player instanceof FakePlayer) if (player instanceof FakePlayer)
return ActionResultType.PASS; return ActionResultType.PASS;
if (player.getHeldItemMainhand().getItem() instanceof BlockItem) if (player.isSneaking())
return ActionResultType.PASS;
if (player.getHeldItemMainhand()
.getItem() instanceof BlockItem)
return ActionResultType.PASS; return ActionResultType.PASS;
if (!player.getItemStackFromSlot(EquipmentSlotType.CHEST) if (!player.getItemStackFromSlot(EquipmentSlotType.CHEST)
.isEmpty()) .isEmpty())
return ActionResultType.PASS; return ActionResultType.PASS;
if (!world.isRemote) { if (!world.isRemote) {
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, .75f, 1);
player.setItemStackToSlot(EquipmentSlotType.CHEST, getItem(world, pos, state)); player.setItemStackToSlot(EquipmentSlotType.CHEST, getItem(world, pos, state));
world.destroyBlock(pos, false); world.destroyBlock(pos, false);
} }
@ -108,4 +157,9 @@ public class CopperBacktankBlock extends HorizontalKineticBlock implements ITE<C
return CopperBacktankTileEntity.class; 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; package com.simibubi.create.content.curiosities.armor;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials; 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.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.PartialBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer; 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.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.util.Direction;
public class CopperBacktankRenderer extends KineticTileEntityRenderer { public class CopperBacktankRenderer extends KineticTileEntityRenderer {
@ -14,6 +21,26 @@ public class CopperBacktankRenderer extends KineticTileEntityRenderer {
super(dispatcher); 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 @Override
protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { protected SuperByteBuffer getRotatedModel(KineticTileEntity te) {
return PartialBufferer.get(AllBlockPartials.COPPER_BACKTANK_SHAFT, te.getBlockState()); return PartialBufferer.get(AllBlockPartials.COPPER_BACKTANK_SHAFT, te.getBlockState());

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.curiosities.armor; package com.simibubi.create.content.curiosities.armor;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.particle.AirParticleData; 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.nbt.CompoundNBT;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.INameable; import net.minecraft.util.INameable;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
@ -37,16 +39,12 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
return; return;
} }
Integer max = AllConfigs.SERVER.curiosities.maxAirInBacktank.get(); int max = getMaxAir();
if (world.isRemote) { if (world.isRemote) {
Vector3d centerOf = VecHelper.getCenterOf(pos); Vector3d centerOf = VecHelper.getCenterOf(pos);
Vector3d v = VecHelper.offsetRandomly(centerOf, Create.random, .65f); Vector3d v = VecHelper.offsetRandomly(centerOf, Create.random, .65f);
Vector3d m = centerOf.subtract(v); Vector3d m = centerOf.subtract(v);
if (airLevel == max) { if (airLevel != max)
if (Create.random.nextFloat() < 1 / 8f) {
world.addParticle(ParticleTypes.HAPPY_VILLAGER, v.x, v.y, v.z, 0, 0, 0);
}
} else
world.addParticle(new AirParticleData(1, .05f), v.x, v.y, v.z, m.x, m.y, m.z); world.addParticle(new AirParticleData(1, .05f), v.x, v.y, v.z, m.x, m.y, m.z);
return; return;
} }
@ -62,6 +60,10 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
airLevelTimer = MathHelper.clamp((int) (128f - abs / 5f) - 108, 0, 20); airLevelTimer = MathHelper.clamp((int) (128f - abs / 5f) - 108, 0, 20);
} }
protected int getMaxAir() {
return AllConfigs.SERVER.curiosities.maxAirInBacktank.get();
}
public int getAirLevel() { public int getAirLevel() {
return airLevel; return airLevel;
} }
@ -91,10 +93,26 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
@Override @Override
protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) {
super.fromTag(state, compound, clientPacket); super.fromTag(state, compound, clientPacket);
int prev = airLevel;
airLevel = compound.getInt("Air"); airLevel = compound.getInt("Air");
airLevelTimer = compound.getInt("Timer"); airLevelTimer = compound.getInt("Timer");
if (compound.contains("CustomName", 8)) if (compound.contains("CustomName", 8))
this.customName = ITextComponent.Serializer.fromJson(compound.getString("CustomName")); 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 @Override
@ -104,4 +122,9 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName
.getTranslationKey()); .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.nbt.CompoundNBT;
import net.minecraft.potion.EffectInstance; import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects; import net.minecraft.potion.Effects;
import net.minecraft.world.World;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@ -22,11 +23,13 @@ public class DivingHelmetItem extends CopperArmorItem {
@SubscribeEvent @SubscribeEvent
public static void breatheUnderwater(LivingUpdateEvent event) { public static void breatheUnderwater(LivingUpdateEvent event) {
LivingEntity entity = event.getEntityLiving(); 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; boolean drowning = entity.getAir() == 0;
if (!second && !drowning) if (world.isRemote)
return; entity.getPersistentData()
.remove("VisualBacktankAir");
if (!AllItems.DIVING_HELMET.get() if (!AllItems.DIVING_HELMET.get()
.isWornBy(entity)) .isWornBy(entity))
@ -52,6 +55,11 @@ public class DivingHelmetItem extends CopperArmorItem {
if (drowning) if (drowning)
entity.setAir(10); entity.setAir(10);
if (world.isRemote)
entity.getPersistentData()
.putInt("VisualBacktankAir", airRemaining);
if (!second) if (!second)
return; return;

View file

@ -121,9 +121,9 @@ public class SymmetryWandScreen extends AbstractSimiScreen {
textRenderer.draw(matrixStack, wand.getDisplayName(), guiLeft + 11, guiTop + 4, 0x6B3802); textRenderer.draw(matrixStack, wand.getDisplayName(), guiLeft + 11, guiTop + 4, 0x6B3802);
renderBlock(matrixStack); renderBlock(matrixStack);
GuiGameElement.of(wand) GuiGameElement.of(wand)
.at(guiLeft + 170, guiTop + 490, -150)
.scale(4) .scale(4)
.rotate(-70, 20, 20) .rotate(-70, 20, 20)
.at(guiLeft + 170, guiTop + 490, -150)
.render(matrixStack); .render(matrixStack);
} }

View file

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

View file

@ -97,7 +97,7 @@ public class AdjustableCrateScreen extends AbstractSimiContainerScreen<Adjustabl
} }
GuiGameElement.of(renderedItem) 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) .scale(5)
.render(matrixStack); .render(matrixStack);
} }

View file

@ -126,7 +126,7 @@ public class StockpileSwitchScreen extends AbstractSimiScreen {
matrixStack.push(); matrixStack.push();
GuiGameElement.of(renderedItem) GuiGameElement.of(renderedItem)
.at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250) .<GuiGameElement.GuiRenderBuilder>at(guiLeft + STOCKSWITCH.width + 15, guiTop + 40, -250)
.scale(5) .scale(5)
.render(matrixStack); .render(matrixStack);
matrixStack.pop(); 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); textRenderer.draw(ms, I18n.format(container.filterItem.getTranslationKey()), x + 15, y + 3, 0xdedede);
GuiGameElement.of(container.filterItem) GuiGameElement.of(container.filterItem)
.at(x + background.width, guiTop + background.height - 60) .<GuiGameElement.GuiRenderBuilder>at(x + background.width, guiTop + background.height - 60)
.scale(5) .scale(5)
.render(ms); .render(ms);

View file

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

View file

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

View file

@ -152,7 +152,7 @@ public class SchematicEditScreen extends AbstractSimiScreen {
x + 93 - textRenderer.getStringWidth(handler.getCurrentSchematicName()) / 2, y + 3, 0xffffff); x + 93 - textRenderer.getStringWidth(handler.getCurrentSchematicName()) / 2, y + 3, 0xffffff);
GuiGameElement.of(AllItems.SCHEMATIC.asStack()) GuiGameElement.of(AllItems.SCHEMATIC.asStack())
.at(guiLeft + 200, guiTop + 82, 0) .<GuiGameElement.GuiRenderBuilder>at(guiLeft + 200, guiTop + 82, 0)
.scale(3) .scale(3)
.render(matrixStack); .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.components.turntable.TurntableHandler;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler; 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.tools.ExtendoGripRenderHandler;
import com.simibubi.create.content.curiosities.zapper.ZapperItem; import com.simibubi.create.content.curiosities.zapper.ZapperItem;
import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler; 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.depot.EjectorTargetHandler;
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler;
import com.simibubi.create.foundation.config.AllConfigs; 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.fluid.FluidHelper;
import com.simibubi.create.foundation.item.ItemDescription; import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.item.TooltipHelper; 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.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.IRenderTypeBuffer.Impl;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.fluid.Fluid; 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.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; 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.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public class ClientEvents { public class ClientEvents {
@ -195,12 +202,20 @@ public class ClientEvents {
@SubscribeEvent @SubscribeEvent
public static void onRenderOverlay(RenderGameOverlayEvent.Post event) { 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) if (event.getType() != ElementType.HOTBAR)
return; return;
onRenderHotbar(event.getMatrixStack(), Minecraft.getInstance() onRenderHotbar(ms, buffers, light, overlay, pt);
.getBufferBuilders()
.getEntityVertexConsumers(), 0xF000F0, OverlayTexture.DEFAULT_UV, event.getPartialTicks());
} }
public static void onRenderHotbar(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, 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

@ -30,11 +30,13 @@ public class AllCommands {
.then(FixLightingCommand.register()) .then(FixLightingCommand.register())
.then(HighlightCommand.register()) .then(HighlightCommand.register())
.then(CouplingCommand.register()) .then(CouplingCommand.register())
.then(CloneCommand.register()) .then(ConfigCommand.register())
.then(PonderCommand.register()) .then(PonderCommand.register())
.then(CloneCommand.register())
// utility // utility
.then(util)); .then(util)
);
createRoot.addChild(buildRedirect("u", util)); createRoot.addChild(buildRedirect("u", util));
@ -54,7 +56,7 @@ public class AllCommands {
.then(ClearBufferCacheCommand.register()) .then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register()) .then(ChunkUtilCommand.register())
.then(FlySpeedCommand.register()) .then(FlySpeedCommand.register())
// .then(KillTPSCommand.register()) //.then(KillTPSCommand.register())
.build(); .build();
} }
@ -72,12 +74,12 @@ public class AllCommands {
* *
* @return the built node * @return the built node
*/ */
public static LiteralCommandNode<CommandSource> buildRedirect(final String alias, public static LiteralCommandNode<CommandSource> buildRedirect(final String alias, final LiteralCommandNode<CommandSource> destination) {
final LiteralCommandNode<CommandSource> destination) {
// Redirects only work for nodes with children, but break the top argument-less command. // 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. // 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. // See https://github.com/Mojang/brigadier/issues/46). Manually clone the node instead.
LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder.<CommandSource>literal(alias) LiteralArgumentBuilder<CommandSource> builder = LiteralArgumentBuilder
.<CommandSource>literal(alias)
.requires(destination.getRequirement()) .requires(destination.getRequirement())
.forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork()) .forward(destination.getRedirect(), destination.getRedirectModifier(), destination.isFork())
.executes(destination.getCommand()); .executes(destination.getCommand());

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

@ -18,8 +18,10 @@ public class FabulousWarningCommand {
ServerPlayerEntity player = ctx.getSource() ServerPlayerEntity player = ctx.getSource()
.asPlayer(); .asPlayer();
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), AllPackets.channel.send(
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fabulousWarning.name(), "")); 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 -> { .executes(ctx -> {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource() AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource()
.getEntity()), .getEntity()),
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true))); new SConfigureConfigPacket(SConfigureConfigPacket.Actions.fixLighting.name(), String.valueOf(true)));
ctx.getSource() ctx.getSource()
.sendFeedback( .sendFeedback(

View file

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

View file

@ -21,26 +21,20 @@ import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
public class PonderCommand { public class PonderCommand {
public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register( public static final SuggestionProvider<CommandSource> ITEM_PONDERS = SuggestionProviders.register(new ResourceLocation("all_ponders"), (iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet().stream(), builder));
new ResourceLocation("all_ponders"),
(iSuggestionProviderCommandContext, builder) -> ISuggestionProvider.func_212476_a(PonderRegistry.all.keySet()
.stream(), builder));
static ArgumentBuilder<CommandSource, ?> register() { static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("ponder") return Commands.literal("ponder")
.requires(cs -> cs.hasPermissionLevel(0)) .requires(cs -> cs.hasPermissionLevel(0))
.executes(ctx -> openScene("index", ctx.getSource() .executes(ctx -> openScene("index", ctx.getSource().asPlayer()))
.asPlayer()))
.then(Commands.argument("scene", ResourceLocationArgument.resourceLocation()) .then(Commands.argument("scene", ResourceLocationArgument.resourceLocation())
.suggests(ITEM_PONDERS) .suggests(ITEM_PONDERS)
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene") .executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), ctx.getSource().asPlayer()))
.toString(),
ctx.getSource()
.asPlayer()))
.then(Commands.argument("targets", EntityArgument.players()) .then(Commands.argument("targets", EntityArgument.players())
.requires(cs -> cs.hasPermissionLevel(2)) .requires(cs -> cs.hasPermissionLevel(2))
.executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene") .executes(ctx -> openScene(ResourceLocationArgument.getResourceLocation(ctx, "scene").toString(), EntityArgument.getPlayers(ctx, "targets")))
.toString(), EntityArgument.getPlayers(ctx, "targets"))))); )
);
} }
@ -53,8 +47,9 @@ public class PonderCommand {
if (player instanceof FakePlayer) if (player instanceof FakePlayer)
continue; continue;
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), AllPackets.channel.send(
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.openPonder.name(), sceneId)); PacketDistributor.PLAYER.with(() -> player),
new SConfigureConfigPacket(SConfigureConfigPacket.Actions.openPonder.name(), sceneId));
} }
return Command.SINGLE_SUCCESS; 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.Create;
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen; import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
import com.simibubi.create.foundation.config.AllConfigs; 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.gui.ScreenOpener;
import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.networking.SimplePacketBase;
import com.simibubi.create.foundation.ponder.PonderRegistry; 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.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.network.NetworkEvent;
public class ConfigureConfigPacket extends SimplePacketBase { public class SConfigureConfigPacket extends SimplePacketBase {
private final String option; private final String option;
private final String value; private final String value;
public ConfigureConfigPacket(String option, String value) { public SConfigureConfigPacket(String option, String value) {
this.option = option; this.option = option;
this.value = value; this.value = value;
} }
public ConfigureConfigPacket(PacketBuffer buffer) { public SConfigureConfigPacket(PacketBuffer buffer) {
this.option = buffer.readString(32767); this.option = buffer.readString(32767);
this.value = buffer.readString(32767); this.value = buffer.readString(32767);
} }
@ -69,7 +70,8 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.setPacketHandled(true); .setPacketHandled(true);
} }
enum Actions { public enum Actions {
configScreen(() -> Actions::configScreen),
rainbowDebug(() -> Actions::rainbowDebug), rainbowDebug(() -> Actions::rainbowDebug),
overlayScreen(() -> Actions::overlayScreen), overlayScreen(() -> Actions::overlayScreen),
fixLighting(() -> Actions::experimentalLighting), fixLighting(() -> Actions::experimentalLighting),
@ -91,6 +93,11 @@ public class ConfigureConfigPacket extends SimplePacketBase {
.accept(value); .accept(value);
} }
@OnlyIn(Dist.CLIENT)
private static void configScreen(String value) {
ScreenOpener.open(new BaseConfigScreen(null));
}
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private static void rainbowDebug(String value) { private static void rainbowDebug(String value) {
ClientPlayerEntity player = Minecraft.getInstance().player; ClientPlayerEntity player = Minecraft.getInstance().player;

View file

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

View file

@ -13,7 +13,9 @@ public class ToggleExperimentalRenderingCommand extends ConfigureConfigCommand {
@Override @Override
protected void sendPacket(ServerPlayerEntity player, String option) { protected void sendPacket(ServerPlayerEntity player, String option) {
AllPackets.channel.send(PacketDistributor.PLAYER.with(() -> player), AllPackets.channel.send(
new ConfigureConfigPacket(ConfigureConfigPacket.Actions.experimentalRendering.name(), option)); 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) { if (comment.length > 0) {
String[] comments = new String[comment.length + 1]; String[] comments = new String[comment.length + 1];
comments[0] = ""; comments[0] = "";
for (int i = 0; i < comment.length; i++) System.arraycopy(comment, 0, comments, 1, comment.length);
comments[i + 1] = comment[i];
builder.comment(comments); builder.comment(comments);
} else } else
builder.comment(""); 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.disableLighting();
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks); renderWindowForeground(matrixStack, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(matrixStack, mouseX, mouseY);
} }
@Override @Override
@ -152,9 +150,12 @@ public abstract class AbstractSimiContainerScreen<T extends Container> extends C
if (!widget.isHovered()) if (!widget.isHovered())
continue; continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip() if (widget instanceof AbstractSimiWidget) {
.isEmpty()) { if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(matrixStack, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); 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; guiTop = (this.height - sHeight) / 2;
} }
@Override
public void tick() {
super.tick();
widgets.stream().filter(w -> w instanceof AbstractSimiWidget).forEach(w -> ((AbstractSimiWidget) w).tick());
}
@Override @Override
public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
partialTicks = partialTicks == 10 ? 0 partialTicks = partialTicks == 10 ? 0
@ -46,8 +53,6 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets) for (Widget widget : widgets)
widget.render(ms, mouseX, mouseY, partialTicks); widget.render(ms, mouseX, mouseY, partialTicks);
renderWindowForeground(ms, mouseX, mouseY, partialTicks); renderWindowForeground(ms, mouseX, mouseY, partialTicks);
for (Widget widget : widgets)
widget.renderToolTip(ms, mouseX, mouseY);
ms.pop(); ms.pop();
} }
@ -62,6 +67,10 @@ public abstract class AbstractSimiScreen extends Screen {
for (Widget widget : widgets) for (Widget widget : widgets)
if (widget.mouseClicked(x, y, button)) if (widget.mouseClicked(x, y, button))
result = true; result = true;
if (!result) {
result = super.mouseClicked(x, y, button);
}
return result; return result;
} }
@ -127,9 +136,12 @@ public abstract class AbstractSimiScreen extends Screen {
if (!widget.isHovered()) if (!widget.isHovered())
continue; continue;
if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip() if (widget instanceof AbstractSimiWidget) {
.isEmpty()) { if (!((AbstractSimiWidget) widget).getToolTip().isEmpty())
renderTooltip(ms, ((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); 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; package com.simibubi.create.foundation.gui;
import java.awt.Color;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.Create; import com.simibubi.create.Create;
@ -80,8 +82,8 @@ public enum AllGuiTextures implements IScreenRenderable {
INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6), INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6),
INDICATOR_RED("widgets.png", 72, 18, 18, 6), INDICATOR_RED("widgets.png", 72, 18, 18, 6),
SPEECH_TOOLTIP("widgets.png", 0, 24, 8, 8), SPEECH_TOOLTIP_BACKGROUND("widgets.png", 0, 24, 8, 8),
SPEECH_TOOLTIP_HIGHLIGHT("widgets.png", 8, 24, 8, 8), SPEECH_TOOLTIP_COLOR("widgets.png", 8, 24, 8, 8),
// PlacementIndicator // PlacementIndicator
PLACEMENT_INDICATOR_SHEET("placement_indicator.png", 0, 0, 16, 256); PLACEMENT_INDICATOR_SHEET("placement_indicator.png", 0, 0, 16, 256);
@ -123,4 +125,9 @@ public enum AllGuiTextures implements IScreenRenderable {
bind(); bind();
screen.drawTexture(ms, x, y, startX, startY, width, height); 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 iconX;
private int iconY; private int iconY;
public static final AllIcons I_ADD = newRow(), I_TRASH = next(), I_3x3 = next(), I_TARGET = next(), public static final AllIcons
I_PRIORITY_VERY_LOW = next(), I_PRIORITY_LOW = next(), I_PRIORITY_HIGH = next(), I_PRIORITY_VERY_HIGH = next(), I_ADD = newRow(),
I_BLACKLIST = next(), I_WHITELIST = next(), I_WHITELIST_OR = next(), I_WHITELIST_AND = next(), I_TRASH = next(),
I_WHITELIST_NOT = next(), I_RESPECT_NBT = next(), I_IGNORE_NBT = 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(), public static final AllIcons
I_ACTIVE = next(), I_PASSIVE = next(), I_ROTATE_PLACE = next(), I_ROTATE_PLACE_RETURNED = next(), I_CONFIRM = newRow(),
I_ROTATE_NEVER_PLACE = next(), I_MOVE_PLACE = next(), I_MOVE_PLACE_RETURNED = next(), I_NONE = next(),
I_MOVE_NEVER_PLACE = next(), I_CART_ROTATE = next(), I_CART_ROTATE_PAUSED = 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(); I_CART_ROTATE_LOCKED = next();
public static final AllIcons I_DONT_REPLACE = newRow(), I_REPLACE_SOLID = next(), I_REPLACE_ANY = next(), public static final AllIcons
I_REPLACE_EMPTY = next(), I_CENTERED = next(), I_ATTACHED = next(), I_INSERTED = next(), I_FILL = next(), I_DONT_REPLACE = newRow(),
I_PLACE = next(), I_REPLACE = next(), I_CLEAR = next(), I_OVERLAY = next(), I_FLATTEN = next(), I_LMB = next(), I_REPLACE_SOLID = next(),
I_SCROLL = next(), I_RMB = 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(), public static final AllIcons
I_DICE = next(), I_TUNNEL_SPLIT = next(), I_TUNNEL_FORCED_SPLIT = next(), I_TUNNEL_ROUND_ROBIN = next(), I_TOOL_DEPLOY = newRow(),
I_TUNNEL_FORCED_ROUND_ROBIN = next(), I_TUNNEL_PREFER_NEAREST = next(), I_TUNNEL_RANDOMIZE = next(), 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_TUNNEL_SYNCHRONIZE = next(),
I_TOOL_MOVE_XZ = newRow(), I_TOOL_MOVE_Y = next(), I_TOOL_ROTATE = next(), I_TOOL_MIRROR = next(), I_TOOL_MOVE_XZ = newRow(),
I_ARM_ROUND_ROBIN = next(), I_ARM_FORCED_ROUND_ROBIN = next(), I_ARM_PREFER_FIRST = next(), 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_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_PLAY = newRow(),
I_HOUR_HAND_FIRST = next(), I_MINUTE_HAND_FIRST = next(), I_HOUR_HAND_FIRST_24 = next(), 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_SOLID = newRow(),
I_PATTERN_CHECKERED = next(),
I_PATTERN_CHECKERED_INVERSED = next(),
I_PATTERN_CHANCE_25 = 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_FOLLOW_MATERIAL = next(),
I_SCHEMATIC = newRow(), 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_LEFT = newRow(),
I_MTD_USER_MODE = next(), I_MTD_SLOW_MODE = next(); 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) { public AllIcons(int x, int y) {
iconX = x * 16; iconX = x * 16;
@ -116,8 +192,12 @@ public class AllIcons implements IScreenRenderable {
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
private void vertex(Entry peek, IVertexBuilder builder, int j, int k, Vector3d rgb, Vector3d vec, float u, public DelegatedStencilElement asStencil() {
float v) { 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) builder.vertex(peek.getModel(), (float) vec.x, (float) vec.y, (float) vec.z)
.color((float) rgb.x, (float) rgb.y, (float) rgb.z, 1) .color((float) rgb.x, (float) rgb.y, (float) rgb.z, 1)
.texture(u, v) .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)); .with(FlowingFluidBlock.LEVEL, 0));
} }
public static abstract class GuiRenderBuilder { public static abstract class GuiRenderBuilder extends RenderElement {
double xBeforeScale, yBeforeScale, zBeforeScale = 0; double xLocal, yLocal, zLocal;
double x, y, z;
double xRot, yRot, zRot; double xRot, yRot, zRot;
double scale = 1; double scale = 1;
int color = 0xFFFFFF; int color = 0xFFFFFF;
Vector3d rotationOffset = Vector3d.ZERO; Vector3d rotationOffset = Vector3d.ZERO;
public GuiRenderBuilder atLocal(double x, double y, double z) { public GuiRenderBuilder atLocal(double x, double y, double z) {
this.x = x; this.xLocal = x;
this.y = y; this.yLocal = y;
this.z = z; this.zLocal = 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;
return this; return this;
} }
@ -136,9 +122,9 @@ public class GuiGameElement {
@Deprecated @Deprecated
protected void transform() { protected void transform() {
RenderSystem.translated(xBeforeScale, yBeforeScale, 0); RenderSystem.translated(x, y, 0);
RenderSystem.scaled(scale, scale, scale); RenderSystem.scaled(scale, scale, scale);
RenderSystem.translated(x, y, z); RenderSystem.translated(xLocal, yLocal, zLocal);
RenderSystem.scaled(1, -1, 1); RenderSystem.scaled(1, -1, 1);
RenderSystem.translated(rotationOffset.x, rotationOffset.y, rotationOffset.z); RenderSystem.translated(rotationOffset.x, rotationOffset.y, rotationOffset.z);
RenderSystem.rotatef((float) zRot, 0, 0, 1); RenderSystem.rotatef((float) zRot, 0, 0, 1);
@ -148,9 +134,9 @@ public class GuiGameElement {
} }
protected void transformMatrix(MatrixStack matrixStack) { protected void transformMatrix(MatrixStack matrixStack) {
matrixStack.translate(xBeforeScale, yBeforeScale, zBeforeScale);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(x, y, z); matrixStack.translate(x, y, z);
matrixStack.scale((float) scale, (float) scale, (float) scale);
matrixStack.translate(xLocal, yLocal, zLocal);
matrixStack.scale(1, -1, 1); matrixStack.scale(1, -1, 1);
matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z); matrixStack.translate(rotationOffset.x, rotationOffset.y, rotationOffset.z);
matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion((float) zRot)); matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion((float) zRot));
@ -272,23 +258,10 @@ public class GuiGameElement {
@Override @Override
public void render(MatrixStack matrixStack) { public void render(MatrixStack matrixStack) {
prepareMatrix(matrixStack); prepareMatrix(matrixStack);
// matrixStack.translate(0, 80, 0);
transformMatrix(matrixStack); transformMatrix(matrixStack);
renderItemIntoGUI(matrixStack, stack); renderItemIntoGUI(matrixStack, stack);
cleanUpMatrix(matrixStack); 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) { public static void renderItemIntoGUI(MatrixStack matrixStack, ItemStack stack) {
ItemRenderer renderer = Minecraft.getInstance() 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()) if (screenHistory.isEmpty())
return false; return false;
Screen previouslyRenderedScreen = screenHistory.get(0); Screen previouslyRenderedScreen = screenHistory.get(0);
if (!(previouslyRenderedScreen instanceof AbstractSimiScreen)) if (!(previouslyRenderedScreen instanceof NavigatableSimiScreen))
return false; return false;
if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen)) if (!screen.isEquivalentTo((NavigatableSimiScreen) previouslyRenderedScreen))
return false; 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; package com.simibubi.create.foundation.gui;
import java.awt.Color;
import javax.annotation.Nonnull;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.MainWindow; import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.shader.Framebuffer; import net.minecraft.client.shader.Framebuffer;
import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Matrix4f;
@ -18,6 +24,10 @@ import net.minecraftforge.fml.client.gui.GuiUtils;
public class UIRenderHelper { public class UIRenderHelper {
public static void enableStencil() {
RenderSystem.recordRenderCall(() -> Minecraft.getInstance().getFramebuffer().enableStencil());
}
public static Framebuffer framebuffer; public static Framebuffer framebuffer;
public static void init() { public static void init() {
@ -27,20 +37,10 @@ public class UIRenderHelper {
framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true, 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.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) { public static void drawFramebuffer(float alpha) {
MainWindow window = Minecraft.getInstance() MainWindow window = Minecraft.getInstance()
.getWindow(); .getWindow();
@ -51,10 +51,6 @@ public class UIRenderHelper {
float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight; float ty = (float) framebuffer.framebufferHeight / (float) framebuffer.framebufferTextureHeight;
RenderSystem.enableTexture(); RenderSystem.enableTexture();
RenderSystem.enableBlend();
RenderSystem.disableLighting();
RenderSystem.disableAlphaTest();
RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
framebuffer.bindFramebufferTexture(); framebuffer.bindFramebufferTexture();
@ -63,33 +59,21 @@ public class UIRenderHelper {
BufferBuilder bufferbuilder = tessellator.getBuffer(); BufferBuilder bufferbuilder = tessellator.getBuffer();
bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE); bufferbuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE);
bufferbuilder.vertex(0, vy, 0) bufferbuilder.vertex(0, vy, 0).color(1, 1, 1, alpha).texture(0, 0).endVertex();
.color(1, 1, 1, alpha) bufferbuilder.vertex(vx, vy, 0).color(1, 1, 1, alpha).texture(tx, 0).endVertex();
.texture(0, 0) bufferbuilder.vertex(vx, 0, 0).color(1, 1, 1, alpha).texture(tx, ty).endVertex();
.endVertex(); bufferbuilder.vertex(0, 0, 0).color(1, 1, 1, alpha).texture(0, ty).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(); tessellator.draw();
framebuffer.unbindFramebufferTexture(); 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 // angle in degrees; 0° -> fading to the right
// x and y specify the middle point of the starting edge // x and y specify the middle point of the starting edge
// width is the total width of the streak // breadth 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) { public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length, int color) {
int a1 = 0xa0 << 24; int a1 = 0xa0 << 24;
int a2 = 0x80 << 24; int a2 = 0x80 << 24;
int a3 = 0x10 << 24; int a3 = 0x10 << 24;
@ -105,7 +89,7 @@ public class UIRenderHelper {
ms.translate(x, y, 0); ms.translate(x, y, 0);
ms.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(angle - 90)); 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(); 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) { private static void streak(MatrixStack ms, int width, int height, int c1, int c2, int c3, int c4) {
double split1 = .5; double split1 = .5;
double split2 = .75; double split2 = .75;
Matrix4f model = ms.peek() Matrix4f model = ms.peek().getModel();
.getModel(); RenderSystem.disableAlphaTest();
GuiUtils.drawGradientRect(model, 0, -width, 0, width, (int) (split1 * height), c1, c2); 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) (split1 * height), width, (int) (split2 * height), c2, c3);
GuiUtils.drawGradientRect(model, 0, -width, (int) (split2 * height), width, height, c3, c4); 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 // 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, public static void breadcrumbArrow(MatrixStack matrixStack, int x, int y, int z, int width, int height, int indent, int startColor, int endColor) {
int startColor, int endColor) {
matrixStack.push(); matrixStack.push();
matrixStack.translate(x - indent, y, z); matrixStack.translate(x - indent, y, z);
@ -170,69 +197,32 @@ public class UIRenderHelper {
Tessellator tessellator = Tessellator.getInstance(); Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer(); BufferBuilder bufferbuilder = tessellator.getBuffer();
Matrix4f model = ms.peek() Matrix4f model = ms.peek().getModel();
.getModel();
bufferbuilder.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); bufferbuilder.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR);
bufferbuilder.vertex(model, x0, y0, 0) bufferbuilder.vertex(model, x0, y0, 0).color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF).endVertex();
.color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF) bufferbuilder.vertex(model, x1, y1, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
.endVertex(); bufferbuilder.vertex(model, x2, y2, 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, x2, y2, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x0, y0, 0) bufferbuilder.vertex(model, x0, y0, 0).color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF).endVertex();
.color(fc1 >> 16 & 0xFF, fc1 >> 8 & 0xFF, fc1 & 0xFF, fc1 >> 24 & 0xFF) bufferbuilder.vertex(model, x2, y2, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
.endVertex(); bufferbuilder.vertex(model, x3, y3, 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, x3, y3, 0)
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x3, y3, 0) bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF) bufferbuilder.vertex(model, x1, y1, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
.endVertex(); bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 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) bufferbuilder.vertex(model, x3, y3, 0).color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF).endVertex();
.color(fc2 >> 16 & 0xFF, fc2 >> 8 & 0xFF, fc2 & 0xFF, fc2 >> 24 & 0xFF) bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
.endVertex(); bufferbuilder.vertex(model, x6, y6, 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, x6, y6, 0)
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF)
.endVertex();
bufferbuilder.vertex(model, x5, y5, 0) bufferbuilder.vertex(model, x5, y5, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF) bufferbuilder.vertex(model, x4, y4, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
.endVertex(); bufferbuilder.vertex(model, x7, y7, 0).color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 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) bufferbuilder.vertex(model, x6, y6, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
.color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF) bufferbuilder.vertex(model, x5, y5, 0).color(fc3 >> 16 & 0xFF, fc3 >> 8 & 0xFF, fc3 & 0xFF, fc3 >> 24 & 0xFF).endVertex();
.endVertex(); bufferbuilder.vertex(model, x8, y8, 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, x8, y8, 0)
.color(fc4 >> 16 & 0xFF, fc4 >> 8 & 0xFF, fc4 & 0xFF, fc4 >> 24 & 0xFF)
.endVertex();
tessellator.draw(); tessellator.draw();
RenderSystem.shadeModel(GL11.GL_FLAT); RenderSystem.shadeModel(GL11.GL_FLAT);
@ -241,4 +231,30 @@ public class UIRenderHelper {
RenderSystem.enableAlphaTest(); RenderSystem.enableAlphaTest();
RenderSystem.enableTexture(); 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.LinkedList;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
@ -11,19 +14,78 @@ import net.minecraft.util.text.StringTextComponent;
public abstract class AbstractSimiWidget extends Widget { public abstract class AbstractSimiWidget extends Widget {
protected List<ITextComponent> toolTip; protected float z;
protected boolean wasHovered = false;
protected List<ITextComponent> toolTip = new LinkedList<>();
protected BiConsumer<Integer, Integer> onClick = (_$, _$$) -> {};
public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) { protected AbstractSimiWidget() {
super(xIn, yIn, widthIn, heightIn, StringTextComponent.EMPTY); this(0, 0);
toolTip = new LinkedList<>(); }
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() { public List<ITextComponent> getToolTip() {
return toolTip; return toolTip;
} }
public void tick() {}
@Override @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 net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
public class IconButton extends AbstractSimiWidget { public class IconButton extends AbstractSimiWidget {
private AllIcons icon; private AllIcons icon;
@ -18,7 +20,7 @@ public class IconButton extends AbstractSimiWidget {
} }
@Override @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) { if (this.visible) {
this.hovered = this.hovered =
mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; 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; package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllGuiTextures;
@ -22,7 +24,7 @@ public class Indicator extends AbstractSimiWidget {
} }
@Override @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; AllGuiTextures toDraw;
switch(state) { switch(state) {
case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break; case ON: toDraw = AllGuiTextures.INDICATOR_WHITE; break;

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.gui.widgets; package com.simibubi.create.foundation.gui.widgets;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
@ -69,7 +71,7 @@ public class Label extends AbstractSimiWidget {
} }
@Override @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) if (!visible)
return; return;
if (text == null || text.getString().isEmpty()) 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.SchematicPlacePacket;
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket; 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.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.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
@ -80,12 +81,13 @@ public enum AllPackets {
PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER), PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER),
TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER), TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER),
EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::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 // Server to Client
SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT),
SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT), SERVER_SPEED(ServerSpeedProvider.Packet.class, ServerSpeedProvider.Packet::new, PLAY_TO_CLIENT),
BEAM_EFFECT(ZapperBeamPacket.class, ZapperBeamPacket::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_STALL(ContraptionStallPacket.class, ContraptionStallPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT), CONTRAPTION_DISASSEMBLE(ContraptionDisassemblyPacket.class, ContraptionDisassemblyPacket::new, PLAY_TO_CLIENT),
GLUE_EFFECT(GlueEffectPacket.class, GlueEffectPacket::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 org.lwjgl.glfw.GLFW;
import com.mojang.blaze3d.matrix.MatrixStack; 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.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.ScreenOpener; 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.UIRenderHelper;
import com.simibubi.create.foundation.ponder.content.PonderTagScreen; import com.simibubi.create.foundation.ponder.content.PonderTagScreen;
import com.simibubi.create.foundation.ponder.ui.PonderButton; import com.simibubi.create.foundation.ponder.ui.PonderButton;
@ -76,9 +78,9 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
if (screen instanceof PonderTagScreen) if (screen instanceof PonderTagScreen)
icon = ((PonderTagScreen) screen).getTag(); icon = ((PonderTagScreen) screen).getTag();
widgets.add(backTrack = new PonderButton(31, height - 31 - PonderButton.SIZE, () -> { widgets.add(backTrack = new PonderButton(31, height - 31 - 20)
ScreenOpener.openPreviousScreen(this, Optional.empty()); .enableFade(0, 5)
}).fade(0, -1)); .withCallback(() -> ScreenOpener.openPreviousScreen(this, Optional.empty())));
backTrack.fade(1); backTrack.fade(1);
if (icon != null) if (icon != null)
@ -97,7 +99,7 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
ms.push(); ms.push();
ms.translate(0, 0, 500); ms.translate(0, 0, 500);
if (backTrack.isHovered()) { 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())) { if (MathHelper.epsilonEquals(arrowAnimation.getValue(), arrowAnimation.getChaseTarget())) {
arrowAnimation.setValue(1); arrowAnimation.setValue(1);
arrowAnimation.setValue(1);// called twice to also set the previous value to 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 @Override
protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { 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); renderBackground(ms);
return; return;
} }
@ -121,14 +134,14 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
// draw last screen into buffer // draw last screen into buffer
if (lastScreen != null && lastScreen != this && !transition.settled()) { if (lastScreen != null && lastScreen != this && !transition.settled()) {
ms.push();// 1 ms.push();
UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC); UIRenderHelper.framebuffer.framebufferClear(Minecraft.IS_RUNNING_ON_MAC);
UIRenderHelper.prepFramebufferSize();
ms.push();// 2
ms.translate(0, 0, -1000); ms.translate(0, 0, -1000);
UIRenderHelper.framebuffer.bindFramebuffer(true); UIRenderHelper.framebuffer.bindFramebuffer(true);
lastScreen.render(ms, mouseX, mouseY, 10); lastScreen.render(ms, mouseX, mouseY, partialTicks);
ms.pop();// 2
ms.pop();
ms.push();
// use the buffer texture // use the buffer texture
Minecraft.getInstance() Minecraft.getInstance()
@ -144,32 +157,23 @@ public abstract class NavigatableSimiScreen extends AbstractSimiScreen {
dpy = ((NavigatableSimiScreen) lastScreen).depthPointY; 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.translate(dpx, dpy, 0);
ms.scale((float) scale, (float) scale, 1); ms.scale(scale, scale, 1);
ms.translate(-dpx, -dpy, 0); ms.translate(-dpx, -dpy, 0);
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
RenderSystem.disableAlphaTest();
UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue)); UIRenderHelper.drawFramebuffer(1f - Math.abs(transitionValue));
ms.pop();// 1 RenderSystem.disableBlend();
RenderSystem.enableAlphaTest();
ms.pop();
} }
// modify current screen as well // modify current screen as well
scale = transitionValue > 0 ? 1 - 0.5f * (1 - transitionValue) : 1 + .5f * (1 + transitionValue); scale = transitionValue > 0 ? 1 - 0.5f * (1 - transitionValue) : 1 + .5f * (1 + transitionValue);
ms.translate(depthPointX, depthPointY, 0); ms.translate(depthPointX, depthPointY, 0);
ms.scale((float) scale, (float) scale, 1); ms.scale(scale, scale, 1);
ms.translate(-depthPointX, -depthPointY, 0); 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 @Override

View file

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

View file

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

View file

@ -10,6 +10,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock; import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock;
import com.simibubi.create.foundation.gui.ScreenOpener; 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.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderRegistry; import com.simibubi.create.foundation.ponder.PonderRegistry;
@ -106,17 +107,17 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
int itemCenterY = (int) (height * itemYmult); int itemCenterY = (int) (height * itemYmult);
for (Item item : items) { for (Item item : items) {
PonderButton button = PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> { .showing(new ItemStack(item))
.withCallback((x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName())) if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return; return;
centerScalingOn(x, y); centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item))); ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
}).showing(new ItemStack(item)); });
button.fade(1); widgets.add(b);
widgets.add(button);
layout.next(); layout.next();
} }
@ -158,8 +159,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(x, y, 0); ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010); 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, 0xffddeeff); textRenderer.draw(ms, "Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop(); ms.pop();
} }
@ -170,8 +171,8 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(x, y, 0); ms.translate(x, y, 0);
UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220, 0x101010); UIRenderHelper.streak(ms, 0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 220);
textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, 0xffddeeff); textRenderer.draw(ms, "Items to inspect", itemArea.getX() - 5, itemArea.getY() - 25, Theme.i(Theme.Key.TEXT));
ms.pop(); ms.pop();
} }
@ -189,7 +190,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
ms.pop(); ms.pop();
} }
@Override /*@Override
public boolean mouseClicked(double x, double y, int button) { public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false); MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> { widgets.forEach(w -> {
@ -207,7 +208,7 @@ public class PonderIndexScreen extends NavigatableSimiScreen {
if (handled.booleanValue()) if (handled.booleanValue())
return true; return true;
return super.mouseClicked(x, y, button); return super.mouseClicked(x, y, button);
} }*/
@Override @Override
public boolean isEquivalentTo(NavigatableSimiScreen other) { 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.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.Create; 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.ScreenOpener;
import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; import com.simibubi.create.foundation.ponder.NavigatableSimiScreen;
import com.simibubi.create.foundation.ponder.PonderLocalization; import com.simibubi.create.foundation.ponder.PonderLocalization;
@ -84,24 +86,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int itemCenterY = getItemsY(); int itemCenterY = getItemsY();
for (Item i : items) { for (Item i : items) {
final boolean canClick = PonderRegistry.all.containsKey(i.getRegistryName()); PonderButton b = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4)
PonderButton button = .showing(new ItemStack(i));
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (mouseX, mouseY) -> {
if (!canClick) if (PonderRegistry.all.containsKey(i.getRegistryName())) {
return; b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY); centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag)); ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag));
}).showing(new ItemStack(i)); });
if (!canClick) } else {
if (i.getRegistryName() if (i.getRegistryName()
.getNamespace() .getNamespace()
.equals(Create.ID)) .equals(Create.ID))
button.customColors(0x70984500, 0x70692400); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else else
button.customColors(0x505000FF, 0x50300077); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1); widgets.add(b);
widgets.add(button);
layout.next(); layout.next();
} }
@ -109,23 +113,26 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ResourceLocation registryName = tag.getMainItem() ResourceLocation registryName = tag.getMainItem()
.getItem() .getItem()
.getRegistryName(); .getRegistryName();
final boolean canClick = PonderRegistry.all.containsKey(registryName);
PonderButton button = PonderButton b = new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10)
new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10, (mouseX, mouseY) -> { .showing(tag.getMainItem());
if (!canClick)
return; if (PonderRegistry.all.containsKey(registryName)) {
b.withCallback((mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY); centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag)); ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag));
}).showing(tag.getMainItem()); });
if (!canClick) } else {
if (registryName.getNamespace() if (registryName.getNamespace()
.equals(Create.ID)) .equals(Create.ID))
button.customColors(0x70984500, 0x70692400); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_CREATE))
.animateColors(false);
else else
button.customColors(0x505000FF, 0x50300077); b.withBorderColors(Theme.p(Theme.Key.PONDER_MISSING_VANILLA))
.animateColors(false);
}
button.fade(1); widgets.add(b);
widgets.add(button);
} }
// chapters // chapters
@ -187,15 +194,21 @@ public class PonderTagScreen extends NavigatableSimiScreen {
String title = tag.getTitle(); String title = tag.getTitle();
int streakHeight = 35; int streakHeight = 35;
UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240, 0x101010); UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, 240);
PonderUI.renderBox(ms, 21, 21, 30, 30, false); //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; y += 8;
x += 0; x += 0;
ms.translate(x, y, 0); ms.translate(x, y, 0);
ms.translate(0, 0, 5); 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.pop();
ms.push(); ms.push();
@ -214,9 +227,16 @@ public class PonderTagScreen extends NavigatableSimiScreen {
int h = textRenderer.getWordWrappedHeight(desc, w); 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); 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(); ms.pop();
} }
@ -232,16 +252,23 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(x, y, 0); 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); ms.translate(0, 0, 200);
// UIRenderHelper.streak(0, itemArea.getX() - 10, itemArea.getY() - 20, 20, 180, 0x101010); // 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); ms.translate(0,0, -200);
UIRenderHelper.streak(ms, 0, 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, 0x101010); UIRenderHelper.streak(ms, 180, 0, 0, itemArea.getHeight() + 10, itemArea.getWidth() / 2 + 75);
ms.pop(); ms.pop();
@ -261,8 +288,8 @@ public class PonderTagScreen extends NavigatableSimiScreen {
ms.push(); ms.push();
ms.translate(chapterX, chapterY, 0); ms.translate(chapterX, chapterY, 0);
UIRenderHelper.streak(ms, 0, chapterArea.getX() - 10, chapterArea.getY() - 20, 20, 220, 0x101010); 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, 0xffddeeff); textRenderer.draw(ms, "More Topics to Ponder about", chapterArea.getX() - 5, chapterArea.getY() - 25, Theme.i(Theme.Key.TEXT_ACCENT_SLIGHT));
ms.pop(); ms.pop();
} }
@ -291,7 +318,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
return hoveredItem; return hoveredItem;
} }
@Override /*@Override
public boolean mouseClicked(double x, double y, int button) { public boolean mouseClicked(double x, double y, int button) {
MutableBoolean handled = new MutableBoolean(false); MutableBoolean handled = new MutableBoolean(false);
widgets.forEach(w -> { widgets.forEach(w -> {
@ -310,7 +337,7 @@ public class PonderTagScreen extends NavigatableSimiScreen {
if (handled.booleanValue()) if (handled.booleanValue())
return true; return true;
return super.mouseClicked(x, y, button); return super.mouseClicked(x, y, button);
} }*/
@Override @Override
public boolean isEquivalentTo(NavigatableSimiScreen other) { public boolean isEquivalentTo(NavigatableSimiScreen other) {

View file

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

View file

@ -4,6 +4,8 @@ import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.mojang.blaze3d.matrix.MatrixStack; 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.PonderLocalization;
import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.PonderUI;
@ -110,7 +112,14 @@ public class TextWindowElement extends AnimatedOverlayElement {
ms.push(); ms.push();
ms.translate(0, sceneToScreen.y, 400); 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); int brighterColor = ColorHelper.mixAlphaColors(color, 0xFFffffdd, 1 / 2f);
if (vec != null) { if (vec != null) {

View file

@ -5,6 +5,7 @@ import java.util.function.BiConsumer;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import com.mojang.blaze3d.matrix.MatrixStack; 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.UIRenderHelper;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.ponder.content.PonderChapter; 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) { public ChapterLabel(PonderChapter chapter, int x, int y, BiConsumer<Integer, Integer> onClick) {
super(x, y, 175, 38); super(x, y, 175, 38);
this.button = new PonderButton(x + 4, y + 4, onClick, 30, 30).showing(chapter); this.button = new PonderButton(x + 4, y + 4, 30, 30)
this.button.fade(1); .showing(chapter)
.withCallback(onClick);
this.chapter = chapter; this.chapter = chapter;
} }
@Override @Override
public void render(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) { 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, 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); button.renderButton(ms, mouseX, mouseY, partialTicks);
super.render(ms, mouseX, mouseY, partialTicks); super.render(ms, mouseX, mouseY, partialTicks);

View file

@ -1,175 +1,105 @@
package com.simibubi.create.foundation.ponder.ui; 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.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.gui.RenderElement;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.gui.Theme;
import com.simibubi.create.foundation.ponder.PonderUI; 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.ColorHelper;
import com.simibubi.create.foundation.utility.Couple;
import com.simibubi.create.foundation.utility.animation.LerpedFloat; import com.simibubi.create.foundation.utility.animation.LerpedFloat;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
public class PonderButton extends AbstractSimiWidget { public class PonderButton extends BoxWidget {
private IScreenRenderable icon; protected ItemStack item;
private ItemStack item; protected KeyBinding shortcut;
protected boolean pressed; protected LerpedFloat flash = LerpedFloat.linear().startWithValue(0).chase(0, 0.1f, LerpedFloat.Chaser.EXP);
private BiConsumer<Integer, Integer> onClick;
private int xFadeModifier;
private int yFadeModifier;
private float fade;
private KeyBinding shortcut;
private LerpedFloat flash;
private Couple<Integer> customPassiveBorder;
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); super(x, y, width, height);
this.onClick = onClick; z = 400;
flash = LerpedFloat.linear() paddingX = 2;
.startWithValue(0); paddingY = 2;
} }
public PonderButton(int x, int y, BiConsumer<Integer, Integer> onClick) { public <T extends PonderButton> T withShortcut(KeyBinding key) {
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) {
this.shortcut = key; this.shortcut = key;
return this; //noinspection unchecked
return (T) this;
} }
public PonderButton fade(int xModifier, int yModifier) { public <T extends PonderButton> T showing(ItemStack item) {
this.xFadeModifier = xModifier; this.item = item;
this.yFadeModifier = yModifier; return super.showingElement(GuiGameElement.of(item)
return this; .scale(1.5f)
.at(-4, -4));
} }
public void fade(float fade) { @Override
this.fade = fade; public <T extends ElementWidget> T showingElement(RenderElement element) {
return super.showingElement(element);
} }
public void flash() { public void flash() {
float value = flash.getValue(); flash.updateChaseTarget(1);
flash.setValue(value + (1 - value) * .2f);
} }
public void dim() { public void dim() {
float value = flash.getValue(); flash.updateChaseTarget(0);
flash.setValue(value * .5f);
} }
@Override @Override
public void renderButton(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { public void tick() {
if (!visible) super.tick();
return; flash.tickChaser();
if (fade < .1f) }
return;
hovered = isMouseOver(mouseX, mouseY) && fade > .75f; @Override
protected void beforeRender(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
ms.push(); super.beforeRender(ms, mouseX, mouseY, partialTicks);
RenderSystem.disableDepthTest();
if (fade < 1)
ms.translate((1 - fade) * -5 * xFadeModifier, (1 - fade) * -5 * yFadeModifier, 0);
float flashValue = flash.getValue(partialTicks); float flashValue = flash.getValue(partialTicks);
if (flashValue > .1f) if (flashValue > .1f) {
fade *= 3 * flashValue + Math.sin((PonderUI.ponderTicks + partialTicks) / 6); float sin = 0.5f + 0.5f * MathHelper.sin((AnimationTickHolder.getTicks(true) + partialTicks) / 6f);
sin *= flashValue;
int backgroundColor = ColorHelper.applyAlpha(0xdd000000, fade); Color c1 = gradientColor1;
int borderColorStart = customPassiveBorder != null ? customPassiveBorder.getFirst() : hovered ? 0x70ffffff : 0x40aa9999; Color c2 = gradientColor2;
int borderColorEnd = customPassiveBorder != null ? customPassiveBorder.getSecond() : hovered ? 0x30ffffff : 0x20aa9999; Color nc1 = new Color(c1.getRed(), c1.getGreen(), c1.getBlue(), MathHelper.clamp(c1.getAlpha() + 50, 0, 255));
borderColorStart = ColorHelper.applyAlpha(borderColorStart, fade); Color nc2 = new Color(c2.getRed(), c2.getGreen(), c2.getBlue(), MathHelper.clamp(c2.getAlpha() + 50, 0, 255));
borderColorEnd = ColorHelper.applyAlpha(borderColorEnd, fade); gradientColor1 = ColorHelper.mixColors(c1, nc1, sin);
gradientColor2 = ColorHelper.mixColors(c2, nc2, sin);
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 (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 @Override
public void onClick(double p_onClick_1_, double p_onClick_3_) { public void renderButton(@Nonnull MatrixStack ms, int mouseX, int mouseY, float partialTicks) {
super.onClick(p_onClick_1_, p_onClick_3_); super.renderButton(ms, mouseX, mouseY, partialTicks);
this.pressed = true; float fadeValue = fade.getValue();
}
@Override if (fadeValue < .1f)
public void onRelease(double p_onRelease_1_, double p_onRelease_3_) { return;
super.onRelease(p_onRelease_1_, p_onRelease_3_);
this.pressed = false;
}
/*public void setToolTip(String text) { if (shortcut != null) {
toolTip.clear(); ms.translate(0, 0, z+50);
toolTip.add(text); 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() { public ItemStack getItem() {
return item; 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 { public class AnimationTickHolder {
private static int ticks; private static int ticks;
private static int paused_ticks;
public static void reset() { public static void reset() {
ticks = 0; ticks = 0;
paused_ticks = 0;
} }
public static void tick() { public static void tick() {
if (!Minecraft.getInstance() if (!Minecraft.getInstance()
.isGamePaused()) { .isGamePaused()) {
ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision 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() { 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() { public static float getRenderTime() {

View file

@ -1,7 +1,10 @@
package com.simibubi.create.foundation.utility; package com.simibubi.create.foundation.utility;
import java.awt.Color;
import java.util.UUID; import java.util.UUID;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -39,6 +42,10 @@ public class ColorHelper {
return (color & 0xFFFFFF) | alphaChannel << 24; 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) { public static int mixColors(int color1, int color2, float w) {
int r1 = (color1 >> 16); int r1 = (color1 >> 16);
int g1 = (color1 >> 8) & 0xFF; int g1 = (color1 >> 8) & 0xFF;
@ -52,6 +59,23 @@ public class ColorHelper {
return color; 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) { public static int mixAlphaColors(int color1, int color2, float w) {
int a1 = (color1 >> 24); int a1 = (color1 >> 24);
int r1 = (color1 >> 16) & 0xFF; int r1 = (color1 >> 16) & 0xFF;

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