diff --git a/game/assets/gui/console/Graphics/Armour_Slot_Body.png b/game/assets/gui/console/Graphics/Armour_Slot_Body.png new file mode 100644 index 000000000..64c7aa19a Binary files /dev/null and b/game/assets/gui/console/Graphics/Armour_Slot_Body.png differ diff --git a/game/assets/gui/console/Graphics/Armour_Slot_Feet.png b/game/assets/gui/console/Graphics/Armour_Slot_Feet.png new file mode 100644 index 000000000..d92aad44d Binary files /dev/null and b/game/assets/gui/console/Graphics/Armour_Slot_Feet.png differ diff --git a/game/assets/gui/console/Graphics/Armour_Slot_Head.png b/game/assets/gui/console/Graphics/Armour_Slot_Head.png new file mode 100644 index 000000000..8bac0a894 Binary files /dev/null and b/game/assets/gui/console/Graphics/Armour_Slot_Head.png differ diff --git a/game/assets/gui/console/Graphics/Armour_Slot_Legs.png b/game/assets/gui/console/Graphics/Armour_Slot_Legs.png new file mode 100644 index 000000000..6781b6aed Binary files /dev/null and b/game/assets/gui/console/Graphics/Armour_Slot_Legs.png differ diff --git a/game/assets/gui/console/Graphics/Arrow_Off.png b/game/assets/gui/console/Graphics/Arrow_Off.png new file mode 100644 index 000000000..21e820d6d Binary files /dev/null and b/game/assets/gui/console/Graphics/Arrow_Off.png differ diff --git a/game/assets/gui/console/Graphics/Arrow_Small_Off.png b/game/assets/gui/console/Graphics/Arrow_Small_Off.png new file mode 100644 index 000000000..c7c86d0a8 Binary files /dev/null and b/game/assets/gui/console/Graphics/Arrow_Small_Off.png differ diff --git a/game/assets/gui/console/Graphics/IconHolder.png b/game/assets/gui/console/Graphics/IconHolder.png new file mode 100644 index 000000000..55a72d14a Binary files /dev/null and b/game/assets/gui/console/Graphics/IconHolder.png differ diff --git a/game/assets/gui/console/Graphics/IconHolderRed.png b/game/assets/gui/console/Graphics/IconHolderRed.png new file mode 100644 index 000000000..6d15f6e5b Binary files /dev/null and b/game/assets/gui/console/Graphics/IconHolderRed.png differ diff --git a/game/assets/gui/console/Graphics/ListButton_Norm.png b/game/assets/gui/console/Graphics/ListButton_Norm.png new file mode 100644 index 000000000..037d7aa20 Binary files /dev/null and b/game/assets/gui/console/Graphics/ListButton_Norm.png differ diff --git a/game/assets/gui/console/Graphics/ListButton_Over.png b/game/assets/gui/console/Graphics/ListButton_Over.png new file mode 100644 index 000000000..8bf8cb980 Binary files /dev/null and b/game/assets/gui/console/Graphics/ListButton_Over.png differ diff --git a/game/assets/gui/console/Graphics/MainMenuButton_Norm.png b/game/assets/gui/console/Graphics/MainMenuButton_Norm.png new file mode 100644 index 000000000..db79450e0 Binary files /dev/null and b/game/assets/gui/console/Graphics/MainMenuButton_Norm.png differ diff --git a/game/assets/gui/console/Graphics/MainMenuButton_Over.png b/game/assets/gui/console/Graphics/MainMenuButton_Over.png new file mode 100644 index 000000000..edbd37b68 Binary files /dev/null and b/game/assets/gui/console/Graphics/MainMenuButton_Over.png differ diff --git a/game/assets/gui/console/Graphics/Panel_BL.png b/game/assets/gui/console/Graphics/Panel_BL.png new file mode 100644 index 000000000..8e200b304 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_BL.png differ diff --git a/game/assets/gui/console/Graphics/Panel_BM.png b/game/assets/gui/console/Graphics/Panel_BM.png new file mode 100644 index 000000000..a46379dea Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_BM.png differ diff --git a/game/assets/gui/console/Graphics/Panel_BR.png b/game/assets/gui/console/Graphics/Panel_BR.png new file mode 100644 index 000000000..5bc190876 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_BR.png differ diff --git a/game/assets/gui/console/Graphics/Panel_ML.png b/game/assets/gui/console/Graphics/Panel_ML.png new file mode 100644 index 000000000..aa9aa4189 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_ML.png differ diff --git a/game/assets/gui/console/Graphics/Panel_MM.png b/game/assets/gui/console/Graphics/Panel_MM.png new file mode 100644 index 000000000..f6efa03ba Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_MM.png differ diff --git a/game/assets/gui/console/Graphics/Panel_MR.png b/game/assets/gui/console/Graphics/Panel_MR.png new file mode 100644 index 000000000..75df3f76d Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_MR.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Bot_L.png b/game/assets/gui/console/Graphics/Panel_Recess_Bot_L.png new file mode 100644 index 000000000..7129dcb0c Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Bot_L.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Bot_M.png b/game/assets/gui/console/Graphics/Panel_Recess_Bot_M.png new file mode 100644 index 000000000..afe63102e Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Bot_M.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Bot_R.png b/game/assets/gui/console/Graphics/Panel_Recess_Bot_R.png new file mode 100644 index 000000000..50019bd8a Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Bot_R.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Mid_L.png b/game/assets/gui/console/Graphics/Panel_Recess_Mid_L.png new file mode 100644 index 000000000..3637ea85f Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Mid_L.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Mid_M.png b/game/assets/gui/console/Graphics/Panel_Recess_Mid_M.png new file mode 100644 index 000000000..3375e76d4 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Mid_M.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Mid_R.png b/game/assets/gui/console/Graphics/Panel_Recess_Mid_R.png new file mode 100644 index 000000000..61bed2907 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Mid_R.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Top_L.png b/game/assets/gui/console/Graphics/Panel_Recess_Top_L.png new file mode 100644 index 000000000..5bf72110b Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Top_L.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Top_M.png b/game/assets/gui/console/Graphics/Panel_Recess_Top_M.png new file mode 100644 index 000000000..cb18fa9c7 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Top_M.png differ diff --git a/game/assets/gui/console/Graphics/Panel_Recess_Top_R.png b/game/assets/gui/console/Graphics/Panel_Recess_Top_R.png new file mode 100644 index 000000000..2868493a7 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_Recess_Top_R.png differ diff --git a/game/assets/gui/console/Graphics/Panel_TL.png b/game/assets/gui/console/Graphics/Panel_TL.png new file mode 100644 index 000000000..96e419ad8 Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_TL.png differ diff --git a/game/assets/gui/console/Graphics/Panel_TM.png b/game/assets/gui/console/Graphics/Panel_TM.png new file mode 100644 index 000000000..bce1e67ae Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_TM.png differ diff --git a/game/assets/gui/console/Graphics/Panel_TR.png b/game/assets/gui/console/Graphics/Panel_TR.png new file mode 100644 index 000000000..db515994e Binary files /dev/null and b/game/assets/gui/console/Graphics/Panel_TR.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_BL.png b/game/assets/gui/console/Graphics/PointerTextPanel_BL.png new file mode 100644 index 000000000..0d30999f5 Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_BL.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_BM.png b/game/assets/gui/console/Graphics/PointerTextPanel_BM.png new file mode 100644 index 000000000..3f785acf0 Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_BM.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_BR.png b/game/assets/gui/console/Graphics/PointerTextPanel_BR.png new file mode 100644 index 000000000..5f486aeb3 Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_BR.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_ML.png b/game/assets/gui/console/Graphics/PointerTextPanel_ML.png new file mode 100644 index 000000000..4957d7389 Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_ML.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_MM.png b/game/assets/gui/console/Graphics/PointerTextPanel_MM.png new file mode 100644 index 000000000..33e385b77 Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_MM.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_MR.png b/game/assets/gui/console/Graphics/PointerTextPanel_MR.png new file mode 100644 index 000000000..14c7a55dc Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_MR.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_TL.png b/game/assets/gui/console/Graphics/PointerTextPanel_TL.png new file mode 100644 index 000000000..dab3969c9 Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_TL.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_TM.png b/game/assets/gui/console/Graphics/PointerTextPanel_TM.png new file mode 100644 index 000000000..22b4646ba Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_TM.png differ diff --git a/game/assets/gui/console/Graphics/PointerTextPanel_TR.png b/game/assets/gui/console/Graphics/PointerTextPanel_TR.png new file mode 100644 index 000000000..beda32167 Binary files /dev/null and b/game/assets/gui/console/Graphics/PointerTextPanel_TR.png differ diff --git a/game/assets/gui/console/Graphics/Slider_Button.png b/game/assets/gui/console/Graphics/Slider_Button.png new file mode 100644 index 000000000..8d6042a50 Binary files /dev/null and b/game/assets/gui/console/Graphics/Slider_Button.png differ diff --git a/game/assets/gui/console/Graphics/Slider_Track.png b/game/assets/gui/console/Graphics/Slider_Track.png new file mode 100644 index 000000000..ca343aa85 Binary files /dev/null and b/game/assets/gui/console/Graphics/Slider_Track.png differ diff --git a/game/assets/gui/console/Graphics/Tick.png b/game/assets/gui/console/Graphics/Tick.png new file mode 100644 index 000000000..112b1e919 Binary files /dev/null and b/game/assets/gui/console/Graphics/Tick.png differ diff --git a/game/assets/gui/console/Graphics/Tickbox_Norm.png b/game/assets/gui/console/Graphics/Tickbox_Norm.png new file mode 100644 index 000000000..a9a273b77 Binary files /dev/null and b/game/assets/gui/console/Graphics/Tickbox_Norm.png differ diff --git a/game/assets/gui/console/Graphics/Tickbox_Over.png b/game/assets/gui/console/Graphics/Tickbox_Over.png new file mode 100644 index 000000000..6419307f5 Binary files /dev/null and b/game/assets/gui/console/Graphics/Tickbox_Over.png differ diff --git a/game/assets/gui/console/Panel.png b/game/assets/gui/console/Panel.png new file mode 100644 index 000000000..5d42fbb94 Binary files /dev/null and b/game/assets/gui/console/Panel.png differ diff --git a/game/assets/gui/console/Panel_Bot_L.png b/game/assets/gui/console/Panel_Bot_L.png new file mode 100644 index 000000000..0002ab98a Binary files /dev/null and b/game/assets/gui/console/Panel_Bot_L.png differ diff --git a/game/assets/gui/console/Panel_Bot_M.png b/game/assets/gui/console/Panel_Bot_M.png new file mode 100644 index 000000000..20b312732 Binary files /dev/null and b/game/assets/gui/console/Panel_Bot_M.png differ diff --git a/game/assets/gui/console/Panel_Bot_R.png b/game/assets/gui/console/Panel_Bot_R.png new file mode 100644 index 000000000..af929caed Binary files /dev/null and b/game/assets/gui/console/Panel_Bot_R.png differ diff --git a/game/assets/gui/console/Panel_Mid_L.png b/game/assets/gui/console/Panel_Mid_L.png new file mode 100644 index 000000000..2eabadbee Binary files /dev/null and b/game/assets/gui/console/Panel_Mid_L.png differ diff --git a/game/assets/gui/console/Panel_Mid_M.png b/game/assets/gui/console/Panel_Mid_M.png new file mode 100644 index 000000000..924f60c18 Binary files /dev/null and b/game/assets/gui/console/Panel_Mid_M.png differ diff --git a/game/assets/gui/console/Panel_Mid_R.png b/game/assets/gui/console/Panel_Mid_R.png new file mode 100644 index 000000000..5ae969b4e Binary files /dev/null and b/game/assets/gui/console/Panel_Mid_R.png differ diff --git a/game/assets/gui/console/Panel_Top_L.png b/game/assets/gui/console/Panel_Top_L.png new file mode 100644 index 000000000..e71069561 Binary files /dev/null and b/game/assets/gui/console/Panel_Top_L.png differ diff --git a/game/assets/gui/console/Panel_Top_M.png b/game/assets/gui/console/Panel_Top_M.png new file mode 100644 index 000000000..5c4eeabaa Binary files /dev/null and b/game/assets/gui/console/Panel_Top_M.png differ diff --git a/game/assets/gui/console/Panel_Top_R.png b/game/assets/gui/console/Panel_Top_R.png new file mode 100644 index 000000000..2d115e949 Binary files /dev/null and b/game/assets/gui/console/Panel_Top_R.png differ diff --git a/game/assets/gui/console/Panorama_Background_N.png b/game/assets/gui/console/Panorama_Background_N.png new file mode 100644 index 000000000..53f9216da Binary files /dev/null and b/game/assets/gui/console/Panorama_Background_N.png differ diff --git a/game/assets/gui/console/Panorama_Background_S.png b/game/assets/gui/console/Panorama_Background_S.png new file mode 100644 index 000000000..bbbf629a2 Binary files /dev/null and b/game/assets/gui/console/Panorama_Background_S.png differ diff --git a/game/assets/gui/console/scrollDown.png b/game/assets/gui/console/scrollDown.png new file mode 100644 index 000000000..16b5ee49b Binary files /dev/null and b/game/assets/gui/console/scrollDown.png differ diff --git a/game/assets/gui/console/scrollUp.png b/game/assets/gui/console/scrollUp.png new file mode 100644 index 000000000..cd5569dee Binary files /dev/null and b/game/assets/gui/console/scrollUp.png differ diff --git a/game/assets/gui/container/entity_slot.png b/game/assets/gui/container/entity_slot.png new file mode 100644 index 000000000..28e251b31 Binary files /dev/null and b/game/assets/gui/container/entity_slot.png differ diff --git a/game/assets/gui/inventory.png b/game/assets/gui/inventory.png index f32ea120b..3df737b75 100644 Binary files a/game/assets/gui/inventory.png and b/game/assets/gui/inventory.png differ diff --git a/game/assets/gui/loading_background.png b/game/assets/gui/loading_background.png new file mode 100644 index 000000000..7e71337de Binary files /dev/null and b/game/assets/gui/loading_background.png differ diff --git a/game/assets/gui/loading_bar.png b/game/assets/gui/loading_bar.png new file mode 100644 index 000000000..52913ed07 Binary files /dev/null and b/game/assets/gui/loading_bar.png differ diff --git a/game/assets/gui/loading_block.png b/game/assets/gui/loading_block.png new file mode 100644 index 000000000..90a083435 Binary files /dev/null and b/game/assets/gui/loading_block.png differ diff --git a/game/assets/gui/slider_highlight.png b/game/assets/gui/slider_highlight.png new file mode 100644 index 000000000..cf8afab20 Binary files /dev/null and b/game/assets/gui/slider_highlight.png differ diff --git a/game/assets/gui/text_field.png b/game/assets/gui/text_field.png new file mode 100644 index 000000000..951643690 Binary files /dev/null and b/game/assets/gui/text_field.png differ diff --git a/game/assets/gui/text_field_highlighted.png b/game/assets/gui/text_field_highlighted.png new file mode 100644 index 000000000..59e7884a1 Binary files /dev/null and b/game/assets/gui/text_field_highlighted.png differ diff --git a/game/assets/lang/en_us.json b/game/assets/lang/en_us.json index 2bf3219ef..f4499f2d2 100644 --- a/game/assets/lang/en_us.json +++ b/game/assets/lang/en_us.json @@ -1,4 +1,75 @@ { + "loadingTip.C418": "Music by C418!", + "loadingTip.animalDespawn": "If an animal can't move more than 20 blocks in any direction, it won't despawn.", + "loadingTip.auMinecon": "Were you at Minecon?", + "loadingTip.bonemeal": "Bonemeal (crafted from a skeleton bone) can be used as a fertilizer, and can make things grow instantly!", + "loadingTip.bugs": "Do not look directly at the bugs.", + "loadingTip.cactus": "Cook cactus in a furnace to get green dye.", + "loadingTip.charcoal": "If you can't find any coal for your torches, you can always make charcoal from trees in a furnace.", + "loadingTip.chickenDuck": "Is it a chicken or is it a duck?", + "loadingTip.chickenEgg": "Chickens lay an egg every 5-10 minutes.", + "loadingTip.cookedPorkchop": "Eating cooked pork chops gives more health than eating raw pork chops.", + "loadingTip.coop": "Connect extra controllers to your computer and press %s on them to join a game at any point.", + "loadingTip.cowArmor": "Harvest leather from cows, and use it to make armor.", + "loadingTip.createObsidian": "Obsidian is created when water hits a lava source block.", + "loadingTip.creeperBorn": "Creepers were born from a coding bug.", + "loadingTip.creeperPowder": "Creepers are the easiest obtainable source of gunpowder.", + "loadingTip.deadmau5": "deadmau5 likes Minecraft!", + "loadingTip.digObsidian": "Obsidian can only be mined with a diamond or diamond pickaxe.", + "loadingTip.diggingDown": "Digging straight down or straight up is not a great idea.", + "loadingTip.diggingSoil": "Digging soil or sand with a spade is faster than with your hand!", + "loadingTip.emptyBucket": "If you have an empty bucket, you can fill it with milk from a cow, or water, or lava!", + "loadingTip.famousNotch": "Notch has over three million followers on twitter!", + "loadingTip.gameUpdate": "There will be an update to this game eventually!", + "loadingTip.gamma": "Alter the gamma settings to make the game brighter or darker.", + "loadingTip.ghastCobblestone": "Cobblestone is resistant to Ghast fireballs, making it useful for guarding portals.", + "loadingTip.ghastFireball": "Hit those fireballs back at the Ghast!", + "loadingTip.hoe": "Use a hoe to prepare areas of ground for planting.", + "loadingTip.junkboysFace": "No-one at Mojang has ever seen junkboy's face.", + "loadingTip.largeChest": "Placing two chests side by side will make one large chest.", + "loadingTip.lavaSmelt": "A single bucket of lava can be used in a furnace to smelt 100 blocks.", + "loadingTip.legacyInfo": "You'll get the latest info on this game from minecraft.net!", + "loadingTip.lightMelt": "Blocks that can be used as a light source will melt snow and ice. This includes torches, glowstone, and Jack O'Lanterns.", + "loadingTip.minecart": "Get to destinations faster with a minecart and rail!", + "loadingTip.mineconCalifornia": "Minecon 2016 was in Anaheim, California, USA!", + "loadingTip.mineconLasVegas": "Minecon 2011 was in Las Vegas, Nevada, USA!", + "loadingTip.mineconLondon": "Minecon 2015 was in London, UK!", + "loadingTip.mineconParis": "Minecon 2012 was in Paris, France!", + "loadingTip.minecraftFamous": "Some famous people play Minecraft!", + "loadingTip.minecraftForum": "minecraftforum has a section dedicated to the Java Edition.", + "loadingTip.minecraftRecords": "Java Edition broke lots of records!", + "loadingTip.minecraftWiki": "Did you know there's a Minecraft Wiki?", + "loadingTip.mojangAwards": "Mojang has more awards than staff!", + "loadingTip.mojangOffice": "Mojang's new office is cool!", + "loadingTip.netherPortal": "Building a portal will allow you to travel to another dimension - The Nether.", + "loadingTip.neutralMobs": "Attacking a wolf will cause any wolves in the immediate vicinity to turn hostile and attack you. This trait is also shared by Zombie Pigmans.", + "loadingTip.neutralPigman": "Zombie Pigmans won't attack you, unless you attack them.", + "loadingTip.neutralSpiders": "Spiders won't attack you during the day - unless you attack them.", + "loadingTip.noteBlockInstrument": "The instrument played by a note block depends on the material beneath it.", + "loadingTip.ohCreeper": "Creepers explode when they get close to you!", + "loadingTip.party": ".party() was excellent!", + "loadingTip.peaceful": "If you set the game difficulty to Peaceful no monsters will come out at night!", + "loadingTip.porkchop": "Harvest pork chops from pigs, and cook and eat them to regain health.", + "loadingTip.removedHerobrine": "We think Mojang has removed Herobrine from the Java Edition, but we're not too sure.", + "loadingTip.rightTool": "Use the right tool for the job!", + "loadingTip.rumors": "Always assume rumors are false, rather than assuming they're true!", + "loadingTip.saplingGrow": "Plant some saplings and they'll grow into trees.", + "loadingTip.sleepingBed": "Sleeping in a bed at night will fast forward the game to dawn, but all players in a multiplayer game need to sleep in beds at the same time.", + "loadingTip.slowLava": "Lava can take minutes to disappear COMPLETELY when the source block is removed.", + "loadingTip.spawnPoint": "You can change your game spawn point and skip to dawn by sleeping in a bed.", + "loadingTip.stackableFences": "Stackable fences are in the game now!", + "loadingTip.swedishCuriosity": "Not all Swedish people have blonde hair. Some, like Jens from Mojang, even have ginger hair!", + "loadingTip.torches": "Make some torches to light up areas at night. Monsters will avoid the areas around these torches.", + "loadingTip.undeadMobs": "Zombies and Skeletons can survive daylight if they are in water.", + "loadingTip.unknownMinecon": "No-one can remember where Minecon 2014 was held.", + "loadingTip.updateInfo": "Read the What's New section in the How To Play menus to see the latest update information about the game.", + "loadingTip.whoNotch": "Who is Notch?", + "loadingTip.wolfCreeper": "Wolves won't attack Creepers.", + "loadingTip.wolfTail": "Tame wolves show their health with the position of their tail. Feed them meat to heal them.", + "loadingTip.wolfTame": "Feed a bone to a wolf to tame it. You can then make it sit or follow you.", + "loadingTip.woolFire": "Take caution when building structures made of wool in open air, as lightning from thunderstorms can set wool on fire.", + "loading.initializing": "Initializing server", + "loading.spawnArea": "Loading spawn area", "options.thirdPerson": "Third Person View", "options.fancyGraphics": "Fancy Graphics", "options.blockOutlines": "Block Outlines", @@ -14,5 +85,42 @@ "options.debugText": "Debug Text", "options.2dTitleLogo": "2D Title Logo", "options.menuPanorama": "Menu Panorama", - "options.value": "%s: %s" + "options.uiTheme": "UI Theme", + "options.uiTheme.pocket": "Pocket", + "options.uiTheme.java": "Java", + "options.uiTheme.console": "Console", + "options.logoType": "Logo Type", + "options.logoType.auto": "Auto", + "options.logoType.pocket": "Pocket", + "options.logoType.java": "Java", + "options.logoType.console": "Console", + "options.logoType.xbox360": "Xbox 360", + "options.logoType.logo3d": "3D", + "options.hudSize": "HUD Size", + "options.value": "%s: %s", + "options.difficulty.peaceful.desc": "In this mode, the player regains health over time, and there are no enemies in the environment.", + "options.difficulty.easy.desc": "In this mode, enemies spawn in the environment, but will do less damage to the player than in the Normal mode.", + "options.difficulty.normal.desc": "In this mode, enemies spawn in the environment, and will do a standard amount of damage to the player.", + "options.difficulty.hard.desc": "In this mode, enemies will spawn in the environment, and will do a great deal of damage to the player. Watch out for the Creepers too, since they are unlikely to cancel their exploding attack when you move away from them!", + "mainMenu.playGame": "Play Game", + "mainMenu.leaderboards": "Leaderboards", + "mainMenu.achievements": "Achievements", + "mainMenu.helpAndOptions": "Help & Options", + "mainMenu.download": "Download Content", + "mainMenu.exitGame": "Exit Game", + "settingsMenu.howToPlay": "How To Play", + "settingsMenu.controls": "Controls", + "settingsMenu.settings": "Settings", + "settingsMenu.credits": "Credits", + "settingsMenu.resetToDefaults": "Reset To Defaults", + "playGame.start": "Start Game", + "playGame.join": "Join Game", + "playGame.createNewWorld": "Create New World", + "playGame.tutorial": "Play Tutorial", + "playGame.joinButton": "%s's Game", + "playGame.noGamesFound": "No Games Found", + "playGame.online": "Online game", + "playGame.inviteOnly": "Invite only", + "pauseMenu.resume": "Resume Game", + "pauseMenu.saveGame": "Save Game" } \ No newline at end of file diff --git a/game/assets/materials/ui.material b/game/assets/materials/ui.material index 8a00b83a8..73b1858d0 100644 --- a/game/assets/materials/ui.material +++ b/game/assets/materials/ui.material @@ -36,9 +36,6 @@ }, "ui_text:ui_texture_and_color": { - "states": [ - "EnableAlphaTest" - ], "fragmentShader": "shaders/text.fragment" }, diff --git a/game/assets/readme.txt b/game/assets/readme.txt index 9538bd391..3a9328e20 100644 --- a/game/assets/readme.txt +++ b/game/assets/readme.txt @@ -1,11 +1,12 @@ Texture credits: +Cjnator38: adapting XSSheep and Goodly's UI textures for use in the console GUI theme GGO4: parts of items.png, parts of terrain.png, cow.png glitchy8015: pack.png, unknown_pack.png Goodly: parts of terrain.png, all mobs except the cow, All of gui.png except touch buttons, clouds.png, font/default.png, p_rose.png, parts of p_crying_obsidian.png iProgramMC: parts of terrain.png, parts of p_crying_obsidian.png Un1q32: parts of terrain.png, particles.png, parts of items.png, p_camera.png -XSSheep: parts of terrain.png, almost all of items.png, arrows.png, pumpkinblur.png, sun.png, moon.png, icons.png, inventory.png, crafting.png, container.png, furnace.png, trap.png Vimdo: touchgui.png, and gui2.png, including the touch d-pad, pause, chat, and pocket ui elements +XSSheep: parts of terrain.png, almost all of items.png, arrows.png, pumpkinblur.png, sun.png, moon.png, icons.png, inventory.png, crafting.png, container.png, furnace.png, trap.png GGO4's textures are licensed under https://mit-license.org/ XSSheep's textures are licensed under https://creativecommons.org/licenses/by-sa/4.0/ diff --git a/game/assets/resource_packs/minecraft/.gitignore b/game/assets/resource_packs/minecraft/.gitignore old mode 100644 new mode 100755 diff --git a/game/assets/resource_packs/minecraft/pack.txt b/game/assets/resource_packs/minecraft/pack.txt old mode 100644 new mode 100755 diff --git a/game/assets/texts/tips.json b/game/assets/texts/tips.json new file mode 100644 index 000000000..2117623b4 --- /dev/null +++ b/game/assets/texts/tips.json @@ -0,0 +1,212 @@ +[ + { + "translate": "loadingTip.hoe" + }, + { + "translate": "loadingTip.spawnPoint" + }, + { + "translate": "loadingTip.famousNotch" + }, + { + "translate": "loadingTip.netherPortal" + }, + { + "translate": "loadingTip.cookedPorkchop" + }, + { + "translate": "loadingTip.bugs" + }, + { + "translate": "loadingTip.torches" + }, + { + "translate": "loadingTip.woolFire" + }, + { + "translate": "loadingTip.swedishCuriosity" + }, + { + "translate": "loadingTip.neutralSpiders" + }, + { + "translate": "loadingTip.diggingDown" + }, + { + "translate": "loadingTip.minecraftWiki" + }, + { + "translate": "loadingTip.noteBlockInstrument" + }, + { + "translate": "loadingTip.ohCreeper" + }, + { + "translate": "loadingTip.removedHerobrine" + }, + { + "translate": "loadingTip.sleepingBed" + }, + { + "translate": "loadingTip.diggingSoil" + }, + { + "translate": "loadingTip.whoNotch" + }, + { + "translate": "loadingTip.saplingGrow" + }, + { + "translate": "loadingTip.emptyBucket" + }, + { + "translate": "loadingTip.minecraftRecords" + }, + { + "translate": "loadingTip.ghastCobblestone" + }, + { + "translate": "loadingTip.minecart" + }, + { + "translate": "loadingTip.ghastFireball" + }, + { + "translate": "loadingTip.charcoal" + }, + { + "translate": "loadingTip.minecraftFamous" + }, + { + "translate": "loadingTip.rightTool" + }, + { + "translate": "loadingTip.gamma" + }, + { + "translate": "loadingTip.auMinecon" + }, + { + "translate": "loadingTip.bonemeal" + }, + { + "translate": "loadingTip.porkchop" + }, + { + "translate": "loadingTip.creeperBorn" + }, + { + "translate": "loadingTip.largeChest" + }, + { + "translate": "loadingTip.legacyInfo" + }, + { + "translate": "loadingTip.chickenDuck" + }, + { + "translate": "loadingTip.cactus" + }, + { + "translate": "loadingTip.digObsidian" + }, + { + "translate": "loadingTip.junkboysFace" + }, + { + "translate": "loadingTip.chickenEgg" + }, + { + "translate": "loadingTip.cowArmor" + }, + { + "translate": "loadingTip.deadmau5" + }, + { + "translate": "loadingTip.lightMelt" + }, + { + "translate": "loadingTip.neutralPigman" + }, + { + "translate": "loadingTip.gameUpdate" + }, + { + "translate": "loadingTip.wolfTame" + }, + { + "translate": "loadingTip.peaceful" + }, + { + "translate": "loadingTip.mojangAwards" + }, + { + "translate": "loadingTip.creeperPowder" + }, + { + "translate": "loadingTip.wolfCreeper" + }, + { + "translate": "loadingTip.mineconParis" + }, + { + "translate": "loadingTip.createObsidian" + }, + { + "translate": "loadingTip.wolfTail" + }, + { + "translate": "loadingTip.mojangOffice" + }, + { + "translate": "loadingTip.neutralMobs" + }, + { + "translate": "loadingTip.slowLava" + }, + { + "translate": "loadingTip.party" + }, + { + "translate": "loadingTip.lavaSmelt" + }, + { + "translate": "loadingTip.undeadMobs" + }, + { + "translate": "loadingTip.mineconLasVegas" + }, + { + "translate": "loadingTip.minecraftForum" + }, + { + "translate": "loadingTip.stackableFences" + }, + { + "translate": "loadingTip.unknownMinecon" + }, + { + "translate": "loadingTip.rumors" + }, + { + "translate": "loadingTip.updateInfo" + }, + { + "translate": "loadingTip.animalFollow" + }, + { + "translate": "loadingTip.mineconLondon" + }, + { + "tip": { + "translate": "loadingTip.coop" + }, + "time": 0 + }, + { + "translate": "loadingTip.mineconCalifornia" + }, + { + "translate": "loadingTip.C418" + } +] \ No newline at end of file diff --git a/game/assets/title/splashes.txt b/game/assets/title/splashes.txt new file mode 100644 index 000000000..e93617875 --- /dev/null +++ b/game/assets/title/splashes.txt @@ -0,0 +1,337 @@ +One star! Deal with it notch! +100% more yellow text! +Glowing creepy eyes! +Toilet friendly! +Annoying touch buttons! +Astronomically accurate! +0xffff-1 chunks! +Cubism! +Pocket! +Mostly harmless! +!!!1! +Dramatic lighting! +As seen on TV! +Awesome! +100% pure! +May contain nuts! +Better than Prey! +Less polygons! +Sexy! +Limited edition! +Flashing letters! +Made by Mojang! +It's here! +Best in class! +It's alpha! +100% dragon free! +Excitement! +More than 500 sold! +One of a kind! +Heaps of hits on YouTube! +Indev! +Spiders everywhere! +Check it out! +Holy cow, man! +It's a game! +Made in Sweden! +Uses C++! +Reticulating splines! +Minecraft! +Yaaay! +Multiplayer! +Touch compatible! +Undocumented! +Ingots! +Exploding creepers! +That's no moon! +l33t! +Create! +Survive! +Dungeon! +Exclusive! +The bee's knees! +Down with O.P.P.! +Open source! +Classy! +Wow! +Not on steam! +Oh man! +Awesome community! +Pixels! +Teetsuuuuoooo! +Kaaneeeedaaaa! +Enhanced! +90% bug free! +Pretty! +12 herbs and spices! +Fat free! +Absolutely no memes! +Free dental! +Ask your doctor! +Minors welcome! +Cloud computing! +Legal in Finland! +Hard to label! +Technically good! +Bringing home the bacon! +Quite Indie! +GOTY! +Euclidian! +Now in 3D! +Inspirational! +Herregud! +Complex cellular automata! +Yes, sir! +Played by cowboys! +Thousands of colors! +Try it! +Age of Wonders is better! +Try the mushroom stew! +Sensational! +Hot tamale, hot hot tamale! +Play him off, keyboard cat! +Guaranteed! +Macroscopic! +Bring it on! +Random splash! +Call your mother! +Monster infighting! +Loved by millions! +Ultimate edition! +Freaky! +You've got a brand new key! +Water proof! +Uninflammable! +Whoa, dude! +All inclusive! +Tell your friends! +NP is not in P! +Notch <3 ez! +Livestreamed! +Haunted! +Polynomial! +Terrestrial! +All is full of love! +Full of stars! +Scientific! +Cooler than Spock! +Collaborate and listen! +Never dig down! +Take frequent breaks! +Not linear! +Han shot first! +Nice to meet you! +Buckets of lava! +Ride the pig! +Larger than Earth! +sqrt(-1) love you! +Phobos anomaly! +Punching wood! +Falling off cliffs! +0% sugar! +150% hyperbole! +Synecdoche! +Let's danec! +Seecret Friday update! +Ported implementation! +Lewd with two dudes with food! +Kiss the sky! +20 GOTO 10! +// [sic] +Verlet intregration! +Peter Griffin! +// Do not distribute! +Redistributable! +Cogito ergo sum! +4815162342 lines of code! +A skeleton popped out! +The Work of Notch! +The sum of its parts! +BTAF used to be good! +I miss ADOM! +umop-apisdn! +OICU812! +Bring me Ray Cokes! +Finger-licking! +Thematic! +Pneumatic! +Sublime! +Octagonal! +Une baguette! +Gargamel plays it! +Rita is the new top dog! +SWM forever! +Representing Edsbyn! +Matt Damon! +Supercalifragilisticexpialidocious! +Consummate V's! +Cow Tools! +Double buffered! +V-synched! +Fan fiction! +Flaxkikare! +Jason! Jason! Jason! +Hotter than the sun! +Internet enabled! +Autonomous! +Engage! +Fantasy! +DRR! DRR! DRR! +Kick it root down! +Regional resources! +Woo, facepunch! +Woo, somethingawful! +Woo, /v/! +Woo, tigsource! +Woo, minecraftforum! +Woo, worldofminecraft! +Woo, reddit! +Woo, 2pp! +Not Google anlyticsed! +Give us Gordon! +Tip your waiter! +Very fun! +12345 is a bad password! +Vote for net neutrality! +Lives in a pineapple under the sea! +Omnipotent! +Gasp! +...! +Bees, bees, bees, bees! +Haha, LOL! +Hampsterdance! +Switches and ores! +Menger sponge! +idspispopd! +Eple (original edit)! +So fresh, so clean! +Don't look directly at the bugs! +Oh, ok, Pigmen! +Scary! +Play Minecraft, Watch Topgear, Get Pig! +Twittered about! +Jump up, jump up, and get down! +Joel is neat! +A riddle, wrapped in a mystery! +Huge tracts of land! +Welcome to your Doom! +Stay a while, stay forever! +Stay a while and listen! +Treatment for your rash! +"Autological" is! +Information wants to be free! +"Almost never" is an interesting concept! +Lots of truthiness! +The creeper is a spy! +It's groundbreaking! +Let our battle's begin! +The sky is the limit! +Jeb has amazing hair! +Casual gaming! +Undefeated! +Kinda like Lemmings! +Follow the train, CJ! +Leveraging synergy! +DungeonQuest is unfair! +110813! +90210! +Tyrion would love it! +Also try VVVVVV! +Also try Super Meat Boy! +Also try Terraria! +Also try Mount And Blade! +Also try Project Zomboid! +Also try World of Goo! +Also try Limbo! +Also try Pixeljunk Shooter! +Also try Braid! +That's super! +Bread is pain! +Read more books! +Khaaaaaaaaan! +Less addictive than TV Tropes! +More addictive than lemonade! +Bigger than a bread box! +Millions of peaches! +Fnord! +This is my true form! +Totally forgot about Dre! +Don't bother with the clones! +Pumpkinhead! +Hobo humping slobo babe! +Endless! +Feature packed! +Boots with the fur! +Stop, hammertime! +Conventional! +Homeomorphic to a 3-sphere! +Doesn't avoid double negatives! +Place ALL the blocks! +Does barrel rolls! +Meeting expectations! +PC gaming since 1873! +Ghoughpteighbteau tchoghs! +Got your nose! +Haley loves Elan! +Afraid of the big, black bat! +Doesn't use the U-word! +Child's play! +See you next Friday or so! +150 bpm for 400000 minutes! +Technologic! +Funk soul brother! +Pumpa kungen! +Helo Cymru! +My life for Aiur! +Lennart lennart = new Lennart(); +I see your vocabulary has improved! +Who put it there? +You can't explain that! +if not ok then return end +SOPA means LOSER in Swedish! +Big Pointy Teeth! +Bekarton guards the gate! +Mmmph, mmph! +Don't feed avocados to parrots! +Swords for everyone! +Plz reply to my tweet! +.party()! +Take her pillow! +Put that cookie down! +Pretty scary! +I have a suggestion. +Now with extra hugs! +// Almost C++11! +Almost C++98! +Woah. +HURNERJSGER? +What's up, Doc? +// custom: +https://github.com/ReMinecraftPE/mcpe +100% (render)dragon free! +// Notch +Also try Minecraft! +Also try Noita! +Also try Castle Crashers! +Also try Unturned! +// TheBrokenRail +Also try Minecraft Pi Reborn! +// atipls +Also try RePocket! +// Wilyicaro +Also try PEtoLE! +Controller support! +Check out our GitHub! +Flint and steel! +I ... am Steve! +Nostalgic! +Now with graphics abstraction! +Now with HAL! +Supports PowerPC! +// These guys carried +The Work of Aron Nieminen! +The Work of Johan Bernhardsson! +The Work of Tommaso Checchi! +Woo, forge! +Woo, fabric! +Woo, newgrounds! \ No newline at end of file diff --git a/platforms/audio/directsound/SoundStreamDS.cpp b/platforms/audio/directsound/SoundStreamDS.cpp index f546433a1..adc7e335d 100644 --- a/platforms/audio/directsound/SoundStreamDS.cpp +++ b/platforms/audio/directsound/SoundStreamDS.cpp @@ -10,8 +10,6 @@ SoundStreamDS::SoundStreamDS(LPDIRECTSOUND ds) : m_totalBufferSize(0), m_isPlaying(false) { - //_createSource(); - _createBuffers(); _setVolume(getVolume()); } @@ -41,8 +39,9 @@ void SoundStreamDS::_createSource() desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_LOCSOFTWARE | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; desc.dwBufferBytes = m_totalBufferSize; // Set in _open desc.lpwfxFormat = &m_waveFormat; + desc.guid3DAlgorithm = GUID_NULL; - HRESULT hr = m_directsound->CreateSoundBuffer(&desc, &m_source, nullptr); + HRESULT hr = m_directsound->CreateSoundBuffer(&desc, &m_source, NULL); DS_ERROR_CHECK(hr); } diff --git a/platforms/audio/directsound/SoundSystemDS.cpp b/platforms/audio/directsound/SoundSystemDS.cpp index 5a779f4e5..2d4d72c0a 100644 --- a/platforms/audio/directsound/SoundSystemDS.cpp +++ b/platforms/audio/directsound/SoundSystemDS.cpp @@ -180,7 +180,7 @@ void SoundSystemDS::playAt(const SoundDesc& sound, const Vec3& pos, float volume bufferDesc.dwSize = sizeof(DSBUFFERDESC); //Because directsound does not support DSBCAPS_CTRL3D on a sound with 2 channels we can only do it on sounds with 1 channel - if (sound.m_header.m_channels == 1) + if (sound.m_header.m_channels == 1 && !is2D) { bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRL3D; } diff --git a/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj b/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj index 6424944c3..fbf89f9d5 100644 --- a/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj +++ b/platforms/macos/projects/Minecraft/Minecraft.xcodeproj/project.pbxproj @@ -198,6 +198,42 @@ 8435BB1A2DCD47F400D38282 /* SoundStreamOAL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8435BB182DCD47F400D38282 /* SoundStreamOAL.cpp */; }; 8441F98F2DB4E911005977BD /* SoundSystemOAL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8441F9862DB4E911005977BD /* SoundSystemOAL.cpp */; }; 8441F9962DB4E911005977BD /* SoundSystemOAL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8441F9862DB4E911005977BD /* SoundSystemOAL.cpp */; }; + 844336EB2F405D8E00EB3115 /* ScrollRenderer_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844336E92F405D8E00EB3115 /* ScrollRenderer_Console.cpp */; }; + 844336EC2F405D8E00EB3115 /* ScrollRenderer_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844336EA2F405D8E00EB3115 /* ScrollRenderer_Console.hpp */; }; + 844336F52F405DCA00EB3115 /* AreaNavigation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844336ED2F405DCA00EB3115 /* AreaNavigation.cpp */; }; + 844336F62F405DCA00EB3115 /* AreaNavigation.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844336EE2F405DCA00EB3115 /* AreaNavigation.hpp */; }; + 844336F72F405DCA00EB3115 /* ScreenChooser_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844336EF2F405DCA00EB3115 /* ScreenChooser_Console.cpp */; }; + 844336F82F405DCA00EB3115 /* ScreenChooser_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844336F02F405DCA00EB3115 /* ScreenChooser_Console.hpp */; }; + 844336F92F405DCA00EB3115 /* ScreenChooser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844336F12F405DCA00EB3115 /* ScreenChooser.cpp */; }; + 844336FA2F405DCA00EB3115 /* ScreenChooser.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844336F22F405DCA00EB3115 /* ScreenChooser.hpp */; }; + 844336FB2F405DCA00EB3115 /* VerticalLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844336F32F405DCA00EB3115 /* VerticalLayout.cpp */; }; + 844336FC2F405DCA00EB3115 /* VerticalLayout.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844336F42F405DCA00EB3115 /* VerticalLayout.hpp */; }; + 8443370B2F405E0600EB3115 /* CreateWorldScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844336FD2F405E0600EB3115 /* CreateWorldScreen_Console.cpp */; }; + 8443370C2F405E0600EB3115 /* CreateWorldScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844336FE2F405E0600EB3115 /* CreateWorldScreen_Console.hpp */; }; + 8443370D2F405E0600EB3115 /* OptionsScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844336FF2F405E0600EB3115 /* OptionsScreen_Console.cpp */; }; + 8443370E2F405E0600EB3115 /* OptionsScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337002F405E0600EB3115 /* OptionsScreen_Console.hpp */; }; + 8443370F2F405E0600EB3115 /* PanelScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337012F405E0600EB3115 /* PanelScreen_Console.cpp */; }; + 844337102F405E0600EB3115 /* PanelScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337022F405E0600EB3115 /* PanelScreen_Console.hpp */; }; + 844337112F405E0600EB3115 /* PauseScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337032F405E0600EB3115 /* PauseScreen_Console.cpp */; }; + 844337122F405E0600EB3115 /* PauseScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337042F405E0600EB3115 /* PauseScreen_Console.hpp */; }; + 844337132F405E0600EB3115 /* ProgressScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337052F405E0600EB3115 /* ProgressScreen_Console.cpp */; }; + 844337142F405E0600EB3115 /* ProgressScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337062F405E0600EB3115 /* ProgressScreen_Console.hpp */; }; + 844337152F405E0600EB3115 /* SelectWorldScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337072F405E0600EB3115 /* SelectWorldScreen_Console.cpp */; }; + 844337162F405E0600EB3115 /* SelectWorldScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337082F405E0600EB3115 /* SelectWorldScreen_Console.hpp */; }; + 844337172F405E0600EB3115 /* StartMenuScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337092F405E0600EB3115 /* StartMenuScreen_Console.cpp */; }; + 844337182F405E0600EB3115 /* StartMenuScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8443370A2F405E0600EB3115 /* StartMenuScreen_Console.hpp */; }; + 8443371B2F405E1C00EB3115 /* ClassicCraftingScreen_Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337192F405E1C00EB3115 /* ClassicCraftingScreen_Console.cpp */; }; + 8443371C2F405E1C00EB3115 /* ClassicCraftingScreen_Console.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8443371A2F405E1C00EB3115 /* ClassicCraftingScreen_Console.hpp */; }; + 844337272F405E5500EB3115 /* LogoRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8443371D2F405E5500EB3115 /* LogoRenderer.cpp */; }; + 844337282F405E5500EB3115 /* LogoRenderer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8443371E2F405E5500EB3115 /* LogoRenderer.hpp */; }; + 844337322F405E7500EB3115 /* TextureAtlas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337302F405E7500EB3115 /* TextureAtlas.cpp */; }; + 844337332F405E7500EB3115 /* TextureAtlas.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337312F405E7500EB3115 /* TextureAtlas.hpp */; }; + 844337382F405E9400EB3115 /* LoadingTipManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337342F405E9400EB3115 /* LoadingTipManager.cpp */; }; + 844337392F405E9400EB3115 /* LoadingTipManager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337352F405E9400EB3115 /* LoadingTipManager.hpp */; }; + 8443373A2F405E9400EB3115 /* SplashManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 844337362F405E9400EB3115 /* SplashManager.cpp */; }; + 8443373B2F405E9400EB3115 /* SplashManager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 844337372F405E9400EB3115 /* SplashManager.hpp */; }; + 8443373E2F4060AD00EB3115 /* TickBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8443373C2F4060AD00EB3115 /* TickBox.cpp */; }; + 8443373F2F4060AD00EB3115 /* TickBox.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 8443373D2F4060AD00EB3115 /* TickBox.hpp */; }; 8443B6EA2A98675F0086730C /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8443B6E92A98675F0086730C /* libSDL2.a */; }; 844496882E7668B0008CF2E0 /* libClient.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B8AEE72AF188D8008DE93D /* libClient.a */; }; 844496892E7668B0008CF2E0 /* libZLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 84498A832AF18C7A005EF5A5 /* libZLib.a */; }; @@ -2198,6 +2234,42 @@ 8435BB182DCD47F400D38282 /* SoundStreamOAL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SoundStreamOAL.cpp; sourceTree = ""; }; 8441F9852DB4E911005977BD /* CustomSoundSystem.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CustomSoundSystem.hpp; sourceTree = ""; }; 8441F9862DB4E911005977BD /* SoundSystemOAL.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SoundSystemOAL.cpp; sourceTree = ""; }; + 844336E92F405D8E00EB3115 /* ScrollRenderer_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollRenderer_Console.cpp; sourceTree = ""; }; + 844336EA2F405D8E00EB3115 /* ScrollRenderer_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ScrollRenderer_Console.hpp; sourceTree = ""; }; + 844336ED2F405DCA00EB3115 /* AreaNavigation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AreaNavigation.cpp; sourceTree = ""; }; + 844336EE2F405DCA00EB3115 /* AreaNavigation.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = AreaNavigation.hpp; sourceTree = ""; }; + 844336EF2F405DCA00EB3115 /* ScreenChooser_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreenChooser_Console.cpp; sourceTree = ""; }; + 844336F02F405DCA00EB3115 /* ScreenChooser_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ScreenChooser_Console.hpp; sourceTree = ""; }; + 844336F12F405DCA00EB3115 /* ScreenChooser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreenChooser.cpp; sourceTree = ""; }; + 844336F22F405DCA00EB3115 /* ScreenChooser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ScreenChooser.hpp; sourceTree = ""; }; + 844336F32F405DCA00EB3115 /* VerticalLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VerticalLayout.cpp; sourceTree = ""; }; + 844336F42F405DCA00EB3115 /* VerticalLayout.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VerticalLayout.hpp; sourceTree = ""; }; + 844336FD2F405E0600EB3115 /* CreateWorldScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CreateWorldScreen_Console.cpp; sourceTree = ""; }; + 844336FE2F405E0600EB3115 /* CreateWorldScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CreateWorldScreen_Console.hpp; sourceTree = ""; }; + 844336FF2F405E0600EB3115 /* OptionsScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionsScreen_Console.cpp; sourceTree = ""; }; + 844337002F405E0600EB3115 /* OptionsScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = OptionsScreen_Console.hpp; sourceTree = ""; }; + 844337012F405E0600EB3115 /* PanelScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PanelScreen_Console.cpp; sourceTree = ""; }; + 844337022F405E0600EB3115 /* PanelScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PanelScreen_Console.hpp; sourceTree = ""; }; + 844337032F405E0600EB3115 /* PauseScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PauseScreen_Console.cpp; sourceTree = ""; }; + 844337042F405E0600EB3115 /* PauseScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PauseScreen_Console.hpp; sourceTree = ""; }; + 844337052F405E0600EB3115 /* ProgressScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProgressScreen_Console.cpp; sourceTree = ""; }; + 844337062F405E0600EB3115 /* ProgressScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ProgressScreen_Console.hpp; sourceTree = ""; }; + 844337072F405E0600EB3115 /* SelectWorldScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectWorldScreen_Console.cpp; sourceTree = ""; }; + 844337082F405E0600EB3115 /* SelectWorldScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SelectWorldScreen_Console.hpp; sourceTree = ""; }; + 844337092F405E0600EB3115 /* StartMenuScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StartMenuScreen_Console.cpp; sourceTree = ""; }; + 8443370A2F405E0600EB3115 /* StartMenuScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StartMenuScreen_Console.hpp; sourceTree = ""; }; + 844337192F405E1C00EB3115 /* ClassicCraftingScreen_Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassicCraftingScreen_Console.cpp; sourceTree = ""; }; + 8443371A2F405E1C00EB3115 /* ClassicCraftingScreen_Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClassicCraftingScreen_Console.hpp; sourceTree = ""; }; + 8443371D2F405E5500EB3115 /* LogoRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LogoRenderer.cpp; sourceTree = ""; }; + 8443371E2F405E5500EB3115 /* LogoRenderer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LogoRenderer.hpp; sourceTree = ""; }; + 844337302F405E7500EB3115 /* TextureAtlas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureAtlas.cpp; sourceTree = ""; }; + 844337312F405E7500EB3115 /* TextureAtlas.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TextureAtlas.hpp; sourceTree = ""; }; + 844337342F405E9400EB3115 /* LoadingTipManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadingTipManager.cpp; sourceTree = ""; }; + 844337352F405E9400EB3115 /* LoadingTipManager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LoadingTipManager.hpp; sourceTree = ""; }; + 844337362F405E9400EB3115 /* SplashManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SplashManager.cpp; sourceTree = ""; }; + 844337372F405E9400EB3115 /* SplashManager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SplashManager.hpp; sourceTree = ""; }; + 8443373C2F4060AD00EB3115 /* TickBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TickBox.cpp; sourceTree = ""; }; + 8443373D2F4060AD00EB3115 /* TickBox.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TickBox.hpp; sourceTree = ""; }; 8443B6E92A98675F0086730C /* libSDL2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSDL2.a; path = /opt/local/lib/libSDL2.a; sourceTree = ""; }; 844496762E76685C008CF2E0 /* MinecraftClient.SDL1 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MinecraftClient.SDL1; sourceTree = BUILT_PRODUCTS_DIR; }; 8444968C2E7668E5008CF2E0 /* libSDL.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSDL.a; path = ../../../../../../../../../opt/local/libexec/libsdl12/lib/libSDL.a; sourceTree = ""; }; @@ -3221,6 +3293,8 @@ 840DD5862AC810620006A435 /* gui */ = { isa = PBXGroup; children = ( + 844336ED2F405DCA00EB3115 /* AreaNavigation.cpp */, + 844336EE2F405DCA00EB3115 /* AreaNavigation.hpp */, 840DD5872AC810620006A435 /* components */, 840DD5962AC810620006A435 /* Gui.cpp */, 840DD5972AC810620006A435 /* Gui.hpp */, @@ -3233,7 +3307,13 @@ 84E022F62F2A021E003C8FFE /* MenuPointer.hpp */, 840DD59A2AC810620006A435 /* Screen.cpp */, 840DD59B2AC810620006A435 /* Screen.hpp */, + 844336F12F405DCA00EB3115 /* ScreenChooser.cpp */, + 844336F22F405DCA00EB3115 /* ScreenChooser.hpp */, + 844336EF2F405DCA00EB3115 /* ScreenChooser_Console.cpp */, + 844336F02F405DCA00EB3115 /* ScreenChooser_Console.hpp */, 840DD59C2AC810620006A435 /* screens */, + 844336F32F405DCA00EB3115 /* VerticalLayout.cpp */, + 844336F42F405DCA00EB3115 /* VerticalLayout.hpp */, ); path = gui; sourceTree = ""; @@ -3251,6 +3331,8 @@ 840DD58D2AC810620006A435 /* RolledSelectionList.hpp */, 840DD58E2AC810620006A435 /* ScrolledSelectionList.cpp */, 840DD58F2AC810620006A435 /* ScrolledSelectionList.hpp */, + 844336E92F405D8E00EB3115 /* ScrollRenderer_Console.cpp */, + 844336EA2F405D8E00EB3115 /* ScrollRenderer_Console.hpp */, 84EE49E92F387DBD00677881 /* SliderButton.cpp */, 84EE49EA2F387DBD00677881 /* SliderButton.hpp */, 840DD5902AC810620006A435 /* SmallButton.cpp */, @@ -3261,6 +3343,8 @@ 84EE49EE2F387DBD00677881 /* SwitchValuesButton.hpp */, 840DD5922AC810620006A435 /* TextBox.cpp */, 840DD5932AC810620006A435 /* TextBox.hpp */, + 8443373C2F4060AD00EB3115 /* TickBox.cpp */, + 8443373D2F4060AD00EB3115 /* TickBox.hpp */, 840DD5942AC810620006A435 /* WorldSelectionList.cpp */, 840DD5952AC810620006A435 /* WorldSelectionList.hpp */, ); @@ -3278,6 +3362,8 @@ 84CED51E2E672826006BC585 /* ConvertWorldScreen.hpp */, 840DD5A12AC810620006A435 /* CreateWorldScreen.cpp */, 840DD5A22AC810620006A435 /* CreateWorldScreen.hpp */, + 844336FD2F405E0600EB3115 /* CreateWorldScreen_Console.cpp */, + 844336FE2F405E0600EB3115 /* CreateWorldScreen_Console.hpp */, 9D3996272F10E9C6002945D3 /* CreditsScreen.cpp */, 9D3996262F10E9C6002945D3 /* CreditsScreen.hpp */, 840DD5A32AC810620006A435 /* DeathScreen.cpp */, @@ -3297,18 +3383,30 @@ 840DD5AE2AC810620006A435 /* JoinGameScreen.hpp */, 840DD5AF2AC810620006A435 /* OptionsScreen.cpp */, 840DD5B02AC810620006A435 /* OptionsScreen.hpp */, + 844336FF2F405E0600EB3115 /* OptionsScreen_Console.cpp */, + 844337002F405E0600EB3115 /* OptionsScreen_Console.hpp */, + 844337012F405E0600EB3115 /* PanelScreen_Console.cpp */, + 844337022F405E0600EB3115 /* PanelScreen_Console.hpp */, 840DD5B12AC810620006A435 /* PauseScreen.cpp */, 840DD5B22AC810620006A435 /* PauseScreen.hpp */, + 844337032F405E0600EB3115 /* PauseScreen_Console.cpp */, + 844337042F405E0600EB3115 /* PauseScreen_Console.hpp */, 840DD5B32AC810620006A435 /* ProgressScreen.cpp */, 840DD5B42AC810620006A435 /* ProgressScreen.hpp */, + 844337052F405E0600EB3115 /* ProgressScreen_Console.cpp */, + 844337062F405E0600EB3115 /* ProgressScreen_Console.hpp */, 840DD5B52AC810620006A435 /* RenameMPLevelScreen.cpp */, 840DD5B62AC810620006A435 /* RenameMPLevelScreen.hpp */, 840DD5B72AC810620006A435 /* SavingWorldScreen.cpp */, 840DD5B82AC810620006A435 /* SavingWorldScreen.hpp */, 840DD5B92AC810620006A435 /* SelectWorldScreen.cpp */, 840DD5BA2AC810620006A435 /* SelectWorldScreen.hpp */, + 844337072F405E0600EB3115 /* SelectWorldScreen_Console.cpp */, + 844337082F405E0600EB3115 /* SelectWorldScreen_Console.hpp */, 840DD5BB2AC810620006A435 /* StartMenuScreen.cpp */, 840DD5BC2AC810620006A435 /* StartMenuScreen.hpp */, + 844337092F405E0600EB3115 /* StartMenuScreen_Console.cpp */, + 8443370A2F405E0600EB3115 /* StartMenuScreen_Console.hpp */, ); path = screens; sourceTree = ""; @@ -4658,6 +4756,8 @@ 84AA8BD82B32F3F3003F5B82 /* LightLayer.hpp */, 84AA8BD92B32F3F3003F5B82 /* LightUpdate.cpp */, 84AA8BDA2B32F3F3003F5B82 /* LightUpdate.hpp */, + 8443371D2F405E5500EB3115 /* LogoRenderer.cpp */, + 8443371E2F405E5500EB3115 /* LogoRenderer.hpp */, 84AA8BDB2B32F3F3003F5B82 /* PatchManager.cpp */, 84AA8BDC2B32F3F3003F5B82 /* PatchManager.hpp */, 84AA8BDD2B32F3F3003F5B82 /* RenderChunk.cpp */, @@ -4839,6 +4939,8 @@ children = ( 84E022E92F2A0211003C8FFE /* ChestScreen.cpp */, 84E022EA2F2A0211003C8FFE /* ChestScreen.hpp */, + 844337192F405E1C00EB3115 /* ClassicCraftingScreen_Console.cpp */, + 8443371A2F405E1C00EB3115 /* ClassicCraftingScreen_Console.hpp */, 84E022EB2F2A0211003C8FFE /* ContainerScreen.cpp */, 84E022EC2F2A0211003C8FFE /* ContainerScreen.hpp */, 84DED1962F3095B8004001C5 /* CraftingScreen.cpp */, @@ -4993,6 +5095,8 @@ 84EB09EA2EE2CCA8008FB007 /* ColorSpace.hpp */, 84EB09EB2EE2CCA8008FB007 /* ImageData.cpp */, 84EB09EC2EE2CCA8008FB007 /* ImageData.hpp */, + 844337302F405E7500EB3115 /* TextureAtlas.cpp */, + 844337312F405E7500EB3115 /* TextureAtlas.hpp */, 84EB09ED2EE2CCA8008FB007 /* TextureData.cpp */, 84EB09EE2EE2CCA8008FB007 /* TextureData.hpp */, ); @@ -5303,6 +5407,8 @@ children = ( 9DA5C63C2F2845F80039B697 /* AppResourceLoader.cpp */, 9DA5C63B2F2845F80039B697 /* AppResourceLoader.hpp */, + 844337342F405E9400EB3115 /* LoadingTipManager.cpp */, + 844337352F405E9400EB3115 /* LoadingTipManager.hpp */, 9DA5C63E2F2845F80039B697 /* Resource.cpp */, 9DA5C63D2F2845F80039B697 /* Resource.hpp */, 9DA5C6402F2845F80039B697 /* ResourceLoader.cpp */, @@ -5317,6 +5423,8 @@ 84F948222F2F5CB700217B16 /* ResourcePackManifest.hpp */, 84F948232F2F5CB700217B16 /* ResourcePackRepository.cpp */, 84F948242F2F5CB700217B16 /* ResourcePackRepository.hpp */, + 844337362F405E9400EB3115 /* SplashManager.cpp */, + 844337372F405E9400EB3115 /* SplashManager.hpp */, ); path = resources; sourceTree = ""; @@ -5534,12 +5642,15 @@ 84F77A692EA1C0A10045C907 /* MultiPlayerLevel.hpp in Headers */, 84B8AF372AF189D8008DE93D /* AppPlatform.hpp in Headers */, 84B8AF382AF189D8008DE93D /* Minecraft.hpp in Headers */, + 8443370E2F405E0600EB3115 /* OptionsScreen_Console.hpp in Headers */, 84B8AF392AF189D8008DE93D /* NinecraftApp.hpp in Headers */, + 844337282F405E5500EB3115 /* LogoRenderer.hpp in Headers */, 84E022F02F2A0211003C8FFE /* ChestScreen.hpp in Headers */, 84B8AF3A2AF189D8008DE93D /* AvailableGamesList.hpp in Headers */, 84B8AF3B2AF189D8008DE93D /* Button.hpp in Headers */, 8477B3A52C4DC374004E1AC5 /* ControllerMoveInput.hpp in Headers */, 84B8AF3C2AF189D8008DE93D /* RolledSelectionList.hpp in Headers */, + 8443373F2F4060AD00EB3115 /* TickBox.hpp in Headers */, 84B8AF3D2AF189D8008DE93D /* ScrolledSelectionList.hpp in Headers */, 84B8AF3E2AF189D8008DE93D /* SmallButton.hpp in Headers */, 84B8AF3F2AF189D8008DE93D /* TextBox.hpp in Headers */, @@ -5571,10 +5682,12 @@ 84B8AF522AF189D8008DE93D /* SelectWorldScreen.hpp in Headers */, 84B8AF532AF189D8008DE93D /* StartMenuScreen.hpp in Headers */, 84EB099C2EE2CC3B008FB007 /* GuiElement.hpp in Headers */, + 844337142F405E0600EB3115 /* ProgressScreen_Console.hpp in Headers */, 84DED1992F3095B8004001C5 /* CraftingScreen.hpp in Headers */, 84EB09D52EE2CC86008FB007 /* QuadrupedModel.hpp in Headers */, 84EB09F42EE2CCA8008FB007 /* RenderMaterialGroup.hpp in Headers */, 84B8AF582AF189D8008DE93D /* ClientSideNetworkHandler.hpp in Headers */, + 844337122F405E0600EB3115 /* PauseScreen_Console.hpp in Headers */, 84EE49F02F387DBD00677881 /* SliderButton.hpp in Headers */, 84B8AF592AF189D8008DE93D /* Options.hpp in Headers */, 84F77A6F2EA1C27B0045C907 /* LocalPlayer.hpp in Headers */, @@ -5593,6 +5706,7 @@ 84F66DE82F18C9DA00DE508E /* GameController.hpp in Headers */, 84B8AF7F2AF189D8008DE93D /* SoundDefs.hpp in Headers */, 84EB09D32EE2CC86008FB007 /* PigModel.hpp in Headers */, + 844336EC2F405D8E00EB3115 /* ScrollRenderer_Console.hpp in Headers */, 84B8AF802AF189D8008DE93D /* SoundEngine.hpp in Headers */, 84B8AF812AF189D8008DE93D /* SoundRepository.hpp in Headers */, 84B8AF822AF189D8008DE93D /* SoundSystem.hpp in Headers */, @@ -5600,6 +5714,8 @@ 84E0011D2AF39E84009B9555 /* CustomInputHolder.hpp in Headers */, 84E0011E2AF39E84009B9555 /* IArea.hpp in Headers */, 84E001202AF39E84009B9555 /* IBuildInput.hpp in Headers */, + 844336F82F405DCA00EB3115 /* ScreenChooser_Console.hpp in Headers */, + 844337392F405E9400EB3115 /* LoadingTipManager.hpp in Headers */, 84E001222AF39E84009B9555 /* IInputHolder.hpp in Headers */, 84E001242AF39E84009B9555 /* IMoveInput.hpp in Headers */, 84E001262AF39E84009B9555 /* IncludeExcludeArea.hpp in Headers */, @@ -5609,9 +5725,11 @@ 84E0012E2AF39E84009B9555 /* Multitouch.hpp in Headers */, 84E001302AF39E84009B9555 /* PolygonArea.hpp in Headers */, 84EB09DF2EE2CC86008FB007 /* ZombieModel.hpp in Headers */, + 844336FC2F405DCA00EB3115 /* VerticalLayout.hpp in Headers */, 84EE49F42F387DBD00677881 /* SwitchValuesButton.hpp in Headers */, 84E001322AF39E84009B9555 /* RectangleArea.hpp in Headers */, 84E001342AF39E84009B9555 /* TouchAreaModel.hpp in Headers */, + 8443371C2F405E1C00EB3115 /* ClassicCraftingScreen_Console.hpp in Headers */, 84E001362AF39E84009B9555 /* TouchInputHolder.hpp in Headers */, 84E001382AF39E84009B9555 /* TouchscreenInput_TestFps.hpp in Headers */, 84EE49F22F387DBD00677881 /* SwitchButton.hpp in Headers */, @@ -5627,6 +5745,7 @@ 9DA5C6472F2845F80039B697 /* Resource.hpp in Headers */, 9DA5C6482F2845F80039B697 /* ResourceLoader.hpp in Headers */, 9DA5C6492F2845F80039B697 /* AppResourceLoader.hpp in Headers */, + 844337182F405E0600EB3115 /* StartMenuScreen_Console.hpp in Headers */, 9DA5C64A2F2845F80039B697 /* ResourceLocation.hpp in Headers */, 84AA8BF02B32F3F3003F5B82 /* DynamicTexture.hpp in Headers */, 84AA8BF22B32F3F3003F5B82 /* ChickenRenderer.hpp in Headers */, @@ -5642,9 +5761,11 @@ 84E022F42F2A0211003C8FFE /* InventoryScreen.hpp in Headers */, 84AA8BFE2B32F3F3003F5B82 /* HumanoidMobRenderer.hpp in Headers */, 84AA8C002B32F3F3003F5B82 /* ItemRenderer.hpp in Headers */, + 844337102F405E0600EB3115 /* PanelScreen_Console.hpp in Headers */, 84AA8C022B32F3F3003F5B82 /* ItemSpriteRenderer.hpp in Headers */, 84AA8C042B32F3F3003F5B82 /* MobRenderer.hpp in Headers */, 84EB09D92EE2CC86008FB007 /* SheepModel.hpp in Headers */, + 844336F62F405DCA00EB3115 /* AreaNavigation.hpp in Headers */, 84AA8C062B32F3F3003F5B82 /* PigRenderer.hpp in Headers */, 84AA8C082B32F3F3003F5B82 /* SheepFurRenderer.hpp in Headers */, 84F9482A2F2F5CB700217B16 /* ResourcePackRepository.hpp in Headers */, @@ -5666,6 +5787,7 @@ 84AA8C232B32F3F3003F5B82 /* ItemInHandRenderer.hpp in Headers */, 84AA8C272B32F3F3003F5B82 /* LevelRenderer.hpp in Headers */, 84AA8C292B32F3F3003F5B82 /* LightLayer.hpp in Headers */, + 844337162F405E0600EB3115 /* SelectWorldScreen_Console.hpp in Headers */, 84EB09DB2EE2CC86008FB007 /* SkeletonModel.hpp in Headers */, 84A2FF182DB61D440090CE3E /* SoundPathRepository.hpp in Headers */, 84EB09FB2EE2CCA8008FB007 /* TextureData.hpp in Headers */, @@ -5673,12 +5795,15 @@ 84AA8C2B2B32F3F3003F5B82 /* LightUpdate.hpp in Headers */, 84AA8C2D2B32F3F3003F5B82 /* PatchManager.hpp in Headers */, 84AA8C2F2B32F3F3003F5B82 /* RenderChunk.hpp in Headers */, + 844337332F405E7500EB3115 /* TextureAtlas.hpp in Headers */, + 844336FA2F405DCA00EB3115 /* ScreenChooser.hpp in Headers */, 84CED5202E672826006BC585 /* ConvertWorldScreen.hpp in Headers */, 84F66DEC2F18C9DA00DE508E /* GameControllerManager.hpp in Headers */, 84A2FF162DB5B7B70090CE3E /* AssetFile.hpp in Headers */, 84AA8C312B32F3F3003F5B82 /* RenderList.hpp in Headers */, 84AA8C332B32F3F3003F5B82 /* Tesselator.hpp in Headers */, 84AA8C342B32F3F3003F5B82 /* Texture.hpp in Headers */, + 8443373B2F405E9400EB3115 /* SplashManager.hpp in Headers */, 84AA8C362B32F3F3003F5B82 /* Textures.hpp in Headers */, 84AA8C382B32F3F3003F5B82 /* TileRenderer.hpp in Headers */, 84AA8C392B32F3F3003F5B82 /* VertexPT.hpp in Headers */, @@ -5687,6 +5812,7 @@ 84EB099D2EE2CC3B008FB007 /* IntRectangle.hpp in Headers */, 84EB09972EE2CC25008FB007 /* AppPlatformListener.hpp in Headers */, 8477B3A72C4DC374004E1AC5 /* MouseBuildInput.hpp in Headers */, + 8443370C2F405E0600EB3115 /* CreateWorldScreen_Console.hpp in Headers */, 84E78C802B58B5CC00D515EF /* RocketRenderer.hpp in Headers */, 84F948262F2F5CB700217B16 /* ResourcePack.hpp in Headers */, 8470AF412BE9B80900BCA54E /* DisconnectionScreen.hpp in Headers */, @@ -6642,13 +6768,17 @@ 84B1E0632E05194A00ED000A /* stb_vorbis.c in Sources */, 84B8AEFD2AF1896F008DE93D /* InvalidLicenseScreen.cpp in Sources */, 84B8AEFE2AF1896F008DE93D /* JoinGameScreen.cpp in Sources */, + 844336FB2F405DCA00EB3115 /* VerticalLayout.cpp in Sources */, 84B8AEFF2AF1896F008DE93D /* OptionsScreen.cpp in Sources */, 84B8AF002AF1896F008DE93D /* PauseScreen.cpp in Sources */, 84B8AF012AF1896F008DE93D /* ProgressScreen.cpp in Sources */, + 8443370B2F405E0600EB3115 /* CreateWorldScreen_Console.cpp in Sources */, 84B8AF022AF1896F008DE93D /* RenameMPLevelScreen.cpp in Sources */, + 844337272F405E5500EB3115 /* LogoRenderer.cpp in Sources */, 84F66DE72F18C9DA00DE508E /* GameController.cpp in Sources */, 84B8AF032AF1896F008DE93D /* SavingWorldScreen.cpp in Sources */, 84B8AF042AF1896F008DE93D /* SelectWorldScreen.cpp in Sources */, + 8443373E2F4060AD00EB3115 /* TickBox.cpp in Sources */, 84F66DE92F18C9DA00DE508E /* GameControllerHandler.cpp in Sources */, 84B8AF052AF1896F008DE93D /* StartMenuScreen.cpp in Sources */, 8477B3A22C4DC374004E1AC5 /* ControllerBuildInput.cpp in Sources */, @@ -6662,6 +6792,7 @@ 84B8AF102AF1896F008DE93D /* KeyboardInput.cpp in Sources */, 84E022F12F2A0211003C8FFE /* ContainerScreen.cpp in Sources */, 84F948272F2F5CB700217B16 /* ResourcePackManifest.cpp in Sources */, + 8443373A2F405E9400EB3115 /* SplashManager.cpp in Sources */, 84B8AF112AF1896F008DE93D /* Mouse.cpp in Sources */, 84B8AF122AF1896F008DE93D /* MouseTurnInput.cpp in Sources */, 84B8AF322AF1896F008DE93D /* SoundData.cpp in Sources */, @@ -6684,6 +6815,7 @@ 84B8AEEF2AF1890A008DE93D /* ScrolledSelectionList.cpp in Sources */, 84B8AEF02AF1890A008DE93D /* SmallButton.cpp in Sources */, 84B8AEF12AF1890A008DE93D /* TextBox.cpp in Sources */, + 844336F72F405DCA00EB3115 /* ScreenChooser_Console.cpp in Sources */, 84EB09F12EE2CCA8008FB007 /* EntityShaderManager.cpp in Sources */, 84CED51F2E672826006BC585 /* ConvertWorldScreen.cpp in Sources */, 84B8AEF22AF1890A008DE93D /* WorldSelectionList.cpp in Sources */, @@ -6696,6 +6828,7 @@ 84EB09D02EE2CC86008FB007 /* Model.cpp in Sources */, 84B8AEF72AF1890A008DE93D /* ConfirmScreen.cpp in Sources */, 84E022EF2F2A0211003C8FFE /* ChestScreen.cpp in Sources */, + 844337322F405E7500EB3115 /* TextureAtlas.cpp in Sources */, 84EE49F12F387DBD00677881 /* SwitchButton.cpp in Sources */, 84F948292F2F5CB700217B16 /* ResourcePackRepository.cpp in Sources */, 84B8AEF82AF1890A008DE93D /* CreateWorldScreen.cpp in Sources */, @@ -6710,6 +6843,7 @@ 84EB09DA2EE2CC86008FB007 /* SkeletonModel.cpp in Sources */, 84E001272AF39E84009B9555 /* ITouchScreenModel.cpp in Sources */, 84E001292AF39E84009B9555 /* MouseDevice.cpp in Sources */, + 8443370D2F405E0600EB3115 /* OptionsScreen_Console.cpp in Sources */, 84E0012B2AF39E84009B9555 /* MouseHandler.cpp in Sources */, 84E0012D2AF39E84009B9555 /* Multitouch.cpp in Sources */, 84E0012F2AF39E84009B9555 /* PolygonArea.cpp in Sources */, @@ -6725,16 +6859,20 @@ 84AA8BED2B32F3F3003F5B82 /* Culler.cpp in Sources */, 9DA5C64B2F2845F80039B697 /* ResourceLocation.cpp in Sources */, 9DA5C64C2F2845F80039B697 /* AppResourceLoader.cpp in Sources */, + 844337382F405E9400EB3115 /* LoadingTipManager.cpp in Sources */, 9DA5C64D2F2845F80039B697 /* Resource.cpp in Sources */, 9DA5C64E2F2845F80039B697 /* ResourceLoader.cpp in Sources */, 9DA5C64F2F2845F80039B697 /* ResourcePackManager.cpp in Sources */, + 844336EB2F405D8E00EB3115 /* ScrollRenderer_Console.cpp in Sources */, 84AA8BEF2B32F3F3003F5B82 /* DynamicTexture.cpp in Sources */, 84EE49EF2F387DBD00677881 /* SliderButton.cpp in Sources */, 84AA8BF12B32F3F3003F5B82 /* ChickenRenderer.cpp in Sources */, 84AA8BF32B32F3F3003F5B82 /* CowRenderer.cpp in Sources */, 84EB09CA2EE2CC86008FB007 /* CowModel.cpp in Sources */, 84AA8BF52B32F3F3003F5B82 /* CreeperRenderer.cpp in Sources */, + 844337112F405E0600EB3115 /* PauseScreen_Console.cpp in Sources */, 84AA8BF72B32F3F3003F5B82 /* EntityRenderDispatcher.cpp in Sources */, + 844336F52F405DCA00EB3115 /* AreaNavigation.cpp in Sources */, 8477B3A42C4DC374004E1AC5 /* ControllerMoveInput.cpp in Sources */, 84EB09EF2EE2CCA8008FB007 /* Fog.cpp in Sources */, 84AA8BF92B32F3F3003F5B82 /* EntityRenderer.cpp in Sources */, @@ -6750,13 +6888,17 @@ 84EB09962EE2CC25008FB007 /* AppPlatformListener.cpp in Sources */, 84AA8C052B32F3F3003F5B82 /* PigRenderer.cpp in Sources */, 84AA8C072B32F3F3003F5B82 /* SheepFurRenderer.cpp in Sources */, + 8443371B2F405E1C00EB3115 /* ClassicCraftingScreen_Console.cpp in Sources */, 84AA8C092B32F3F3003F5B82 /* SheepRenderer.cpp in Sources */, 9D3996292F10E9C6002945D3 /* CreditsScreen.cpp in Sources */, 84AA8C0D2B32F3F3003F5B82 /* SpiderRenderer.cpp in Sources */, + 844337132F405E0600EB3115 /* ProgressScreen_Console.cpp in Sources */, + 8443370F2F405E0600EB3115 /* PanelScreen_Console.cpp in Sources */, 84AA8C0F2B32F3F3003F5B82 /* TntRenderer.cpp in Sources */, 84AA8C112B32F3F3003F5B82 /* TripodCameraRenderer.cpp in Sources */, 84EB09D42EE2CC86008FB007 /* QuadrupedModel.cpp in Sources */, 84F77A6E2EA1C27B0045C907 /* LocalPlayer.cpp in Sources */, + 844336F92F405DCA00EB3115 /* ScreenChooser.cpp in Sources */, 84F77A6A2EA1C0A10045C907 /* MultiplayerLocalPlayer.cpp in Sources */, 84AA8C152B32F3F3003F5B82 /* FireTexture.cpp in Sources */, 84AA8C162B32F3F3003F5B82 /* FoliageColor.cpp in Sources */, @@ -6765,6 +6907,7 @@ 84AA8C1C2B32F3F3003F5B82 /* FrustumCuller.cpp in Sources */, 84A2FF1A2DB61D720090CE3E /* SoundPathRepository.cpp in Sources */, 84DFC1E52F285ECA00F5434F /* ShaderGroup.cpp in Sources */, + 844337172F405E0600EB3115 /* StartMenuScreen_Console.cpp in Sources */, 84AA8C1E2B32F3F3003F5B82 /* GameRenderer.cpp in Sources */, 84EB09F52EE2CCA8008FB007 /* ScreenRenderer.cpp in Sources */, 84AA8C202B32F3F3003F5B82 /* GrassColor.cpp in Sources */, @@ -6787,6 +6930,7 @@ 84A2FF1E2DB61F6C0090CE3E /* SoundStream.cpp in Sources */, 84AA8C372B32F3F3003F5B82 /* TileRenderer.cpp in Sources */, 84AA8C3A2B32F3F3003F5B82 /* WaterSideTexture.cpp in Sources */, + 844337152F405E0600EB3115 /* SelectWorldScreen_Console.cpp in Sources */, 84AA8C3B2B32F3F3003F5B82 /* WaterTexture.cpp in Sources */, 84EB09DC2EE2CC86008FB007 /* SpiderModel.cpp in Sources */, 84EB09F82EE2CCA8008FB007 /* ImageData.cpp in Sources */, diff --git a/platforms/windows/projects/Client/Client.vcxproj b/platforms/windows/projects/Client/Client.vcxproj index c34a51671..c046d534d 100644 --- a/platforms/windows/projects/Client/Client.vcxproj +++ b/platforms/windows/projects/Client/Client.vcxproj @@ -235,11 +235,29 @@ + + + + + + + + + + + + + + + + + + @@ -391,6 +409,8 @@ + + @@ -398,6 +418,22 @@ + + + + + + + + + + + + + + + + diff --git a/platforms/windows/projects/Client/Client.vcxproj.filters b/platforms/windows/projects/Client/Client.vcxproj.filters index 86807309a..55cd0f467 100644 --- a/platforms/windows/projects/Client/Client.vcxproj.filters +++ b/platforms/windows/projects/Client/Client.vcxproj.filters @@ -60,9 +60,6 @@ {7ce8acc7-4fb7-440b-bace-76d8a3514038} - - {dd9a353b-2a43-442d-a40f-56a04100b71b} - {d7896ae3-f50c-4976-9897-336cbfb70dea} @@ -129,6 +126,9 @@ {8d211c71-2764-43ef-8587-7414109f4ff5} + + {dd9a353b-2a43-442d-a40f-56a04100b71b} + @@ -599,6 +599,12 @@ Header Files\Locale + + Header Files\Renderer\Texture + + + Header Files\Renderer + Header Files\Resources @@ -620,9 +626,57 @@ Header Files\GUI\Components + + Header Files\GUI + + + Header Files\GUI\Screens + + + Header Files\GUI\Components + + + Header Files\GUI\Components + Header Files\App + + Header Files\GUI\Screens + + + Header Files\Resources + + + Header Files\Resources + + + Header Files\GUI + + + Header Files\GUI + + + Header Files\GUI\Screens + + + Header Files\GUI\Screens + + + Header Files\GUI\Screens + + + Header Files\GUI\Screens + + + Header Files\GUI\Screens + + + Header Files\GUI + + + Header Files\GUI\Screens\Inventory + @@ -824,22 +878,22 @@ Source Files\Renderer - Source Files\Sound + Header Files\Resources\Sound - Source Files\Sound + Header Files\Resources\Sound - Source Files\Sound + Header Files\Resources\Sound - Source Files\Sound + Header Files\Resources\Sound - Source Files\Sound + Header Files\Resources\Sound - Source Files\Sound + Header Files\Resources\Sound Source Files\App @@ -1069,9 +1123,18 @@ Source Files\GUI\Screens\Inventory + + Source Files\GUI\Screens\Inventory + Source Files\Locale + + Source Files\Renderer\Texture + + + Source Files\Renderer + Source Files\Resources @@ -1093,5 +1156,53 @@ Source Files\GUI\Components + + Source Files\GUI + + + Source Files\GUI\Screens + + + Source Files\GUI + + + Source Files\GUI\Components + + + Source Files\GUI\Components + + + Source Files\GUI\Screens + + + Source Files\Resources + + + Source Files\Resources + + + Source Files\GUI + + + Source Files\GUI\Screens + + + Source Files\GUI\Screens + + + Source Files\GUI\Screens + + + Source Files\GUI\Screens + + + Source Files\GUI\Screens + + + Source Files\GUI + + + Source Files\GUI\Screens\Inventory + \ No newline at end of file diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index c41a4aee5..36493fd02 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -30,6 +30,8 @@ add_library(reminecraftpe-core STATIC client/resources/ResourcePackManager.cpp client/resources/ResourcePackManifest.cpp client/resources/ResourcePackRepository.cpp + client/resources/SplashManager.cpp + client/resources/LoadingTipManager.cpp client/options/Options.cpp client/renderer/LevelRenderer.cpp client/renderer/Culler.cpp @@ -57,6 +59,7 @@ add_library(reminecraftpe-core STATIC client/renderer/renderer/Tesselator.cpp client/renderer/texture/ImageData.cpp client/renderer/texture/TextureData.cpp + client/renderer/texture/TextureAtlas.cpp client/renderer/RenderList.cpp client/renderer/ScreenRenderer.cpp client/renderer/Chunk.cpp @@ -81,6 +84,7 @@ add_library(reminecraftpe-core STATIC client/renderer/FireTexture.cpp client/renderer/FoliageColor.cpp client/renderer/GrassColor.cpp + client/renderer/LogoRenderer.cpp client/sound/SoundData.cpp client/sound/SoundPathRepository.cpp client/sound/SoundStream.cpp @@ -88,14 +92,20 @@ add_library(reminecraftpe-core STATIC client/sound/SoundRepository.cpp client/sound/SoundEngine.cpp client/gui/Screen.cpp + client/gui/ScreenChooser.cpp + client/gui/ScreenChooser_Console.cpp client/gui/screens/CreditsScreen.cpp client/gui/screens/OptionsScreen.cpp + client/gui/screens/OptionsScreen_Console.cpp client/gui/screens/StartMenuScreen.cpp + client/gui/screens/StartMenuScreen_Console.cpp client/gui/screens/ConvertWorldScreen.cpp client/gui/screens/CreateWorldScreen.cpp + client/gui/screens/CreateWorldScreen_Console.cpp client/gui/screens/DirectConnectScreen.cpp client/gui/screens/DisconnectionScreen.cpp client/gui/screens/SelectWorldScreen.cpp + client/gui/screens/SelectWorldScreen_Console.cpp client/gui/screens/SavingWorldScreen.cpp client/gui/screens/InvalidLicenseScreen.cpp client/gui/screens/ConfirmScreen.cpp @@ -104,13 +114,17 @@ add_library(reminecraftpe-core STATIC client/gui/screens/ChatScreen.cpp client/gui/screens/RenameMPLevelScreen.cpp client/gui/screens/ProgressScreen.cpp + client/gui/screens/ProgressScreen_Console.cpp client/gui/screens/JoinGameScreen.cpp client/gui/screens/IngameBlockSelectionScreen.cpp client/gui/screens/PauseScreen.cpp + client/gui/screens/PauseScreen_Console.cpp client/gui/screens/DeathScreen.cpp + client/gui/screens/PanelScreen_Console.cpp client/gui/screens/inventory/ContainerScreen.cpp client/gui/screens/inventory/InventoryScreen.cpp client/gui/screens/inventory/CraftingScreen.cpp + client/gui/screens/inventory/ClassicCraftingScreen_Console.cpp client/gui/screens/inventory/ChestScreen.cpp client/gui/components/ScrolledSelectionList.cpp client/gui/components/AvailableGamesList.cpp @@ -121,13 +135,17 @@ add_library(reminecraftpe-core STATIC client/gui/components/SliderButton.cpp client/gui/components/SwitchButton.cpp client/gui/components/SwitchValuesButton.cpp + client/gui/components/TickBox.cpp client/gui/components/WorldSelectionList.cpp client/gui/components/OptionList.cpp + client/gui/components/ScrollRenderer_Console.cpp client/locale/Language.cpp client/gui/Gui.cpp client/gui/GuiComponent.cpp client/gui/GuiElement.cpp client/gui/MenuPointer.cpp + client/gui/VerticalLayout.cpp + client/gui/AreaNavigation.cpp client/model/geom/PolygonQuad.cpp client/model/geom/Cube.cpp client/model/geom/ModelPart.cpp diff --git a/source/client/app/Minecraft.cpp b/source/client/app/Minecraft.cpp index e8889b512..82f093afe 100644 --- a/source/client/app/Minecraft.cpp +++ b/source/client/app/Minecraft.cpp @@ -43,6 +43,7 @@ #include "client/renderer/PatchManager.hpp" #include "renderer/RenderContextImmediate.hpp" +#include "client/renderer/LogoRenderer.hpp" float Minecraft::_renderScaleMultiplier = 1.0f; @@ -66,6 +67,7 @@ const char* Minecraft::progressMessages[] = Minecraft::Minecraft() { m_pOptions = nullptr; + m_pScreenChooser = nullptr; field_18 = false; m_bIsGamePaused = false; m_pResourceLoader = nullptr; @@ -124,6 +126,7 @@ Minecraft::~Minecraft() SAFE_DELETE(m_pGameMode); SAFE_DELETE(m_pFont); SAFE_DELETE(m_pTextures); + SAFE_DELETE(m_pScreenChooser); if (m_pLevel) { @@ -259,6 +262,7 @@ void Minecraft::recenterMouse() void Minecraft::setScreen(Screen* pScreen) { + float lastScale = getBestScaleForThisScreenSize(Minecraft::width, Minecraft::height); #ifndef ORIGINAL_CODE if (pScreen == nullptr && !isLevelGenerated()) { @@ -283,7 +287,8 @@ void Minecraft::setScreen(Screen* pScreen) if (m_pScreen) { m_pScreen->removed(); - delete m_pScreen; + if (pScreen && pScreen->m_bDeletePrevious) + delete m_pScreen; } Mouse::reset(); @@ -292,16 +297,29 @@ void Minecraft::setScreen(Screen* pScreen) Multitouch::resetThisUpdate(); m_pScreen = pScreen; + + if (pScreen) + { + pScreen->init(this, Gui::GuiWidth, Gui::GuiHeight); + } + + float scale = getBestScaleForThisScreenSize(Minecraft::width, Minecraft::height); + + if (scale != lastScale) + { + sizeUpdate(Minecraft::width, Minecraft::height); + if (pScreen) + pScreen->initMenuPointer(); + } + if (pScreen) { releaseMouse(); - // the ceil prevents under-drawing - pScreen->init(this, ceil(width * Gui::InvGuiScale), ceil(height * Gui::InvGuiScale)); if (pScreen->isPauseScreen()) { if (m_pLevel && isLevelGenerated()) - return m_pLevel->saveGame(); + m_pLevel->saveGame(); } } else @@ -506,7 +524,7 @@ void Minecraft::tickInput() { if (m_pScreen) { - if (!m_pScreen->field_10) + if (!m_pScreen->m_bPassEvents) { m_bUsingScreen = true; m_pScreen->updateEvents(); @@ -570,7 +588,7 @@ void Minecraft::tickInput() { getOptions()->m_thirdPerson.toggle(); } - else if (getOptions()->isKey(KM_MENU_CANCEL, keyCode)) + else if (getOptions()->isKey(KM_MENU_PAUSE, keyCode)) { handleBack(false); } @@ -798,6 +816,8 @@ void Minecraft::tick() m_pGui->tick(); + LogoRenderer::singleton().tick(); + // if the level has been prepared, delete the prep thread if (!m_bPreparingLevel) { @@ -849,17 +869,7 @@ void Minecraft::tick() void Minecraft::update() { - if (isGamePaused() && m_pLevel) - { - // Don't advance renderTicks when we're paused - float x = m_timer.m_renderTicks; - m_timer.advanceTime(); - m_timer.m_renderTicks = x; - } - else - { - m_timer.advanceTime(); - } + m_timer.advanceTime(isGamePaused() && m_pLevel); platform()->tick(); @@ -889,7 +899,7 @@ void Minecraft::update() renderContext.beginRender(); - m_pGameRenderer->render(m_timer.m_renderTicks); + m_pGameRenderer->render(m_timer); // Added by iProgramInCpp if (m_pGameMode) @@ -1008,16 +1018,22 @@ void Minecraft::prepareLevel(const std::string& unused) void Minecraft::sizeUpdate(int newWidth, int newHeight) { // re-calculate the GUI scale. - Gui::InvGuiScale = getBestScaleForThisScreenSize(newWidth, newHeight) / getRenderScaleMultiplier(); + Gui::GuiScale = getBestScaleForThisScreenSize(newWidth, newHeight) / getRenderScaleMultiplier(); // The ceil gives an extra pixel to the screen's width and height, in case the GUI scale doesn't // divide evenly into width or height, so that none of the game screen is uncovered. + Gui::GuiHeight = ceilf(Minecraft::height * Gui::GuiScale); + Gui::GuiScale = float(Gui::GuiHeight) / height; + Gui::GuiWidth = ceilf(Minecraft::width * Gui::GuiScale); + if (m_pScreen) m_pScreen->setSize( - int(ceilf(Minecraft::width * Gui::InvGuiScale)), - int(ceilf(Minecraft::height * Gui::InvGuiScale)) + Gui::GuiWidth, + Gui::GuiHeight ); + LogoRenderer::singleton().build(Gui::GuiWidth); + if (m_pInputHolder) m_pInputHolder->setScreenSize(Minecraft::width, Minecraft::height); } @@ -1030,6 +1046,15 @@ void Minecraft::setTextboxText(const std::string& text) float Minecraft::getBestScaleForThisScreenSize(int width, int height) { + if (m_pScreen) + { + float scale = m_pScreen->getScale(width, height); + if (scale > 0) + return scale; + } + else if (m_pOptions->getUiTheme() == UI_CONSOLE) + return Screen::GetConsoleScale(height); + #if MC_PLATFORM_XBOX #define USE_JAVA_SCREEN_SCALING #endif @@ -1038,7 +1063,7 @@ float Minecraft::getBestScaleForThisScreenSize(int width, int height) for (scale = 1; width / (scale + 1) >= 320 && height / (scale + 1) >= 240; ++scale) { } - return 1.0f / scale; + return scale; #endif if (height > 1800) @@ -1125,7 +1150,7 @@ void Minecraft::generateLevel(const std::string& unused, Level* pLevel) m_bPreparingLevel = false; if (m_pRakNetInstance && m_pRakNetInstance->m_bIsHost) - m_pRakNetInstance->announceServer(m_pUser->field_0); + m_pRakNetInstance->announceServer(m_pUser->m_name); } void* Minecraft::prepareLevel_tspawn(void* ptr) @@ -1147,7 +1172,7 @@ bool Minecraft::pauseGame() m_bIsGamePaused = true; } m_pLevel->savePlayerData(); - setScreen(new PauseScreen); + getScreenChooser()->pushPauseScreen(); return true; } @@ -1222,7 +1247,7 @@ void Minecraft::selectLevel(const std::string& levelDir, const std::string& leve field_D9C = 1; hostMultiplayer(); - setScreen(new ProgressScreen); + getScreenChooser()->pushProgressScreen(); } const char* Minecraft::getProgressMessage() @@ -1252,6 +1277,21 @@ ItemStack& Minecraft::getSelectedItem() return item; } +ScreenChooser* Minecraft::getScreenChooser() +{ + if (!m_pScreenChooser || m_pScreenChooser->m_uiTheme != getOptions()->getUiTheme()) + { + SAFE_DELETE(m_pScreenChooser); + m_pScreenChooser = ScreenChooser::Create(this); + } + return m_pScreenChooser; +} + +UITheme Minecraft::getUiTheme() +{ + return m_pScreen ? m_pScreen->m_uiTheme : getOptions()->getUiTheme(); +} + void Minecraft::reloadFancy(bool isFancy) { } @@ -1276,7 +1316,7 @@ void Minecraft::gotoMainMenu() #if MC_PLATFORM_CONSOLE m_pSoundEngine->playMusic(); #endif - setScreen(new StartMenuScreen); + getScreenChooser()->pushStartScreen(); } void Minecraft::hostMultiplayer() @@ -1285,7 +1325,7 @@ void Minecraft::hostMultiplayer() return; #ifdef FEATURE_NETWORKING - m_pRakNetInstance->host(m_pUser->field_0, C_DEFAULT_PORT, C_MAX_CONNECTIONS); + m_pRakNetInstance->host(m_pUser->m_name, C_DEFAULT_PORT, C_MAX_CONNECTIONS); m_pNetEventCallback = new ServerSideNetworkHandler(this, m_pRakNetInstance); #endif } diff --git a/source/client/app/Minecraft.hpp b/source/client/app/Minecraft.hpp index 8146742c9..edd594852 100644 --- a/source/client/app/Minecraft.hpp +++ b/source/client/app/Minecraft.hpp @@ -14,6 +14,7 @@ #include "common/Timer.hpp" #include "client/gui/Gui.hpp" #include "client/gui/Screen.hpp" +#include "client/gui/ScreenChooser.hpp" #include "network/RakNetInstance.hpp" #include "network/NetEventCallback.hpp" #include "client/player/input/IInputHolder.hpp" @@ -110,6 +111,8 @@ class Minecraft : public App LevelStorageSource* getLevelSource(); ItemStack& getSelectedItem(); Options* getOptions() const { return m_pOptions; } + ScreenChooser* getScreenChooser(); + UITheme getUiTheme(); //const Entity& getCameraEntity() const { return *m_pCameraEntity; } private: @@ -127,7 +130,8 @@ class Minecraft : public App static int customDebugId; protected: - Options *m_pOptions; + Options* m_pOptions; + ScreenChooser* m_pScreenChooser; public: bool field_18; diff --git a/source/client/app/NinecraftApp.cpp b/source/client/app/NinecraftApp.cpp index 97eb70792..a591064f5 100644 --- a/source/client/app/NinecraftApp.cpp +++ b/source/client/app/NinecraftApp.cpp @@ -27,6 +27,9 @@ #include "renderer/ConstantBufferMetaDataManager.hpp" #include "renderer/RenderContextImmediate.hpp" #include "renderer/RenderMaterial.hpp" +#include "client/resources/LoadingTipManager.hpp" +#include "client/renderer/LogoRenderer.hpp" +#include "client/resources/SplashManager.hpp" #ifdef DEMO #include "world/level/storage/MemoryLevelStorageSource.hpp" @@ -84,6 +87,8 @@ void NinecraftApp::_initTextures() if (GrassColor::isAvailable()) GrassColor::init(); if (FoliageColor::isAvailable()) FoliageColor::init(); + + LogoRenderer::singleton().init(this); } void NinecraftApp::_initRenderMaterials() @@ -207,6 +212,8 @@ void NinecraftApp::_initAll() m_pSoundEngine->init(getOptions()); Language::singleton().init(getOptions()); + LoadingTipManager::singleton().init(); + SplashManager::singleton().init(m_pUser->m_name); field_D9C = 0; diff --git a/source/client/gui/AreaNavigation.cpp b/source/client/gui/AreaNavigation.cpp new file mode 100644 index 000000000..1fc9b5458 --- /dev/null +++ b/source/client/gui/AreaNavigation.cpp @@ -0,0 +1,81 @@ +#include +#include "AreaNavigation.hpp" +#include "common/Utils.hpp" +#include "common/Mth.hpp" + +AreaNavigation::ID AreaNavigation::navigate(Direction dir, int x, int y, bool cycle) +{ + m_index = -1; + + float bestScore = FLT_MAX; + int nearest = -1; + + float dirX = 0, dirY = 0; + switch (dir) + { + case UP: dirY = -1; break; + case DOWN: dirY = 1; break; + case LEFT: dirX = -1; break; + case RIGHT: dirX = 1; break; + default: return -1; + } + + if (cycle) + { + if (dirX) x = dirX < 0 ? m_area.w : m_area.x; + else if (dirY) y = dirY < 0 ? m_area.h : m_area.y; + } + + int elementX = 0; + int elementY = 0; + + while (next(elementX, elementY, cycle)) + { + constexpr float maxAngle = 75.0f; + constexpr float penalty = 1.5f; + + int tx = elementX - x; + int ty = elementY - y; + + float distance = Mth::sqrt(tx * tx + ty * ty); + if (distance < 1e-4f) continue; + + float len = distance; + float nx = tx / len; + float ny = ty / len; + + float cosTheta = nx * dirX + ny * dirY; + + if (cosTheta < Mth::cos(maxAngle * M_PI / 180.0f)) + continue; + + float projectedDist = distance * cosTheta; + + float lateralPenalty = distance * Mth::sqrt(1.0f - cosTheta * cosTheta) * penalty; + + float score = projectedDist + lateralPenalty; + + if (score < bestScore) + { + bestScore = score; + nearest = m_index; + } + } + + return nearest; +} + +AreaNavigation::ID AreaNavigation::navigateCyclic(Direction dir, int x, int y) +{ + AreaNavigation::ID index = navigate(dir, x, y); + + if (index < 0) + index = navigate(dir, x, y, true); + + return isValid(index) ? index : -1; +} + +bool AreaNavigation::isValid(ID id) +{ + return true; +} diff --git a/source/client/gui/AreaNavigation.hpp b/source/client/gui/AreaNavigation.hpp new file mode 100644 index 000000000..8cdda9d8b --- /dev/null +++ b/source/client/gui/AreaNavigation.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "IntRectangle.hpp" + +class AreaNavigation +{ +public: + typedef int ID; + +public: + enum Direction + { + UP, + DOWN, + LEFT, + RIGHT + }; + +public: + ID navigate(Direction dir, int x, int y, bool cycle = false); + ID navigateCyclic(Direction dir, int x, int y); + + virtual bool next(int& x, int& y, bool cycle) = 0; + virtual bool isValid(ID); + +protected: + ID m_index; + IntRectangle m_area; +}; \ No newline at end of file diff --git a/source/client/gui/Gui.cpp b/source/client/gui/Gui.cpp index 36140c45f..d8e94fcdf 100644 --- a/source/client/gui/Gui.cpp +++ b/source/client/gui/Gui.cpp @@ -6,6 +6,7 @@ SPDX-License-Identifier: BSD-1-Clause ********************************************************************/ +//#include "Gui.hpp" // apparently this breaks building on clang or something #include "client/app/Minecraft.hpp" #include "client/gui/screens/IngameBlockSelectionScreen.hpp" #include "client/gui/screens/ChatScreen.hpp" @@ -29,10 +30,12 @@ Gui::Materials::Materials() } #ifdef ENH_USE_GUI_SCALE_2 -float Gui::InvGuiScale = 1.0f / 2.0f; +float Gui::GuiScale = 1.0f / 2.0f; #else -float Gui::InvGuiScale = 1.0f / 3.0f; +float Gui::GuiScale = 1.0f / 3.0f; #endif +int Gui::GuiWidth = Minecraft::width; +int Gui::GuiHeight = Minecraft::height; bool Gui::_isVignetteAvailable = false; // false because PE never seemed to have it @@ -43,7 +46,7 @@ Gui::Gui(Minecraft* pMinecraft) field_24 = 0; field_28 = 0; field_2C = 0; - field_9FC = 0; + m_ticks = 0; field_A00 = ""; field_A18 = 0; field_A1C = false; @@ -51,18 +54,10 @@ Gui::Gui(Minecraft* pMinecraft) field_A3C = true; m_bRenderMessages = true; m_bRenderHunger = false; - m_width = 0; - m_height = 0; m_pMinecraft = pMinecraft; } -void Gui::_updateHudPositions() -{ - m_width = int(ceilf(Minecraft::width * InvGuiScale)); - m_height = int(ceilf(Minecraft::height * InvGuiScale)); -} - void Gui::addMessage(const std::string& s) { // if the message contains a new line, add each line separately: @@ -161,30 +156,39 @@ void Gui::render(float f, bool bHaveScreen, int mouseX, int mouseY) Minecraft& mc = *m_pMinecraft; GameRenderer& renderer = *mc.m_pGameRenderer; Textures& textures = *mc.m_pTextures; - bool isTouchscreen = AppPlatform::singleton()->isTouchscreen(); + bool isPocket = mc.getOptions()->getUiTheme() == UI_POCKET; + bool isConsole = mc.getOptions()->getUiTheme() == UI_CONSOLE; renderer.setupGuiScreen(); - if (!mc.m_pLevel || !mc.m_pLocalPlayer) + if (bHaveScreen && isConsole) return; - _updateHudPositions(); + if (!mc.m_pLevel || !mc.m_pLocalPlayer) + return; - if (mc.getOptions()->m_fancyGraphics.get() && isVignetteAvailable()) + if (mc.getOptions()->m_fancyGraphics.get() && isVignetteAvailable() && !isConsole) { - renderVignette(mc.m_pLocalPlayer->getBrightness(f), m_width, m_height); + renderVignette(mc.m_pLocalPlayer->getBrightness(f), GuiWidth, GuiHeight); } ItemStack& headGear = mc.m_pLocalPlayer->m_pInventory->getArmor(Item::SLOT_HEAD); if (!mc.getOptions()->m_thirdPerson.get() && !headGear.isEmpty() && headGear.getId() == Tile::pumpkin->m_ID) - renderPumpkin(m_width, m_height); + renderPumpkin(GuiWidth, GuiHeight); - renderProgressIndicator(m_width, m_height); + renderProgressIndicator(GuiWidth, GuiHeight); currentShaderColor = Color::WHITE; currentShaderDarkColor = Color::WHITE; + MatrixStack::Ref matrix = MatrixStack::World.push(); + matrix->translate(Vec3(GuiWidth / 2, GuiHeight, 0)); + if (isConsole) + { + matrix->translate(Vec3(0, -35, 0)); + matrix->scale(mc.getOptions()->m_hudSize.get()); + } if (mc.m_pGameMode->canHurtPlayer()) { textures.loadAndBindTexture("gui/icons.png"); @@ -193,11 +197,11 @@ void Gui::render(float f, bool bHaveScreen, int mouseX, int mouseY) t.begin(0); t.voidBeginAndEndCalls(true); - renderHearts(isTouchscreen); - renderArmor(isTouchscreen); - renderBubbles(isTouchscreen); + renderHearts(isPocket); + renderArmor(isPocket); + renderBubbles(isPocket); if (m_bRenderHunger) - renderHunger(isTouchscreen); + renderHunger(isPocket); t.voidBeginAndEndCalls(false); t.draw(m_materials.ui_textured); @@ -210,6 +214,7 @@ void Gui::render(float f, bool bHaveScreen, int mouseX, int mouseY) alpha = 0.50f; // 0.65f on 0.12.1 #endif renderToolBar(f, alpha); + matrix.release(); if (m_bRenderMessages) { @@ -222,7 +227,7 @@ void Gui::tick() if (field_A18 > 0) field_A18--; - field_9FC++; + m_ticks++; for (size_t i = 0; i < m_guiMessages.size(); i++) { @@ -271,8 +276,8 @@ void Gui::renderSlotOverlay(int slot, int x, int y, float f) int Gui::getSlotIdAt(int mouseX, int mouseY) { - int scaledY = int(InvGuiScale * mouseY); - int scaledHeight = int(InvGuiScale * Minecraft::height); + int scaledY = int(GuiScale * mouseY); + int scaledHeight = int(GuiScale * Minecraft::height); if (scaledY >= scaledHeight) return -1; @@ -281,7 +286,7 @@ int Gui::getSlotIdAt(int mouseX, int mouseY) int hotbarOffset = getNumSlots() * 20 / 2 - 2; - int slotX = (int(InvGuiScale * mouseX) - int(InvGuiScale * Minecraft::width) / 2 + hotbarOffset + 20) / 20; + int slotX = (int(GuiScale * mouseX) - int(GuiScale * Minecraft::width) / 2 + hotbarOffset + 20) / 20; if (slotX >= 0) slotX--; @@ -385,10 +390,7 @@ void Gui::handleKeyPressed(int keyCode) void Gui::renderMessages(bool bShowAll) { - //int width = Minecraft::width * InvGuiScale, - int height = int(ceilf(Minecraft::height * InvGuiScale)); - - int topEdge = height - 49; + int topEdge = GuiHeight - 49; if (m_pMinecraft->isTouchscreen()) topEdge = 49; @@ -428,36 +430,30 @@ void Gui::renderMessages(bool bShowAll) void Gui::renderHearts(bool topLeft) { + m_random.setSeed(m_ticks * 312871); + LocalPlayer* player = m_pMinecraft->m_pLocalPlayer; - int cenX = m_width / 2; + bool b1 = player->m_invulnerableTime >= 10 && player->m_invulnerableTime / 3 % 2; - int emptyHeartX = 16; - bool b1 = false; - if (player->m_invulnerableTime < 10) - { - b1 = player->m_invulnerableTime / 3 % 2; - emptyHeartX += 9 * b1; - } - int heartX; int heartYStart; - - if (topLeft) - { - heartX = 2; - heartYStart = 2; - } - else - { - // @NOTE: At the default scale, this would go off screen. - // Renders to the left of the hotbar, why? - /*heartX = cenX - 191; // why? - heartYStart = m_height - 10;*/ - - heartX = cenX - 91; - heartYStart = m_height - 32; - } + + if (topLeft) + { + heartX = -GuiWidth / 2 + 2; + heartYStart = -GuiHeight + 2; + } + else + { + // @NOTE: At the default scale, this would go off screen. + // Renders to the left of the hotbar, why? + /*heartX = cenX - 191; // why? + heartYStart = height - 10;*/ + + heartX = -91; + heartYStart = -32; + } int playerHealth = player->m_health; int maxHealth = player->getMaxHealth(); @@ -469,7 +465,7 @@ void Gui::renderHearts(bool topLeft) if (playerHealth <= 4 && m_random.genrand_int32() % 2) heartY++; - blit(heartX, heartY, emptyHeartX, 0, 9, 9, 0, 0); + blit(heartX, heartY, 16 + b1 * 9, 0, 9, 9, 0, 0); if (b1) { @@ -493,12 +489,10 @@ void Gui::renderArmor(bool topLeft) int armor = m_pMinecraft->m_pLocalPlayer->m_pInventory->getArmorValue(); if (armor <= 0) return; - - int cenX = m_width / 2; int hotbarWidth = (topLeft) ? 0 : (2 + getNumSlots() * 20); - int armorX = (topLeft) ? (m_width - 11) : cenX - 91 + (hotbarWidth - 9); - int armorY = (topLeft) ? 2 : (m_height - 32); + int armorX = (topLeft) ? (GuiWidth / 2 - 11) : - 91 + (hotbarWidth - 9); + int armorY = (topLeft) ? 2 - GuiHeight : -32; if (armor > 0) { @@ -528,8 +522,6 @@ void Gui::renderBubbles(bool topLeft) { LocalPlayer* player = m_pMinecraft->m_pLocalPlayer; - int cenX = m_width / 2; - if (player->isUnderLiquid(Material::water)) { int breathRaw = player->m_airCapacity; @@ -541,8 +533,8 @@ void Gui::renderBubbles(bool topLeft) if (topLeft) { - bubbleX = 2; - bubbleY = 12; + bubbleX = -GuiWidth / 2 + 2; + bubbleY = -GuiHeight + 12; } else if (m_bRenderHunger) { @@ -554,9 +546,9 @@ void Gui::renderBubbles(bool topLeft) { // Renders to the left of the hotbar, why? /*bubbleX = cenX - 191; - bubbleY = m_height - 19;*/ - bubbleX = cenX - 91; - bubbleY = m_height - 41; + bubbleY = height - 19;*/ + bubbleX = -91; + bubbleY = -41; } //@NOTE: Not sure this works as it should @@ -585,7 +577,11 @@ void Gui::renderProgressIndicator(int width, int height) { // draw crosshair textures.loadAndBindTexture("gui/icons.png"); - blit(width / 2 - 8, height / 2 - 8, 0, 0, 16, 16, 0, 0, &m_guiMaterials.ui_crosshair); + MatrixStack::Ref matrix = MatrixStack::World.push(); + matrix->translate(Vec3(width / 2, height / 2, 0)); + if (mc.getOptions()->getUiTheme() == UI_CONSOLE) + matrix->scale(mc.getOptions()->m_hudSize.get()); + blit(-8, -8, 0, 0, 16, 16, 0, 0, &m_guiMaterials.ui_crosshair); } else { @@ -611,14 +607,14 @@ void Gui::renderProgressIndicator(int width, int height) textures.loadAndBindTexture("gui/feedback_outer.png"); currentShaderColor = Color::WHITE; - blit(InvGuiScale * xPos - 44.0f, InvGuiScale * yPos - 44.0f, 0, 0, 88, 88, 256, 256, &m_guiMaterials.ui_overlay_textured); + blit(GuiScale * xPos - 44.0f, GuiScale * yPos - 44.0f, 0, 0, 88, 88, 256, 256, &m_guiMaterials.ui_overlay_textured); textures.loadAndBindTexture("gui/feedback_fill.png"); // note: scale starts from 4.0f float halfWidth = (40.0f * breakProgress + 48.0f) / 2.0f; - blit(InvGuiScale * xPos - halfWidth, InvGuiScale * yPos - halfWidth, 0, 0, halfWidth * 2, halfWidth * 2, 256, 256, &m_guiMaterials.ui_invert_overlay_textured); + blit(GuiScale * xPos - halfWidth, GuiScale * yPos - halfWidth, 0, 0, halfWidth * 2, halfWidth * 2, 256, 256, &m_guiMaterials.ui_invert_overlay_textured); } } else @@ -628,7 +624,7 @@ void Gui::renderProgressIndicator(int width, int height) textures.loadAndBindTexture("gui/feedback_outer.png"); currentShaderColor = Color(1.0f, 1.0f, 1.0f, Mth::Min(1.0f, input.m_feedbackAlpha)); - blit(InvGuiScale * xPos - 44.0f, InvGuiScale * yPos - 44.0f, 0, 0, 88, 88, 256, 256, &m_guiMaterials.ui_overlay_textured); + blit(GuiScale * xPos - 44.0f, GuiScale * yPos - 44.0f, 0, 0, 88, 88, 256, 256, &m_guiMaterials.ui_overlay_textured); } } } @@ -656,44 +652,40 @@ void Gui::renderToolBar(float f, float alpha) int nSlots = getNumSlots(); int hotbarWidth = 2 + nSlots * 20; - mce::MaterialPtr* material = &m_materials.ui_textured_and_glcolor; - // hotbar - int cenX = m_width / 2; - int mainWidth = std::min(hotbarWidth - 2, 180); - blit(cenX - hotbarWidth / 2, m_height - 22, 0, 0, mainWidth, 22, 0, 0, material); + blit(-hotbarWidth / 2, -22, 0, 0, hotbarWidth - 2, 22, 0, 0); // if there is a tenth hotbar slot, it is given another slot area (for mobile devices) if (hotbarWidth > 182) { int extraWidth = hotbarWidth - 182 + 2; int textureUV = 182 - extraWidth; - blit(cenX - hotbarWidth / 2 + 180, m_height - 22, textureUV, 0, extraWidth, 22, 0, 0, material); + blit(-hotbarWidth / 2 + 180, -22, textureUV, 0, extraWidth, 22, 0, 0); } - blit(cenX + hotbarWidth / 2 - 2, m_height - 22, 180, 0, 2, 22, 0, 0, material); + blit(hotbarWidth / 2 - 2, -22, 180, 0, 2, 22, 0, 0); Inventory* inventory = player->m_pInventory; // selection mark - blit(cenX - 1 - hotbarWidth / 2 + 20 * inventory->m_selectedSlot, m_height - 23, 0, 22, 24, 22, 0, 0, material); + blit(-1 - hotbarWidth / 2 + 20 * inventory->m_selectedSlot, -23, 0, 22, 24, 22, 0, 0); textures->loadAndBindTexture(C_BLOCKS_NAME); int diff = mc->isTouchscreen(); - int slotX = cenX - hotbarWidth / 2 + 3; + int slotX = -hotbarWidth / 2 + 3; for (int i = 0; i < nSlots - diff; i++) { - renderSlot(i, slotX, m_height - 19, f); + renderSlot(i, slotX, -19, f); slotX += 20; } - slotX = cenX - hotbarWidth / 2 + 3; + slotX = -hotbarWidth / 2 + 3; for (int i = 0; i < nSlots - diff; i++) { - renderSlotOverlay(i, slotX, m_height - 19, f); + renderSlotOverlay(i, slotX, -19, f); slotX += 20; } @@ -706,7 +698,7 @@ void Gui::renderToolBar(float f, float alpha) if (mc->isTouchscreen()) { textures->loadAndBindTexture(C_TERRAIN_NAME); - blit(cenX + hotbarWidth / 2 - 19, m_height - 19, 208, 208, 16, 16, 0, 0, material); + blit(hotbarWidth / 2 - 19, -19, 208, 208, 16, 16, 0, 0); } } @@ -726,10 +718,10 @@ int Gui::getNumUsableSlots() RectangleArea Gui::getRectangleArea(bool b) { float centerX = Minecraft::width / 2; - float hotbarWidthHalf = (10 * getNumSlots() + 5) / InvGuiScale; + float hotbarWidthHalf = (10 * getNumSlots() + 5) / GuiScale; return RectangleArea( b ? (centerX - hotbarWidthHalf) : 0, - Minecraft::height - 24.0f / InvGuiScale, + Minecraft::height - 24.0f / GuiScale, centerX + hotbarWidthHalf, Minecraft::height); } diff --git a/source/client/gui/Gui.hpp b/source/client/gui/Gui.hpp index 5e60ec1d6..9957d2f65 100644 --- a/source/client/gui/Gui.hpp +++ b/source/client/gui/Gui.hpp @@ -53,9 +53,6 @@ class Gui : public GuiComponent public: Gui(Minecraft* pMinecraft); -private: - void _updateHudPositions(); - public: void addMessage(const std::string& str); void inventoryUpdated(); @@ -82,7 +79,9 @@ class Gui : public GuiComponent RectangleArea getRectangleArea(bool b); public: - static float InvGuiScale; + static float GuiScale; + static int GuiWidth; + static int GuiHeight; protected: Materials m_guiMaterials; @@ -96,7 +95,7 @@ class Gui : public GuiComponent int field_2C; Random m_random; Minecraft* m_pMinecraft; - int field_9FC; + int m_ticks; std::string field_A00; int field_A18; bool field_A1C; @@ -105,7 +104,5 @@ class Gui : public GuiComponent bool field_A3C; bool m_bRenderMessages; bool m_bRenderHunger; - int m_width; - int m_height; }; diff --git a/source/client/gui/GuiElement.cpp b/source/client/gui/GuiElement.cpp index dd0384f1d..d6b88b931 100644 --- a/source/client/gui/GuiElement.cpp +++ b/source/client/gui/GuiElement.cpp @@ -1,8 +1,9 @@ #include "GuiElement.hpp" -GuiElement::GuiElement(GuiElement::ID id) +GuiElement::GuiElement() { - m_ID = id; + m_ID = -1; + m_uiTheme = UI_POCKET; m_width = 0; m_height = 0; m_xPos = 0; @@ -11,6 +12,7 @@ GuiElement::GuiElement(GuiElement::ID id) m_bVisible = true; m_bSelected = false; m_bHasFocus = false; + m_bNavigable = true; } void GuiElement::setBackground(const Color& color) @@ -26,7 +28,7 @@ void GuiElement::_onFocusChanged() { } -bool GuiElement::_clicked(const MenuPointer& pointer) +bool GuiElement::_isHovered(const MenuPointer& pointer) { if (!isEnabled()) return false; @@ -56,6 +58,11 @@ bool GuiElement::pointerReleased(Minecraft* pMinecraft, const MenuPointer& point return false; } +bool GuiElement::areaNavigation(Minecraft* pMinecraft, AreaNavigation::Direction) +{ + return false; +} + void GuiElement::handleButtonPress(Minecraft* pMinecraft, int key) { } @@ -68,6 +75,29 @@ void GuiElement::handleClipboardPaste(const std::string& content) { } +void GuiElement::handleScroll(float force) +{ +} + +bool GuiElement::isHovered(Minecraft* pMinecraft, const MenuPointer& pointer) +{ + return _isHovered(pointer); +} + +void GuiElement::pressed(Minecraft* pMinecraft) +{ +} + +void GuiElement::pressed(Minecraft* pMinecraft, const MenuPointer& pointer) +{ + pressed(pMinecraft); +} + +void GuiElement::released(const MenuPointer& pointer) +{ + +} + void GuiElement::render(Minecraft* pMinecraft, const MenuPointer& pointer) { } @@ -98,6 +128,16 @@ void GuiElement::setFocused(bool value) _onFocusChanged(); } +void GuiElement::setId(ID id) +{ + m_ID = id; +} + +void GuiElement::setNavigable(bool isNavigable) +{ + m_bNavigable = isNavigable; +} + void GuiElement::setMessage(const std::string& message) { m_message = message; diff --git a/source/client/gui/GuiElement.hpp b/source/client/gui/GuiElement.hpp index 36626bb97..8ac2bc45c 100644 --- a/source/client/gui/GuiElement.hpp +++ b/source/client/gui/GuiElement.hpp @@ -3,6 +3,7 @@ #include "common/math/Color.hpp" #include "client/gui/MenuPointer.hpp" #include "GuiComponent.hpp" +#include "AreaNavigation.hpp" #define C_SOUND_UI_BACK "ui.back" #define C_SOUND_UI_FOCUS "ui.focus" @@ -25,7 +26,7 @@ class GuiElement : public GuiComponent }; public: - GuiElement(GuiElement::ID id); + GuiElement(); public: void setBackground(const Color& color); @@ -33,21 +34,29 @@ class GuiElement : public GuiComponent protected: virtual void _onSelectedChanged(); virtual void _onFocusChanged(); - virtual bool _clicked(const MenuPointer& pointer); + virtual bool _isHovered(const MenuPointer& pointer); public: virtual void setupPositions(); virtual void tick(Minecraft* pMinecraft); virtual bool pointerPressed(Minecraft* pMinecraft, const MenuPointer& pointer); virtual bool pointerReleased(Minecraft* pMinecraft, const MenuPointer& pointer); + virtual bool areaNavigation(Minecraft* pMinecraft, AreaNavigation::Direction); virtual void handleButtonPress(Minecraft* pMinecraft, int key); virtual void handleTextChar(Minecraft* pMinecraft, int chr); virtual void handleClipboardPaste(const std::string& content); + virtual void handleScroll(float force); + virtual bool isHovered(Minecraft*, const MenuPointer& pointer); + virtual void pressed(Minecraft* pMinecraft); + virtual void pressed(Minecraft*, const MenuPointer& pointer); + virtual void released(const MenuPointer& pointer); virtual void render(Minecraft* pMinecraft, const MenuPointer& pointer); virtual void setEnabled(bool isEnabled); virtual void setVisible(bool isVisible); virtual void setSelected(bool isSelected); virtual void setFocused(bool hasFocus); + virtual void setId(ID); + virtual void setNavigable(bool isNavigable); virtual void setMessage(const std::string& message); virtual void setTextboxText(const std::string& text); virtual Type getType() const { return TYPE_UNKNOWN; } @@ -59,6 +68,7 @@ class GuiElement : public GuiComponent bool isVisible() const { return m_bVisible; } bool isSelected() const { return m_bSelected; } bool hasFocus() const { return m_bHasFocus; } + bool isNavigable() const { return m_bNavigable; } private: std::string m_message; @@ -68,11 +78,13 @@ class GuiElement : public GuiComponent Color m_backgroundColor; bool m_bSelected; bool m_bHasFocus; + bool m_bNavigable; public: int m_width; int m_height; int m_xPos; int m_yPos; + UITheme m_uiTheme; }; diff --git a/source/client/gui/IntRectangle.hpp b/source/client/gui/IntRectangle.hpp index 756299dbf..55bfe7068 100644 --- a/source/client/gui/IntRectangle.hpp +++ b/source/client/gui/IntRectangle.hpp @@ -7,6 +7,15 @@ struct IntRectangle int w; int h; + IntRectangle(int x, int y, int width, int height) : + x(x), + y(y), + w(width), + h(height) + { + + } + IntRectangle() { x = 0; diff --git a/source/client/gui/Screen.cpp b/source/client/gui/Screen.cpp index cb231ef6b..230a85921 100644 --- a/source/client/gui/Screen.cpp +++ b/source/client/gui/Screen.cpp @@ -20,7 +20,7 @@ #define C_POINTER_FAST_MOVE_SPEED 0.09f #define C_POINTER_MINIMUM_SPEED 0.04f #define C_POINTER_DIAGONAL_SPEED 0.4f -#define C_POINTER_FRICTION 15.0f +#define C_POINTER_FRICTION 1500.0f #define C_ANGLE8 (45.0f * MTH_DEG_TO_RAD) #define C_ANGLE16 (22.5f * MTH_DEG_TO_RAD) @@ -35,165 +35,48 @@ bool Screen::_isPanoramaAvailable = false; Screen::Screen() { m_bLastPointerPressedState = false; - m_currentUpdateTime = 0.0; - m_lastUpdateTime = 0.0; m_width = 1; m_height = 1; - field_10 = false; + m_bPassEvents = false; + m_bDeletePrevious = true; m_pMinecraft = nullptr; - m_elementListIndex = 0; - m_elementIndex = 0; - m_bTabWrap = true; + m_pSelectedElement = nullptr; m_pFont = nullptr; - m_pClickedButton = 0; + m_pClickedElement = 0; m_yOffset = -1; m_bRenderPointer = false; m_lastTimeMoved = 0; m_cursorTick = 0; - - _addElementList(); + m_uiTheme = UI_POCKET; } Screen::~Screen() { - m_pClickedButton = nullptr; + m_pClickedElement = nullptr; m_elements.clear(); } -void Screen::_controllerEvent(GameController::ID controllerId) +void Screen::controllerEvent(GameController::StickID stickID, double deltaTime) { // @TODO: this probably shouldn't be here GameController::StickEvent event; - event.id = controllerId; - event.state = GameControllerManager::getDirection(controllerId); + event.id = stickID; + event.state = GameControllerManager::getDirection(stickID); if (event.state != GameController::STICK_STATE_NONE) { - event.x = GameControllerManager::getX(controllerId); - event.y = GameControllerManager::getY(controllerId); - handleControllerStickEvent(event); - } -} - -bool Screen::_nextElement() -{ - if (!doElementTabbing()) - return false; - - if (_getElementList().empty()) - return false; - - if (!m_bTabWrap && (m_elementIndex + 1) == _getElementList().size()) - return false; - - _deselectCurrentElement(); - - m_elementIndex++; - - if (m_bTabWrap && m_elementIndex == _getElementList().size()) - { - m_elementIndex = 0; + event.x = GameControllerManager::getX(stickID); + event.y = GameControllerManager::getY(stickID); + handleControllerStickEvent(event, deltaTime); } - - _selectCurrentElement(); - - return true; } -bool Screen::_prevElement() -{ - if (!doElementTabbing()) - return false; - - if (_getElementList().empty()) - return false; - - if (!m_bTabWrap && m_elementIndex == 0) - return false; - - _deselectCurrentElement(); - - if (m_bTabWrap && m_elementIndex == 0) - { - m_elementIndex = _getElementList().size() - 1; - } - else - { - m_elementIndex--; - } - - _selectCurrentElement(); - - return true; -} - -void Screen::_addElement(GuiElement& element, bool isTabbable) -{ - _addElementToList(m_elementListIndex, element, isTabbable); -} - -void Screen::_addElementToList(unsigned int index, GuiElement& element, bool isTabbable) +void Screen::_addElement(GuiElement& element, bool navigable) { + element.setId(m_elements.size()); + element.setNavigable(navigable); m_elements.push_back(&element); - m_elementsById[element.getId()] = &element; - if (isTabbable) - _getElementList(index).push_back(&element); -} - -bool Screen::_nextElementList() -{ - if (m_elementTabLists.size() == 1) - return false; - - if (!m_bTabWrap && (m_elementListIndex + 1) == m_elementTabLists.size()) - return false; - - _deselectCurrentElement(); - - m_elementListIndex++; - - if (m_bTabWrap && m_elementListIndex == m_elementTabLists.size()) - { - m_elementListIndex = 0; - } - - m_elementIndex = 0; - - _selectCurrentElement(); - - return true; -} - -bool Screen::_prevElementList() -{ - if (m_elementTabLists.size() == 1) - return false; - - if (!m_bTabWrap && m_elementListIndex == 0) - return false; - - _deselectCurrentElement(); - - if (m_bTabWrap && m_elementListIndex == 0) - { - m_elementListIndex = m_elementTabLists.size() - 1; - } - else - { - m_elementListIndex--; - } - - m_elementIndex = 0; - - _selectCurrentElement(); - - - return true; -} - -void Screen::_addElementList() -{ - m_elementTabLists.push_back(GuiElementList()); + element.m_uiTheme = m_uiTheme; } void Screen::_selectCurrentElement() @@ -207,7 +90,10 @@ void Screen::_deselectCurrentElement() { GuiElement* element = _getSelectedElement(); if (element) + { element->setSelected(false); + element->setFocused(false); + } } void Screen::_playSelectSound() @@ -218,7 +104,7 @@ void Screen::_playSelectSound() m_pMinecraft->m_pSoundEngine->playUI(C_SOUND_UI_FOCUS, 1.0f, pitch); } -void Screen::_centerMenuPointer() +void Screen::initMenuPointer() { handlePointerLocation(m_width / 2, m_height / 2); } @@ -226,54 +112,20 @@ void Screen::_centerMenuPointer() void Screen::_renderPointer() { GameRenderer& gameRenderer = *m_pMinecraft->m_pGameRenderer; - - double deltaTime = m_pMinecraft->m_fDeltaTime; - m_menuPointer.x = Mth::Lerp(m_menuPointer.x, m_targetMenuPointer.x, deltaTime * C_POINTER_FRICTION); - m_menuPointer.y = Mth::Lerp(m_menuPointer.y, m_targetMenuPointer.y, deltaTime * C_POINTER_FRICTION); - gameRenderer.renderPointer(m_menuPointer); } -GuiElement* Screen::_getInternalElement(unsigned int index) -{ - GuiElementList& list = m_elements; - if (index >= list.size()) - return nullptr; - - return list[index]; -} - -GuiElement* Screen::_getElementByIndex(unsigned int index) +GuiElement* Screen::_getElement(GuiElement::ID id) { - GuiElementList& list = _getElementList(); - if (index >= list.size()) - return nullptr; - - return list[index]; -} - -GuiElement* Screen::_getElementById(GuiElement::ID id) -{ - GuiElementMap::const_iterator it = m_elementsById.find(id); - if (it != m_elementsById.end()) - return it->second; + if (id >= 0 && id < GuiElement::ID(m_elements.size())) + return m_elements[id]; return nullptr; } GuiElement* Screen::_getSelectedElement() { - return _getElementByIndex(m_elementIndex); -} - -GuiElementList& Screen::_getElementList(unsigned int index) -{ - return m_elementTabLists[index]; -} - -GuiElementList& Screen::_getElementList() -{ - return _getElementList(m_elementListIndex); + return m_pSelectedElement; } bool Screen::_useController() const @@ -281,17 +133,15 @@ bool Screen::_useController() const return m_pMinecraft->useController(); } -void Screen::init(Minecraft* pMinecraft, int a3, int a4) +void Screen::init(Minecraft* pMinecraft, int width, int height) { - m_width = a3; - m_height = a4; m_pMinecraft = pMinecraft; m_pFont = pMinecraft->m_pFont; - _centerMenuPointer(); - - init(); + setSize(width, height); + initMenuPointer(); _updateTabButtonSelection(); + m_bLastPointerPressedState = false; } void Screen::keyPressed(int key) @@ -304,11 +154,11 @@ void Screen::keyPressed(int key) m_pMinecraft->handleBack(false); } - if (options.isKey(KM_MENU_LEFT, key)) + if (m_pMinecraft->getOptions()->isKey(KM_MENU_TAB_LEFT, key)) { prevTab(); } - if (options.isKey(KM_MENU_RIGHT, key)) + if (m_pMinecraft->getOptions()->isKey(KM_MENU_TAB_RIGHT, key)) { nextTab(); } @@ -317,28 +167,28 @@ void Screen::keyPressed(int key) { if (options.isKey(KM_MENU_DOWN, key)) { - nextElement(); + _areaNavigation(AreaNavigation::DOWN); } - if (options.isKey(KM_MENU_UP, key)) + else if (options.isKey(KM_MENU_UP, key)) { - prevElement(); + _areaNavigation(AreaNavigation::UP); } - if (options.isKey(KM_MENU_OK, key)) + else if (options.isKey(KM_MENU_RIGHT, key)) + { + _areaNavigation(AreaNavigation::RIGHT); + } + else if (options.isKey(KM_MENU_LEFT, key)) + { + _areaNavigation(AreaNavigation::LEFT); + } + else if (options.isKey(KM_MENU_OK, key)) { if (element && element->isEnabled()) { - switch (element->getType()) - { - case GuiElement::TYPE_BUTTON: - { - Button* button = (Button*)element; - m_pMinecraft->m_pSoundEngine->playUI(C_SOUND_UI_PRESS); - button->pressed(m_pMinecraft, MenuPointer(button->m_xPos, button->m_yPos)); - _buttonClicked(button); - break; - } - default: break; - } + m_pMinecraft->m_pSoundEngine->playUI(C_SOUND_UI_PRESS); + element->pressed(m_pMinecraft); + if (element->getType() == GuiElement::TYPE_BUTTON) + _buttonClicked((Button*)element); } } @@ -370,6 +220,16 @@ void Screen::keyboardTextPaste(const std::string& text) } } +float Screen::getScale(int width, int height) +{ + return m_uiTheme == UI_CONSOLE ? GetConsoleScale(height) : 0.0f; +} + +float Screen::GetConsoleScale(int height) +{ + return 1.0f / float(Mth::round((Mth::round(height / 180.0f) * 180) / 360.0f) / 2.0f); +} + void Screen::setTextboxText(const std::string& text) { GuiElement* element = _getSelectedElement(); @@ -403,6 +263,12 @@ static float g_panoramaAngle = 0.0f; void Screen::renderMenuBackground(float f) { + if (m_uiTheme == UI_CONSOLE) + { + renderConsolePanorama(); + return; + } + if (!m_pMinecraft->getOptions()->m_menuPanorama.get()) { renderDirtBackground(0); @@ -414,7 +280,7 @@ void Screen::renderMenuBackground(float f) g_panoramaAngle += float(30.0 * m_pMinecraft->m_fDeltaTime); float aspectRatio = 1.0f; - //aspectRatio = float(m_width) / float(m_height); + //aspectRatio = float(width) / float(height); // @HAL: this should be using ui_cubemap, but for whatever reason we need to disable culling mce::MaterialPtr& materialPtr = m_screenMaterials.ui_background; @@ -484,22 +350,48 @@ void Screen::renderMenuBackground(float f) fillGradient(0, 0, m_width, m_height, Color(0, 0, 0, 137), Color(255, 255, 255, 137)); } +void Screen::renderConsolePanorama(bool isNight) +{ + m_pMinecraft->m_pTextures->setSmoothing(true); + blitTexture(*m_pMinecraft->m_pTextures, isNight ? "gui/console/Panorama_Background_N.png" : "gui/console/Panorama_Background_S.png", 0, 0, getTimeS() * 1000 * m_height / 360 / 66.32f, 1, m_width, m_height + 2, m_height * 820 / 144, m_height + 2); + m_pMinecraft->m_pTextures->setSmoothing(false); +} + +void Screen::renderConsolePanorama() +{ + renderConsolePanorama(m_pMinecraft->m_pLevel && !m_pMinecraft->m_pLevel->isDay()); +} + +void Screen::renderConsoleLoading(int x, int y, int blockSize, int blockDistance) +{ + int blockD = (blockSize + blockDistance); + for (int i = 0; i < 8; i++) + { + int v = (i + 1) * 100; + int n = (i + 3) * 100; + float l = (getTimeMs() % 1000) / 4.0f; + float alpha = l >= v - 100 ? (l <= v ? l / v : (n - l) / 200.0f) : 0; + if (alpha > 0) + { + currentShaderColor.a = alpha; + blitSprite(*m_pMinecraft->m_pTextures, "gui/loading_block.png", x + (i <= 2 ? i : i >= 4 ? i == 7 ? 0 : 6 - i : 2) * blockD, y + (i <= 2 ? 0 : i == 3 || i == 7 ? 1 : 2) * blockD, blockSize, blockSize); + } + } + currentShaderColor = Color::WHITE; +} + void Screen::pointerPressed(const MenuPointer& pointer, MouseButtonType btn) // d = clicked? { if (btn == MOUSE_BUTTON_NONE) return; for (size_t i = 0; i < m_elements.size(); i++) { - GuiElement* element = _getInternalElement((unsigned int)i); + GuiElement* element = _getElement((unsigned int)i); element->pointerPressed(m_pMinecraft, pointer); - if (element->getType() != GuiElement::TYPE_BUTTON) - continue; - - Button* button = (Button*)element; - if (button->clicked(m_pMinecraft, pointer)) + if (element->isHovered(m_pMinecraft, pointer)) { - m_pClickedButton = button; + m_pClickedElement = element; if (!m_pMinecraft->isTouchscreen()) { @@ -507,8 +399,9 @@ void Screen::pointerPressed(const MenuPointer& pointer, MouseButtonType btn) // m_pMinecraft->m_pSoundEngine->playUI(C_SOUND_UI_PRESS); else m_pMinecraft->m_pSoundEngine->playUI(C_SOUND_BTN_CLICK); - button->pressed(m_pMinecraft, pointer); - _buttonClicked(button); + element->pressed(m_pMinecraft, pointer); + if (m_pClickedElement->getType() == GuiElement::TYPE_BUTTON) + _buttonClicked((Button*)m_pClickedElement); } } } @@ -539,16 +432,17 @@ void Screen::pointerReleased(const MenuPointer& pointer, MouseButtonType btn) // @TODO: call GuiElement::pointerReleased(m_pMinecraft, pointer); - if (m_pClickedButton) + if (m_pClickedElement) { - if (m_pMinecraft->isTouchscreen() && m_pClickedButton->clicked(m_pMinecraft, pointer)) + if (m_pMinecraft->isTouchscreen() && m_pClickedElement->isHovered(m_pMinecraft, pointer)) { m_pMinecraft->m_pSoundEngine->playUI(C_SOUND_BTN_RELEASE); - m_pClickedButton->pressed(m_pMinecraft, pointer); - _buttonClicked(m_pClickedButton); + m_pClickedElement->pressed(m_pMinecraft, pointer); + if (m_pClickedElement->getType() == GuiElement::TYPE_BUTTON) + _buttonClicked((Button*)m_pClickedElement); } - m_pClickedButton->released(pointer); - m_pClickedButton = nullptr; + m_pClickedElement->released(pointer); + m_pClickedElement = nullptr; } } @@ -556,7 +450,7 @@ void Screen::render(float a) { for (size_t i = 0; i < m_elements.size(); i++) { - GuiElement* element = _getInternalElement(i); + GuiElement* element = _getElement(i); if (!element) continue; element->tick(m_pMinecraft); @@ -571,13 +465,14 @@ void Screen::tick() void Screen::setSize(int width, int height) { + if (width != m_width || height != m_height) + handlePointerLocation(m_menuPointer.x * width / m_width, m_menuPointer.y * height / m_height); + m_width = width; m_height = height; // not original code. Will need to re-init again m_elements.clear(); - m_elementTabLists.clear(); - _addElementList(); init(); } @@ -607,62 +502,44 @@ bool Screen::onBack(bool b) return result; } -bool Screen::selectElement(GuiElement::ID id) +bool Screen::selectElementById(GuiElement::ID id) { - // @TODO: this is pretty inefficient and should be redone - // we are doing a bruteforce search for an element with a matching ID - for (size_t i = 0; i < m_elementTabLists.size(); i++) + GuiElement* element = _getElement(id); + + if (element) { - GuiElementList& list = _getElementList(i); - for (size_t j = 0; j < list.size(); j++) - { - if (_getElementByIndex(j)->getId() == id) - { - m_elementListIndex = (unsigned int)i; - m_elementIndex = (unsigned int)j; - return true; - } - } + selectElement(element); + return true; } return false; } -void Screen::onClose() +void Screen::selectElement(GuiElement* element) { - m_pMinecraft->setScreen(nullptr); + _deselectCurrentElement(); + m_pSelectedElement = element; + _selectCurrentElement(); } -bool Screen::nextElement() +bool Screen::_areaNavigation(AreaNavigation::Direction dir) { - bool result = _nextElement(); - if (result) - _playSelectSound(); - return result; -} + if (!m_pSelectedElement) return false; -bool Screen::prevElement() -{ - bool result = _prevElement(); - if (result) - _playSelectSound(); - return result; -} + if (m_pSelectedElement->areaNavigation(m_pMinecraft, dir)) return true; -bool Screen::nextElementList() -{ - bool result = _nextElementList(); - if (result) + if (selectElementById(Navigation(this).navigateCyclic(dir, m_pSelectedElement->m_xPos + m_pSelectedElement->m_width / 2, m_pSelectedElement->m_yPos + m_pSelectedElement->m_height / 2))) + { _playSelectSound(); - return result; + return true; + } + + return false; } -bool Screen::prevElementList() +void Screen::onClose() { - bool result = _prevElementList(); - if (result) - _playSelectSound(); - return result; + m_pMinecraft->setScreen(nullptr); } bool Screen::nextTab() @@ -693,7 +570,7 @@ int Screen::getYOffset() GuiElement* element = _getSelectedElement(); if (element && element->getType() == GuiElement::TYPE_TEXTBOX) { - int heightLeft = m_height - int(float(keybOffset) * Gui::InvGuiScale); + int heightLeft = m_height - int(float(keybOffset) * Gui::GuiScale); // we want to keep the center of the text box in the center of the screen int textCenterY = element->m_yPos + element->m_height / 2; @@ -772,10 +649,16 @@ void Screen::_controllerDirectionHeld(GameController::StickID stickId, GameContr switch (stickState) { case GameController::STICK_STATE_UP: - prevElement(); + _areaNavigation(AreaNavigation::UP); break; case GameController::STICK_STATE_DOWN: - nextElement(); + _areaNavigation(AreaNavigation::DOWN); + break; + case GameController::STICK_STATE_LEFT: + _areaNavigation(AreaNavigation::LEFT); + break; + case GameController::STICK_STATE_RIGHT: + _areaNavigation(AreaNavigation::RIGHT); break; default: break; @@ -798,9 +681,16 @@ void Screen::_updateTabButtonSelection() if (!_useController() || m_bRenderPointer) return; - for (size_t i = 0; i < _getElementList().size(); i++) + if (!m_pSelectedElement) { - _getElementByIndex(i)->setSelected(m_elementIndex == i); + selectElementById(Navigation(this).navigate(AreaNavigation::DOWN, m_width / 2, 0)); + } + + for (size_t i = 0; i < m_elements.size(); i++) + { + GuiElement* element = m_elements[i]; + element->setFocused(element == m_pSelectedElement); + element->setSelected(element == m_pSelectedElement); } } @@ -816,12 +706,7 @@ bool Screen::_prevTab() void Screen::updateEvents() { - if (field_10) return; - - m_currentUpdateTime = getTimeS(); - - if (m_lastUpdateTime == 0.0) - m_lastUpdateTime = m_currentUpdateTime; + if (m_bPassEvents) return; while (Mouse::next()) mouseEvent(); @@ -834,8 +719,6 @@ void Screen::updateEvents() checkForPointerEvent(MOUSE_BUTTON_LEFT); controllerEvent(); } - - m_lastUpdateTime = m_currentUpdateTime; } void Screen::mouseEvent() @@ -877,8 +760,7 @@ void Screen::controllerEvent() _processControllerDirection(1); _processControllerDirection(2); - _controllerEvent(1); - _controllerEvent(2); + controllerEvent(2); } void Screen::checkForPointerEvent(MouseButtonType button) @@ -897,9 +779,8 @@ bool Screen::handleBackEvent(bool b) void Screen::handlePointerLocation(MenuPointer::Unit x, MenuPointer::Unit y) { - m_menuPointer.x = Mth::clamp(x, 0.0f, m_width); - m_menuPointer.y = Mth::clamp(y, 0.0f, m_height); - m_targetMenuPointer = m_menuPointer; + m_menuPointer.x = Mth::clamp(x, 0.0f, float(m_width)); + m_menuPointer.y = Mth::clamp(y, 0.0f, float(m_height)); } void Screen::handlePointerPressed(bool isPressed) @@ -923,9 +804,13 @@ void Screen::handlePointerAction(const MenuPointer& pointer, MouseButtonType but void Screen::handleScrollWheel(float force) { + for (size_t i = 0; i < m_elements.size(); i++) + { + m_elements[i]->handleScroll(force); + } } -void Screen::handleControllerStickEvent(const GameController::StickEvent& stick) +void Screen::handleControllerStickEvent(const GameController::StickEvent& stick, double deltaTime) { if (m_bRenderPointer && stick.id == 1) { @@ -933,6 +818,7 @@ void Screen::handleControllerStickEvent(const GameController::StickEvent& stick) float baseSensitivity = m_pMinecraft->getOptions()->m_sensitivity.get(); float sensitivity = baseSensitivity * 2.0f; float moveSensitivity = baseSensitivity * 2.0f; + //float affectY = Mth::clamp((sensitivity - 0.4f) * 1.67f, 0, 1); Vec2 stickPos(stick.x, stick.y); @@ -952,19 +838,12 @@ void Screen::handleControllerStickEvent(const GameController::StickEvent& stick) Vec2 targetVelocity(snap * speed * moveSensitivity); targetVelocity.x = stickAbs.x < C_POINTER_MINIMUM_SPEED ? C_POINTER_MINIMUM_SPEED * Mth::signum(targetVelocity.x) : targetVelocity.x; targetVelocity.y = stickAbs.y < C_POINTER_MINIMUM_SPEED ? C_POINTER_MINIMUM_SPEED * Mth::signum(targetVelocity.y) : targetVelocity.y; // * speedY; + targetVelocity *= Gui::GuiScale; // Multiply by delta for smooth movement - double deltaTime = m_currentUpdateTime - m_lastUpdateTime; - if (deltaTime > 0.1f) deltaTime = 0.1f; - m_pointerVelocity.x = Mth::Lerp(m_pointerVelocity.x, targetVelocity.x, deltaTime * C_POINTER_FRICTION); - m_pointerVelocity.y = Mth::Lerp(m_pointerVelocity.y, targetVelocity.y, deltaTime * C_POINTER_FRICTION); - Vec2 move = m_pointerVelocity * deltaTime; - - // Scale to our GUI - move *= m_height / Gui::InvGuiScale; + Vec2 move = targetVelocity * C_POINTER_FRICTION * deltaTime; - m_targetMenuPointer.x = Mth::clamp(m_menuPointer.x + move.x, 0.0f, m_width); - m_targetMenuPointer.y = Mth::clamp(m_menuPointer.y - move.y, 0.0f, m_height); + handlePointerLocation(m_menuPointer.x + move.x, m_menuPointer.y - move.y); } else if (stick.id == 2) { @@ -985,7 +864,10 @@ void Screen::renderBackground(int vo) } else { - renderDirtBackground(vo); + if (m_uiTheme == UI_CONSOLE) + renderConsolePanorama(); + else + renderDirtBackground(vo); } } @@ -1010,3 +892,31 @@ void Screen::renderDirtBackground(int vo) //t.setOffset(0, 0, 0); t.draw(m_materials.ui_texture_and_color); } + +Screen::Navigation::Navigation(Screen* screen) : m_pScreen(screen) +{ + m_area.w = screen->m_width; + m_area.h = screen->m_height; +} + +bool Screen::Navigation::next(int& x, int& y, bool cycle) +{ + while (++m_index < int(m_pScreen->m_elements.size())) + { + GuiElement* element = m_pScreen->m_elements[m_index]; + + if (!element->isVisible() || !element->isNavigable() || !(cycle || isValid(m_index))) continue; + + x = element->m_xPos + element->m_width / 2; + y = element->m_yPos + element->m_height / 2; + + return true; + } + + return false; +} + +bool Screen::Navigation::isValid(ID id) +{ + return !m_pScreen->m_pSelectedElement || m_pScreen->m_pSelectedElement->getId() != id; +} diff --git a/source/client/gui/Screen.hpp b/source/client/gui/Screen.hpp index 67dfff2ac..a936e10ed 100644 --- a/source/client/gui/Screen.hpp +++ b/source/client/gui/Screen.hpp @@ -18,11 +18,12 @@ #include "client/player/input/GameController.hpp" #include "GuiElement.hpp" #include "MenuPointer.hpp" +#include "AreaNavigation.hpp" class Button; +class VerticalLayout; typedef std::vector GuiElementList; -typedef std::map GuiElementMap; class Screen : public GuiComponent { @@ -53,28 +54,14 @@ class Screen : public GuiComponent Screen(); virtual ~Screen(); -private: - void _controllerEvent(GameController::ID controllerId); - protected: - bool _nextElement(); - bool _prevElement(); - void _addElement(GuiElement& element, bool isTabbable = true); - void _addElementToList(unsigned int index, GuiElement& element, bool isTabbable = true); - bool _nextElementList(); - bool _prevElementList(); - void _addElementList(); + void _addElement(GuiElement& element, bool navigable = true); void _selectCurrentElement(); void _deselectCurrentElement(); void _playSelectSound(); - void _centerMenuPointer(); void _renderPointer(); - GuiElement* _getInternalElement(unsigned int index); // returns any element - GuiElement* _getElementByIndex(unsigned int index); // only returns tabbable element - GuiElement* _getElementById(GuiElement::ID id); // returns any element + GuiElement* _getElement(GuiElement::ID id); GuiElement* _getSelectedElement(); - GuiElementList& _getElementList(unsigned int index); - GuiElementList& _getElementList(); bool _useController() const; public: @@ -82,18 +69,17 @@ class Screen : public GuiComponent void setSize(int width, int height); void onRender(float f); bool onBack(bool b); - bool selectElement(GuiElement::ID id); - bool prevElement(); - bool nextElement(); - bool nextElementList(); - bool prevElementList(); + bool selectElementById(GuiElement::ID id); + void selectElement(GuiElement*); bool nextTab(); bool prevTab(); int getYOffset(); unsigned int getCursorMoveThrottle() const { return 65; } bool doElementTabbing() const; + void controllerEvent(GameController::StickID stickId, double deltaTime = 0.0); protected: + virtual bool _areaNavigation(AreaNavigation::Direction); virtual void _processControllerDirection(GameController::StickID stickId); virtual void _controllerDirectionChanged(GameController::StickID stickId, GameController::StickState stickState); virtual void _controllerDirectionHeld(GameController::StickID stickId, GameController::StickState stickState); @@ -106,6 +92,7 @@ class Screen : public GuiComponent public: virtual void render(float a); virtual void init() {}; + virtual void initMenuPointer(); virtual void updateEvents(); virtual void mouseEvent(); virtual void keyboardEvent(); @@ -117,7 +104,7 @@ class Screen : public GuiComponent virtual void handlePointerPressed(bool isPressed); virtual void handlePointerAction(const MenuPointer& pointer, MouseButtonType button); virtual void handleScrollWheel(float force); - virtual void handleControllerStickEvent(const GameController::StickEvent& stick); + virtual void handleControllerStickEvent(const GameController::StickEvent& stick, double deltaTime); virtual void tick(); virtual void removed() {}; virtual void renderBackground(int vo); @@ -133,34 +120,49 @@ class Screen : public GuiComponent virtual void keyPressed(int); virtual void handleTextChar(char); virtual void keyboardTextPaste(const std::string& text); + virtual float getScale(int width, int height); + static float GetConsoleScale(int height); virtual void setTextboxText(const std::string& text); virtual void handleKeyboardClosed(); // ported from 0.8 virtual void renderMenuBackground(float f); + void renderConsolePanorama(bool isNight); + void renderConsolePanorama(); + void renderConsoleLoading(int x, int y, int blockSize = 42, int blockDistance = 12); protected: Materials m_screenMaterials; MenuPointer m_menuPointer; - MenuPointer m_targetMenuPointer; - Vec2 m_pointerVelocity; bool m_bLastPointerPressedState; - double m_currentUpdateTime; - double m_lastUpdateTime; public: + friend class VerticalLayout; + + class Navigation : public AreaNavigation + { + public: + Navigation(Screen*); + + bool next(int& x, int& y, bool invert) override; + + bool isValid(ID) override; + + private: + Screen* m_pScreen; + }; + int m_width; int m_height; - bool field_10; + bool m_bPassEvents; + //@NOTE: This should be enabled only if the the actual screen handles the deletion of the previous screen, otherwise, there will be a memory leak! + bool m_bDeletePrevious; Minecraft* m_pMinecraft; GuiElementList m_elements; - GuiElementMap m_elementsById; - std::vector m_elementTabLists; - unsigned int m_elementListIndex; - unsigned int m_elementIndex; - bool m_bTabWrap; + GuiElement* m_pSelectedElement; Font* m_pFont; - Button* m_pClickedButton; + GuiElement* m_pClickedElement; + UITheme m_uiTheme; #ifndef ORIGINAL_CODE int m_yOffset; diff --git a/source/client/gui/ScreenChooser.cpp b/source/client/gui/ScreenChooser.cpp new file mode 100644 index 000000000..d2620083f --- /dev/null +++ b/source/client/gui/ScreenChooser.cpp @@ -0,0 +1,75 @@ +#include "ScreenChooser.hpp" +#include "client/app/Minecraft.hpp" + +#include "screens/StartMenuScreen.hpp" +#include "screens/PauseScreen.hpp" +#include "screens/inventory/CraftingScreen.hpp" +#include "screens/inventory/ChestScreen.hpp" +#include "screens/OptionsScreen.hpp" +#include "screens/OptionsScreen_Console.hpp" +#include "screens/CreateWorldScreen.hpp" +#include "screens/ProgressScreen.hpp" +#include "screens/CreditsScreen.hpp" + +#include "ScreenChooser_Console.hpp" + +ScreenChooser::ScreenChooser(Minecraft* mc, UITheme uiTheme) : + m_pMinecraft(mc) + , m_uiTheme(uiTheme) +{ +} + +ScreenChooser::~ScreenChooser() +{ +} + +void ScreenChooser::pushStartScreen() +{ + m_pMinecraft->setScreen(new StartMenuScreen); +} + +void ScreenChooser::pushPauseScreen() +{ + m_pMinecraft->setScreen(new PauseScreen); +} + +void ScreenChooser::pushCreateWorldScreen(Screen* parent) +{ + m_pMinecraft->setScreen(new CreateWorldScreen(parent)); +} + +void ScreenChooser::pushOptionsScreen(Screen* parent) +{ + m_pMinecraft->setScreen(new OptionsScreen(parent)); +} + +void ScreenChooser::pushProgressScreen() +{ + m_pMinecraft->setScreen(new ProgressScreen); +} + +void ScreenChooser::pushCraftingScreen(Player* player, const TilePos& pos) +{ + m_pMinecraft->setScreen(new CraftingScreen(player->m_pInventory, pos, player->m_pLevel)); +} + +void ScreenChooser::pushChestScreen(Player* player, Container* container) +{ + m_pMinecraft->setScreen(new ChestScreen(player->m_pInventory, container)); +} + +void ScreenChooser::pushCreditsScreen(Screen* parent) +{ + m_pMinecraft->setScreen(new CreditsScreen(parent)); +} + +ScreenChooser* ScreenChooser::Create(Minecraft* mc) +{ + switch (mc->getOptions()->getUiTheme()) + { + case UI_CONSOLE: + return new ScreenChooser_Console(mc); + default: + return new ScreenChooser(mc, mc->getOptions()->getUiTheme()); + } +} diff --git a/source/client/gui/ScreenChooser.hpp b/source/client/gui/ScreenChooser.hpp new file mode 100644 index 000000000..c052f6233 --- /dev/null +++ b/source/client/gui/ScreenChooser.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "client/options/Options.hpp" + +struct TilePos; +class Player; +class Minecraft; +class Container; +class Screen; + +//@NOTE: This is just based on MCPE, not really a decompilation, make it accurate if necessary +class ScreenChooser +{ +public: + ScreenChooser(Minecraft*, UITheme uiTheme); + virtual ~ScreenChooser(); + +public: + virtual void pushStartScreen(); + virtual void pushPauseScreen(); + virtual void pushCreateWorldScreen(Screen*); + virtual void pushOptionsScreen(Screen*); + virtual void pushProgressScreen(); + virtual void pushCraftingScreen(Player*, const TilePos&); // originally pushWorkbenchScreen + virtual void pushChestScreen(Player*, Container*); + virtual void pushCreditsScreen(Screen*); + + static ScreenChooser* Create(Minecraft*); + +protected: + Minecraft* m_pMinecraft; + +public: + UITheme m_uiTheme; +}; diff --git a/source/client/gui/ScreenChooser_Console.cpp b/source/client/gui/ScreenChooser_Console.cpp new file mode 100644 index 000000000..5424faf9e --- /dev/null +++ b/source/client/gui/ScreenChooser_Console.cpp @@ -0,0 +1,47 @@ +#include "ScreenChooser_Console.hpp" +#include "client/app/Minecraft.hpp" + +#include "screens/StartMenuScreen_Console.hpp" +#include "screens/PauseScreen_Console.hpp" +#include "screens/inventory/ClassicCraftingScreen_Console.hpp" +#include "screens/OptionsScreen_Console.hpp" +#include "screens/CreateWorldScreen_Console.hpp" +#include "screens/ProgressScreen_Console.hpp" + +ScreenChooser_Console::ScreenChooser_Console(Minecraft* mc) : ScreenChooser(mc, UI_CONSOLE) +{ +} + +ScreenChooser_Console::~ScreenChooser_Console() +{ +} + +void ScreenChooser_Console::pushStartScreen() +{ + m_pMinecraft->setScreen(new StartMenuScreen_Console); +} + +void ScreenChooser_Console::pushPauseScreen() +{ + m_pMinecraft->setScreen(new PauseScreen_Console); +} + +void ScreenChooser_Console::pushOptionsScreen(Screen* parent) +{ + m_pMinecraft->setScreen(new OptionsScreen_Console(parent)); +} + +void ScreenChooser_Console::pushProgressScreen() +{ + m_pMinecraft->setScreen(new ProgressScreen_Console); +} + +void ScreenChooser_Console::pushCreateWorldScreen(Screen* parent) +{ + m_pMinecraft->setScreen(new CreateWorldScreen_Console(*m_pMinecraft->getOptions(), parent)); +} + +void ScreenChooser_Console::pushCraftingScreen(Player* player, const TilePos& pos) +{ + m_pMinecraft->setScreen(new ClassicCraftingScreen_Console(player->m_pInventory, pos, player->m_pLevel)); +} diff --git a/source/client/gui/ScreenChooser_Console.hpp b/source/client/gui/ScreenChooser_Console.hpp new file mode 100644 index 000000000..d1cb890d8 --- /dev/null +++ b/source/client/gui/ScreenChooser_Console.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "ScreenChooser.hpp" + +class ScreenChooser_Console : public ScreenChooser +{ +public: + ScreenChooser_Console(Minecraft*); + ~ScreenChooser_Console(); + +public: + void pushStartScreen() override; + void pushPauseScreen() override; + void pushOptionsScreen(Screen*) override; + void pushProgressScreen() override; + void pushCreateWorldScreen(Screen*) override; + void pushCraftingScreen(Player*, const TilePos&) override; +}; \ No newline at end of file diff --git a/source/client/gui/VerticalLayout.cpp b/source/client/gui/VerticalLayout.cpp new file mode 100644 index 000000000..b85fc8847 --- /dev/null +++ b/source/client/gui/VerticalLayout.cpp @@ -0,0 +1,288 @@ +#include "VerticalLayout.hpp" + +VerticalLayout::VerticalLayout(Screen* screen) : + m_pScreen(screen) + , m_pSelectedElement(nullptr) + , m_pClickedElement(nullptr) + , m_spacing(0) + , m_bCyclic(false) + , m_scrollAmount(0) + , m_elementsOnScreen(0) + , m_bCanScrollDown(false) + , m_bottom(0) +{ +} + +VerticalLayout::~VerticalLayout() +{ + clear(); +} + +GuiElement* VerticalLayout::getElement(ID index) const +{ + if (index >= 0 && index < ID(m_elements.size())) + return m_elements[index]; + + return nullptr; +} + +bool VerticalLayout::selectElementById(ID id, bool sound) +{ + GuiElement* element = getElement(id); + if (element) + { + selectElement(element); + if (sound) + m_pScreen->_playSelectSound(); + return true; + } + return false; +} + +void VerticalLayout::selectElement(GuiElement* element) +{ + if (element != m_pSelectedElement) + { + if (m_pSelectedElement) + m_pSelectedElement->setSelected(false); + m_pSelectedElement = element; + if (m_pSelectedElement) + m_pSelectedElement->setSelected(true); + } +} + +void VerticalLayout::init(const IntRectangle& rect, int spacing, bool cyclic) +{ + m_xPos = rect.x; + m_yPos = rect.y; + m_width = rect.w; + m_height = rect.h; + m_spacing = spacing; + m_bCyclic = cyclic; + + m_pScreen->_addElement(*this, !m_elements.empty()); + + organize(); +} + +void VerticalLayout::organize() +{ + m_bottom = m_yPos; + m_bCanScrollDown = false; + + m_elementsOnScreen = 0; + + int yDiff = 0; + + for (size_t i = m_scrollAmount; i < m_elements.size(); ++i) + { + GuiElement* element = m_elements[i]; + + if (yDiff + element->m_height > m_height) + { + m_bCanScrollDown = true; + break; + } + + element->m_uiTheme = m_pScreen->m_uiTheme; + element->setId(ID(i)); + element->m_width = m_width; + element->m_xPos = m_xPos; + element->m_yPos = m_yPos + yDiff; + + if (element->m_yPos > m_bottom) + m_bottom = element->m_yPos; + + ++m_elementsOnScreen; + + yDiff += element->m_height + m_spacing; + } + + if (isSelected() && !m_pSelectedElement && m_pScreen->_useController()) + selectElementById(0, false); +} + +void VerticalLayout::clear() +{ + if (m_elements.empty()) return; + + m_pSelectedElement = nullptr; + m_pClickedElement = nullptr; + + for (GuiElementList::iterator it = m_elements.begin(); it != m_elements.end(); it = m_elements.erase(it)) + { + delete (*it); + } +} + +bool VerticalLayout::areaNavigation(Minecraft* mc, AreaNavigation::Direction dir) +{ + if (m_pSelectedElement && m_pSelectedElement->areaNavigation(mc, dir)) return true; + + if (dir == AreaNavigation::DOWN) + { + GuiElement* element = m_pSelectedElement; + if (element && isBottomElement(*element)) + { + if (m_bCyclic && !m_bCanScrollDown && m_scrollAmount > 0) + { + int x = element->m_xPos + element->m_width / 2; + updateScroll(0); + AreaNavigation::ID id = Navigation(this).navigate(dir, x, 0, true); + if (id >= 0) + selectElementById(m_scrollAmount + id); + return true; + } + + handleScroll(false); + areaNavigation(dir, element == getElement(ID(m_elements.size() - 1))); + return true; + } + areaNavigation(dir); + return true; + } + else if (dir == AreaNavigation::UP) + { + GuiElement* element = m_pSelectedElement; + if (element && isTopElement(*element)) + { + if (m_bCyclic && !m_scrollAmount) + { + int x = element->m_xPos + element->m_width / 2; + while (m_bCanScrollDown) + { + updateScroll(m_scrollAmount + 1); + } + AreaNavigation::ID id = Navigation(this).navigate(dir, x, 0, true); + if (id >= 0) + selectElementById(m_scrollAmount + id); + return true; + } + + handleScroll(true); + } + areaNavigation(dir); + return true; + } + + return false; +} + +void VerticalLayout::areaNavigation(AreaNavigation::Direction dir, bool cyclic) +{ + GuiElement* element = m_pSelectedElement; + + if (!element) return; + + AreaNavigation::ID id; + if (m_bCyclic && cyclic) + id = Navigation(this).navigateCyclic(dir, element->m_xPos + element->m_width / 2, element->m_yPos + element->m_height / 2); + else + id = Navigation(this).navigate(dir, element->m_xPos + element->m_width / 2, element->m_yPos + element->m_height / 2); + + if (id >= 0) + selectElementById(m_scrollAmount + id); +} + +void VerticalLayout::setSelected(bool b) +{ + GuiElement::setSelected(b); + + if (b && !m_pSelectedElement && m_pScreen->_useController()) + selectElementById(0, false); + + if (!b) + selectElement(nullptr); +} + +bool VerticalLayout::handleScroll(bool up) +{ + if ((m_scrollAmount > 0 && up) || (m_bCanScrollDown && !up)) + { + updateScroll(m_scrollAmount + (up ? -1 : 1)); + return true; + } + return false; +} + +void VerticalLayout::handleScroll(float force) +{ + handleScroll(force > 0); +} + +void VerticalLayout::updateScroll(int amount) +{ + m_scrollRenderer.updateScroll(amount < m_scrollAmount ? AreaNavigation::UP : AreaNavigation::DOWN); + m_scrollAmount = amount; + organize(); +} + +void VerticalLayout::pressed(Minecraft* mc, const MenuPointer& pointer) +{ + for (int i = 0; i < m_elementsOnScreen; ++i) + { + GuiElement* element = m_elements[m_scrollAmount + i]; + if (element->isHovered(mc, pointer)) + { + m_pClickedElement = element; + element->pressed(mc, pointer); + return; + } + } +} + +void VerticalLayout::released(const MenuPointer& pointer) +{ + if (m_pClickedElement) + { + m_pClickedElement->released(pointer); + m_pClickedElement = nullptr; + } +} + +void VerticalLayout::pressed(Minecraft* mc) +{ + if (m_pSelectedElement) + m_pSelectedElement->pressed(mc); +} + +void VerticalLayout::render(Minecraft* mc, const MenuPointer& pointer) +{ + for (int i = 0; i < m_elementsOnScreen; ++i) + { + m_elements[m_scrollAmount + i]->render(mc, pointer); + } + + if (m_scrollAmount > 0) + m_scrollRenderer.renderScroll(AreaNavigation::UP, *mc->m_pTextures, m_xPos + m_width - 64, m_yPos + m_height + 8); + if (m_bCanScrollDown) + m_scrollRenderer.renderScroll(AreaNavigation::DOWN, *mc->m_pTextures, m_xPos + m_width - 32, m_yPos + m_height + 8); +} + +VerticalLayout::Navigation::Navigation(VerticalLayout* layout) : m_pLayout(layout) +{ + m_area.w = layout->m_pScreen->m_width; + m_area.h = layout->m_pScreen->m_height; +} + +bool VerticalLayout::Navigation::next(int& x, int& y, bool cycle) +{ + while (++m_index < m_pLayout->m_elementsOnScreen) + { + GuiElement* element = m_pLayout->m_elements[m_pLayout->m_scrollAmount + m_index]; + + if (!element->isVisible() || !element->isNavigable() || !(cycle || isValid(m_index))) continue; + + x = element->m_xPos + element->m_width / 2; + y = element->m_yPos + element->m_height / 2; + + return true; + } + + return false; +} + +bool VerticalLayout::Navigation::isValid(ID id) +{ + return m_pLayout->m_pSelectedElement->getId() != (m_pLayout->m_scrollAmount + id); +} \ No newline at end of file diff --git a/source/client/gui/VerticalLayout.hpp b/source/client/gui/VerticalLayout.hpp new file mode 100644 index 000000000..d3dd64699 --- /dev/null +++ b/source/client/gui/VerticalLayout.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "Screen.hpp" +#include "IntRectangle.hpp" +#include "components/ScrollRenderer_Console.hpp" + +//@TODO: create an abstraction for this, like GuiElementContainer +class VerticalLayout : public GuiElement +{ +public: + VerticalLayout(Screen* screen); + ~VerticalLayout(); + + GuiElement* getElement(ID) const; + bool isTopElement(GuiElement& element) const { return element.m_yPos == m_yPos; }; + bool isBottomElement(GuiElement& element) const { return element.m_yPos == m_bottom; }; + bool selectElementById(ID, bool sound = true); + void selectElement(GuiElement*); + + void init(const IntRectangle&, int spacing = 8, bool cyclic = true); + void organize(); + void clear(); + + bool areaNavigation(Minecraft*, AreaNavigation::Direction) override; + void areaNavigation(AreaNavigation::Direction, bool cyclic = false); + void setSelected(bool); + + bool handleScroll(bool up); + void handleScroll(float) override; + void updateScroll(int amount); + + void pressed(Minecraft*, const MenuPointer& pointer) override; + void released(const MenuPointer& pointer) override; + void pressed(Minecraft*) override; + + void render(Minecraft*, const MenuPointer&) override; + +public: + class Navigation : public AreaNavigation + { + public: + Navigation(VerticalLayout*); + + bool next(int& x, int& y, bool invert) override; + + bool isValid(ID) override; + private: + VerticalLayout* m_pLayout; + }; + + Screen* m_pScreen; + GuiElementList m_elements; + GuiElement* m_pSelectedElement; + GuiElement* m_pClickedElement; + ScrollRenderer_Console m_scrollRenderer; + int m_spacing; + bool m_bCyclic; + ID m_scrollAmount; + ID m_elementsOnScreen; + bool m_bCanScrollDown; + int m_bottom; +}; \ No newline at end of file diff --git a/source/client/gui/components/Button.cpp b/source/client/gui/components/Button.cpp index 7f11363bf..6010a8ea6 100644 --- a/source/client/gui/components/Button.cpp +++ b/source/client/gui/components/Button.cpp @@ -19,7 +19,61 @@ void Button::_init() #endif } -Button::Button(int buttonId, int xPos, int yPos, int btnWidth, int btnHeight, const std::string& text) : GuiElement(buttonId) +void Button::_renderBg(Minecraft* mc, const MenuPointer& pointer) +{ + int iYPos = 20 * getYImage(isSelected()) + 46; + mc->m_pTextures->loadAndBindTexture("gui/gui.png"); + blit(m_xPos, m_yPos, 0, iYPos, m_width / 2, m_height, 0, 20, &m_materials.ui_textured_and_glcolor); + blit(m_xPos + m_width / 2, m_yPos, 200 - m_width / 2, iYPos, m_width / 2, m_height, 0, 20, &m_materials.ui_textured_and_glcolor); +} + +void Button::_renderBgConsole(Minecraft* mc, const MenuPointer& pointer) +{ + Textures& texs = *mc->m_pTextures; + + if (!isEnabled()) + currentShaderColor.a *= 0.5f; + blitSprite(texs, isSelected() && !hasFocus() ? "gui/console/Graphics/MainMenuButton_Over.png" : "gui/console/Graphics/MainMenuButton_Norm.png", m_xPos, m_yPos, m_width, m_height, &m_materials.ui_textured_and_glcolor); + if (hasFocus()) + { + float timer = (getTimeMs() % 1200) / 1200.0f; + currentShaderColor.a *= 0.5f + (timer >= 0.5f ? 1 - timer : timer); + blitSprite(texs, "gui/console/Graphics/MainMenuButton_Over.png", m_xPos, m_yPos, m_width, m_height, &m_materials.ui_textured_and_glcolor); + currentShaderColor = m_color; + } +} + +void Button::_renderMessage(Font& font) +{ + Color textColor; + if (!isEnabled()) + textColor = Color(160, 160, 160, m_color.a); // 0xFFA0A0A0 + else if (isSelected()) + textColor = Color(255, 255, 160, m_color.a); // 0xFFFFA0U + else + textColor = Color(224, 224, 224, m_color.a); // 0xE0E0E0U + drawCenteredString(font, getMessage(), m_xPos + m_width / 2, m_yPos + (m_height - 8) / 2, textColor); +} + +void Button::_renderMessageConsole(Font& font) +{ + Color textColor; + if (hasFocus()) + { + float timer = (getTimeMs() % 1200) / 1200.0f; + textColor = Color(220, 220, Mth::round((0.5f - (timer >= 0.5f ? 1 - timer : timer)) * 220), currentShaderColor.a); + } + else if (isSelected()) + { + textColor = Color(220, 220, 0, currentShaderColor.a); // 0xDCDC00 + } + else + textColor = Color(224, 224, 224, currentShaderColor.a); // 0xE0E0E0U + int textWidth = font.width(getMessage()) * 2; + font.drawScalableShadow(getMessage(), m_xPos + (m_width - textWidth) / 2, m_yPos + (m_height - 16) / 2, textColor); +} + +Button::Button(int xPos, int yPos, int btnWidth, int btnHeight, const std::string& text) { _init(); @@ -30,7 +84,7 @@ Button::Button(int buttonId, int xPos, int yPos, int btnWidth, int btnHeight, co m_height = btnHeight; } -Button::Button(int buttonId, int xPos, int yPos, const std::string& text) : GuiElement(buttonId) +Button::Button(int xPos, int yPos, const std::string& text) { _init(); @@ -41,7 +95,7 @@ Button::Button(int buttonId, int xPos, int yPos, const std::string& text) : GuiE m_height = 24; } -Button::Button(int buttonId, const std::string& text) : GuiElement(buttonId) +Button::Button(const std::string& text) { _init(); @@ -50,15 +104,6 @@ Button::Button(int buttonId, const std::string& text) : GuiElement(buttonId) m_height = 24; } -bool Button::clicked(Minecraft* pMinecraft, const MenuPointer& pointer) -{ - return _clicked(pointer); -} - -void Button::pressed(Minecraft* pMinecraft, const MenuPointer& pointer) -{ -} - int Button::getYImage(bool bHovered) { if (!isEnabled()) return 0; @@ -66,14 +111,12 @@ int Button::getYImage(bool bHovered) return 1; } -void Button::released(const MenuPointer& pointer) -{ - -} - void Button::renderBg(Minecraft* pMinecraft, const MenuPointer& pointer) { - + if (m_uiTheme == UI_CONSOLE) + _renderBgConsole(pMinecraft, pointer); + else + _renderBg(pMinecraft, pointer); } void Button::render(Minecraft* pMinecraft, const MenuPointer& pointer) @@ -81,31 +124,18 @@ void Button::render(Minecraft* pMinecraft, const MenuPointer& pointer) if (!isVisible()) return; if (!pMinecraft->m_pScreen->doElementTabbing()) - setSelected(clicked(pMinecraft, pointer)); + setSelected(isHovered(pMinecraft, pointer)); if (m_color.a == 0.0f) return; - Font& font = *pMinecraft->m_pFont; - Textures& texs = *pMinecraft->m_pTextures; - - texs.loadAndBindTexture("gui/gui.png"); - currentShaderColor = m_color; - int iYPos = 20 * getYImage(isSelected()) + 46; - - blit(m_xPos, m_yPos, 0, iYPos, m_width / 2, m_height, 0, 20, &m_materials.ui_textured_and_glcolor); - blit(m_xPos + m_width / 2, m_yPos, 200 - m_width / 2, iYPos, m_width / 2, m_height, 0, 20, &m_materials.ui_textured_and_glcolor); - renderBg(pMinecraft, pointer); - Color textColor; - if (!isEnabled()) - textColor = Color(160, 160, 160, m_color.a); // 0xFFA0A0A0 - else if (isSelected()) - textColor = Color(255, 255, 160, m_color.a); // 0xFFFFA0 - else - textColor = Color(224, 224, 224, m_color.a); // 0xE0E0E0 + Font& font = *pMinecraft->m_pFont; - drawCenteredString(font, getMessage(), m_xPos + m_width / 2, m_yPos + (m_height - 8) / 2, textColor); + if (m_uiTheme == UI_CONSOLE) + _renderMessageConsole(font); + else + _renderMessage(font); } diff --git a/source/client/gui/components/Button.hpp b/source/client/gui/components/Button.hpp index f3a224b9b..891ee3c8a 100644 --- a/source/client/gui/components/Button.hpp +++ b/source/client/gui/components/Button.hpp @@ -17,20 +17,23 @@ class Button : public GuiElement { private: void _init(); + +protected: + void _renderBg(Minecraft*, const MenuPointer& pointer); + void _renderBgConsole(Minecraft*, const MenuPointer& pointer); + void _renderMessage(Font&); + void _renderMessageConsole(Font&); + public: - Button(int, int x, int y, int width, int height, const std::string&); - Button(int, int x, int y, const std::string&); - Button(int, const std::string&); + Button(int x, int y, int width, int height, const std::string&); + Button(int x, int y, const std::string&); + Button(const std::string&); public: Type getType() const override { return TYPE_BUTTON; } public: - // I can't possibly explain why Minecraft is referenced here - virtual bool clicked(Minecraft*, const MenuPointer& pointer); - virtual void pressed(Minecraft*, const MenuPointer& pointer); virtual int getYImage(bool bHovered); - virtual void released(const MenuPointer& pointer); virtual void renderBg(Minecraft*, const MenuPointer& pointer); void render(Minecraft* pMinecraft, const MenuPointer& pointer) override; diff --git a/source/client/gui/components/OptionList.cpp b/source/client/gui/components/OptionList.cpp index de2322991..062f32f5e 100644 --- a/source/client/gui/components/OptionList.cpp +++ b/source/client/gui/components/OptionList.cpp @@ -12,9 +12,6 @@ #define C_OPTION_ITEM_HEIGHT (22) -#define C_SWITCH_VALUES_WIDTH (60) -#define C_SWITCH_VALUES_HEIGHT (18) - OptionList::OptionList(Minecraft* pMinecraft, int width, int height, int something, int something2) : ScrolledSelectionList(pMinecraft, width, height, something, something2, C_OPTION_ITEM_HEIGHT) { @@ -124,7 +121,7 @@ void OptionList::onClickItem(int index, const MenuPointer& pointer, int relMouse Button* button = ((Button*)pItem); - if (!button->clicked(m_pMinecraft, pointer)) return; + if (!button->isHovered(m_pMinecraft, pointer)) return; button->pressed(m_pMinecraft, pointer); } @@ -147,22 +144,16 @@ void OptionList::initDefaultMenu() initVideoMenu(); } -#define HEADER(text) do { m_items.push_back(new OptionHeader(0, text)); currentIndex++; } while (0) -#define OPTION(name) do { pOptions->name.addGuiElement(m_items, pOptions->name.getName()); currentIndex++; } while (0) +#define HEADER(text) do { m_items.push_back(new OptionHeader(text)); currentIndex++; } while (0) +#define OPTION(name) do { pOptions->name.addGuiElement(m_items, UI_POCKET); currentIndex++; } while (0) void OptionList::initGameplayMenu() { Options* pOptions = m_pMinecraft->getOptions(); int currentIndex = -1; - HEADER("Game"); - OPTION(m_difficulty); - OPTION(m_thirdPerson); - OPTION(m_serverVisibleDefault); - - HEADER("Audio"); - OPTION(m_musicVolume); - OPTION(m_masterVolume); + OPTIONS_LIST_GAMEPLAY_GAME; + OPTIONS_LIST_GAMEPLAY_AUDIO; #ifndef FEATURE_NETWORKING m_items[currentIndex]->setEnabled(false); @@ -176,20 +167,9 @@ void OptionList::initControlsMenu() int currentIndex = -1; int idxSplit = -1, idxController = -1; - HEADER("Controls"); - OPTION(m_sensitivity); - OPTION(m_invertMouse); - OPTION(m_splitControls); idxSplit = currentIndex; - //OPTION(m_swapJumpSneak); - //OPTION(m_buttonSize); - OPTION(m_autoJump); - OPTION(m_bUseController); idxController = currentIndex; - - /*HEADER("Feedback"); - OPTION(m_vibrate);*/ - - HEADER("Experimental"); - OPTION(m_flightHax); + OPTIONS_LIST_CONTROLS_CONTROLS; + OPTIONS_LIST_CONTROLS_FEEDBACK; + OPTIONS_LIST_CONTROLS_EXPERIMENTAL; if (!m_pMinecraft->isTouchscreen()) m_items[idxSplit]->setEnabled(false); @@ -202,28 +182,8 @@ void OptionList::initVideoMenu() int currentIndex = -1; int idxPano = -1; - HEADER("Graphics"); - //OPTION(m_brightness); - OPTION(m_viewDistance); - //OPTION(m_antiAliasing); - //OPTION(m_guiScale); - //OPTION(m_fov); - OPTION(m_ambientOcclusion); - OPTION(m_fancyGraphics); - OPTION(m_viewBobbing); - OPTION(m_anaglyphs); - OPTION(m_blockOutlines); - OPTION(m_fancyGrass); - OPTION(m_biomeColors); - OPTION(m_dynamicHand); - - HEADER("Experimental"); - OPTION(m_hideGui); - OPTION(m_debugText); - OPTION(m_b2dTitleLogo); -#ifdef ENH_MENU_BACKGROUND - OPTION(m_menuPanorama); idxPano = currentIndex; -#endif + OPTIONS_LIST_VIDEO_GRAPHICS; + OPTIONS_LIST_VIDEO_EXPERIMENTAL; #ifdef ENH_MENU_BACKGROUND if (!Screen::isMenuPanoramaAvailable()) @@ -231,9 +191,8 @@ void OptionList::initVideoMenu() #endif } -OptionHeader::OptionHeader(GuiElement::ID id, const std::string& text) - : GuiElement(id) - , m_text(text) +OptionHeader::OptionHeader(const std::string& text) + : m_text(text) { } diff --git a/source/client/gui/components/OptionList.hpp b/source/client/gui/components/OptionList.hpp index 5b23bc237..bbb03fec1 100644 --- a/source/client/gui/components/OptionList.hpp +++ b/source/client/gui/components/OptionList.hpp @@ -41,7 +41,7 @@ class OptionList : public ScrolledSelectionList class OptionHeader : public GuiElement { public: - OptionHeader(GuiElement::ID id, const std::string& text); + OptionHeader(const std::string& text); public: void render(Minecraft* pMinecraft, const MenuPointer& pointer) override; diff --git a/source/client/gui/components/ScrollRenderer_Console.cpp b/source/client/gui/components/ScrollRenderer_Console.cpp new file mode 100644 index 000000000..cb9e23aee --- /dev/null +++ b/source/client/gui/components/ScrollRenderer_Console.cpp @@ -0,0 +1,39 @@ +#include + +#include "ScrollRenderer_Console.hpp" +#include "renderer/ShaderConstants.hpp" + +std::string ScrollRenderer_Console::SCROLLS[] = { "gui/console/scrollUp.png", "gui/console/scrollDown.png", "gui/console/scrollLeft.png", "gui/console/scrollRight.png" }; + +ScrollRenderer_Console::ScrollRenderer_Console() +{ + memset(m_lastScrolled, 0, sizeof(m_lastScrolled)); +} + +void ScrollRenderer_Console::updateScroll(AreaNavigation::Direction dir) +{ + m_lastScrolled[dir] = getTimeMs(); +} + +void ScrollRenderer_Console::renderScroll(AreaNavigation::Direction dir, Textures& texs, int x, int y) +{ + switch (dir) + { + case AreaNavigation::LEFT: case AreaNavigation::RIGHT: + renderScroll(dir, texs, x, y, SCROLLS[dir], 26, 22); + break; + case AreaNavigation::UP: case AreaNavigation::DOWN: + renderScroll(dir, texs, x, y, SCROLLS[dir], 32, 22); + break; + } +} + +void ScrollRenderer_Console::renderScroll(AreaNavigation::Direction dir, Textures& texs, int x, int y, const std::string& sprite, int width, int height) +{ + int l = m_lastScrolled[dir]; + if (l > 0) + currentShaderColor = Color(1.0f, 1.0f, 1.0f, getAlpha(l)); + blitSprite(texs, sprite, x, y, width, height, &m_materials.ui_textured_and_glcolor); + if (l > 0) + currentShaderColor = Color::WHITE; +} diff --git a/source/client/gui/components/ScrollRenderer_Console.hpp b/source/client/gui/components/ScrollRenderer_Console.hpp new file mode 100644 index 000000000..e597caae4 --- /dev/null +++ b/source/client/gui/components/ScrollRenderer_Console.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "../AreaNavigation.hpp" +#include "../GuiComponent.hpp" +#include "common/Mth.hpp" + +class ScrollRenderer_Console : public GuiComponent +{ +public: + ScrollRenderer_Console(); + +public: + void updateScroll(AreaNavigation::Direction); + void renderScroll(AreaNavigation::Direction, Textures&, int x, int y); + void renderScroll(AreaNavigation::Direction, Textures&, int x, int y, const std::string&, int width, int height); + + static float getAlpha(int last) + { + float f = (getTimeMs() - last) / 320.0f; + return Mth::Min(1.0f, f < 0.5f ? 1 - f * 2.0f : (f - 0.5f) * 2.0f); + } + +public: + int m_lastScrolled[4]; + + static std::string SCROLLS[]; +}; \ No newline at end of file diff --git a/source/client/gui/components/ScrolledSelectionList.cpp b/source/client/gui/components/ScrolledSelectionList.cpp index 9027a1401..f62e6a1f2 100644 --- a/source/client/gui/components/ScrolledSelectionList.cpp +++ b/source/client/gui/components/ScrolledSelectionList.cpp @@ -223,8 +223,8 @@ void ScrolledSelectionList::render(const MenuPointer& pointer, float f) renderHeader(itemX, scrollY, t); // Note, X/Y are the lower left's X/Y coordinates, not the upper left's. - int lowerY = Minecraft::height - int(m_y1 / Gui::InvGuiScale); - int upperY = Minecraft::height - int(m_y0 / Gui::InvGuiScale); + int lowerY = Minecraft::height - int(m_y1 / Gui::GuiScale); + int upperY = Minecraft::height - int(m_y0 / Gui::GuiScale); { mce::EnableScissorTest scissor(0, lowerY, Minecraft::width, upperY - lowerY); @@ -352,6 +352,6 @@ void ScrolledSelectionList::setRenderHeader(bool b, int i) void ScrolledSelectionList::handleScrollWheel(float force) { - float diff = 5.0f * force; + float diff = 16.0f * force; m_accumulatedScroll -= diff; } diff --git a/source/client/gui/components/SliderButton.cpp b/source/client/gui/components/SliderButton.cpp index aa81906ea..48ed76eaf 100644 --- a/source/client/gui/components/SliderButton.cpp +++ b/source/client/gui/components/SliderButton.cpp @@ -1,19 +1,41 @@ #include "SliderButton.hpp" #include "renderer/ShaderConstants.hpp" -SliderButton::SliderButton(int id, int x, int y, FloatOption* option, const std::string& message, float initialValue) : Button(id, x, y, 150, 20, message), +SliderButton::SliderButton(int x, int y, int width, int height, OptionEntry* option, const std::string& message, float initialValue) : Button(x, y, width, height, message), m_pOption(option), m_value(initialValue), m_bDragging(false) { } +bool SliderButton::areaNavigation(Minecraft* pMinecraft, AreaNavigation::Direction dir) +{ + float oldValue = m_value; + if (dir == AreaNavigation::LEFT) + { + getOption().addUnit(-1); + updateValue(); + } + else if (dir == AreaNavigation::RIGHT) + { + getOption().addUnit(1); + updateValue(); + } + + if (oldValue != m_value) + { + pMinecraft->m_pSoundEngine->playUI(C_SOUND_UI_SCROLL); + return true; + } + + return false; +} + void SliderButton::pressed(Minecraft* mc, const MenuPointer& pointer) { m_value = (pointer.x - (m_xPos + 4)) / float(m_width - 8); - getOption().set(m_value = Mth::clamp(m_value, 0.0f, 1.0f)); - setMessage(getOption().getMessage()); + getOption().fromFloat(m_value = Mth::clamp(m_value, 0.0f, 1.0f)); m_bDragging = true; } @@ -29,17 +51,37 @@ void SliderButton::released(const MenuPointer& pointer) void SliderButton::renderBg(Minecraft* mc, const MenuPointer& pointer) { - if (!isVisible()) return; + if (m_uiTheme != UI_CONSOLE) + Button::renderBg(mc, pointer); if (m_bDragging) { m_value = (pointer.x - (m_xPos + 4)) / float(m_width - 8); - getOption().set(m_value = Mth::clamp(m_value, 0.0f, 1.0f)); - setMessage(getOption().getMessage()); + getOption().fromFloat(m_value = Mth::clamp(m_value, 0.0f, 1.0f)); + updateValue(); } currentShaderColor = m_color; - blit(m_xPos + int(m_value * float(m_width - 8)), m_yPos, 0, 66, 4, m_height - 1, 0, 0); - blit(m_xPos + int(m_value * float(m_width - 8)) + 4, m_yPos, 196, 66, 4, m_height - 1, 0, 0); + + if (m_uiTheme == UI_CONSOLE) + { + Textures& texs = *mc->m_pTextures; + blitSprite(texs, "gui/console/Graphics/Slider_Track.png", m_xPos, m_yPos, m_width - 2, m_height, nullptr, 0.0f, 0.0f, m_width - 2); + blitSprite(texs, "gui/console/Graphics/Slider_Track.png", m_xPos + m_width - 2, m_yPos, 2, m_height, nullptr, 0.0f, 0.0f, 2.0f); + if (isSelected()) + blitNineSlice(texs, "gui/slider_highlight.png", m_xPos - 3, m_yPos - 3, m_width + 6, m_height + 6, 5); + blitSprite(texs, "gui/console/Graphics/Slider_Button.png", m_xPos + int(m_value * float(m_width - 16)), m_yPos, 16, m_height); + } + else + { + blit(m_xPos + int(m_value * float(m_width - 8)), m_yPos, 0, 66, 4, m_height, 0, 20); + blit(m_xPos + int(m_value * float(m_width - 8)) + 4, m_yPos, 196, 66, 4, m_height, 0, 20); + } +} + +void SliderButton::updateValue() +{ + setMessage(getOption().getMessage()); + m_value = getOption().toFloat(); } diff --git a/source/client/gui/components/SliderButton.hpp b/source/client/gui/components/SliderButton.hpp index 9ba75bec8..32284a0d9 100644 --- a/source/client/gui/components/SliderButton.hpp +++ b/source/client/gui/components/SliderButton.hpp @@ -5,17 +5,20 @@ class SliderButton : public Button { public: - SliderButton(int id, int x, int y, FloatOption*, const std::string&, float initialValue); + SliderButton(int x, int y, int width, int height, OptionEntry*, const std::string&, float initialValue); + bool areaNavigation(Minecraft* pMinecraft, AreaNavigation::Direction) override; void pressed(Minecraft*, const MenuPointer& pointer) override; int getYImage(bool bHovered) override; void released(const MenuPointer& pointer) override; void renderBg(Minecraft*, const MenuPointer& pointer) override; - FloatOption& getOption() { return *m_pOption; }; + void updateValue(); + + OptionEntry& getOption() { return *m_pOption; }; private: - FloatOption* m_pOption; + OptionEntry* m_pOption; public: float m_value; diff --git a/source/client/gui/components/SmallButton.cpp b/source/client/gui/components/SmallButton.cpp index 33aed890b..04418ae22 100644 --- a/source/client/gui/components/SmallButton.cpp +++ b/source/client/gui/components/SmallButton.cpp @@ -11,32 +11,29 @@ // @NOTE: Used in the ConfirmScreen. // I reckon this was used in the OptionsScreen as well, since the button sizes are the same. -SmallButton::SmallButton(int id, int x, int y, const std::string& str) : - Button(id, x, y, 150, 20, str), +SmallButton::SmallButton(int x, int y, const std::string& str) : + Button(x, y, 150, 20, str), m_pOption(nullptr) { } -SmallButton::SmallButton(int id, int x, int y, int width, int height, const std::string& str) : - Button(id, x, y, width, height, str), +SmallButton::SmallButton(int x, int y, int width, int height, const std::string& str) : + Button(x, y, width, height, str), m_pOption(nullptr) { } -SmallButton::SmallButton(int id, int x, int y, OptionEntry* pOption, const std::string& str) : - Button(id, x, y, 150, 20, str), +SmallButton::SmallButton(int x, int y, OptionEntry* pOption, const std::string& str) : + Button(x, y, 150, 20, str), m_pOption(pOption) { } -bool SmallButton::clicked(Minecraft* mc, const MenuPointer& pointer) +void SmallButton::pressed(Minecraft* mc) { - if (!Button::clicked(mc, pointer)) return false; if (m_pOption) { getOption().toggle(); setMessage(getOption().getMessage()); } - - return true; } \ No newline at end of file diff --git a/source/client/gui/components/SmallButton.hpp b/source/client/gui/components/SmallButton.hpp index 84e75405d..383b30b21 100644 --- a/source/client/gui/components/SmallButton.hpp +++ b/source/client/gui/components/SmallButton.hpp @@ -13,10 +13,10 @@ class SmallButton : public Button { public: - SmallButton(int id, int x, int y, const std::string& str); - SmallButton(int id, int x, int y, int width, int height, const std::string& str); - SmallButton(int id, int x, int y, OptionEntry* pOption, const std::string& str); - bool clicked(Minecraft*, const MenuPointer& pointer) override; + SmallButton(int x, int y, const std::string& str); + SmallButton(int x, int y, int width, int height, const std::string& str); + SmallButton(int x, int y, OptionEntry* pOption, const std::string& str); + void pressed(Minecraft*) override; OptionEntry& getOption() { return *m_pOption; diff --git a/source/client/gui/components/SwitchButton.cpp b/source/client/gui/components/SwitchButton.cpp index d989415e8..5785266f9 100644 --- a/source/client/gui/components/SwitchButton.cpp +++ b/source/client/gui/components/SwitchButton.cpp @@ -5,7 +5,7 @@ #define C_ON_OFF_SWITCH_WIDTH (38) #define C_ON_OFF_SWITCH_HEIGHT (19) -SwitchButton::SwitchButton(int id, int x, int y, BoolOption* option, const std::string& message) : Button(id, x, y, 150, 20, message), +SwitchButton::SwitchButton(int x, int y, BoolOption* option, const std::string& message) : Button(x, y, 150, 20, message), m_pOption(option) { } @@ -14,10 +14,16 @@ void SwitchButton::pressed(Minecraft* mc, const MenuPointer& pointer) { if (pointer.x >= m_xPos + m_width - C_ON_OFF_SWITCH_WIDTH - 6 && pointer.x < m_xPos + m_width - 6) { - getOption().toggle(); + pressed(mc); } } +void SwitchButton::pressed(Minecraft* mc) +{ + if (!isEnabled()) return; + getOption().toggle(); +} + void SwitchButton::render(Minecraft* mc, const MenuPointer& pointer) { if (!isVisible()) return; diff --git a/source/client/gui/components/SwitchButton.hpp b/source/client/gui/components/SwitchButton.hpp index 0813dc916..ae434d6b9 100644 --- a/source/client/gui/components/SwitchButton.hpp +++ b/source/client/gui/components/SwitchButton.hpp @@ -5,9 +5,10 @@ class SwitchButton : public Button { public: - SwitchButton(int id, int x, int y, BoolOption*, const std::string&); + SwitchButton(int x, int y, BoolOption*, const std::string&); void pressed(Minecraft*, const MenuPointer& pointer) override; + void pressed(Minecraft*) override; void render(Minecraft*, const MenuPointer& pointer) override; BoolOption& getOption() { return *m_pOption; }; diff --git a/source/client/gui/components/SwitchValuesButton.cpp b/source/client/gui/components/SwitchValuesButton.cpp index aa95e5fa4..53c047c4f 100644 --- a/source/client/gui/components/SwitchValuesButton.cpp +++ b/source/client/gui/components/SwitchValuesButton.cpp @@ -5,16 +5,22 @@ #define C_SWITCH_VALUES_WIDTH (60) #define C_SWITCH_VALUES_HEIGHT (18) -SwitchValuesButton::SwitchValuesButton(int id, int x, int y, ValuesOption* option, const std::string& message) : Button(id, x, y, 150, 20, message), +SwitchValuesButton::SwitchValuesButton(int x, int y, OptionEntry* option, const std::string& message) : Button(x, y, 150, 20, message), m_pOption(option) { } +void SwitchValuesButton::pressed(Minecraft*) +{ + if (!isEnabled()) return; + getOption().toggle(); +} + void SwitchValuesButton::pressed(Minecraft* mc, const MenuPointer& pointer) { if (pointer.x >= m_xPos + m_width - C_SWITCH_VALUES_WIDTH - 6 && pointer.x < m_xPos + m_width - 6) { - getOption().toggle(); + pressed(mc); } } diff --git a/source/client/gui/components/SwitchValuesButton.hpp b/source/client/gui/components/SwitchValuesButton.hpp index e6e058268..b0a3488b6 100644 --- a/source/client/gui/components/SwitchValuesButton.hpp +++ b/source/client/gui/components/SwitchValuesButton.hpp @@ -5,13 +5,14 @@ class SwitchValuesButton : public Button { public: - SwitchValuesButton(int id, int x, int y, ValuesOption*, const std::string&); + SwitchValuesButton(int x, int y, OptionEntry*, const std::string&); + void pressed(Minecraft*) override; void pressed(Minecraft*, const MenuPointer& pointer) override; void render(Minecraft*, const MenuPointer& pointer) override; - ValuesOption& getOption() { return *m_pOption; }; + OptionEntry& getOption() { return *m_pOption; }; private: - ValuesOption* m_pOption; + OptionEntry* m_pOption; }; \ No newline at end of file diff --git a/source/client/gui/components/TextBox.cpp b/source/client/gui/components/TextBox.cpp index e25bef2ce..f18371498 100644 --- a/source/client/gui/components/TextBox.cpp +++ b/source/client/gui/components/TextBox.cpp @@ -20,7 +20,7 @@ static bool IsInvalidCharacter(char c) return c == '\n' || c < ' ' || c > '~'; } -TextBox::TextBox(Screen* parent, GuiElement::ID id, int x, int y, int width, int height, const std::string& placeholder, const std::string& text) : GuiElement(id) +TextBox::TextBox(Screen* parent, int x, int y, int width, int height, const std::string& placeholder, const std::string& text) : GuiElement() { m_xPos = x; m_yPos = y; @@ -35,6 +35,7 @@ TextBox::TextBox(Screen* parent, GuiElement::ID id, int x, int y, int width, int m_pParent = parent; m_maxLength = -1; m_scrollPos = 0; + m_bBordered = true; } TextBox::~TextBox() @@ -64,10 +65,10 @@ void TextBox::_onFocusChanged() VirtualKeyboard keyboard; IntRectangle& rect = keyboard.rect; - rect.x = (int)(((float)m_xPos) / Gui::InvGuiScale); - rect.y = (int)(((float)m_yPos) / Gui::InvGuiScale); - rect.w = (int)(((float)m_width) / Gui::InvGuiScale); - rect.h = (int)(((float)m_height) / Gui::InvGuiScale); + rect.x = (int)(((float)m_xPos) / Gui::GuiScale); + rect.y = (int)(((float)m_yPos) / Gui::GuiScale); + rect.w = (int)(((float)m_width) / Gui::GuiScale); + rect.h = (int)(((float)m_height) / Gui::GuiScale); keyboard.defaultText = m_text; @@ -89,13 +90,12 @@ void TextBox::init(Font* pFont) bool TextBox::pointerPressed(Minecraft* pMinecraft, const MenuPointer& pointer) { - bool result = _clicked(pointer); - setSelected(result); + bool result = _isHovered(pointer); setFocused(result); if (result) { // scuffed as hell - pMinecraft->m_pScreen->selectElement(getId()); + pMinecraft->m_pScreen->selectElementById(getId()); } return result; } @@ -429,30 +429,46 @@ void TextBox::render(Minecraft* pMinecraft, const MenuPointer& pointer) { if (!m_pFont) return; - // blue: 0xFFE9B3A9 - // button-yellow: 0xFFA0FFFF - fill(m_xPos, m_yPos, m_xPos + m_width, m_yPos + m_height, isSelected() ? 0xFFA0FFFF : 0xFFAAAAAA); - fill(m_xPos + 1, m_yPos + 1, m_xPos + m_width - 1, m_yPos + m_height - 1, 0xFF000000); + if (m_bBordered) + { + if (m_uiTheme == UI_CONSOLE) + { + blitNineSlice(*pMinecraft->m_pTextures, isSelected() ? "gui/text_field_highlighted.png" : "gui/text_field.png", m_xPos, m_yPos, m_width, m_height, 3); + } + else + { + // blue: 0xFFE9B3A9 + // button-yellow: 0xFFA0FFFF + fill(m_xPos, m_yPos, m_xPos + m_width, m_yPos + m_height, isSelected() ? 0xFFA0FFFF : 0xFFAAAAAA); + fill(m_xPos + 1, m_yPos + 1, m_xPos + m_width - 1, m_yPos + m_height - 1, 0xFF000000); + } + } - int text_color; + Color text_color; int scroll_pos; std::string rendered_text; if (m_text.empty()) { rendered_text = m_placeholder; - text_color = 0x404040; + text_color = Color::TEXT_GREY; scroll_pos = 0; } else { rendered_text = m_text; - text_color = 0xffffff; + text_color = Color::WHITE; scroll_pos = m_scrollPos; } rendered_text = getRenderedText(scroll_pos, rendered_text); int textYPos = (m_height - 8) / 2; - drawString(*m_pFont, rendered_text, m_xPos + PADDING, m_yPos + textYPos, text_color); + if (m_uiTheme == UI_CONSOLE) + { + textYPos -= 4; + m_pFont->drawScalable(rendered_text, m_xPos + PADDING * 2, m_yPos + textYPos, text_color); + } + else + drawString(*m_pFont, rendered_text, m_xPos + PADDING, m_yPos + textYPos, text_color); if (m_bCursorOn) { @@ -464,7 +480,10 @@ void TextBox::render(Minecraft* pMinecraft, const MenuPointer& pointer) std::string str; str += CURSOR_CHAR; - drawString(*m_pFont, str, m_xPos + xPos, m_yPos + textYPos + 2, 0xffffff); + if (m_uiTheme == UI_CONSOLE) + m_pFont->drawScalable(str, m_xPos + xPos * 2, m_yPos + textYPos + 2, Color::WHITE); + else + drawString(*m_pFont, str, m_xPos + xPos, m_yPos + textYPos + 2, Color::WHITE); } } } @@ -553,4 +572,9 @@ void TextBox::setMaxLength(int max_length) m_maxLength = max_length; } +void TextBox::setBordered(bool bordered) +{ + m_bBordered = bordered; +} + #endif diff --git a/source/client/gui/components/TextBox.hpp b/source/client/gui/components/TextBox.hpp index 5b8038d3d..59c02b0b1 100644 --- a/source/client/gui/components/TextBox.hpp +++ b/source/client/gui/components/TextBox.hpp @@ -24,7 +24,7 @@ class TextBox : public GuiElement std::string m_text; public: - TextBox(Screen*, GuiElement::ID, int x, int y, int width = 200, int height = 12, const std::string& placeholder = "", const std::string& text = ""); + TextBox(Screen*, int x, int y, int width = 200, int height = 12, const std::string& placeholder = "", const std::string& text = ""); ~TextBox(); protected: @@ -47,6 +47,7 @@ class TextBox : public GuiElement void tick(Minecraft* pMinecraft) override; void setTextboxText(const std::string& text) override; void setMaxLength(int max_length); + void setBordered(bool); const std::string& getText() const { return m_text; } @@ -66,6 +67,7 @@ class TextBox : public GuiElement Screen* m_pParent; int m_maxLength; int m_scrollPos; + bool m_bBordered; }; #endif diff --git a/source/client/gui/components/TickBox.cpp b/source/client/gui/components/TickBox.cpp new file mode 100644 index 000000000..2bce1cf86 --- /dev/null +++ b/source/client/gui/components/TickBox.cpp @@ -0,0 +1,75 @@ +#include "TickBox.hpp" +#include "client/app/Minecraft.hpp" +#include "renderer/ShaderConstants.hpp" + +#define C_TICKBOX_SIZE (24) +#define C_DEFAULT_TICKBOX_WIDTH (400) +#define C_DEFAULT_TICKBOX_HEIGHT (27) + +TickBox::TickBox(int x, int y, BoolOption* option, const std::string& message) : + m_pOption(option), + m_bOn(option->get()) +{ + m_xPos = x; + m_yPos = y; + m_width = C_DEFAULT_TICKBOX_WIDTH; + m_height = C_DEFAULT_TICKBOX_HEIGHT; + setMessage(message); +} + +TickBox::TickBox(int x, int y, bool initial, const std::string& message) : + m_pOption(nullptr), + m_bOn(initial) +{ + m_xPos = x; + m_yPos = y; + m_width = C_DEFAULT_TICKBOX_WIDTH; + m_height = C_DEFAULT_TICKBOX_HEIGHT; + setMessage(message); +} + +void TickBox::pressed(Minecraft* mc, const MenuPointer& pointer) +{ + pressed(mc); +} + +void TickBox::pressed(Minecraft* mc) +{ + if (!isEnabled()) return; + m_bOn ^= 1; + if (m_pOption) + getOption().set(m_bOn); +} + +void TickBox::render(Minecraft* mc, const MenuPointer& pointer) +{ + if (!isVisible()) return; + + if (!mc->m_pScreen->doElementTabbing()) + setSelected(isHovered(mc, pointer)); + + if (!isEnabled()) + currentShaderColor.a *= 0.5f; + + Color unselectedColor = Color::TEXT_GREY; + unselectedColor.a = currentShaderColor.a; + mc->m_pFont->drawScalable( + getMessage(), + m_xPos + C_TICKBOX_SIZE + 5, + m_yPos + m_height / 2 - 8, + unselectedColor); + + if (isSelected()) + mc->m_pFont->drawScalable( + getMessage(), + m_xPos + C_TICKBOX_SIZE + 4, + m_yPos + m_height / 2 - 9, + Color(204, 196, 13, currentShaderColor.a)); + + blitSprite(*mc->m_pTextures, isSelected() ? "gui/console/Graphics/Tickbox_Over.png" : "gui/console/Graphics/Tickbox_Norm.png", m_xPos, m_yPos + (m_height - C_TICKBOX_SIZE) / 2, C_TICKBOX_SIZE, C_TICKBOX_SIZE, &m_materials.ui_textured_and_glcolor); + + if (m_bOn) + blitSprite(*mc->m_pTextures, "gui/console/Graphics/Tick.png", m_xPos, m_yPos + (m_height - C_TICKBOX_SIZE) / 2, 28, 24, &m_materials.ui_textured_and_glcolor); + + currentShaderColor = Color::WHITE; +} diff --git a/source/client/gui/components/TickBox.hpp b/source/client/gui/components/TickBox.hpp new file mode 100644 index 000000000..b2e0520a4 --- /dev/null +++ b/source/client/gui/components/TickBox.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "../GuiElement.hpp" + +class TickBox : public GuiElement +{ +public: + TickBox(int x, int y, BoolOption*, const std::string&); + TickBox(int x, int y, bool, const std::string&); + + void pressed(Minecraft*, const MenuPointer& pointer) override; + void pressed(Minecraft*) override; + void render(Minecraft*, const MenuPointer& pointer) override; + + BoolOption& getOption() { return *m_pOption; }; + +private: + BoolOption* m_pOption; + +public: + bool m_bOn; +}; \ No newline at end of file diff --git a/source/client/gui/screens/ChatScreen.cpp b/source/client/gui/screens/ChatScreen.cpp index b8071365e..748b0aeac 100644 --- a/source/client/gui/screens/ChatScreen.cpp +++ b/source/client/gui/screens/ChatScreen.cpp @@ -8,32 +8,12 @@ #include "ChatScreen.hpp" -// @NOTE: This is unused. - -ChatScreen::ChatScreen(bool slash) : m_textChat(this, 1, 0, 0), m_btnSend(2, 0, 0, "Send") +ChatScreen::ChatScreen(bool slash) : m_textChat(this, 0, 0), m_btnSend(0, 0, "Send") { if (slash) m_textChat.setTextboxText("/"); } -void ChatScreen::_controllerDirectionHeld(GameController::StickID stickId, GameController::StickState stickState) -{ - if (stickId == 1) - { - switch (stickState) - { - case GameController::STICK_STATE_LEFT: - prevElement(); - break; - case GameController::STICK_STATE_RIGHT: - nextElement(); - break; - default: - break; - } - } -} - void ChatScreen::_buttonClicked(Button* pButton) { if (pButton->getId() == m_btnSend.getId()) @@ -53,7 +33,9 @@ void ChatScreen::init() // set focus directly on the chat text box m_textChat.init(m_pFont); + m_textChat.setSelected(true); m_textChat.setFocused(true); + m_pSelectedElement = &m_textChat; _addElement(m_textChat); _addElement(m_btnSend); @@ -78,12 +60,23 @@ void ChatScreen::render(float f) void ChatScreen::keyPressed(int keyCode) { - if (m_pMinecraft->getOptions()->isKey(KM_MENU_OK, keyCode)) - sendMessageAndExit(); + if (!_useController()) + { + if (m_pMinecraft->getOptions()->isKey(KM_MENU_OK, keyCode)) + sendMessageAndExit(); + } Screen::keyPressed(keyCode); } +void ChatScreen::handleKeyboardClosed() +{ + if (_useController()) + sendMessageAndExit(); + else + Screen::handleKeyboardClosed(); +} + void ChatScreen::sendMessageAndExit() { m_pMinecraft->sendMessage(m_textChat.getText()); diff --git a/source/client/gui/screens/ChatScreen.hpp b/source/client/gui/screens/ChatScreen.hpp index 504f7bc86..2be599ab8 100644 --- a/source/client/gui/screens/ChatScreen.hpp +++ b/source/client/gui/screens/ChatScreen.hpp @@ -18,7 +18,6 @@ class ChatScreen : public Screen ChatScreen(bool slash = false); protected: - void _controllerDirectionHeld(GameController::StickID stickId, GameController::StickState stickState) override; void _buttonClicked(Button*) override; public: @@ -26,6 +25,7 @@ class ChatScreen : public Screen void removed() override; void render(float f) override; void keyPressed(int keyCode) override; + void handleKeyboardClosed() override; void sendMessageAndExit(); diff --git a/source/client/gui/screens/ConfirmScreen.cpp b/source/client/gui/screens/ConfirmScreen.cpp index 199a5ed8e..6812f6800 100644 --- a/source/client/gui/screens/ConfirmScreen.cpp +++ b/source/client/gui/screens/ConfirmScreen.cpp @@ -13,8 +13,8 @@ ConfirmScreen::ConfirmScreen(Screen* pScreen, const std::string& line1, const st field_40(x), m_textLine1(line1), m_textLine2(line2), - m_btnOK (0, 0, 0, "Ok"), - m_btnCancel(1, 0, 0, "Cancel") + m_btnOK (0, 0, "Ok"), + m_btnCancel(0, 0, "Cancel") { } @@ -23,8 +23,8 @@ ConfirmScreen::ConfirmScreen(Screen* pScreen, const std::string& line1, const st field_40(x), m_textLine1(line1), m_textLine2(line2), - m_btnOK (0, 0, 0, ok), - m_btnCancel(1, 0, 0, cancel) + m_btnOK (0, 0, ok), + m_btnCancel(0, 0, cancel) { } diff --git a/source/client/gui/screens/ConfirmScreen.hpp b/source/client/gui/screens/ConfirmScreen.hpp index b1d6bdd1c..62fdd6398 100644 --- a/source/client/gui/screens/ConfirmScreen.hpp +++ b/source/client/gui/screens/ConfirmScreen.hpp @@ -24,7 +24,7 @@ class ConfirmScreen : public Screen virtual void postResult(bool b); -private: +protected: Screen* m_pScreen; int field_40; std::string m_textLine1; diff --git a/source/client/gui/screens/CreateWorldScreen.cpp b/source/client/gui/screens/CreateWorldScreen.cpp index d2ac5025a..fcb7c2521 100644 --- a/source/client/gui/screens/CreateWorldScreen.cpp +++ b/source/client/gui/screens/CreateWorldScreen.cpp @@ -7,22 +7,23 @@ ********************************************************************/ #include "CreateWorldScreen.hpp" -#include "SelectWorldScreen.hpp" -#include "ProgressScreen.hpp" #include "common/Util.hpp" static char g_CreateWorldFilterArray[] = { '/','\n','\r','\x09','\0','\xC','`','?','*','\\','<','>','|','"',':' }; -CreateWorldScreen::CreateWorldScreen() : - m_textName(this, 1, 0, 0, 0, 0, "", "Unnamed world"), - m_textSeed(this, 2, 0, 0, 0, 0, ""), - m_btnGameMode(5, "Game Mode"), - m_btnBack(3, "Cancel"), - m_btnCreate(4, "Create New World") +CreateWorldScreen::CreateWorldScreen(Screen* parent) : + m_pParent(parent), + m_textName(this, 0, 0, 0, 0, "", "Unnamed world"), + m_textSeed(this, 0, 0, 0, 0, ""), + m_btnGameMode("Game Mode"), + m_btnBack("Cancel"), + m_btnCreate("Create New World"), + m_gameMode(GAME_TYPE_SURVIVAL) { + m_bDeletePrevious = false; } -static std::string GetUniqueLevelName(LevelStorageSource* pSource, const std::string& in) +std::string CreateWorldScreen::GetUniqueLevelName(LevelStorageSource* pSource, const std::string& in) { std::set maps; @@ -46,6 +47,13 @@ static std::string GetUniqueLevelName(LevelStorageSource* pSource, const std::st out += "-"; } + for (size_t i = 0; i < sizeof(g_CreateWorldFilterArray); i++) + { + std::string str; + str.push_back(g_CreateWorldFilterArray[i]); + Util::stringReplace(out, str, ""); + } + return out; } @@ -62,16 +70,7 @@ void CreateWorldScreen::_buttonClicked(Button* pButton) std::string seedStr = m_textSeed.getText(); std::string levelNickname = Util::stringTrim(nameStr); - std::string levelUniqueName = levelNickname; - - for (size_t i = 0; i < sizeof(g_CreateWorldFilterArray); i++) - { - std::string str; - str.push_back(g_CreateWorldFilterArray[i]); - Util::stringReplace(levelUniqueName, str, ""); - } - - levelUniqueName = GetUniqueLevelName(m_pMinecraft->m_pLevelStorageSource, levelUniqueName); + std::string levelUniqueName = GetUniqueLevelName(m_pMinecraft->m_pLevelStorageSource, levelNickname); int seed = int(getEpochTimeS()); @@ -142,8 +141,6 @@ void CreateWorldScreen::init() // calculate after crush m_btnGameMode.m_xPos = m_width / 2 - m_btnGameMode.m_width / 2; m_btnCreate.m_xPos = m_width / 2 - m_btnCreate.m_width - 5; - - m_gameMode = GAME_TYPE_SURVIVAL; } void CreateWorldScreen::render(float f) @@ -173,7 +170,7 @@ bool CreateWorldScreen::handleBackEvent(bool b) { if (!b) { - m_pMinecraft->setScreen(new SelectWorldScreen); + m_pMinecraft->setScreen(m_pParent); } return true; diff --git a/source/client/gui/screens/CreateWorldScreen.hpp b/source/client/gui/screens/CreateWorldScreen.hpp index 78afda52f..c68359feb 100644 --- a/source/client/gui/screens/CreateWorldScreen.hpp +++ b/source/client/gui/screens/CreateWorldScreen.hpp @@ -17,7 +17,7 @@ class CreateWorldScreen : public Screen { public: - CreateWorldScreen(); + CreateWorldScreen(Screen*); protected: void _buttonClicked(Button* pButton) override; @@ -27,6 +27,11 @@ class CreateWorldScreen : public Screen void render(float f) override; bool handleBackEvent(bool b) override; + static std::string GetUniqueLevelName(LevelStorageSource* pSource, const std::string& in); + +private: + Screen* m_pParent; + public: TextBox m_textName; TextBox m_textSeed; diff --git a/source/client/gui/screens/CreateWorldScreen_Console.cpp b/source/client/gui/screens/CreateWorldScreen_Console.cpp new file mode 100644 index 000000000..3de2b5952 --- /dev/null +++ b/source/client/gui/screens/CreateWorldScreen_Console.cpp @@ -0,0 +1,95 @@ +#include "CreateWorldScreen_Console.hpp" +#include "common/Util.hpp" +#include "client/locale/Language.hpp" +#include "CreateWorldScreen.hpp" + +CreateWorldScreen_Console::CreateWorldScreen_Console(Options& options, Screen* parent) : + PanelScreen_Console(parent), + m_onlineGame(0, 0, true, Language::get("playGame.online")), + m_inviteOnly(0, 0, false, Language::get("playGame.inviteOnly")), + m_textName(this, 0, 0, 400, 38, "", "New World"), + m_textSeed(this, 0, 0, 400, 38, ""), + m_difficultySlider(0, 0, 400, 32, &options.m_difficulty, options.m_difficulty.getMessage(), options.m_difficulty.toFloat()), + m_btnCreate(0, 0, 400, 40, Language::get("playGame.createNewWorld")) +{ + m_onlineGame.setEnabled(false); + m_inviteOnly.setEnabled(false); +} + +void CreateWorldScreen_Console::_buttonClicked(Button* pButton) +{ + if (pButton->getId() == m_btnCreate.getId()) + { + std::string nameStr = m_textName.getText(); + std::string seedStr = m_textSeed.getText(); + + std::string levelNickname = Util::stringTrim(nameStr); + std::string levelUniqueName = CreateWorldScreen::GetUniqueLevelName(m_pMinecraft->m_pLevelStorageSource, levelNickname); + + int seed = int(getEpochTimeS()); + + std::string seedThing = Util::stringTrim(seedStr); + if (!seedThing.empty()) + { + int num; + if (sscanf(seedThing.c_str(), "%d", &num) > 0) + seed = num; + else + seed = Util::hashCode(seedThing); + } + + LevelSettings levelSettings(seed); + m_pMinecraft->selectLevel(levelUniqueName, levelNickname, levelSettings); + } +} + +void CreateWorldScreen_Console::init() +{ + m_panel.w = 450; + m_panel.h = 390; + m_panel.x = (m_width - m_panel.w) / 2; + m_panel.y = (m_height - m_panel.h) / 2 + 45; + + int left = m_panel.x + 25; + m_onlineGame.m_xPos = left; + m_onlineGame.m_yPos = m_panel.y + 17; + _addElement(m_onlineGame); + + m_inviteOnly.m_xPos = left; + m_inviteOnly.m_yPos = m_panel.y + 53; + _addElement(m_inviteOnly); + + m_textName.m_xPos = left; + m_textName.m_yPos = m_panel.y + 113; + _addElement(m_textName); + + m_textSeed.m_xPos = left; + m_textSeed.m_yPos = m_panel.y + 188; + _addElement(m_textSeed); + + m_difficultySlider.m_xPos = left; + m_difficultySlider.m_yPos = m_panel.y + 267; + _addElement(m_difficultySlider); + + m_btnCreate.m_xPos = left; + m_btnCreate.m_yPos = m_panel.y + 322; + _addElement(m_btnCreate); + + m_textName.init(m_pFont); + m_textSeed.init(m_pFont); +} + +void CreateWorldScreen_Console::render(float f) +{ + PanelScreen_Console::render(f); + + Font& font = *m_pFont; + font.drawScalable(Language::get("selectWorld.enterName"), m_textName.m_xPos + 1, m_textName.m_yPos - 19, Color::TEXT_GREY); + font.drawScalable(Language::get("selectWorld.enterSeed"), m_textSeed.m_xPos + 1, m_textSeed.m_yPos - 19, Color::TEXT_GREY); + font.drawScalable(Language::get("selectWorld.seedInfo"), m_textSeed.m_xPos + 1, m_textSeed.m_yPos + 41, Color::TEXT_GREY); +} + +void CreateWorldScreen_Console::renderPanel(float f) +{ + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::PANEL_SLICES, m_panel.x, m_panel.y, m_panel.w, m_panel.h, 32); +} diff --git a/source/client/gui/screens/CreateWorldScreen_Console.hpp b/source/client/gui/screens/CreateWorldScreen_Console.hpp new file mode 100644 index 000000000..7643a1196 --- /dev/null +++ b/source/client/gui/screens/CreateWorldScreen_Console.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "PanelScreen_Console.hpp" +#include "client/gui/components/Button.hpp" +#include "client/gui/components/TickBox.hpp" +#include "client/gui/components/SliderButton.hpp" +#include "client/gui/components/TextBox.hpp" + +class CreateWorldScreen_Console : public PanelScreen_Console +{ +public: + CreateWorldScreen_Console(Options&, Screen*); + +protected: + void _buttonClicked(Button* pButton) override; + +public: + void init() override; + void render(float f) override; + void renderPanel(float f) override; + +public: + TickBox m_onlineGame; + TickBox m_inviteOnly; + TextBox m_textName; + TextBox m_textSeed; + SliderButton m_difficultySlider; + Button m_btnCreate; +}; \ No newline at end of file diff --git a/source/client/gui/screens/CreditsScreen.cpp b/source/client/gui/screens/CreditsScreen.cpp index 7267ac130..b5bfb604d 100644 --- a/source/client/gui/screens/CreditsScreen.cpp +++ b/source/client/gui/screens/CreditsScreen.cpp @@ -2,9 +2,11 @@ #include "StartMenuScreen.hpp" #include "client/resources/Resource.hpp" -CreditsScreen::CreditsScreen() : - m_btnBack(3, "Back") +CreditsScreen::CreditsScreen(Screen* parent) : + m_pParent(parent), + m_btnBack("Back") { + m_bDeletePrevious = false; _initCreditsText(); } @@ -36,8 +38,8 @@ void CreditsScreen::_initCreditsText() void CreditsScreen::init() { - m_btnBack.m_yPos = m_height - 28; - m_btnBack.m_width = 84; + m_btnBack.m_yPos = m_height - 28; + m_btnBack.m_width = 84; m_btnBack.m_height = 24; m_btnBack.m_xPos = m_width / 2 - m_btnBack.m_width / 2; @@ -64,6 +66,8 @@ void CreditsScreen::render(float f) { renderBackground(); + m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png"); + // Add dark background Tesselator& t = Tesselator::instance; float widthf = float(m_width); @@ -101,12 +105,12 @@ bool CreditsScreen::handleBackEvent(bool b) if (b) return true; - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->setScreen(m_pParent); return true; } void CreditsScreen::_buttonClicked(Button* pButton) { if (pButton->getId() == m_btnBack.getId()) - m_pMinecraft->setScreen(new StartMenuScreen); + handleBackEvent(false); } diff --git a/source/client/gui/screens/CreditsScreen.hpp b/source/client/gui/screens/CreditsScreen.hpp index cb7cf3a9e..27185894e 100644 --- a/source/client/gui/screens/CreditsScreen.hpp +++ b/source/client/gui/screens/CreditsScreen.hpp @@ -6,7 +6,7 @@ class CreditsScreen : public Screen { public: - CreditsScreen(); + CreditsScreen(Screen* parent); ~CreditsScreen(); private: @@ -21,9 +21,10 @@ class CreditsScreen : public Screen bool handleBackEvent(bool b) override; void _buttonClicked(Button* pButton) override; -public: - Button m_btnBack; - private: + Screen* m_pParent; std::vector m_credits; + +public: + Button m_btnBack; }; diff --git a/source/client/gui/screens/DeathScreen.cpp b/source/client/gui/screens/DeathScreen.cpp index 7670d5c2e..db8df9581 100644 --- a/source/client/gui/screens/DeathScreen.cpp +++ b/source/client/gui/screens/DeathScreen.cpp @@ -1,8 +1,8 @@ #include "DeathScreen.hpp" DeathScreen::DeathScreen() : - m_btnRespawn(1, "Respawn!"), - m_btnTitle (2, "Main menu") + m_btnRespawn("Respawn!"), + m_btnTitle ("Main menu") { m_tickCounter = 0; } @@ -26,7 +26,7 @@ void DeathScreen::_buttonClicked(Button* pButton) m_pMinecraft->m_pLocalPlayer->respawn(); m_pMinecraft->setScreen(nullptr); } - if (pButton->getId() == m_btnTitle.getId()) + else if (pButton->getId() == m_btnTitle.getId()) { m_pMinecraft->leaveGame(false); } @@ -37,10 +37,6 @@ void DeathScreen::tick() m_tickCounter++; } -void DeathScreen::keyPressed(int key) -{ -} - void DeathScreen::render(float f) { fillGradient(0, 0, m_width, m_height, 0xA0303080, 0x60000050); diff --git a/source/client/gui/screens/DeathScreen.hpp b/source/client/gui/screens/DeathScreen.hpp index d772f0cea..29abd78b9 100644 --- a/source/client/gui/screens/DeathScreen.hpp +++ b/source/client/gui/screens/DeathScreen.hpp @@ -16,11 +16,13 @@ class DeathScreen : public Screen public: DeathScreen(); - virtual void init() override; - virtual void _buttonClicked(Button* pButton) override; - virtual void tick() override; - virtual void keyPressed(int key) override; - virtual void render(float f) override; +protected: + void _buttonClicked(Button* pButton) override; + +public: + void init() override; + void tick() override; + void render(float f) override; private: int m_tickCounter; diff --git a/source/client/gui/screens/DeleteWorldScreen.cpp b/source/client/gui/screens/DeleteWorldScreen.cpp index 32b20ec47..a6bbbaf48 100644 --- a/source/client/gui/screens/DeleteWorldScreen.cpp +++ b/source/client/gui/screens/DeleteWorldScreen.cpp @@ -17,7 +17,7 @@ DeleteWorldScreen::DeleteWorldScreen(const LevelSummary& level) : m_level(level) { // highlight the cancel button so the user will have to do 1 extra action to delete their world - m_elementIndex = 1; + m_pSelectedElement = &m_btnCancel; } void DeleteWorldScreen::postResult(bool b) diff --git a/source/client/gui/screens/DirectConnectScreen.cpp b/source/client/gui/screens/DirectConnectScreen.cpp index 1d747886b..20440dd12 100644 --- a/source/client/gui/screens/DirectConnectScreen.cpp +++ b/source/client/gui/screens/DirectConnectScreen.cpp @@ -7,14 +7,13 @@ ********************************************************************/ #include "DirectConnectScreen.hpp" -#include "ProgressScreen.hpp" #include "JoinGameScreen.hpp" #include "common/Util.hpp" DirectConnectScreen::DirectConnectScreen() : - m_textAddress(this, 1, 0, 0, 0), - m_btnCancel(3, "Cancel"), - m_btnJoin(2, "Join Server") + m_textAddress(this, 0, 0, 0), + m_btnCancel("Cancel"), + m_btnJoin("Join Server") {} void DirectConnectScreen::_buttonClicked(Button* pButton) @@ -36,7 +35,7 @@ void DirectConnectScreen::_buttonClicked(Button* pButton) newPgs.m_address = sysAddress; m_pMinecraft->joinMultiplayer(newPgs); - m_pMinecraft->setScreen(new ProgressScreen); + m_pMinecraft->getScreenChooser()->pushProgressScreen(); m_btnJoin.setEnabled(false); m_textAddress.setEnabled(false); diff --git a/source/client/gui/screens/DisconnectionScreen.cpp b/source/client/gui/screens/DisconnectionScreen.cpp index bcd754657..c78a16499 100644 --- a/source/client/gui/screens/DisconnectionScreen.cpp +++ b/source/client/gui/screens/DisconnectionScreen.cpp @@ -11,13 +11,13 @@ DisconnectionScreen::DisconnectionScreen(const std::string& text) : m_text(text), - m_btnOK (0, 0, 0, "OK") + m_btnOK (0, 0, "OK") { } void DisconnectionScreen::_buttonClicked(Button* pButton) { - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen();; } void DisconnectionScreen::init() diff --git a/source/client/gui/screens/IngameBlockSelectionScreen.cpp b/source/client/gui/screens/IngameBlockSelectionScreen.cpp index f191116ed..16a91edf3 100644 --- a/source/client/gui/screens/IngameBlockSelectionScreen.cpp +++ b/source/client/gui/screens/IngameBlockSelectionScreen.cpp @@ -18,10 +18,10 @@ std::string g_sNotAvailableInDemoVersion = "Not available in the demo version"; IngameBlockSelectionScreen::IngameBlockSelectionScreen() : - m_btnPause(0, "\xF0"), // 3 lined bars - m_btnChat(1, "\x01\x27"), // face and comma - m_btnCraft(2, "Craft"), - m_btnArmor(3, "Armor") + m_btnPause("\xF0"), // 3 lined bars + m_btnChat("\x01\x27"), // face and comma + m_btnCraft("Craft"), + m_btnArmor("Armor") { m_bRenderPointer = true; m_selectedSlot = 0; @@ -289,7 +289,7 @@ void IngameBlockSelectionScreen::render(float f) void IngameBlockSelectionScreen::_buttonClicked(Button* pButton) { if (pButton->getId() == m_btnPause.getId()) - m_pMinecraft->setScreen(new PauseScreen); + m_pMinecraft->getScreenChooser()->pushPauseScreen(); if (pButton->getId() == m_btnChat.getId()) m_pMinecraft->setScreen(new ChatScreen(true)); @@ -325,12 +325,12 @@ void IngameBlockSelectionScreen::pointerReleased(const MenuPointer& pointer, Mou for (unsigned int i = 0; i < m_elements.size(); i++) { - GuiElement* element = _getInternalElement(i); + GuiElement* element = _getElement(i); if (element->getType() != GuiElement::TYPE_BUTTON) continue; Button* btn = (Button*)element; - if (btn->clicked(m_pMinecraft, pointer)) + if (btn->isHovered(m_pMinecraft, pointer)) return; } diff --git a/source/client/gui/screens/InvalidLicenseScreen.cpp b/source/client/gui/screens/InvalidLicenseScreen.cpp index 2782b52d2..507338f9c 100644 --- a/source/client/gui/screens/InvalidLicenseScreen.cpp +++ b/source/client/gui/screens/InvalidLicenseScreen.cpp @@ -10,8 +10,8 @@ InvalidLicenseScreen::InvalidLicenseScreen(int error, bool bHasQuitButton) : m_error(error), - m_btnOk (1, "Ok"), - m_btnBuy(2, "Buy"), + m_btnOk ("Ok"), + m_btnBuy("Buy"), m_bHasQuitButton(bHasQuitButton), field_E4(0) { diff --git a/source/client/gui/screens/JoinGameScreen.cpp b/source/client/gui/screens/JoinGameScreen.cpp index f774b292e..1815ea6b7 100644 --- a/source/client/gui/screens/JoinGameScreen.cpp +++ b/source/client/gui/screens/JoinGameScreen.cpp @@ -8,13 +8,11 @@ #include "JoinGameScreen.hpp" #include "DirectConnectScreen.hpp" -#include "ProgressScreen.hpp" -#include "StartMenuScreen.hpp" JoinGameScreen::JoinGameScreen() : - m_btnJoin(2, "Join Game"), - m_btnDirectConnect(3, "Direct Connect"), - m_btnBack(4, "Back"), + m_btnJoin("Join Game"), + m_btnDirectConnect("Direct Connect"), + m_btnBack("Back"), m_pAvailableGamesList(nullptr) { } @@ -24,24 +22,6 @@ JoinGameScreen::~JoinGameScreen() SAFE_DELETE(m_pAvailableGamesList); } -void JoinGameScreen::_controllerDirectionHeld(GameController::StickID stickId, GameController::StickState stickState) -{ - if (stickId == 1) - { - switch (stickState) - { - case GameController::STICK_STATE_LEFT: - prevElement(); - break; - case GameController::STICK_STATE_RIGHT: - nextElement(); - break; - default: - break; - } - } -} - void JoinGameScreen::_buttonClicked(Button* pButton) { if (pButton->getId() == m_btnJoin.getId()) @@ -49,7 +29,7 @@ void JoinGameScreen::_buttonClicked(Button* pButton) if (isIndexValid(m_pAvailableGamesList->m_selectedIndex)) { m_pMinecraft->joinMultiplayer(m_pAvailableGamesList->m_games[m_pAvailableGamesList->m_selectedIndex]); - m_pMinecraft->setScreen(new ProgressScreen); + m_pMinecraft->getScreenChooser()->pushProgressScreen(); m_btnJoin.setEnabled(false); m_btnDirectConnect.setEnabled(false); @@ -64,7 +44,7 @@ void JoinGameScreen::_buttonClicked(Button* pButton) if (pButton->getId() == m_btnBack.getId()) { - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen(); } } @@ -73,7 +53,7 @@ bool JoinGameScreen::handleBackEvent(bool b) if (!b) { m_pMinecraft->cancelLocateMultiplayer(); - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen(); } return true; diff --git a/source/client/gui/screens/JoinGameScreen.hpp b/source/client/gui/screens/JoinGameScreen.hpp index cec0cefb9..793d54a35 100644 --- a/source/client/gui/screens/JoinGameScreen.hpp +++ b/source/client/gui/screens/JoinGameScreen.hpp @@ -19,7 +19,6 @@ class JoinGameScreen : public Screen ~JoinGameScreen(); protected: - void _controllerDirectionHeld(GameController::StickID stickId, GameController::StickState stickState) override; void _buttonClicked(Button* pButton) override; public: diff --git a/source/client/gui/screens/OptionsScreen.cpp b/source/client/gui/screens/OptionsScreen.cpp index 27715e409..2490863a9 100644 --- a/source/client/gui/screens/OptionsScreen.cpp +++ b/source/client/gui/screens/OptionsScreen.cpp @@ -12,19 +12,17 @@ #ifndef OLD_OPTIONS_SCREEN -#define MIN_CATEGORY_BUTTON_ID 1 -#define MAX_CATEGORY_BUTTON_ID 3 -#define BACK_BUTTON_ID 100 - -OptionsScreen::OptionsScreen() : +OptionsScreen::OptionsScreen(Screen* parent) : + m_pParent(parent), m_pList(nullptr), m_currentCategory(OC_MIN), - m_gameplayButton(MIN_CATEGORY_BUTTON_ID, "Gameplay"), - m_controlsButton(MIN_CATEGORY_BUTTON_ID + 1, "Controls"), - m_videoButton(MIN_CATEGORY_BUTTON_ID + 2, "Video"), - m_backButton(BACK_BUTTON_ID, "Done") + m_gameplayButton("Gameplay"), + m_controlsButton("Controls"), + m_videoButton("Video"), + m_backButton("Done") { m_bRenderPointer = true; + m_bDeletePrevious = false; } OptionsScreen::~OptionsScreen() @@ -107,7 +105,7 @@ void OptionsScreen::render(float f) Screen::render(f); - //drawCenteredString(*m_pFont, "Options", m_width / 2, 10, 0xFFFFFF); + //drawCenteredString(*m_pFont, "Options", width / 2, 10, 0xFFFFFF); } void OptionsScreen::removed() @@ -118,9 +116,9 @@ void OptionsScreen::removed() } void OptionsScreen::setCategory(OptionsCategory category) { - _getInternalElement(m_currentCategory)->setEnabled(true); + _getElement(m_currentCategory)->setEnabled(true); m_currentCategory = category; - _getInternalElement(m_currentCategory)->setEnabled(false); + _getElement(m_currentCategory)->setEnabled(false); m_pList->clear(); switch (category) @@ -141,24 +139,21 @@ void OptionsScreen::setCategory(OptionsCategory category) void OptionsScreen::_buttonClicked(Button* pButton) { - if (pButton->getId() >= MIN_CATEGORY_BUTTON_ID && pButton->getId() <= MAX_CATEGORY_BUTTON_ID) - { - setCategory((OptionsCategory)(pButton->getId() - MIN_CATEGORY_BUTTON_ID)); - } - else if (pButton->getId() == BACK_BUTTON_ID) - { + if (pButton->getId() == m_gameplayButton.getId()) + setCategory(OC_GAMEPLAY); + else if (pButton->getId() == m_controlsButton.getId()) + setCategory(OC_CONTROLS); + else if (pButton->getId() == m_videoButton.getId()) + setCategory(OC_VIDEO); + else if (pButton->getId() == m_backButton.getId()) handleBackEvent(false); - } } bool OptionsScreen::handleBackEvent(bool b) { if (!b) { - if (m_pMinecraft->isLevelGenerated()) - m_pMinecraft->setScreen(new PauseScreen); - else - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->setScreen(m_pParent); } return true; @@ -272,18 +267,18 @@ bool OptionsScreen::isCramped() void OptionsScreen::setWidthAllButtons(int width) { - m_AOButton.m_width = - m_srvVisButton.m_width = - m_fancyGfxButton.m_width = - m_viewDistButton.m_width = - m_blockLinesButton.m_width = - m_invertYButton.m_width = - m_anaglyphsButton.m_width = - m_viewBobButton.m_width = - m_flightHaxButton.m_width = - m_autoJumpButton.m_width = - m_fancyGrassButton.m_width = - m_biomeColorsButton.m_width = width; + m_AOButton.width = + m_srvVisButton.width = + m_fancyGfxButton.width = + m_viewDistButton.width = + m_blockLinesButton.width = + m_invertYButton.width = + m_anaglyphsButton.width = + m_viewBobButton.width = + m_flightHaxButton.width = + m_autoJumpButton.width = + m_fancyGrassButton.width = + m_biomeColorsButton.width = width; } void OptionsScreen::init() @@ -313,23 +308,23 @@ void OptionsScreen::init() setWidthAllButtons(150); } - m_BackButton.m_xPos = m_width / 2 - m_BackButton.m_width / 2; - m_BackButton.m_height = 20; - m_BackButton.m_yPos = m_height - m_BackButton.m_height - backGap; + m_BackButton.m_xPos = width / 2 - m_BackButton.width / 2; + m_BackButton.height = 20; + m_BackButton.m_yPos = height - m_BackButton.height - backGap; m_AOButton.m_xPos = m_srvVisButton.m_xPos = m_fancyGfxButton.m_xPos = m_viewDistButton.m_xPos = m_blockLinesButton.m_xPos = - m_fancyGrassButton.m_xPos = m_width / 2 - m_AOButton.m_width - 5; + m_fancyGrassButton.m_xPos = width / 2 - m_AOButton.width - 5; m_invertYButton.m_xPos = m_anaglyphsButton.m_xPos = m_viewBobButton.m_xPos = m_flightHaxButton.m_xPos = m_autoJumpButton.m_xPos = - m_biomeColorsButton.m_xPos = m_width / 2 + 5; + m_biomeColorsButton.m_xPos = width / 2 + 5; m_AOButton.m_yPos = m_invertYButton.m_yPos = yPos; yPos += incrementY; m_srvVisButton.m_yPos = m_anaglyphsButton.m_yPos = yPos; yPos += incrementY; @@ -365,15 +360,15 @@ void OptionsScreen::render(int a, int b, float c) if (!m_pMinecraft->isLevelGenerated()) renderMenuBackground(c); - fillGradient(0, 0, m_width, m_height, 0xC0101010, 0xD0101010); + fillGradient(0, 0, width, height, 0xC0101010, 0xD0101010); if (m_pMinecraft->m_pPlatform->getUserInputStatus() >= 0) { - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen(); } #ifndef ORIGINAL_CODE - drawCenteredString(*m_pFont, "Options", m_width / 2, isCramped() ? 5 : 20, 0xFFFFFF); + drawCenteredString(*m_pFont, "Options", width / 2, isCramped() ? 5 : 20, 0xFFFFFF); Screen::render(a, b, c); #endif @@ -399,7 +394,7 @@ void OptionsScreen::_buttonClicked(Button* pButton) if (m_pMinecraft->isLevelGenerated()) m_pMinecraft->setScreen(new PauseScreen); else - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen(); return; case OB_AO: diff --git a/source/client/gui/screens/OptionsScreen.hpp b/source/client/gui/screens/OptionsScreen.hpp index dbe668de2..0100b20a9 100644 --- a/source/client/gui/screens/OptionsScreen.hpp +++ b/source/client/gui/screens/OptionsScreen.hpp @@ -28,7 +28,7 @@ enum OptionsCategory class OptionsScreen : public Screen { public: - OptionsScreen(); + OptionsScreen(Screen*); ~OptionsScreen(); protected: @@ -46,6 +46,7 @@ class OptionsScreen : public Screen private: void setCategory(OptionsCategory category); + Screen* m_pParent; OptionList* m_pList; OptionsCategory m_currentCategory; diff --git a/source/client/gui/screens/OptionsScreen_Console.cpp b/source/client/gui/screens/OptionsScreen_Console.cpp new file mode 100644 index 000000000..934283210 --- /dev/null +++ b/source/client/gui/screens/OptionsScreen_Console.cpp @@ -0,0 +1,146 @@ +#include "OptionsScreen_Console.hpp" +#include "client/locale/Language.hpp" +#include "client/renderer/LogoRenderer.hpp" + +OptionsScreen_Console::OptionsScreen_Console(Screen* screen) : + m_pParent(screen), + m_btnHowToPlay(Language::get("settingsMenu.howToPlay")), + m_btnControls(Language::get("settingsMenu.controls")), + m_btnSettings(Language::get("settingsMenu.settings")), + m_btnCredits(Language::get("settingsMenu.credits")), + m_btnResetToDefaults(Language::get("settingsMenu.resetToDefaults")) +{ + m_bDeletePrevious = false; + m_btnHowToPlay.setEnabled(false); + + m_uiTheme = UI_CONSOLE; +} + +void OptionsScreen_Console::_buttonClicked(Button* btn) +{ + if (btn->getId() == m_btnControls.getId()) + m_pMinecraft->setScreen(new ControlsPanelScreen(this, m_pMinecraft)); + else if (btn->getId() == m_btnSettings.getId()) + m_pMinecraft->setScreen(new SettingsPanelScreen(this, *m_pMinecraft->getOptions())); + else if (btn->getId() == m_btnCredits.getId()) + m_pMinecraft->getScreenChooser()->pushCreditsScreen(this); + else if (btn->getId() == m_btnResetToDefaults.getId()) + { + m_pMinecraft->getOptions()->reset(); + //Certainly you wouldn't want to reset this option + m_pMinecraft->getOptions()->m_uiTheme.set(m_uiTheme); + m_pMinecraft->saveOptionsAsync(); + } +} + +void OptionsScreen_Console::init() +{ + Button* layoutButtons[] = {&m_btnHowToPlay, &m_btnControls, &m_btnSettings, &m_btnCredits, &m_btnResetToDefaults}; + + int buttonsWidth = 450; + int buttonsHeight = 40; + int y= m_height / 3 + 10; + int ySpacing = 50; + + for (size_t i = 0; i < 5; ++i) + { + Button* button = layoutButtons[i]; + button->m_width = buttonsWidth; + button->m_height = buttonsHeight; + button->m_xPos = (m_width - button->m_width) / 2; + button->m_yPos = y + ySpacing * i; + _addElement(*button); + } +} + +void OptionsScreen_Console::render(float f) +{ + renderBackground(); + LogoRenderer::singleton().render(f); + Screen::render(f); +} + +bool OptionsScreen_Console::handleBackEvent(bool b) +{ + if (!b) + { + m_pMinecraft->setScreen(m_pParent); + } + + return true; +} + +#define HEADER(text) do { m_layout.m_elements.push_back(new OptionHeader_Console(text)); currentIndex++; } while (0) +#define OPTION(name) do { options.name.addGuiElement(m_layout.m_elements, m_uiTheme); currentIndex++; } while (0) + +ControlsPanelScreen::ControlsPanelScreen(Screen* parent, Minecraft* mc) : PanelScreen_Console(parent) +{ + Options& options = *mc->getOptions(); + int currentIndex = -1; + int idxSplit = -1, idxController = -1; + + OPTIONS_LIST_CONTROLS_CONTROLS; + OPTIONS_LIST_CONTROLS_FEEDBACK; + OPTIONS_LIST_CONTROLS_EXPERIMENTAL; + + if (!mc->isTouchscreen()) + m_layout.m_elements[idxSplit]->setEnabled(false); + m_layout.m_elements[idxController]->setEnabled(false); +} + +void ControlsPanelScreen::removed() +{ + m_pMinecraft->saveOptionsAsync(); +} + +SettingsPanelScreen::SettingsPanelScreen(Screen* parent, Options& options) : PanelScreen_Console(parent) +{ + int currentIndex = -1; + int idxPano = -1; + + OPTIONS_LIST_GAMEPLAY_GAME; + OPTIONS_LIST_GAMEPLAY_AUDIO; + OPTIONS_LIST_VIDEO_GRAPHICS; + OPTIONS_LIST_VIDEO_EXPERIMENTAL; + +#ifdef ENH_MENU_BACKGROUND + if (!Screen::isMenuPanoramaAvailable()) + m_layout.m_elements[idxPano]->setEnabled(false); +#endif + + (void)currentIndex; // compiler will warn about an unused variable sometimes if this isn't here +} + +void SettingsPanelScreen::render(float f) +{ + PanelScreen_Console::render(f); + + constexpr int difficultyPanelWidth = 701; + constexpr int difficultyPanelHeight = 111; + int difficultyPanelX = (m_width - difficultyPanelWidth) / 2; + int difficultyPanelY = m_panel.y + m_panel.h + 17; + + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::POINTER_TEXT_PANEL_SLICES, difficultyPanelX, difficultyPanelY, difficultyPanelWidth, difficultyPanelHeight, 8); + + m_pFont->drawWordWrap(Language::get(m_pMinecraft->getOptions()->m_difficulty.getValue() + ".desc"), difficultyPanelX + 11, difficultyPanelY + 15, Color::WHITE, (difficultyPanelWidth - 22) / 2, 22, false, true); +} + +void SettingsPanelScreen::removed() +{ + m_pMinecraft->saveOptionsAsync(); +} + +OptionHeader_Console::OptionHeader_Console(const std::string& text) + : m_text(text) +{ + m_height = 22; +} + +void OptionHeader_Console::render(Minecraft* pMinecraft, const MenuPointer& pointer) +{ + pMinecraft->m_pFont->drawScalable( + m_text, + m_xPos, + m_yPos + 8, + Color::TEXT_GREY); +} diff --git a/source/client/gui/screens/OptionsScreen_Console.hpp b/source/client/gui/screens/OptionsScreen_Console.hpp new file mode 100644 index 000000000..3a7a3cbe7 --- /dev/null +++ b/source/client/gui/screens/OptionsScreen_Console.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "PanelScreen_Console.hpp" +#include "client/gui/components/Button.hpp" + +class ControlsPanelScreen : public PanelScreen_Console +{ +public: + ControlsPanelScreen(Screen*, Minecraft*); + + void removed() override; +}; + +class SettingsPanelScreen : public PanelScreen_Console +{ +public: + SettingsPanelScreen(Screen*, Options&); + + void render(float) override; + void removed() override; +}; + +class OptionsScreen_Console : public Screen +{ +public: + OptionsScreen_Console(Screen*); + +protected: + void _buttonClicked(Button*) override; + +public: + void init() override; + void render(float) override; + bool handleBackEvent(bool) override; + +private: + Screen* m_pParent; + Button m_btnHowToPlay; + Button m_btnControls; + Button m_btnSettings; + Button m_btnCredits; + Button m_btnResetToDefaults; +}; + +class OptionHeader_Console : public GuiElement +{ +public: + OptionHeader_Console(const std::string& text); + +public: + void render(Minecraft* pMinecraft, const MenuPointer& pointer) override; + +private: + std::string m_text; +}; + diff --git a/source/client/gui/screens/PanelScreen_Console.cpp b/source/client/gui/screens/PanelScreen_Console.cpp new file mode 100644 index 000000000..d70b231be --- /dev/null +++ b/source/client/gui/screens/PanelScreen_Console.cpp @@ -0,0 +1,47 @@ +#include "PanelScreen_Console.hpp" +#include "client/renderer/LogoRenderer.hpp" +#include "renderer/ShaderConstants.hpp" + +PanelScreen_Console::PanelScreen_Console(Screen* parent) : + m_pParent(parent) + , m_layout(this) +{ + m_uiTheme = UI_CONSOLE; + m_bDeletePrevious = false; +} + +void PanelScreen_Console::init() +{ + m_panel.w = 354; + m_panel.h = 325; + m_panel.x = (m_width - m_panel.w) / 2; + m_panel.y = (m_height - m_panel.h) / 2 - 22; + m_layout.init(IntRectangle(m_panel.x + 15, m_panel.y + 14, 324, 272)); +} + +void PanelScreen_Console::render(float f) +{ + currentShaderColor = Color::WHITE; + + // @TODO: abstract this out into a Screen base class, since there's tons of console screens that use this + renderBackground(); + LogoRenderer::singleton().render(f); + + renderPanel(f); + Screen::render(f); +} + +void PanelScreen_Console::renderPanel(float f) +{ + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::SMALL_PANEL_SLICES, m_panel.x, m_panel.y, m_panel.w, m_panel.h, 16); +} + +bool PanelScreen_Console::handleBackEvent(bool b) +{ + if (!b) + { + m_pMinecraft->setScreen(m_pParent); + } + + return true; +} \ No newline at end of file diff --git a/source/client/gui/screens/PanelScreen_Console.hpp b/source/client/gui/screens/PanelScreen_Console.hpp new file mode 100644 index 000000000..9edf9663f --- /dev/null +++ b/source/client/gui/screens/PanelScreen_Console.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "../Screen.hpp" +#include "client/gui/components/Button.hpp" + +#include "../VerticalLayout.hpp" + +class PanelScreen_Console : public Screen +{ +public: + PanelScreen_Console(Screen*); + +public: + void init() override; + void render(float f) override; + virtual void renderPanel(float f); + bool handleBackEvent(bool b) override; + +public: + Screen* m_pParent; + IntRectangle m_panel; + VerticalLayout m_layout; +}; diff --git a/source/client/gui/screens/PauseScreen.cpp b/source/client/gui/screens/PauseScreen.cpp index e688aacd8..0700e676c 100644 --- a/source/client/gui/screens/PauseScreen.cpp +++ b/source/client/gui/screens/PauseScreen.cpp @@ -7,18 +7,18 @@ ********************************************************************/ #include "PauseScreen.hpp" -#include "OptionsScreen.hpp" #include "server/ServerSideNetworkHandler.hpp" +#include "client/renderer/LogoRenderer.hpp" PauseScreen::PauseScreen() : //m_oPos(0), field_40(0), - m_btnBack(1, "Back to game"), - m_btnQuit(2, "Quit to title"), - m_btnQuitAndCopy(3, "Quit and copy map"), - m_btnVisible(4, "") + m_btnBack("Back to game"), + m_btnQuit("Quit to title"), + m_btnQuitAndCopy("Quit and copy map"), + m_btnVisible("") #ifdef ENH_ADD_OPTIONS_PAUSE - , m_btnOptions(999, "Options") + , m_btnOptions("Options") #endif { } @@ -26,69 +26,37 @@ PauseScreen::PauseScreen() : void PauseScreen::init() { bool bAddVisibleButton = m_pMinecraft->m_pRakNetInstance && m_pMinecraft->m_pRakNetInstance->m_bIsHost; - - int nButtons = 2; - - if (bAddVisibleButton) - nButtons++; - -#ifdef ENH_ADD_OPTIONS_PAUSE - nButtons++; -#endif - - int currY = 48, inc = 32; - bool cramped = m_height < currY + inc * nButtons + 10; // also add some padding - if (cramped) - inc = 25; - - m_btnQuit.m_width = 160; - m_btnBack.m_width = 160; - m_btnVisible.m_width = 160; - m_btnQuitAndCopy.m_width = 160; - - m_btnBack.m_yPos = currY; currY += inc; - m_btnQuit.m_yPos = currY; currY += inc; - m_btnBack.m_xPos = (m_width - 160) / 2; - m_btnQuit.m_xPos = (m_width - 160) / 2; - m_btnVisible.m_xPos = (m_width - 160) / 2; - m_btnQuitAndCopy.m_xPos = (m_width - 160) / 2; - - m_btnVisible.m_yPos = - m_btnQuitAndCopy.m_yPos = currY; + std::vector layoutButtons; + layoutButtons.push_back(&m_btnBack); #ifdef ENH_ADD_OPTIONS_PAUSE - // TODO: when visible or quit© are on, lower this - m_btnOptions.m_width = 160; - m_btnOptions.m_yPos = currY; - m_btnOptions.m_xPos = m_btnBack.m_xPos; + layoutButtons.push_back(&m_btnOptions); #endif - currY += inc; - - // add the buttons to the screen: - _addElement(m_btnBack); - -#ifdef ENH_ADD_OPTIONS_PAUSE - _addElement(m_btnOptions); -#endif - if (bAddVisibleButton) { updateServerVisibilityText(); - _addElement(m_btnVisible); -#ifdef ENH_ADD_OPTIONS_PAUSE - m_btnOptions.m_yPos += inc; -#endif + layoutButtons.push_back(&m_btnVisible); } + layoutButtons.push_back(&m_btnQuit); - _addElement(m_btnQuit); - - //_addElement(m_btnQuitAndCopy); + int buttonsWidth = 160; + int buttonsHeight = 25; + int y = 48; + int ySpacing = 32; + bool cramped = m_height < y + ySpacing * int(layoutButtons.size()) + 10; // also add some padding + if (cramped) + ySpacing = 25; -#ifdef ENH_ADD_OPTIONS_PAUSE - //swap the options and quit buttons around (??) - std::swap(m_btnOptions.m_yPos, m_btnQuit.m_yPos); -#endif + for (size_t i = 0; i < layoutButtons.size(); ++i) + { + Button* button = layoutButtons[i]; + button->m_width = buttonsWidth; + button->m_height = buttonsHeight; + button->m_xPos = (m_width - button->m_width) / 2; + button->m_yPos = y + ySpacing * i; + _addElement(*button); + } #ifndef FEATURE_NETWORKING m_btnVisible.setEnabled(false); @@ -118,6 +86,7 @@ void PauseScreen::render(float f) renderBackground(); drawCenteredString(*m_pFont, "Game menu", m_width / 2, 24, 0xFFFFFF); + Screen::render(f); } @@ -145,6 +114,8 @@ void PauseScreen::_buttonClicked(Button* pButton) #ifdef ENH_ADD_OPTIONS_PAUSE if (pButton->getId() == m_btnOptions.getId()) - m_pMinecraft->setScreen(new OptionsScreen); + { + m_pMinecraft->getScreenChooser()->pushOptionsScreen(this); + } #endif } diff --git a/source/client/gui/screens/PauseScreen_Console.cpp b/source/client/gui/screens/PauseScreen_Console.cpp new file mode 100644 index 000000000..9c20d057d --- /dev/null +++ b/source/client/gui/screens/PauseScreen_Console.cpp @@ -0,0 +1,57 @@ +#include "PauseScreen_Console.hpp" +#include "client/locale/Language.hpp" +#include "client/renderer/LogoRenderer.hpp" + +PauseScreen_Console::PauseScreen_Console() : + m_btnResume(Language::get("pauseMenu.resume")), + m_btnHelpAndOptions(Language::get("mainMenu.helpAndOptions")), + m_btnLeaderboards(Language::get("mainMenu.leaderboards")), + m_btnAchievements(Language::get("mainMenu.achievements")), + m_btnSaveGame(Language::get("pauseMenu.saveGame")), + m_btnExitGame(Language::get("mainMenu.exitGame")) +{ + m_bDeletePrevious = false; + m_btnLeaderboards.setEnabled(false); + m_btnAchievements.setEnabled(false); + + m_uiTheme = UI_CONSOLE; +} + +void PauseScreen_Console::init() +{ + Button* layoutButtons[] = { &m_btnResume, &m_btnLeaderboards, &m_btnAchievements, &m_btnHelpAndOptions, &m_btnSaveGame, &m_btnExitGame }; + + int buttonsWidth = 400; + int buttonsHeight = 40; + int y = m_height / 3 + 10; + int ySpacing = 50; + + for (size_t i = 0; i < 6; ++i) + { + Button* button = layoutButtons[i]; + button->m_width = buttonsWidth; + button->m_height = buttonsHeight; + button->m_xPos = (m_width - button->m_width) / 2; + button->m_yPos = y + ySpacing * i; + _addElement(*button); + } +} + +void PauseScreen_Console::render(float f) +{ + renderBackground(); + LogoRenderer::singleton().render(f); + Screen::render(f); +} + +void PauseScreen_Console::_buttonClicked(Button* btn) +{ + if (btn->getId() == m_btnResume.getId()) + m_pMinecraft->resumeGame(); + else if (btn->getId() == m_btnHelpAndOptions.getId()) + m_pMinecraft->getScreenChooser()->pushOptionsScreen(this); + else if (btn->getId() == m_btnSaveGame.getId()) + m_pMinecraft->m_pLevel->saveGame(); // Minecraft auto-saves automatically when we hit the pause screen + else if (btn->getId() == m_btnExitGame.getId()) + m_pMinecraft->leaveGame(false); +} \ No newline at end of file diff --git a/source/client/gui/screens/PauseScreen_Console.hpp b/source/client/gui/screens/PauseScreen_Console.hpp new file mode 100644 index 000000000..018fef1e8 --- /dev/null +++ b/source/client/gui/screens/PauseScreen_Console.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "../Screen.hpp" +#include "client/gui/components/Button.hpp" + +class PauseScreen_Console : public Screen +{ +public: + PauseScreen_Console(); + void init() override; + void render(float) override; + void _buttonClicked(Button*) override; + +private: + Button m_btnResume; + Button m_btnHelpAndOptions; + Button m_btnLeaderboards; + Button m_btnAchievements; + Button m_btnSaveGame; + Button m_btnExitGame; +}; diff --git a/source/client/gui/screens/ProgressScreen.cpp b/source/client/gui/screens/ProgressScreen.cpp index 994782d5e..fa881e884 100644 --- a/source/client/gui/screens/ProgressScreen.cpp +++ b/source/client/gui/screens/ProgressScreen.cpp @@ -16,58 +16,29 @@ bool ProgressScreen::isInGameScreen() void ProgressScreen::render(float f) { - renderBackground(); + renderDirtBackground(0); - // render the dirt background - // for some reason, this was manually written: - - m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png"); - - //! why not use the screen stuff - int x_width = int(Minecraft::width * Gui::InvGuiScale); - int x_height = int(Minecraft::height * Gui::InvGuiScale); - - Tesselator& t = Tesselator::instance; - t.begin(4); - t.color(0x404040); - t.vertexUV(0.0f, float(x_height), 0, 0, float(x_height) / 32.0f); - t.vertexUV(float(x_width), float(x_height), 0, float(x_width) / 32.0f, float(x_height) / 32.0f); - t.vertexUV(float(x_width), 0, 0, float(x_width) / 32.0f, 0); - t.vertexUV(0.0f, 0, 0, 0, 0); - t.draw(m_materials.ui_texture_and_color); - - int yPos = x_height / 2; + int yPos = m_height / 2; if (m_pMinecraft->m_progressPercent >= 0) { - float lX = float(x_width) / 2 - 50, rX = float(x_width) / 2 + 50; + float lX = float(m_width) / 2 - 50, rX = float(m_width) / 2 + 50; float prog = float(m_pMinecraft->m_progressPercent); - t.begin(8); - - t.color(0x808080); // gray background - t.vertex(lX, float(yPos + 16), 0); - t.vertex(lX, float(yPos + 18), 0); - t.vertex(rX, float(yPos + 18), 0); - t.vertex(rX, float(yPos + 16), 0); - - t.color(0x80FF80); // the green stuff - t.vertex(lX, float(yPos + 16), 0); - t.vertex(lX, float(yPos + 18), 0); - t.vertex(lX + prog, float(yPos + 18), 0); - t.vertex(lX + prog, float(yPos + 16), 0); - - t.draw(m_materials.ui_fill_gradient); + // gray background + fill(lX, yPos + 16.0f, rX, yPos + 18.0f, 0xFF808080); + // the green stuff + fill(lX, yPos + 16.0f, lX + prog, yPos + 18.0f, 0xFF80FF80); } //! Using m_pMinecraft->m_pFont instead of m_pFont. Font* pFont = m_pMinecraft->m_pFont; int width = pFont->width("Generating world"); - pFont->drawShadow("Generating world", (x_width - width) / 2, yPos - 20, 0xFFFFFF); + pFont->drawShadow("Generating world", (m_width - width) / 2, yPos - 20, 0xFFFFFF); width = pFont->width(m_pMinecraft->getProgressMessage()); - pFont->drawShadow(m_pMinecraft->getProgressMessage(), (x_width - width) / 2, yPos + 4, 0xFFFFFF); + pFont->drawShadow(m_pMinecraft->getProgressMessage(), (m_width - width) / 2, yPos + 4, 0xFFFFFF); #ifdef ORIGINAL_CODE sleepMs(50); @@ -84,4 +55,4 @@ void ProgressScreen::updateEvents() } Screen::updateEvents(); -} +} \ No newline at end of file diff --git a/source/client/gui/screens/ProgressScreen_Console.cpp b/source/client/gui/screens/ProgressScreen_Console.cpp new file mode 100644 index 000000000..2f2d0353c --- /dev/null +++ b/source/client/gui/screens/ProgressScreen_Console.cpp @@ -0,0 +1,77 @@ +#include "ProgressScreen_Console.hpp" +#include "client/resources/LoadingTipManager.hpp" +#include "client/locale/Language.hpp" +#include "client/renderer/LogoRenderer.hpp" +#include "client/app/Minecraft.hpp" + +bool ProgressScreen_Console::isInGameScreen() +{ + return false; +} + +void ProgressScreen_Console::init() +{ + m_uiTheme = UI_CONSOLE; + Screen::init(); + + m_header = Language::get("loading.initializing"); +} + +void ProgressScreen_Console::render(float f) +{ + renderMenuBackground(f); + + int loadingBarX = m_width / 2 - 320; + int loadingBarY = m_height / 2 + 30; + m_pFont->drawScalableShadow(m_pMinecraft->getProgressMessage(), loadingBarX + 7, loadingBarY - 15, Color::WHITE, 1.5f); + blitTexture(*m_pMinecraft->m_pTextures, "gui/loading_background.png", loadingBarX, loadingBarY, 0, 0, 640, 20); + + float prog = Mth::clamp(m_pMinecraft->m_progressPercent / 100.0f, 0.0f, 1.0f); + + if (prog >= 0) + blitTexture(*m_pMinecraft->m_pTextures, "gui/loading_bar.png", loadingBarX + 2, loadingBarY + 2, 0, 0, int(636 * Mth::clamp(prog, 0.0f, 1.0f)), 16, 636, 16); + + const LoadingTip& tip = LoadingTipManager::singleton().getActual(); + if (!tip.text.empty()) + { + int panelWidth = 801; + int panelHeight = 81; + int loadingBarBottom = loadingBarY + 20; + int panelY = loadingBarBottom + ((m_height - loadingBarBottom) - panelHeight) / 2; + + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::POINTER_TEXT_PANEL_SLICES, (m_width - panelWidth) / 2, panelY, panelWidth, panelHeight, 8); + + if (m_loadingTip != tip.text) + { + m_loadingTip = tip.text; + m_loadingTipLines = m_pFont->split(tip.text, (panelWidth - 60) / 2); + } + + for (std::vector::iterator it = m_loadingTipLines.begin(); it != m_loadingTipLines.end(); ++it) + { + std::string& line = *it; + + int lineWidth = m_pFont->width(line); + + m_pFont->drawScalable(line, m_width / 2 - lineWidth, panelY + 11, Color::WHITE); + + panelY += 24; + } + } + + m_pFont->drawOutlinedString(m_header, (m_width - m_pFont->width(m_header) * 4) / 2, loadingBarY - 105, Color::WHITE, Color::BLACK); + + LogoRenderer::singleton().render(f); +} + +void ProgressScreen_Console::updateEvents() +{ + if (m_pMinecraft->isLevelGenerated()) + { + + m_pMinecraft->setScreen(nullptr); + return; + } + + Screen::updateEvents(); +} \ No newline at end of file diff --git a/source/client/gui/screens/ProgressScreen_Console.hpp b/source/client/gui/screens/ProgressScreen_Console.hpp new file mode 100644 index 000000000..80c434eb7 --- /dev/null +++ b/source/client/gui/screens/ProgressScreen_Console.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "../Screen.hpp" + +class ProgressScreen_Console : public Screen +{ +public: + void render(float f) override; + void updateEvents() override; + bool isInGameScreen() override; + void init() override; + +private: + std::string m_header; + + std::string m_loadingTip; + std::vector m_loadingTipLines; +}; + diff --git a/source/client/gui/screens/RenameMPLevelScreen.cpp b/source/client/gui/screens/RenameMPLevelScreen.cpp index 332b06a1c..0e33c1e58 100644 --- a/source/client/gui/screens/RenameMPLevelScreen.cpp +++ b/source/client/gui/screens/RenameMPLevelScreen.cpp @@ -34,5 +34,5 @@ void RenameMPLevelScreen::render(float f) } } - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen(); } diff --git a/source/client/gui/screens/RenameMPLevelScreen.hpp b/source/client/gui/screens/RenameMPLevelScreen.hpp index d998659ec..61a523353 100644 --- a/source/client/gui/screens/RenameMPLevelScreen.hpp +++ b/source/client/gui/screens/RenameMPLevelScreen.hpp @@ -14,6 +14,8 @@ class RenameMPLevelScreen : public Screen { public: RenameMPLevelScreen(const std::string& levelName); + +public: void init() override; void render(float f) override; diff --git a/source/client/gui/screens/SavingWorldScreen.cpp b/source/client/gui/screens/SavingWorldScreen.cpp index 3935d8bf2..bf165d5d5 100644 --- a/source/client/gui/screens/SavingWorldScreen.cpp +++ b/source/client/gui/screens/SavingWorldScreen.cpp @@ -23,8 +23,8 @@ void SavingWorldScreen::render(float f) { renderDirtBackground(0); - int x_width = int(Minecraft::width * Gui::InvGuiScale); - int x_height = int(Minecraft::height * Gui::InvGuiScale); + int x_width = int(Minecraft::width * Gui::GuiScale); + int x_height = int(Minecraft::height * Gui::GuiScale); int yPos = x_height / 2; int width = m_pFont->width("Saving chunks"); diff --git a/source/client/gui/screens/SelectWorldScreen.cpp b/source/client/gui/screens/SelectWorldScreen.cpp index b48bd5732..18c54f512 100644 --- a/source/client/gui/screens/SelectWorldScreen.cpp +++ b/source/client/gui/screens/SelectWorldScreen.cpp @@ -14,17 +14,17 @@ #include "common/Util.hpp" SelectWorldScreen::SelectWorldScreen() : - m_btnDelete (1, "Delete"), - m_btnCreateNew(2, "Create New"), - m_btnBack (3, "Back"), - m_btnWorld (4, ""), + m_btnDelete ("Delete"), + m_btnCreateNew("Create New"), + m_btnBack ("Back"), + m_btnWorld (""), m_pWorldSelectionList(nullptr) { - m_bTabWrap = false; m_btnDelete.setEnabled(false); - m_btnWorld.setVisible(false); + m_btnWorld.m_color.a = 0.0f; field_12C = false; field_130 = 0; + m_pSelectedElement = &m_btnWorld; } SelectWorldScreen::~SelectWorldScreen() @@ -32,44 +32,19 @@ SelectWorldScreen::~SelectWorldScreen() SAFE_DELETE(m_pWorldSelectionList); } -void SelectWorldScreen::_controllerDirectionHeld(GameController::StickID stickId, GameController::StickState stickState) +bool SelectWorldScreen::_areaNavigation(AreaNavigation::Direction dir) { - if (stickId == 1) + if (m_btnWorld.isSelected() && (dir == AreaNavigation::LEFT || dir == AreaNavigation::RIGHT)) { - switch (stickState) - { - case GameController::STICK_STATE_UP: - if (prevElementList()) - _nextElement(); // skip to "Create New" button - break; - case GameController::STICK_STATE_DOWN: - if (nextElementList()) - _nextElement(); // skip to "Create New" button - break; - case GameController::STICK_STATE_LEFT: - if (m_btnWorld.isSelected()) - { - m_pWorldSelectionList->stepLeft(); - } - else - { - prevElement(); - } - break; - case GameController::STICK_STATE_RIGHT: - if (m_btnWorld.isSelected()) - { - m_pWorldSelectionList->stepRight(); - } - else - { - nextElement(); - } - break; - default: - break; - } + if (dir == AreaNavigation::LEFT) + m_pWorldSelectionList->stepLeft(); + else + m_pWorldSelectionList->stepRight(); + + return true; } + + return Screen::_areaNavigation(dir); } void SelectWorldScreen::init() @@ -80,8 +55,6 @@ void SelectWorldScreen::init() loadLevelSource(); m_pWorldSelectionList->commit(); - m_btnWorld.setSelected(true); - m_btnDelete.m_yPos = m_btnBack.m_yPos = m_btnCreateNew.m_yPos = m_height - 28; m_btnDelete.m_width = m_btnBack.m_width = m_btnCreateNew.m_width = 84; m_btnDelete.m_height = m_btnBack.m_height = m_btnCreateNew.m_height = 24; @@ -91,13 +64,9 @@ void SelectWorldScreen::init() m_btnBack.m_xPos = m_width / 2 + 46; _addElement(m_btnWorld); - - _addElementList(); - _nextElementList(); - _addElement(m_btnDelete); - _addElement(m_btnCreateNew); - _addElement(m_btnBack); - _prevElementList(); + _addElement(m_btnDelete); + _addElement(m_btnCreateNew); + _addElement(m_btnBack); field_12C = m_menuPointer.isPressed; } @@ -229,7 +198,7 @@ bool SelectWorldScreen::handleBackEvent(bool b) return true; // @TODO: m_pMinecraft->cancelLocateMultiplayer(); - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen(); return true; } @@ -238,7 +207,7 @@ void SelectWorldScreen::_buttonClicked(Button* pButton) if (pButton->getId() == m_btnCreateNew.getId()) { #ifndef ORIGINAL_CODE - m_pMinecraft->setScreen(new CreateWorldScreen); + m_pMinecraft->getScreenChooser()->pushCreateWorldScreen(this); #else m_pMinecraft->platform()->showDialog(AppPlatform::DLG_CREATE_WORLD); m_pMinecraft->platform()->createUserInput(); @@ -255,7 +224,7 @@ void SelectWorldScreen::_buttonClicked(Button* pButton) if (pButton->getId() == m_btnBack.getId()) { // @TODO: m_pMinecraft->cancelLocateMultiplayer(); - m_pMinecraft->setScreen(new StartMenuScreen); + m_pMinecraft->getScreenChooser()->pushStartScreen(); } if (pButton->getId() == m_btnWorld.getId()) diff --git a/source/client/gui/screens/SelectWorldScreen.hpp b/source/client/gui/screens/SelectWorldScreen.hpp index 7f5e071b4..7d1937175 100644 --- a/source/client/gui/screens/SelectWorldScreen.hpp +++ b/source/client/gui/screens/SelectWorldScreen.hpp @@ -19,7 +19,7 @@ class SelectWorldScreen : public Screen ~SelectWorldScreen(); protected: - void _controllerDirectionHeld(GameController::StickID stickId, GameController::StickState stickState) override; + bool _areaNavigation(AreaNavigation::Direction) override; public: void init() override; diff --git a/source/client/gui/screens/SelectWorldScreen_Console.cpp b/source/client/gui/screens/SelectWorldScreen_Console.cpp new file mode 100644 index 000000000..4bfd5d92c --- /dev/null +++ b/source/client/gui/screens/SelectWorldScreen_Console.cpp @@ -0,0 +1,210 @@ +#include "SelectWorldScreen_Console.hpp" +#include "client/locale/Language.hpp" +#include "renderer/ShaderConstants.hpp" + +SelectWorldScreen_Console::SelectWorldScreen_Console(Minecraft* mc, Screen* parent) : PanelScreen_Console(parent), + m_joinLayout(this) +{ + fillSaves(mc); +} + +void SelectWorldScreen_Console::init() +{ + m_panel.w = 1040; + m_panel.h = 426; + m_panel.x = (m_width - m_panel.w) / 2; + m_panel.y = (m_height - m_panel.h) / 2 + 59; + m_startPanel.x = m_panel.x + 18; + m_startPanel.y = m_panel.y + 22; + m_startPanel.w = 500; + m_startPanel.h = 380; + m_joinPanel = m_startPanel; + m_joinPanel.x = m_panel.x + m_panel.w - m_joinPanel.w - 16; + m_layout.init(IntRectangle(m_startPanel.x + 20, m_startPanel.y + 42, 460, 300), 0); + m_joinLayout.init(IntRectangle(m_joinPanel.x + 20, m_joinPanel.y + 42, 460, 300), 0); +} + +void SelectWorldScreen_Console::fillSaves(Minecraft* mc) +{ + m_layout.clear(); + + m_layout.m_elements.push_back(new CreateButton(Language::get("playGame.createNewWorld"))); + ListButton* playTutorial = new ListButton(Language::get("playGame.tutorial")); + playTutorial->setEnabled(false); + m_layout.m_elements.push_back(playTutorial); + + std::vector levels; + + mc->getLevelSource()->getLevelList(levels); + std::sort(levels.begin(), levels.end()); + + for (size_t i = 0; i < levels.size(); ++i) + { + LevelSummary& level = levels[i]; + if (level.m_fileName == "_LastJoinedServer") + continue; + + m_layout.m_elements.push_back(new SaveButton(level)); + } + + if (m_layout.m_elements.size() > 2) + m_layout.selectElementById(2, false); +} + +void SelectWorldScreen_Console::fillServers() +{ + m_joinLayout.clear(); + + m_joinLayout.setNavigable(!m_servers.empty()); + + for (size_t i = 0; i < m_servers.size(); ++i) + { + m_joinLayout.m_elements.push_back(new JoinButton(m_servers[i])); + } + m_joinLayout.organize(); +} + +void SelectWorldScreen_Console::tick() +{ + std::vector* serverList, serverListFiltered; + serverList = m_pMinecraft->m_pRakNetInstance->getServerList(); + + for (size_t i = 0; i < serverList->size(); i++) + { + const PingedCompatibleServer& pcs = (*serverList)[i]; + if (pcs.m_name.GetLength()) + serverListFiltered.push_back(pcs); + } + + if (serverListFiltered.size() != m_servers.size()) + { + PingedCompatibleServer selectedItem; + + m_servers = serverListFiltered; + fillServers(); + } + else if (!serverListFiltered.empty()) + { + bool changed = false; + for (int i = int(m_servers.size() - 1); i >= 0; i--) + { + size_t j = 0; + for (; j < serverListFiltered.size(); j++) + { + if (serverListFiltered[j].m_address == m_servers[i].m_address) + break; + } + + if (j == serverListFiltered.size()) + continue; + + if (m_servers[i].m_name != serverListFiltered[j].m_name) + { + m_servers[i].m_name = serverListFiltered[j].m_name; + changed = true; + } + } + + if (changed) + fillServers(); + } +} + +bool SelectWorldScreen_Console::handleBackEvent(bool b) +{ + if (!b) + m_pMinecraft->cancelLocateMultiplayer(); + return PanelScreen_Console::handleBackEvent(b); +} + +void SelectWorldScreen_Console::renderPanel(float f) +{ + PanelScreen_Console::renderPanel(f); + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::PANEL_RECESS_SLICES, m_startPanel.x, m_startPanel.y, m_startPanel.w, m_startPanel.h, 16); + currentShaderColor.a = 0.5f; + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::PANEL_RECESS_SLICES, m_joinPanel.x, m_joinPanel.y, m_joinPanel.w, m_joinPanel.h, 16, &m_materials.ui_textured_and_glcolor); + currentShaderColor.a = 1.0f; + + const std::string& startGame = Language::get("playGame.start"); + m_pFont->drawScalable(startGame, m_startPanel.x + m_startPanel.w / 2 - m_pFont->width(startGame), m_startPanel.y + 14, Color::TEXT_GREY); + + const std::string& joinGame = Language::get("playGame.join"); + m_pFont->drawScalable(joinGame, m_joinPanel.x + m_joinPanel.w / 2 - m_pFont->width(joinGame), m_joinPanel.y + 14, Color::TEXT_GREY); + + if (m_servers.empty()) + m_pFont->drawScalable(Language::get("playGame.noGamesFound"), m_joinPanel.x + 151, m_joinPanel.y + 192, Color::TEXT_GREY); +} + +ListButton::ListButton(const std::string& text) : Button(0, 0, 460, 60, text) +{ +} + +void ListButton::render(Minecraft* mc, const MenuPointer& pointer) +{ + if (!mc->m_pScreen->doElementTabbing()) + setSelected(isHovered(mc, pointer)); + + Textures& texs = *mc->m_pTextures; + if (!isEnabled()) + currentShaderColor.a *= 0.5f; + blitSprite(texs, isSelected() && !hasFocus() ? "gui/console/Graphics/ListButton_Over.png" : "gui/console/Graphics/ListButton_Norm.png", m_xPos, m_yPos, m_width, m_height, &m_materials.ui_textured_and_glcolor); + + Color textColor; + if (isSelected()) + { + textColor = Color(220, 220, 0, currentShaderColor.a); // 0xDCDC00 + } + else + textColor = Color(224, 224, 224, currentShaderColor.a); // 0xE0E0E0U + renderMessage(*mc->m_pFont, textColor); + + currentShaderColor = Color::WHITE; +} + +void ListButton::renderMessage(Font& font, const Color& textColor) +{ + font.drawScalableShadow(getMessage(), m_xPos + 67, m_yPos + (m_height - 16) / 2, textColor); +} + +CreateButton::CreateButton(const std::string& text) : ListButton(text) +{ +} + +void CreateButton::pressed(Minecraft* mc) +{ + mc->getScreenChooser()->pushCreateWorldScreen(mc->m_pScreen); +} + +SaveButton::SaveButton(const LevelSummary& summary) : ListButton(summary.m_levelName), + m_summary(summary) +{ +} + +void SaveButton::render(Minecraft* mc, const MenuPointer& pointer) +{ + ListButton::render(mc, pointer); + + blitTexture(*mc->m_pTextures, "gui/default_world.png", m_xPos + 10, m_yPos + 10, 0, 0, 40, 40); +} + +void SaveButton::pressed(Minecraft* mc) +{ + //@TODO: Replace this with Load Save screen + mc->selectLevel(m_summary); +} + +JoinButton::JoinButton(const PingedCompatibleServer& server) : ListButton(Util::format(Language::get("playGame.joinButton").c_str(), server.m_name.C_String())), + m_server(server) +{ +} + +void JoinButton::renderMessage(Font& font, const Color& textColor) +{ + font.drawScalableShadow(getMessage(), m_xPos + 10, m_yPos + (m_height - 16) / 2, textColor); +} + +void JoinButton::pressed(Minecraft* mc) +{ + mc->joinMultiplayer(m_server); + mc->getScreenChooser()->pushProgressScreen(); +} diff --git a/source/client/gui/screens/SelectWorldScreen_Console.hpp b/source/client/gui/screens/SelectWorldScreen_Console.hpp new file mode 100644 index 000000000..6a5ca9b4f --- /dev/null +++ b/source/client/gui/screens/SelectWorldScreen_Console.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "PanelScreen_Console.hpp" +#include "client/gui/components/Button.hpp" +#include "network/PingedCompatibleServer.hpp" + +class ListButton : public Button +{ +public: + ListButton(const std::string&); + + void render(Minecraft*, const MenuPointer&) override; + virtual void renderMessage(Font&, const Color&); +}; + +class CreateButton : public ListButton +{ +public: + CreateButton(const std::string&); + + void pressed(Minecraft*) override; +}; + +class SaveButton : public ListButton +{ +public: + SaveButton(const LevelSummary&); + + void render(Minecraft*, const MenuPointer&) override; + void pressed(Minecraft*) override; + +public: + LevelSummary m_summary; +}; + +class JoinButton : public ListButton +{ +public: + JoinButton(const PingedCompatibleServer&); + + void renderMessage(Font&, const Color&) override; + void pressed(Minecraft*) override; + +public: + PingedCompatibleServer m_server; +}; + +class SelectWorldScreen_Console : public PanelScreen_Console +{ +public: + SelectWorldScreen_Console(Minecraft*, Screen*); + + void init() override; + void fillSaves(Minecraft*); + void fillServers(); + void tick() override; + bool handleBackEvent(bool) override; + void renderPanel(float) override; + +public: + VerticalLayout m_joinLayout; + IntRectangle m_startPanel; + IntRectangle m_joinPanel; + std::vector m_servers; +}; \ No newline at end of file diff --git a/source/client/gui/screens/StartMenuScreen.cpp b/source/client/gui/screens/StartMenuScreen.cpp index d98f2f9e7..4d2dc03ac 100644 --- a/source/client/gui/screens/StartMenuScreen.cpp +++ b/source/client/gui/screens/StartMenuScreen.cpp @@ -9,518 +9,25 @@ #include "StartMenuScreen.hpp" #include "client/renderer/ScreenRenderer.hpp" -#include "client/renderer/renderer/RenderMaterialGroup.hpp" -#include "renderer/RenderContextImmediate.hpp" -#include "renderer/ShaderConstants.hpp" +#include "client/renderer/LogoRenderer.hpp" #include "InvalidLicenseScreen.hpp" -#include "OptionsScreen.hpp" -#include "ProgressScreen.hpp" #include "SelectWorldScreen.hpp" #include "JoinGameScreen.hpp" -#include "CreditsScreen.hpp" - -// special mode so that we can crop out the title: -//#define TITLE_CROP_MODE - -#define C_TITLE_PATH_DEFAULT "title/mclogo.png" -#define C_TITLE_PATH_FALLBACK "gui/title.png" // everyone should have this -#define C_TITLE_PATH_POCKET "gui/title_pe.png" -#define C_TITLE_PATH_XBOX360 "gui/title_xbox360.png" -#define C_TITLE_SCALE_DEFAULT 1.0f - -#if MC_PLATFORM_MOBILE -#define C_TITLE_PATH C_TITLE_PATH_POCKET -#elif MC_PLATFORM_XBOX360 -#define C_TITLE_PATH C_TITLE_PATH_XBOX360 -#define C_TITLE_SCALE 0.5f -#else -#define C_TITLE_PATH C_TITLE_PATH_DEFAULT -#define C_USING_JAVA_TITLE -#endif - -#ifndef C_TITLE_SCALE -#define C_TITLE_SCALE C_TITLE_SCALE_DEFAULT -#endif - -const char gLogoLine1[] = "??? ??? # # # # # ### ### ### ### ### ### $$$ $$$"; -const char gLogoLine2[] = "? ? ? ## ## # ## # # # # # # # # # $ $ $ "; -const char gLogoLine3[] = "?? ?? # # # # # # # ## # ## ### ## # $$ $$ "; -const char gLogoLine4[] = "? ? ? # # # # ## # # # # # # # # $ $ "; -const char gLogoLine5[] = "? ? ??? # # # # # ### ### # # # # # # $ $$$"; - -const char* gLogoLines[] = { - gLogoLine1, - gLogoLine2, - gLogoLine3, - gLogoLine4, - gLogoLine5, -}; - -// actual name -const char* gSplashes[] = -{ - "One star! Deal with it notch!", - "100% more yellow text!", - "Glowing creepy eyes!", - "Toilet friendly!", - "Annoying touch buttons!", - "Astronomically accurate!", - "0xffff-1 chunks!", - "Cubism!", - "Pocket!", - "Mostly harmless!", - "!!!1!", - "Dramatic lighting!", - "As seen on TV!", - "Awesome!", - "100% pure!", - "May contain nuts!", - "Better than Prey!", - "Less polygons!", - "Sexy!", - "Limited edition!", - "Flashing letters!", - "Made by Mojang!", - "It's here!", - "Best in class!", - "It's alpha!", - "100% dragon free!", - "Excitement!", - "More than 500 sold!", - "One of a kind!", - "Heaps of hits on YouTube!", - "Indev!", - "Spiders everywhere!", - "Check it out!", - "Holy cow, man!", - "It's a game!", - "Made in Sweden!", - "Uses C++!", - "Reticulating splines!", - "Minecraft!", - "Yaaay!", - "Multiplayer!", - "Touch compatible!", - "Undocumented!", - "Ingots!", - "Exploding creepers!", - "That's no moon!", - "l33t!", - "Create!", - "Survive!", - "Dungeon!", - "Exclusive!", - "The bee's knees!", - "Down with O.P.P.!", - "Open source!", //"Closed source!", - "Classy!", - "Wow!", - "Not on steam!", - "Oh man!", - "Awesome community!", - "Pixels!", - "Teetsuuuuoooo!", - "Kaaneeeedaaaa!", - "Enhanced!", - "90% bug free!", - "Pretty!", - "12 herbs and spices!", - "Fat free!", - "Absolutely no memes!", - "Free dental!", - "Ask your doctor!", - "Minors welcome!", - "Cloud computing!", - "Legal in Finland!", - "Hard to label!", - "Technically good!", - "Bringing home the bacon!", - "Quite Indie!", - "GOTY!", - "Euclidian!", - "Now in 3D!", - "Inspirational!", - "Herregud!", - "Complex cellular automata!", - "Yes, sir!", - "Played by cowboys!", -#if MCE_GFX_API_OGL -#ifdef USE_GLES - "OpenGL ES 1.1!", -#else - "OpenGL 1.5!", -#endif -#elif MCE_GFX_API_D3D11 - "Direct3D 11.1!", -#elif MCE_GFX_API_D3D9 - "Direct3D 9!", -#endif - "Thousands of colors!", - "Try it!", - "Age of Wonders is better!", - "Try the mushroom stew!", - "Sensational!", - "Hot tamale, hot hot tamale!", - "Play him off, keyboard cat!", - "Guaranteed!", - "Macroscopic!", - "Bring it on!", - "Random splash!", - "Call your mother!", - "Monster infighting!", - "Loved by millions!", - "Ultimate edition!", - "Freaky!", - "You've got a brand new key!", - "Water proof!", - "Uninflammable!", - "Whoa, dude!", - "All inclusive!", - "Tell your friends!", - "NP is not in P!", - "Notch <3 ez!", - "Livestreamed!", - "Haunted!", - "Polynomial!", - "Terrestrial!", - "All is full of love!", - "Full of stars!", - "Scientific!", - "Cooler than Spock!", - "Collaborate and listen!", - "Never dig down!", - "Take frequent breaks!", - "Not linear!", - "Han shot first!", - "Nice to meet you!", - "Buckets of lava!", - "Ride the pig!", - "Larger than Earth!", - "sqrt(-1) love you!", - "Phobos anomaly!", - "Punching wood!", - "Falling off cliffs!", - "0% sugar!", - "150% hyperbole!", - "Synecdoche!", - "Let's danec!", - "Seecret Friday update!", - "Ported implementation!", - "Lewd with two dudes with food!", - "Kiss the sky!", - "20 GOTO 10!", - "Verlet intregration!", // [sic] - "Peter Griffin!", - "Redistributable!", // Do not distribute! - "Cogito ergo sum!", - "4815162342 lines of code!", - "A skeleton popped out!", - "The Work of Notch!", - "The sum of its parts!", - "BTAF used to be good!", - "I miss ADOM!", - "umop-apisdn!", - "OICU812!", - "Bring me Ray Cokes!", - "Finger-licking!", - "Thematic!", - "Pneumatic!", - "Sublime!", - "Octagonal!", - "Une baguette!", - "Gargamel plays it!", - "Rita is the new top dog!", - "SWM forever!", - "Representing Edsbyn!", - "Matt Damon!", - "Supercalifragilisticexpialidocious!", - "Consummate V's!", - "Cow Tools!", - "Double buffered!", - "V-synched!", - "Fan fiction!", - "Flaxkikare!", - "Jason! Jason! Jason!", - "Hotter than the sun!", - "Internet enabled!", - "Autonomous!", - "Engage!", - "Fantasy!", - "DRR! DRR! DRR!", - "Kick it root down!", - "Regional resources!", - "Woo, facepunch!", - "Woo, somethingawful!", - "Woo, /v/!", - "Woo, tigsource!", - "Woo, minecraftforum!", - "Woo, worldofminecraft!", - "Woo, reddit!", - "Woo, 2pp!", - "Not Google anlyticsed!", - "Give us Gordon!", - "Tip your waiter!", - "Very fun!", - "12345 is a bad password!", - "Vote for net neutrality!", - "Lives in a pineapple under the sea!", - "Omnipotent!", - "Gasp!", - "...!", - "Bees, bees, bees, bees!", - "Haha, LOL!", - "Hampsterdance!", - "Switches and ores!", - "Menger sponge!", - "idspispopd!", - "Eple (original edit)!", - "So fresh, so clean!", - "Don't look directly at the bugs!", - "Oh, ok, Pigmen!", - "Scary!", - "Play Minecraft, Watch Topgear, Get Pig!", - "Twittered about!", - "Jump up, jump up, and get down!", - "Joel is neat!", - "A riddle, wrapped in a mystery!", - "Huge tracts of land!", - "Welcome to your Doom!", - "Stay a while, stay forever!", - "Stay a while and listen!", - "Treatment for your rash!", - "\"Autological\" is!", - "Information wants to be free!", - "\"Almost never\" is an interesting concept!", - "Lots of truthiness!", - "The creeper is a spy!", - "It's groundbreaking!", - "Let our battle's begin!", - "The sky is the limit!", - "Jeb has amazing hair!", - "Casual gaming!", - "Undefeated!", - "Kinda like Lemmings!", - "Follow the train, CJ!", - "Leveraging synergy!", - "DungeonQuest is unfair!", - "110813!", - "90210!", - "Tyrion would love it!", - "Also try VVVVVV!", - "Also try Super Meat Boy!", - "Also try Terraria!", - "Also try Mount And Blade!", - "Also try Project Zomboid!", - "Also try World of Goo!", - "Also try Limbo!", - "Also try Pixeljunk Shooter!", - "Also try Braid!", - "That's super!", - "Bread is pain!", - "Read more books!", - "Khaaaaaaaaan!", - "Less addictive than TV Tropes!", - "More addictive than lemonade!", - "Bigger than a bread box!", - "Millions of peaches!", - "Fnord!", - "This is my true form!", - "Totally forgot about Dre!", - "Don't bother with the clones!", - "Pumpkinhead!", - "Hobo humping slobo babe!", - "Endless!", - "Feature packed!", - "Boots with the fur!", - "Stop, hammertime!", - "Conventional!", - "Homeomorphic to a 3-sphere!", - "Doesn't avoid double negatives!", - "Place ALL the blocks!", - "Does barrel rolls!", - "Meeting expectations!", - "PC gaming since 1873!", - "Ghoughpteighbteau tchoghs!", - "Got your nose!", - "Haley loves Elan!", - "Afraid of the big, black bat!", - "Doesn't use the U-word!", - "Child's play!", - "See you next Friday or so!", - "150 bpm for 400000 minutes!", - "Technologic!", - "Funk soul brother!", - "Pumpa kungen!", - "Helo Cymru!", - "My life for Aiur!", - "Lennart lennart = new Lennart();", - "I see your vocabulary has improved!", - "Who put it there?", - "You can't explain that!", - "if not ok then return end", - "SOPA means LOSER in Swedish!", - "Big Pointy Teeth!", - "Bekarton guards the gate!", - "Mmmph, mmph!", - "Don't feed avocados to parrots!", - "Swords for everyone!", - "Plz reply to my tweet!", - ".party()!", - "Take her pillow!", - "Put that cookie down!", - "Pretty scary!", - "I have a suggestion.", - "Now with extra hugs!", - "Almost C++98!", // "Almost C++11!", - "Woah.", - "HURNERJSGER?", - "What's up, Doc?", - - // custom: - "https://github.com/ReMinecraftPE/mcpe", - "100% (render)dragon free!", - "Also try Minecraft!", // Notch - "Also try Noita!", - "Also try Castle Crashers!", - "Also try Unturned!", - "Also try Minecraft Pi Reborn!", // TheBrokenRail - "Also try RePocket!", // atipls - "Also try PEtoLE!", // Wilyicaro - "Controller support!", - "Check out our GitHub!", - "Flint and steel!", - "I ... am Steve!", - "Nostalgic!", - "Now with graphics abstraction!", - "Now with HAL!", - "Supports PowerPC!", - // These guys carried - "The Work of Aron Nieminen!", // https://minecraft.wiki/w/Aron_Nieminen - "The Work of Johan Bernhardsson!", // https://minecraft.wiki/w/Johan_Bernhardsson - "The Work of Tommaso Checchi!", // https://minecraft.wiki/w/Tommaso_Checchi - "Woo, forge!", - "Woo, fabric!", - "Woo, newgrounds!", -}; - -StartMenuScreen::Materials::Materials() -{ - MATERIAL_PTR(common, ui_title_tile); - MATERIAL_PTR(common, ui_title_tile_shadow); -} +#include "client/resources/SplashManager.hpp" StartMenuScreen::StartMenuScreen() : - m_startButton (2, 0, 0, 160, 24, "Start Game"), - m_joinButton (3, 0, 0, 160, 24, "Join Game"), - m_optionsButton(4, 0, 0, 78, 22, "Options"), - m_testButton (999, 0, 0, 78, 22, "Test"), - m_buyButton (5, 0, 0, 78, 22, "Buy"), - m_creditsButton(6, 0, 0, 78, 22, "") + m_startButton (0, 0, 160, 24, "Start Game"), + m_joinButton (0, 0, 160, 24, "Join Game"), + m_optionsButton(0, 0, 78, 22, "Options"), + m_buyButton (0, 0, 78, 22, "Buy"), + m_creditsButton(0, 0, 78, 22, "") { - m_pTiles = nullptr; - m_chosenSplash = -1; - m_bUsingJavaLogo = false; - - // note: do it here because we don't want the title to - // show up differently when you resize - TitleTile::regenerate(); + m_chosenSplash = SplashManager::singleton().getSplash(); } StartMenuScreen::~StartMenuScreen() { - SAFE_DELETE_ARRAY(m_pTiles); -} - -void StartMenuScreen::_initTextures() -{ - if (!m_p2dTitleTexPath.empty()) - return; - - Textures* tx = m_pMinecraft->m_pTextures; - std::string path = C_TITLE_PATH; - if (tx->getTextureData(path, false)) - { -#ifdef C_USING_JAVA_TITLE - m_bUsingJavaLogo = true; -#endif - } - else - { - path = C_TITLE_PATH_FALLBACK; - // "preload" texture data - tx->getTextureData(path, true); - } - - m_p2dTitleTexPath = path; -} - -void StartMenuScreen::_initResources() -{ - _initTextures(); - _build2dTitleMesh(); -} - -void StartMenuScreen::_build2dTitleMesh() -{ - // bool crampedMode = false; - - int yPos, width, height, left; - - TextureData* pTex = m_pMinecraft->m_pTextures->getTextureData(m_p2dTitleTexPath, true); - if (!pTex) - return; - - if (m_bUsingJavaLogo) - { - yPos = 30; - width = 274; - height = 44; - left = m_width / 2 - width / 2; - - if (m_width * 3 / 4 < m_2dTitleBounds.w) - { - // crampedMode = true; - yPos = 4; - } - - Tesselator& t = Tesselator::instance; - t.begin(8); - t.vertexUV(left, yPos + height, 0, 0.0f, 44.0f / 256.0f); - t.vertexUV(left + 155, yPos + height, 0, 155.0f / 256.0f, 44.0f / 256.0f); - t.vertexUV(left + 155, yPos, 0, 155.0f / 256.0f, 0.0f); - t.vertexUV(left, yPos, 0, 0.0f, 0.0f); - t.vertexUV(left + 155, yPos + height, 0, 0.0f, (45.0f + 44.0f) / 256.0f); - t.vertexUV(left + 310, yPos + height, 0, 155.0f / 256.0f, (45.0f + 44.0f) / 256.0f); - t.vertexUV(left + 310, yPos, 0, 155.0f / 256.0f, 45.0f / 256.0f); - t.vertexUV(left + 155, yPos, 0, 0.0f, 45.0f / 256.0f); - m_2dTitleMesh = t.end(); - } - else - { - yPos = 15; - width = pTex->m_imageData.m_width; - height = pTex->m_imageData.m_height; - if (C_TITLE_SCALE != 1.0f) - { - width = ceilf(((float)width) * C_TITLE_SCALE); - height = ceilf(((float)height) * C_TITLE_SCALE); - } - left = (m_width - width) / 2; - - if (m_width * 3 / 4 < m_2dTitleBounds.w) - { - // crampedMode = true; - yPos = 4; - } - - m_2dTitleBounds.x = left; - m_2dTitleBounds.y = yPos; - m_2dTitleBounds.w = width; - m_2dTitleBounds.h = height; - - blit(m_2dTitleMesh, m_2dTitleBounds); - } } void StartMenuScreen::_updateLicense() @@ -578,11 +85,11 @@ void StartMenuScreen::_buttonClicked(Button* pButton) } else if (pButton->getId() == m_optionsButton.getId()) { - m_pMinecraft->setScreen(new OptionsScreen); + m_pMinecraft->getScreenChooser()->pushOptionsScreen(this); } else if (pButton->getId() == m_creditsButton.getId()) { - m_pMinecraft->setScreen(new CreditsScreen); + m_pMinecraft->getScreenChooser()->pushCreditsScreen(this); } } @@ -590,13 +97,16 @@ void StartMenuScreen::init() { int yPos = m_height / 2; + m_startButton.m_width = m_joinButton.m_width = 160; + m_optionsButton.m_width = m_buyButton.m_width = 78; + m_startButton.m_height = m_joinButton.m_height = m_optionsButton.m_height = m_buyButton.m_height = 25; + m_joinButton.m_yPos = yPos + 25; m_startButton.m_yPos = yPos - 3; yPos += 55; m_optionsButton.m_yPos = yPos; - m_testButton.m_yPos = yPos; m_buyButton.m_yPos = yPos; m_startButton.m_xPos = (m_width - m_startButton.m_width) / 2; @@ -605,9 +115,8 @@ void StartMenuScreen::init() m_joinButton.m_xPos = x1 / 2; m_optionsButton.m_xPos = x1 / 2; - + m_buyButton.m_xPos = x1 / 2 + m_optionsButton.m_width + 4; - m_testButton.m_xPos = x1 / 2 + m_optionsButton.m_width + 4; m_creditsButton.m_xPos = 0; m_creditsButton.m_yPos = 0; @@ -638,24 +147,23 @@ void StartMenuScreen::init() _addElement(m_buyButton); } - _addElement(m_creditsButton); + _addElement(m_creditsButton, false); - field_154 = "\xFFMojang AB"; - field_16C = m_width - 1 - m_pFont->width(field_154); + m_watermarkText = "\xFFMojang AB"; + m_watermarkX = m_width - 1 - m_pFont->width(m_watermarkText); - field_170 = m_pMinecraft->getVersionString(); + m_versionText = m_pMinecraft->getVersionString(); #ifdef DEMO " (Demo)" #endif ; - field_188 = (m_width - m_pFont->width(field_170)) / 2; + m_versionTextX = (m_width - m_pFont->width(m_versionText)) / 2; #ifndef DEMO m_buyButton.setMessage("Quit"); #endif - _initResources(); _updateLicense(); } @@ -664,141 +172,10 @@ bool StartMenuScreen::isInGameScreen() return false; } -void StartMenuScreen::draw2dTitle() -{ - currentShaderColor = Color::WHITE; - m_pMinecraft->m_pTextures->loadAndBindTexture(m_p2dTitleTexPath); - m_2dTitleMesh.render(m_materials.ui_textured); -} - -void StartMenuScreen::draw3dTitle(float f) -{ - int Width = int(sizeof gLogoLine1 - 1); - int Height = int(sizeof gLogoLines / sizeof * gLogoLines); - - if (!m_pTiles) - { - m_pTiles = new TitleTile*[Width * Height]; - - for (int y = 0; y < Height; y++) - for (int x = 0; x < Width; x++) - m_pTiles[y * Width + x] = new TitleTile(this, x, y); - } - - int titleHeight = int(120 / Gui::InvGuiScale); - - if (m_width * 3 / 4 < 256) // cramped mode - titleHeight = int(80 / Gui::InvGuiScale); - - MatrixStack::Ref projMtx = MatrixStack::Projection.pushIdentity(); - projMtx->setPerspective(70.0f, float(Minecraft::width) / titleHeight, 0.05f, 100.0f); - - mce::RenderContext& renderContext = mce::RenderContextImmediate::get(); - - mce::ViewportOrigin viewportOrigin; - { - viewportOrigin.leftX = 0; - viewportOrigin.bottomLeftY = Minecraft::height - titleHeight; - viewportOrigin.topLeftY = 0; - } - renderContext.setViewport(Minecraft::width, titleHeight, 0.0f, 0.7f, viewportOrigin); - - MatrixStack::Ref viewMtx = MatrixStack::View.pushIdentity(); - - mce::MaterialPtr* pMaterial; - - for (int i = 0; i < 2; i++) - { - MatrixStack::Ref matrix = MatrixStack::World.push(); - matrix->translate(Vec3(0.4f, 0.6f, -12.0f)); - switch (i) - { - case 0: // shadow - //glClear(GL_DEPTH_BUFFER_BIT); - renderContext.clearDepthStencilBuffer(); - matrix->translate(Vec3(0.0f, -0.5f, -0.5f)); - //glEnable(GL_BLEND); - //force set alpha - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // default - break; - - case 1: // tiles - //glDisable(GL_BLEND); - //glClear(GL_DEPTH_BUFFER_BIT); - renderContext.clearDepthStencilBuffer(); - //revert - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // default - break; - - case 2: // tiles again - //glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_COLOR, GL_ONE); - break; - } - - matrix->scale(Vec3(1.0f, -1.0f, 1.0f)); - matrix->rotate(8.0f, Vec3::UNIT_X); - //matrix->rotate(15.0f, Vec3::UNIT_X); - matrix->scale(Vec3(0.89f, 1.0f, 0.4f)); - matrix->translate(Vec3(-Width * 0.5f, -Height * 0.5f, 0.0f)); - - m_pMinecraft->m_pTextures->loadAndBindTexture(C_TERRAIN_NAME); - if (i == 0) - { - m_pMinecraft->m_pTextures->loadAndBindTexture("gui/black.png"); - pMaterial = &m_screenMaterials.ui_title_tile_shadow; - //currentShaderColor = Color(0, 0, 0, 100); - } - else - { - pMaterial = &m_screenMaterials.ui_title_tile; - currentShaderColor = Color::WHITE; - } - - for (int y = 0; y < Height; y++) - { - for (int x = 0; x < Width; x++) - { - if (gLogoLines[y][x] == ' ') - continue; - - Tile* pTile = TitleTile::getTileFromChar(gLogoLines[y][x]); - - MatrixStack::Ref matrix = MatrixStack::World.push(); - - TitleTile* pTTile = m_pTiles[y * Width + x]; - float z = Mth::Lerp(pTTile->lastHeight, pTTile->height, f); - float scale = 1.0f; - float bright = 1.0f; - float rotation = 180.0f; - - if (i == 0) - { - scale = z * 0.04f + 1.0f; - bright = 1.0f / scale; - z = 0.0f; - } - - matrix->translate(Vec3(x, y, z)); - matrix->scale(scale); - matrix->scale(Vec3(-1.0f, 1.0f, 1.0f)); - matrix->rotate(rotation, Vec3::UNIT_Z); - - // rotate 90 deg on the X axis to correct lighting - matrix->rotate(90.0f, Vec3::UNIT_X); - - m_tileRenderer.renderTile(FullTile(pTile, i == 0 ? 255 : 0), *pMaterial, bright, true); - } - } - } - - renderContext.setViewport(Minecraft::width, Minecraft::height, 0.0f, 0.7f); -} - void StartMenuScreen::render(float f) { #ifdef TITLE_CROP_MODE - fill(0, 0, m_width, m_height, 0xFF00FF00); + fill(0, 0, width, height, 0xFF00FF00); #else //renderBackground(); renderMenuBackground(f); @@ -815,13 +192,13 @@ void StartMenuScreen::render(float f) titleYPos = 4; } - if (m_pMinecraft->getOptions()->m_b2dTitleLogo.get()) - draw2dTitle(); - else - draw3dTitle(f); + LogoRenderer::singleton().render(f); - drawString(*m_pFont, field_170, field_188, 58 + titleYPos, Color(204, 204, 204)); - drawString(*m_pFont, field_154, field_16C, m_height - 10, Color::WHITE); + if (m_uiTheme != UI_CONSOLE) + { + drawString(*m_pFont, m_versionText, m_versionTextX, 58 + titleYPos, Color(204, 204, 204)); + drawString(*m_pFont, m_watermarkText, m_watermarkX, m_height - 10, Color::WHITE); + } // Draw the splash text, if we have enough room. #ifndef TITLE_CROP_MODE @@ -836,24 +213,13 @@ void StartMenuScreen::tick() { Screen::tick(); _updateLicense(); - - if (m_pTiles) - { - int Width = int(sizeof gLogoLine1 - 1); - int Height = int(sizeof gLogoLines / sizeof * gLogoLines); - for (int i = 0; i < Width * Height; i++) - m_pTiles[i]->tick(); - } } void StartMenuScreen::drawSplash() { MatrixStack::Ref mtx = MatrixStack::World.push(); - std::string splashText = getSplashString(); - int textWidth = m_pFont->width(splashText); - //int textHeight = m_pFont->height(splashText); - + int textWidth = m_pFont->width(m_chosenSplash); mtx->translate(Vec3(float(m_width) / 2.0f + 90.0f, 70.0f, 0.0f)); mtx->rotate(-20.0f, Vec3::UNIT_Z); @@ -862,18 +228,7 @@ void StartMenuScreen::drawSplash() scale = (scale * 100.0f) / (32.0f + textWidth); mtx->scale(scale); - drawCenteredString(*m_pFont, splashText, 0, -8, Color::YELLOW); -} - -std::string StartMenuScreen::getSplashString() -{ - if (m_chosenSplash == -1) - { - Random random; - m_chosenSplash = random.nextInt(int(sizeof(gSplashes) / sizeof(*gSplashes))); - } - - return std::string(gSplashes[m_chosenSplash]); + drawCenteredString(*m_pFont, m_chosenSplash, 0, -8, Color::YELLOW); } bool StartMenuScreen::handleBackEvent(bool b) @@ -883,96 +238,4 @@ bool StartMenuScreen::handleBackEvent(bool b) m_pMinecraft->quit(); } return true; -} - -Tile* TitleTile::_tiles[3]; -Random TitleTile::_random; -bool TitleTile::_firstTimeInit = true; - -TitleTile::TitleTile(StartMenuScreen* pScreen, int x, int y) -{ - height = float(10 + y) + 32.0f * pScreen->m_random.nextFloat() + float(y); - lastHeight = height; - dropVel = 0; -} - -void TitleTile::tick() -{ - lastHeight = height; - - if (height > 0.0f) - dropVel -= 0.6f; - - height += dropVel; - dropVel *= 0.9f; - - if (height < 0.0f) - { - height = 0.0f; - dropVel = 0.0f; - } -} - -Tile* TitleTile::getTileFromChar(char c) -{ - switch (c) - { - case '?': return _tiles[1]; - case '$': return _tiles[2]; - default: return _tiles[0]; - } -} - -// NOTE: Using the tile enum instead of Tile::tileName->id, may want to.. not? -static const int _tileBlockList[] = { - TILE_BOOKSHELF, - TILE_TOPSNOW, - TILE_GRASS, - TILE_INFO_UPDATEGAME1, - TILE_INFO_UPDATEGAME2, - TILE_LEAVES_CARRIED -}; -static const int _tileBlockListSize = sizeof _tileBlockList / sizeof(int); - -Tile* TitleTile::getRandomTile(Tile* except1, Tile* except2) -{ - TileID id; - for (;;) - { - id = _random.nextInt(256); - for (int i = 0; i < _tileBlockListSize; i++) { - if (_tileBlockList[i] == id) { - // N.B. Air does not have a tile - id = TILE_AIR; - break; - } - } - - if (!Tile::tiles[id]) - continue; - - // If found a tile, check if it can be rendered - Tile* pTile = Tile::tiles[id]; - eRenderShape renderShape = pTile->getRenderShape(); - if (!TileRenderer::canRender(renderShape) || renderShape != SHAPE_SOLID) - continue; - - if (pTile == except1 || pTile == except2) - continue; - - return pTile; - } -} - -void TitleTile::regenerate() -{ - if (_firstTimeInit) - { - _firstTimeInit = false; - _random.setSeed(getTimeMs()); - } - - _tiles[0] = getRandomTile(nullptr, nullptr); - _tiles[1] = getRandomTile(_tiles[0], nullptr); - _tiles[2] = getRandomTile(_tiles[0], _tiles[1]); -} +} \ No newline at end of file diff --git a/source/client/gui/screens/StartMenuScreen.hpp b/source/client/gui/screens/StartMenuScreen.hpp index ca9d6e7b0..f924d935f 100644 --- a/source/client/gui/screens/StartMenuScreen.hpp +++ b/source/client/gui/screens/StartMenuScreen.hpp @@ -13,50 +13,14 @@ #include "client/gui/components/Button.hpp" #include "client/renderer/TileRenderer.hpp" -class StartMenuScreen; - -class TitleTile -{ -public: - TitleTile(StartMenuScreen*, int x, int y); - void tick(); - - static Tile* getTileFromChar(char c); - static void regenerate(); - -protected: - friend class StartMenuScreen; - float height; - float lastHeight; - float dropVel; - -private: - static Tile* _tiles[3]; - static bool _firstTimeInit; - static Random _random; - static Tile* getRandomTile(Tile* except1, Tile* except2); -}; - class StartMenuScreen : public Screen { protected: - class Materials - { - public: - mce::MaterialPtr ui_title_tile; - mce::MaterialPtr ui_title_tile_shadow; - - Materials(); - }; - public: StartMenuScreen(); ~StartMenuScreen(); protected: - void _initTextures(); - void _initResources(); - void _build2dTitleMesh(); void _updateLicense(); public: @@ -67,37 +31,20 @@ class StartMenuScreen : public Screen void tick() override; void drawSplash(); - void draw2dTitle(); - void draw3dTitle(float f); - - std::string getSplashString(); bool handleBackEvent(bool b) override; protected: - friend class TitleTile; - Button m_startButton; Button m_joinButton; Button m_optionsButton; - Button m_testButton; Button m_buyButton; Button m_creditsButton; - std::string field_154; - int field_16C; - std::string field_170; - int field_188; - - int m_chosenSplash; - - std::string m_p2dTitleTexPath; - bool m_bUsingJavaLogo; - mce::Mesh m_2dTitleMesh; - IntRectangle m_2dTitleBounds; + std::string m_watermarkText; + int m_watermarkX; + std::string m_versionText; + int m_versionTextX; - TileRenderer m_tileRenderer; - Random m_random; - TitleTile** m_pTiles; - Materials m_screenMaterials; + std::string m_chosenSplash; }; diff --git a/source/client/gui/screens/StartMenuScreen_Console.cpp b/source/client/gui/screens/StartMenuScreen_Console.cpp new file mode 100644 index 000000000..f67c0e40d --- /dev/null +++ b/source/client/gui/screens/StartMenuScreen_Console.cpp @@ -0,0 +1,75 @@ +#include "StartMenuScreen_Console.hpp" +#include "client/locale/Language.hpp" +#include "client/renderer/LogoRenderer.hpp" +#include "client/resources/SplashManager.hpp" +#include "SelectWorldScreen_Console.hpp" + +StartMenuScreen_Console::StartMenuScreen_Console() : + m_btnPlayGame(Language::get("mainMenu.playGame")), + m_btnLeaderboards(Language::get("mainMenu.leaderboards")), + m_btnAchievements(Language::get("mainMenu.achievements")), + m_btnHelpAndOptions(Language::get("mainMenu.helpAndOptions")), + m_btnDownload(Language::get("mainMenu.download")), + m_btnExitGame(Language::get("mainMenu.exitGame")) +{ + m_bDeletePrevious = false; + m_btnLeaderboards.setEnabled(false); + m_btnAchievements.setEnabled(false); + m_btnDownload.setEnabled(false); + + m_uiTheme = UI_CONSOLE; + + m_splash = SplashManager::singleton().getSplash(); +} + +void StartMenuScreen_Console::init() +{ + Button* layoutButtons[] = { &m_btnPlayGame, &m_btnLeaderboards, &m_btnAchievements, &m_btnHelpAndOptions, &m_btnDownload, &m_btnExitGame }; + + int buttonsWidth = 450; + int buttonsHeight = 40; + int y = m_height / 3 + 10; + int ySpacing = 50; + + for (size_t i = 0; i < 6; ++i) + { + Button* button = layoutButtons[i]; + button->m_width = buttonsWidth; + button->m_height = buttonsHeight; + button->m_xPos = (m_width - button->m_width) / 2; + button->m_yPos = y + ySpacing * i; + _addElement(*button); + } +} + +void StartMenuScreen_Console::render(float f) +{ + renderBackground(); + LogoRenderer::singleton().render(f); + MatrixStack::Ref mtx = MatrixStack::World.push(); + + int textWidth = m_pFont->width(m_splash); + mtx->translate(Vec3(float(m_width) / 2.0f + 230.0f, 170.0f, 0.0f)); + mtx->rotate(-15.0f, Vec3::UNIT_Z); + float timeMS = float(getTimeMs() % 1000) / 1000.0f; + float scale = 1.8f - Mth::abs(0.1f * Mth::sin(2.0f * float(M_PI) * timeMS)); + scale = (scale * 100.0f) / (32.0f + textWidth) * 3; + mtx->scale(scale); + + drawCenteredString(*m_pFont, m_splash, 0, -8, Color::YELLOW); + mtx.release(); + Screen::render(f); +} + +void StartMenuScreen_Console::_buttonClicked(Button* btn) +{ + if (btn->getId() == m_btnPlayGame.getId()) + { + m_pMinecraft->locateMultiplayer(); + m_pMinecraft->setScreen(new SelectWorldScreen_Console(m_pMinecraft, this)); + } + else if (btn->getId() == m_btnHelpAndOptions.getId()) + m_pMinecraft->getScreenChooser()->pushOptionsScreen(this); + else if (btn->getId() == m_btnExitGame.getId()) + m_pMinecraft->quit(); +} \ No newline at end of file diff --git a/source/client/gui/screens/StartMenuScreen_Console.hpp b/source/client/gui/screens/StartMenuScreen_Console.hpp new file mode 100644 index 000000000..715122f1f --- /dev/null +++ b/source/client/gui/screens/StartMenuScreen_Console.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "../Screen.hpp" +#include "client/gui/components/Button.hpp" + +class StartMenuScreen_Console : public Screen +{ +public: + StartMenuScreen_Console(); + void init() override; + void render(float) override; + void _buttonClicked(Button*) override; + +private: + Button m_btnPlayGame; + Button m_btnLeaderboards; + Button m_btnAchievements; + Button m_btnHelpAndOptions; + Button m_btnDownload; + Button m_btnExitGame; + std::string m_splash; +}; diff --git a/source/client/gui/screens/inventory/ChestScreen.cpp b/source/client/gui/screens/inventory/ChestScreen.cpp index a7786a941..312618638 100644 --- a/source/client/gui/screens/inventory/ChestScreen.cpp +++ b/source/client/gui/screens/inventory/ChestScreen.cpp @@ -14,8 +14,8 @@ ChestScreen::ChestScreen(Container* inventory, Container* container) : Container void ChestScreen::_renderLabels() { - m_pFont->draw(m_pContainer->getName(), 8, 6, 0x404040); - m_pFont->draw(m_pInventory->getName(), 8, m_imageHeight - 96 + 2, 0x404040); + m_pFont->draw(m_pContainer->getName(), 8, 6, Color::TEXT_GREY); + m_pFont->draw(m_pInventory->getName(), 8, m_imageHeight - 96 + 2, Color::TEXT_GREY); } void ChestScreen::_renderBg(float partialTicks) @@ -26,3 +26,21 @@ void ChestScreen::_renderBg(float partialTicks) blit(m_leftPos, m_topPos, 0, 0, m_imageWidth, m_containerRows * 18 + 17, 0, 0); blit(m_leftPos, m_topPos + m_containerRows * 18 + 17, 0, 126, m_imageWidth, 96, 0, 0); } + +SlotDisplay ChestScreen::_createSlotDisplay(const Slot& slot) +{ + constexpr int slotSize = 18; + int rows = m_pContainer->getContainerSize() / 9; + int verticalOffset = (rows - 4) * slotSize; + switch (slot.m_group) + { + case Slot::CONTAINER: + return SlotDisplay(8 + (slot.m_slot % 9) * slotSize, 18 + verticalOffset + ((slot.m_slot / 9) - 1) * slotSize, slotSize); + case Slot::INVENTORY: + return SlotDisplay(8 + (slot.m_slot % 9) * slotSize, 103 + verticalOffset + ((slot.m_slot / 9) - 1) * slotSize, slotSize); + case Slot::HOTBAR: + return SlotDisplay(8 + (slot.m_slot % 9) * slotSize, 142, slotSize); + default: + return SlotDisplay(); + } +} diff --git a/source/client/gui/screens/inventory/ChestScreen.hpp b/source/client/gui/screens/inventory/ChestScreen.hpp index 5d72720b5..e5b4a92b8 100644 --- a/source/client/gui/screens/inventory/ChestScreen.hpp +++ b/source/client/gui/screens/inventory/ChestScreen.hpp @@ -10,6 +10,7 @@ class ChestScreen : public ContainerScreen protected: void _renderLabels() override; void _renderBg(float partialTicks) override; + SlotDisplay _createSlotDisplay(const Slot&); private: Container* m_pInventory; diff --git a/source/client/gui/screens/inventory/ClassicCraftingScreen_Console.cpp b/source/client/gui/screens/inventory/ClassicCraftingScreen_Console.cpp new file mode 100644 index 000000000..56619d6bb --- /dev/null +++ b/source/client/gui/screens/inventory/ClassicCraftingScreen_Console.cpp @@ -0,0 +1,53 @@ +#include "ClassicCraftingScreen_Console.hpp" +#include "world/inventory/CraftingMenu.hpp" +#include "renderer/ShaderConstants.hpp" + +ClassicCraftingScreen_Console::ClassicCraftingScreen_Console(Inventory* inventory, const TilePos& tilePos, Level* level) : + ContainerScreen(new CraftingMenu(inventory, tilePos, level)) +{ + m_uiTheme = UI_CONSOLE; +} + +void ClassicCraftingScreen_Console::init() +{ + ContainerScreen::init(); + m_imageWidth = 428; + m_imageHeight = 450; +} + +void ClassicCraftingScreen_Console::renderBackground() +{ +} + +void ClassicCraftingScreen_Console::_renderLabels() +{ + CraftingMenu* craftingMenu = (CraftingMenu*)m_pMenu; + + m_pFont->drawScalable(craftingMenu->m_pCraftSlots->getName(), m_imageWidth / 2 - m_pFont->width(craftingMenu->m_pCraftSlots->getName()), 17, Color::TEXT_GREY); + m_pFont->drawScalable(m_pMinecraft->m_pLocalPlayer->m_pInventory->getName(), 28, 213, Color::TEXT_GREY); +} + +void ClassicCraftingScreen_Console::_renderBg(float partialTick) +{ + currentShaderColor = Color::WHITE; + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::PANEL_SLICES, m_leftPos, m_topPos, m_imageWidth, m_imageHeight, 32); + blitSprite(*m_pMinecraft->m_pTextures, "gui/console/Graphics/Arrow_Off.png", m_leftPos + 206, m_topPos + 100, 72, 48); +} + +SlotDisplay ClassicCraftingScreen_Console::_createSlotDisplay(const Slot& slot) +{ + constexpr int slotSize = 42; + switch (slot.m_group) + { + case Slot::OUTPUT: + return SlotDisplay(308, 97, 64, true); + case Slot::INPUT: + return SlotDisplay(62 + (slot.m_slot % 3) * slotSize, 64 + (slot.m_slot / 3) * slotSize, slotSize, true); + case Slot::INVENTORY: + return SlotDisplay(28 + (slot.m_slot % 9) * slotSize, 240 + ((slot.m_slot / 9) - 1) * slotSize, slotSize, true); + case Slot::HOTBAR: + return SlotDisplay(28 + (slot.m_slot % 9) * slotSize, 379, slotSize, true); + default: + return SlotDisplay(); + } +} \ No newline at end of file diff --git a/source/client/gui/screens/inventory/ClassicCraftingScreen_Console.hpp b/source/client/gui/screens/inventory/ClassicCraftingScreen_Console.hpp new file mode 100644 index 000000000..d5e5b5091 --- /dev/null +++ b/source/client/gui/screens/inventory/ClassicCraftingScreen_Console.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "ContainerScreen.hpp" + +class ClassicCraftingScreen_Console : public ContainerScreen +{ +public: + ClassicCraftingScreen_Console(Inventory* inventory, const TilePos& tilePos, Level* level); + + void init() override; + void renderBackground() override; + +protected: + void _renderLabels() override; + void _renderBg(float partialTick) override; + SlotDisplay _createSlotDisplay(const Slot&); +}; diff --git a/source/client/gui/screens/inventory/ContainerScreen.cpp b/source/client/gui/screens/inventory/ContainerScreen.cpp index b25f09048..991e74357 100644 --- a/source/client/gui/screens/inventory/ContainerScreen.cpp +++ b/source/client/gui/screens/inventory/ContainerScreen.cpp @@ -3,6 +3,7 @@ #include "client/renderer/Lighting.hpp" #include "client/renderer/entity/ItemRenderer.hpp" #include "renderer/ShaderConstants.hpp" +#include ContainerScreen::ContainerScreen(ContainerMenu* menu) : m_pMenu(menu), @@ -15,23 +16,44 @@ ContainerScreen::ContainerScreen(ContainerMenu* menu) : m_bRenderPointer = true; } -void ContainerScreen::_renderSlot(Slot* slot) +void ContainerScreen::_renderSlot(Slot& slot) { - int x = slot->m_x; - int y = slot->m_y; - ItemStack& item = slot->getItem(); + const SlotDisplay& display = getSlotDisplay(slot); + + if (!display.bVisible) return; + + if (display.bIconHolder) + { + MatrixStack::Ref matrix = MatrixStack::World.push(); + float off = 3 * display.size / 50.0f; + matrix->translate(Vec3(-off, -off, 0.0f)); + blitSprite(*m_pMinecraft->m_pTextures, "gui/console/Graphics/IconHolder.png", display.x, display.y, display.size, display.size); + } + MatrixStack::Ref matrix = MatrixStack::World.push(); + matrix->translate(Vec3(display.x, display.y, 0)); + matrix->scale(display.size / 18.0f); + ItemStack& item = slot.getItem(); if (item.isEmpty()) { - int icon = slot->getNoItemIcon(); - if (icon >= 0) + const std::string& noItemSprite = display.noItemSprite; + + if (!noItemSprite.empty()) { - m_pMinecraft->m_pTextures->loadAndBindTexture("gui/items.png"); - blit(x, y, (icon % 16) * 16, (icon / 16) * 16, 16, 16, 0, 0); + blitSprite(*m_pMinecraft->m_pTextures, noItemSprite, 0, 0, 16, 16); return; } + + int icon = display.noItemIcon; + if (icon >= 0) + { + m_pMinecraft->m_pTextures->loadAndBindTexture(C_ITEMS_NAME); + blit(0, 0, (icon % 16) * 16, (icon / 16) * 16, 16, 16, 0, 0); + } + + return; } - ItemRenderer::singleton().renderGuiItem(m_pFont, m_pMinecraft->m_pTextures, item, x, y, true); - ItemRenderer::singleton().renderGuiItemOverlay(m_pFont, m_pMinecraft->m_pTextures, item, x, y); + ItemRenderer::singleton().renderGuiItem(m_pFont, m_pMinecraft->m_pTextures, item, 0, 0, true); + ItemRenderer::singleton().renderGuiItemOverlay(m_pFont, m_pMinecraft->m_pTextures, item, 0, 0); } Slot* ContainerScreen::_findSlot() @@ -44,21 +66,24 @@ Slot* ContainerScreen::_findSlot(int mouseX, int mouseY) for (std::vector::iterator it = m_pMenu->m_slots.begin(); it != m_pMenu->m_slots.end(); ++it) { Slot* slot = *it; - if (_isHovering(slot)) return slot; + if (_isHovering(*slot)) return slot; } return nullptr; } -bool ContainerScreen::_isHovering(Slot* slot) const +bool ContainerScreen::_isHovering(const Slot& slot) const { return _isHovering(slot, m_menuPointer.x, m_menuPointer.y); } -bool ContainerScreen::_isHovering(Slot* slot, int mouseX, int mouseY) const +bool ContainerScreen::_isHovering(const Slot& slot, int mouseX, int mouseY) const { + const SlotDisplay& display = getSlotDisplay(slot); + if (!display.bVisible) return false; mouseX -= m_leftPos; mouseY -= m_topPos; - return mouseX >= slot->m_x - 1 && mouseX < slot->m_x + 17 && mouseY >= slot->m_y - 1 && mouseY < slot->m_y + 17; + float off = 3 * display.size / 50.0f; + return mouseX >= display.x - off && mouseX < display.x + display.size - off && mouseY >= display.y - off && mouseY < display.y + display.size - off; } void ContainerScreen::_playInteractSound() @@ -72,12 +97,68 @@ void ContainerScreen::_tryPlayInteractSound() _playInteractSound(); } +void ContainerScreen::_selectSlot(Slot* slot) +{ + if (!slot) return; + const SlotDisplay& display = getSlotDisplay(*slot); + if (!display.bVisible) return; + int off = 3 * display.size / 50; + handlePointerLocation(m_leftPos + display.x - off + display.size / 2, m_topPos + display.y - off + display.size / 2); +} + +bool ContainerScreen::_selectSlotInDirection(AreaNavigation::Direction dir) +{ + AreaNavigation::ID found = SlotNavigation(this).navigateCyclic(dir, m_menuPointer.x, m_menuPointer.y); + + if (found >= 0) + { + _selectSlot(m_pMenu->getSlot(found)); + return true; + } + + return false; +} + +void ContainerScreen::_controllerDirectionChanged(GameController::StickID stickId, GameController::StickState stickState) +{ + Screen::_controllerDirectionChanged(stickId, stickState); + if (stickId == 1 && stickState == GameController::STICK_STATE_NONE) + { + _selectSlot(_findSlot()); + } +} + +void ContainerScreen::initMenuPointer() +{ + //@NOTE: Calling this as a fallback, if for some reason, there isn't a slot available + Screen::initMenuPointer(); + + if (!_useController()) return; + + for (std::vector::iterator it = m_pMenu->m_slots.begin(); it != m_pMenu->m_slots.end(); ++it) + { + Slot* slot = *it; + //@NOTE: Selects the first hotbar slot + if (slot->m_slot == 0 && m_pMinecraft->m_pLocalPlayer && slot->m_pContainer == m_pMinecraft->m_pLocalPlayer->m_pInventory) + { + _selectSlot(slot); + break; + } + } +} + void ContainerScreen::init() { Screen::init(); m_pMinecraft->m_pLocalPlayer->m_pContainerMenu = m_pMenu; m_leftPos = (m_width - m_imageWidth) / 2; m_topPos = (m_height - m_imageHeight) / 2; + + m_slotDisplays.clear(); + for (std::vector::iterator it = m_pMenu->m_slots.begin(); it != m_pMenu->m_slots.end(); ++it) + { + m_slotDisplays.push_back(_createSlotDisplay(*(*it))); + } } void ContainerScreen::render(float partialTicks) @@ -97,14 +178,16 @@ void ContainerScreen::render(float partialTicks) for (std::vector::iterator it = m_pMenu->m_slots.begin(); it != m_pMenu->m_slots.end(); ++it) { Slot* slot = *it; - _renderSlot(slot); - if (_isHovering(slot)) + _renderSlot(*slot); + if (_isHovering(*slot)) { + const SlotDisplay& display = getSlotDisplay(*slot); hoveredSlot = slot; - int slotX = slot->m_x; - int slotY = slot->m_y; //@NOTE: fillGradient is being used instead of fill, so the shader color won't be changed, I think the same happened on the original - fillGradient(slotX, slotY, slotX + 16, slotY + 16, 0x80FFFFFF, 0x80FFFFFF); + MatrixStack::Ref highlightMatrix = MatrixStack::World.push(); + highlightMatrix->translate(Vec3(display.x, display.y, 0)); + highlightMatrix->scale(display.size / 18.0f); + fillGradient(0, 0, 16, 16, 0x80FFFFFF, 0x80FFFFFF); } } @@ -112,8 +195,12 @@ void ContainerScreen::render(float partialTicks) if (!inv->getCarried().isEmpty()) { matrix->translate(Vec3(0.0f, 0.0f, 200.0f)); - ItemRenderer::singleton().renderGuiItem(m_pFont, m_pMinecraft->m_pTextures, inv->getCarried(), m_menuPointer.x - m_leftPos - 8, m_menuPointer.y - m_topPos - 8, true); - ItemRenderer::singleton().renderGuiItemOverlay(m_pFont, m_pMinecraft->m_pTextures, inv->getCarried(), m_menuPointer.x - m_leftPos - 8, m_menuPointer.y - m_topPos - 8); + MatrixStack::Ref carriedMatrix = MatrixStack::World.push(); + carriedMatrix->translate(Vec3(m_menuPointer.x - m_leftPos - 8, m_menuPointer.y - m_topPos - 8, 0.0f)); + if (m_uiTheme == UI_CONSOLE) + carriedMatrix->scale(3.0f); // 54 / 18.0f + ItemRenderer::singleton().renderGuiItem(m_pFont, m_pMinecraft->m_pTextures, inv->getCarried(), 0, 0, true); + ItemRenderer::singleton().renderGuiItemOverlay(m_pFont, m_pMinecraft->m_pTextures, inv->getCarried(), 0, 0); } Lighting::turnOff(); @@ -123,11 +210,20 @@ void ContainerScreen::render(float partialTicks) std::string name = Language::get(hoveredSlot->getItem().getDescriptionId() + ".name"); if (!name.empty()) { + int w = m_pFont->width(name); int tx = m_menuPointer.x - m_leftPos + 12; int ty = m_menuPointer.y - m_topPos - 12; - int w = m_pFont->width(name); - fillGradient(tx - 3, ty - 3, tx + w + 3, ty + 8 + 3, 0xC0000000, 0xC0000000); - m_pFont->drawShadow(name, tx, ty, -1); + if (m_uiTheme == UI_CONSOLE) + { + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::POINTER_TEXT_PANEL_SLICES, tx - 6, ty - 6, w * 2 + 12, 28, 8); + MatrixStack::Ref tooltipMatrix = MatrixStack::World.push(); + m_pFont->drawScalable(name, tx, ty, -1); + } + else + { + fillGradient(tx - 3, ty - 3, tx + w + 3, ty + 8 + 3, 0xC0000000, 0xC0000000); + m_pFont->drawShadow(name, tx, ty, -1); + } } } @@ -163,7 +259,7 @@ void ContainerScreen::handlePointerPressed(bool isPressed) } } -void ContainerScreen::slotClicked(const MenuPointer& pointer, MouseButtonType button) +void ContainerScreen::slotClicked(const MenuPointer& pointer, MouseButtonType button, bool quick) { if (button == MOUSE_BUTTON_LEFT || button == MOUSE_BUTTON_RIGHT) { @@ -173,7 +269,7 @@ void ContainerScreen::slotClicked(const MenuPointer& pointer, MouseButtonType bu if (slot) index = slot->m_index; if (outside) index = -999; if (index != -1) - slotClicked(slot, index, button, index != -999 && m_pMinecraft->m_pPlatform->shiftPressed()); + slotClicked(slot, index, button, index != -999 && quick); } } @@ -183,6 +279,11 @@ void ContainerScreen::slotClicked(Slot* slot, int index, MouseButtonType button, m_pMinecraft->m_pGameMode->handleInventoryMouseClick(m_pMenu->m_containerId, index, button, quick, m_pMinecraft->m_pLocalPlayer); } +void ContainerScreen::slotClicked(const MenuPointer& pointer, MouseButtonType button) +{ + slotClicked(pointer, button, m_pMinecraft->m_pPlatform->shiftPressed()); +} + void ContainerScreen::keyPressed(int keyCode) { if (!_useController() && m_pMinecraft->getOptions()->isKey(KM_INVENTORY, keyCode)) @@ -191,38 +292,33 @@ void ContainerScreen::keyPressed(int keyCode) } else if (m_pMinecraft->getOptions()->isKey(KM_CONTAINER_QUICKMOVE, keyCode) && _useController()) { - // bad hack - Slot* slot = _findSlot(); - bool outside = m_menuPointer.x < m_leftPos || m_menuPointer.y < m_topPos || m_menuPointer.x >= m_leftPos + m_imageWidth || m_menuPointer.y >= m_topPos + m_imageHeight; - int index = -1; - if (slot) index = slot->m_index; - if (outside) index = -999; - if (index != -1) - { - _tryPlayInteractSound(); - m_pMinecraft->m_pGameMode->handleInventoryMouseClick(m_pMenu->m_containerId, index, MOUSE_BUTTON_LEFT, true, m_pMinecraft->m_pLocalPlayer); - } + slotClicked(m_menuPointer, MOUSE_BUTTON_LEFT, true); } else if (m_pMinecraft->getOptions()->isKey(KM_CONTAINER_SPLIT, keyCode) && _useController()) { - // bad hack - Slot* slot = _findSlot(); - bool outside = m_menuPointer.x < m_leftPos || m_menuPointer.y < m_topPos || m_menuPointer.x >= m_leftPos + m_imageWidth || m_menuPointer.y >= m_topPos + m_imageHeight; - int index = -1; - if (slot) index = slot->m_index; - if (outside) index = -999; - if (index != -1) - { - _tryPlayInteractSound(); - m_pMinecraft->m_pGameMode->handleInventoryMouseClick(m_pMenu->m_containerId, index, MOUSE_BUTTON_RIGHT, false, m_pMinecraft->m_pLocalPlayer); - } + slotClicked(m_menuPointer, MOUSE_BUTTON_RIGHT, false); } else { + if (_useController() && + ((m_pMinecraft->getOptions()->isKey(KM_MENU_UP, keyCode) && _selectSlotInDirection(AreaNavigation::UP)) || + (m_pMinecraft->getOptions()->isKey(KM_MENU_DOWN, keyCode) && _selectSlotInDirection(AreaNavigation::DOWN)) || + (m_pMinecraft->getOptions()->isKey(KM_MENU_RIGHT, keyCode) && _selectSlotInDirection(AreaNavigation::RIGHT)) || + (m_pMinecraft->getOptions()->isKey(KM_MENU_LEFT, keyCode) && _selectSlotInDirection(AreaNavigation::LEFT)))) + { + _playSelectSound(); + return; + } + Screen::keyPressed(keyCode); } } +const SlotDisplay& ContainerScreen::getSlotDisplay(const Slot& slot) const +{ + return m_slotDisplays[slot.m_index]; +} + void ContainerScreen::onClose() { if (m_pMinecraft->m_pLocalPlayer) @@ -244,3 +340,33 @@ bool ContainerScreen::isPauseScreen() { return false; } + +ContainerScreen::SlotNavigation::SlotNavigation(ContainerScreen* screen) : m_pScreen(screen) +{ + m_area.w = screen->m_width; + m_area.h = screen->m_height; +} + +bool ContainerScreen::SlotNavigation::next(int& x, int& y, bool cycle) +{ + while (++m_index < int(m_pScreen->m_slotDisplays.size())) + { + const SlotDisplay& display = m_pScreen->m_slotDisplays[m_index]; + + if (!display.bVisible || !(cycle || isValid(m_index))) continue; + + int off = 3 * display.size / 50; + x = m_pScreen->m_leftPos + display.x - off + display.size / 2; + y = m_pScreen->m_topPos + display.y - off + display.size / 2; + + return true; + } + + return false; +} + +bool ContainerScreen::SlotNavigation::isValid(ID id) +{ + Slot* hovered = m_pScreen->_findSlot(); + return !hovered || hovered->m_index != id; +} diff --git a/source/client/gui/screens/inventory/ContainerScreen.hpp b/source/client/gui/screens/inventory/ContainerScreen.hpp index bd6b37739..274120153 100644 --- a/source/client/gui/screens/inventory/ContainerScreen.hpp +++ b/source/client/gui/screens/inventory/ContainerScreen.hpp @@ -1,26 +1,60 @@ #pragma once #include "client/gui/Screen.hpp" +#include "client/gui/IntRectangle.hpp" #include "world/inventory/ContainerMenu.hpp" #include "world/inventory/Slot.hpp" +struct SlotDisplay +{ + int x, y, size, noItemIcon; + std::string noItemSprite; + bool bVisible, bIconHolder; + + SlotDisplay() : + x(0), + y(0), + size(0), + noItemIcon(-1), + noItemSprite(""), + bVisible(false), + bIconHolder(false) + { + } + + SlotDisplay(int x, int y, int size = 18, bool iconHolder = false, int noItemIcon = -1, const std::string& noItemSprite = "") : + x(x), + y(y), + size(size), + noItemIcon(noItemIcon), + noItemSprite(noItemSprite), + bVisible(true), + bIconHolder(iconHolder) + { + } +}; + class ContainerScreen : public Screen { public: ContainerScreen(ContainerMenu* menu); private: - void _renderSlot(Slot* slot); + void _renderSlot(Slot& slot); Slot* _findSlot(); Slot* _findSlot(int mouseX, int mouseY); - bool _isHovering(Slot* slot) const; - bool _isHovering(Slot* slot, int mouseX, int mouseY) const; + bool _isHovering(const Slot& slot) const; + bool _isHovering(const Slot& slot, int mouseX, int mouseY) const; protected: virtual void _renderLabels() = 0; virtual void _renderBg(float partialTick) = 0; + virtual SlotDisplay _createSlotDisplay(const Slot&) = 0; virtual void _playInteractSound(); virtual void _tryPlayInteractSound(); + virtual void _selectSlot(Slot*); + virtual bool _selectSlotInDirection(AreaNavigation::Direction dir); + virtual void _controllerDirectionChanged(GameController::StickID stickId, GameController::StickState stickState) override; public: void init() override; @@ -33,12 +67,29 @@ class ContainerScreen : public Screen void handlePointerPressed(bool isPressed) override; void keyPressed(int key) override; + const SlotDisplay& getSlotDisplay(const Slot&) const; + public: + virtual void initMenuPointer() override; virtual void slotsChanged(Container* container); - virtual void slotClicked(const MenuPointer& pointer, MouseButtonType button); + virtual void slotClicked(const MenuPointer& pointer, MouseButtonType button, bool quick); virtual void slotClicked(Slot* slot, int index, MouseButtonType button, bool quick); + void slotClicked(const MenuPointer& pointer, MouseButtonType button); public: + class SlotNavigation : public AreaNavigation + { + public: + SlotNavigation(ContainerScreen*); + + bool next(int& x, int& y, bool cycle) override; + + bool isValid(ID) override; + + private: + ContainerScreen* m_pScreen; + }; + ContainerMenu* m_pMenu; protected: @@ -46,6 +97,7 @@ class ContainerScreen : public Screen int m_imageHeight; int m_leftPos; int m_topPos; + std::vector m_slotDisplays; private: int m_timeSlotDragged; diff --git a/source/client/gui/screens/inventory/CraftingScreen.cpp b/source/client/gui/screens/inventory/CraftingScreen.cpp index 1851a1ca4..3a66ffc37 100644 --- a/source/client/gui/screens/inventory/CraftingScreen.cpp +++ b/source/client/gui/screens/inventory/CraftingScreen.cpp @@ -5,13 +5,15 @@ CraftingScreen::CraftingScreen(Inventory* inventory, const TilePos& tilePos, Level* level) : ContainerScreen(new CraftingMenu(inventory, tilePos, level)) { + m_uiTheme = UI_JAVA; } void CraftingScreen::_renderLabels() { CraftingMenu* craftingMenu = (CraftingMenu*)m_pMenu; - m_pFont->draw(craftingMenu->m_pCraftSlots->getName(), 28, 6, 0x404040); - m_pFont->draw(m_pMinecraft->m_pLocalPlayer->m_pInventory->getName(), 8, m_imageHeight - 96 + 2, 0x404040); + + m_pFont->draw(craftingMenu->m_pCraftSlots->getName(), 28, 6, Color::TEXT_GREY); + m_pFont->draw(m_pMinecraft->m_pLocalPlayer->m_pInventory->getName(), 8, m_imageHeight - 96 + 2, Color::TEXT_GREY); } void CraftingScreen::_renderBg(float partialTick) @@ -21,3 +23,21 @@ void CraftingScreen::_renderBg(float partialTick) blit(m_leftPos, m_topPos, 0, 0, m_imageWidth, m_imageHeight, 0, 0); } + +SlotDisplay CraftingScreen::_createSlotDisplay(const Slot& slot) +{ + constexpr int slotSize = 18; + switch (slot.m_group) + { + case Slot::OUTPUT: + return SlotDisplay(124, 35); + case Slot::INPUT: + return SlotDisplay(30 + (slot.m_slot % 3) * slotSize, 17 + (slot.m_slot / 3) * slotSize); + case Slot::INVENTORY: + return SlotDisplay(8 + (slot.m_slot % 9) * slotSize, 84 + ((slot.m_slot / 9) - 1) * slotSize, slotSize); + case Slot::HOTBAR: + return SlotDisplay(8 + (slot.m_slot % 9) * slotSize, 142, slotSize); + default: + return SlotDisplay(); + } +} diff --git a/source/client/gui/screens/inventory/CraftingScreen.hpp b/source/client/gui/screens/inventory/CraftingScreen.hpp index e3bb13dbf..facd0e37f 100644 --- a/source/client/gui/screens/inventory/CraftingScreen.hpp +++ b/source/client/gui/screens/inventory/CraftingScreen.hpp @@ -11,4 +11,5 @@ class CraftingScreen : public ContainerScreen protected: void _renderLabels() override; void _renderBg(float partialTick) override; -}; \ No newline at end of file + SlotDisplay _createSlotDisplay(const Slot&); +}; diff --git a/source/client/gui/screens/inventory/InventoryScreen.cpp b/source/client/gui/screens/inventory/InventoryScreen.cpp index 2226b2321..1055a7b79 100644 --- a/source/client/gui/screens/inventory/InventoryScreen.cpp +++ b/source/client/gui/screens/inventory/InventoryScreen.cpp @@ -1,34 +1,91 @@ #include "InventoryScreen.hpp" #include "client/renderer/Lighting.hpp" #include "renderer/ShaderConstants.hpp" +#include "world/inventory/ArmorSlot.hpp" //#include "stats/Achievement.hpp" +std::string InventoryScreen::CONSOLE_ARMOR_SLOTS[] = { "gui/console/Graphics/Armour_Slot_Feet.png", "gui/console/Graphics/Armour_Slot_Legs.png", "gui/console/Graphics/Armour_Slot_Body.png", "gui/console/Graphics/Armour_Slot_Head.png" }; + InventoryScreen::InventoryScreen(Player* player) : ContainerScreen(player->m_pInventoryMenu) { //player->awardStat(Achievements::openInventory); } +void InventoryScreen::init() +{ + m_uiTheme = m_pMinecraft->getOptions()->getUiTheme() ; + if (m_uiTheme == UI_CONSOLE) + { + m_imageWidth = 432; + m_imageHeight = 436; + } + ContainerScreen::init(); + if (m_uiTheme == UI_CONSOLE) + m_topPos = Mth::Max(24, m_topPos - 48); +} + +void InventoryScreen::renderBackground() +{ + if (m_uiTheme != UI_CONSOLE) + ContainerScreen::renderBackground(); +} + void InventoryScreen::_renderLabels() { InventoryMenu* craftingMenu = (InventoryMenu*)m_pMenu; - m_pFont->draw(craftingMenu->m_pCraftSlots->getName(), 86, 16, 0x404040); + if (m_uiTheme == UI_CONSOLE) + { + if (m_pMinecraft->getOptions()->m_classicCrafting.get()) + m_pFont->drawScalable(craftingMenu->m_pCraftSlots->getName(), 220, 40, Color::TEXT_GREY); + m_pFont->drawScalable(m_pMinecraft->m_pLocalPlayer->m_pInventory->getName(), 27, 207, Color::TEXT_GREY); + } + else + m_pFont->draw(craftingMenu->m_pCraftSlots->getName(), 86, 16, Color::TEXT_GREY); } void InventoryScreen::_renderBg(float partialTick) { currentShaderColor = Color::WHITE; + int playerX; + int playerY; + float scale; + + if (m_uiTheme == UI_CONSOLE) + { + playerX = 243; + playerY = 185; + scale = 75.0f; + blitNineSlice(*m_pMinecraft->m_pTextures, ScreenRenderer::PANEL_SLICES, m_leftPos, m_topPos, m_imageWidth, m_imageHeight, 32); + int playerSlotX = m_leftPos + 180; + int playerSlotY = m_topPos + 27; + + if (m_pMinecraft->getOptions()->m_classicCrafting.get()) + { + playerX -= 100; + playerSlotX -= 100; + blitSprite(*m_pMinecraft->m_pTextures, "gui/console/Graphics/Arrow_Small_Off.png", m_leftPos + 309, m_topPos + 89, 32, 32); + } - m_pMinecraft->m_pTextures->loadAndBindTexture("gui/inventory.png"); + //For some reason, TU0 didn't had a texture for the player slot, but we do! + blitNineSlice(*m_pMinecraft->m_pTextures, "gui/container/entity_slot.png", playerSlotX, playerSlotY, 126, 168, 2); + currentShaderColor = Color::WHITE; + } + else + { + playerX = 51; + playerY = 75; + scale = 30.0f; + m_pMinecraft->m_pTextures->loadAndBindTexture("gui/inventory.png"); - blit(m_leftPos, m_topPos, 0, 0, m_imageWidth, m_imageHeight, 0, 0); + blit(m_leftPos, m_topPos, 0, 0, m_imageWidth, m_imageHeight, 0, 0); + } #if MCE_GFX_API_OGL && !defined(FEATURE_GFX_SHADERS) glEnable(GL_RESCALE_NORMAL); #endif MatrixStack::Ref matrix = MatrixStack::World.push(); - matrix->translate(Vec3(m_leftPos + 51.0f, m_topPos + 75.0f, 50.0f)); - const float scale = 30.0f; + matrix->translate(Vec3(m_leftPos + playerX, m_topPos + playerY, 50.0f)); matrix->scale(Vec3(-scale, scale, scale)); matrix->rotate(180.0f, Vec3(0.0f, 0.0f, 1.0f)); @@ -38,8 +95,8 @@ void InventoryScreen::_renderBg(float partialTick) float prevXRot = player->m_rot.x; float prevYRot = player->m_rot.y; - float dx = m_leftPos + 51.0f - m_menuPointer.x; - float dy = m_topPos + 75 - 50 - m_menuPointer.y; + float dx = m_leftPos + playerX - m_menuPointer.x; + float dy = m_topPos + playerY - 50 - m_menuPointer.y; matrix->rotate(135.0f, Vec3(0.0f, 1.0f, 0.0f)); Lighting::turnOn(); @@ -68,3 +125,51 @@ void InventoryScreen::_renderBg(float partialTick) glDisable(GL_RESCALE_NORMAL); #endif } + +SlotDisplay InventoryScreen::_createSlotDisplay(const Slot& slot) +{ + if (m_uiTheme == UI_CONSOLE) + { + constexpr int slotSize = 42; + switch (slot.m_group) + { + case Slot::OUTPUT: + return m_pMinecraft->getOptions()->m_classicCrafting.get() ? SlotDisplay(352, 83, 54, true) : SlotDisplay(); + case Slot::INPUT: + return m_pMinecraft->getOptions()->m_classicCrafting.get() ? SlotDisplay(221 + (slot.m_slot % 2) * slotSize, 67 + (slot.m_slot / 2) * slotSize, slotSize, true) : SlotDisplay(); + case Slot::ARMOR: + { + const ArmorSlot& armorSlot = (const ArmorSlot&)slot; + return SlotDisplay(m_pMinecraft->getOptions()->m_classicCrafting.get() ? 27 : 127, 29 + (Item::SLOT_HEAD - armorSlot.m_equipmentSlot) * slotSize, slotSize, true, -1, CONSOLE_ARMOR_SLOTS[armorSlot.m_equipmentSlot]); + } + case Slot::INVENTORY: + return SlotDisplay(28 + (slot.m_slot % 9) * slotSize, 233 + ((slot.m_slot / 9) - 1) * slotSize, slotSize, true); + case Slot::HOTBAR: + return SlotDisplay(28 + (slot.m_slot % 9) * slotSize, 372, slotSize, true); + default: + return SlotDisplay(); + } + } + else + { + constexpr int slotSize = 18; + switch (slot.m_group) + { + case Slot::OUTPUT: + return SlotDisplay(144, 36); + case Slot::INPUT: + return SlotDisplay(88 + (slot.m_slot % 2) * slotSize, 26 + (slot.m_slot / 2) * slotSize); + case Slot::ARMOR: + { + const ArmorSlot& armorSlot = (const ArmorSlot&)slot; + return SlotDisplay(8, 8 + (Item::SLOT_HEAD - armorSlot.m_equipmentSlot) * slotSize, slotSize, false, 16 * ((Item::SLOT_HEAD - armorSlot.m_equipmentSlot) + 1) - 1); + } + case Slot::INVENTORY: + return SlotDisplay(8 + (slot.m_slot % 9) * slotSize, 84 + ((slot.m_slot / 9) - 1) * slotSize, slotSize); + case Slot::HOTBAR: + return SlotDisplay(8 + (slot.m_slot % 9) * slotSize, 142, slotSize); + default: + return SlotDisplay(); + } + } +} diff --git a/source/client/gui/screens/inventory/InventoryScreen.hpp b/source/client/gui/screens/inventory/InventoryScreen.hpp index 628902df0..73ed2f5ac 100644 --- a/source/client/gui/screens/inventory/InventoryScreen.hpp +++ b/source/client/gui/screens/inventory/InventoryScreen.hpp @@ -8,7 +8,14 @@ class InventoryScreen : public ContainerScreen public: InventoryScreen(Player* player); + void init() override; + void renderBackground() override; + protected: - virtual void _renderLabels() override; - virtual void _renderBg(float partialTick) override; + void _renderLabels() override; + void _renderBg(float partialTick) override; + SlotDisplay _createSlotDisplay(const Slot&); + +public: + static std::string CONSOLE_ARMOR_SLOTS[]; }; \ No newline at end of file diff --git a/source/client/locale/Language.cpp b/source/client/locale/Language.cpp index bd1b7613f..4610893c4 100644 --- a/source/client/locale/Language.cpp +++ b/source/client/locale/Language.cpp @@ -28,7 +28,7 @@ bool Language::loadLanguageFile(const std::string& path) Document d; d.Parse(file.c_str()); - if (d.ObjectEmpty()) return false; + if (!d.IsObject()) return false; for (Value::ConstMemberIterator it = d.MemberBegin(); it != d.MemberEnd(); ++it) { diff --git a/source/client/network/ClientSideNetworkHandler.cpp b/source/client/network/ClientSideNetworkHandler.cpp index d74cf22ad..7b5fd9559 100644 --- a/source/client/network/ClientSideNetworkHandler.cpp +++ b/source/client/network/ClientSideNetworkHandler.cpp @@ -66,7 +66,7 @@ void ClientSideNetworkHandler::onConnect(const RakNet::RakNetGUID& rakGuid) // s m_serverGUID = rakGuid; clearChunksLoaded(); - LoginPacket* pLoginPkt = new LoginPacket(m_pMinecraft->m_pUser->field_0, NETWORK_PROTOCOL_VERSION); + LoginPacket* pLoginPkt = new LoginPacket(m_pMinecraft->m_pUser->m_name, NETWORK_PROTOCOL_VERSION); m_pRakNetInstance->send(pLoginPkt); } diff --git a/source/client/options/Options.cpp b/source/client/options/Options.cpp index 2a0ab0c1c..6cbc4bead 100644 --- a/source/client/options/Options.cpp +++ b/source/client/options/Options.cpp @@ -27,6 +27,8 @@ #include "client/gui/components/SliderButton.hpp" #include "client/gui/components/SwitchButton.hpp" #include "client/gui/components/SwitchValuesButton.hpp" +#include "client/gui/components/TickBox.hpp" +#include "client/renderer/LogoRenderer.hpp" void Options::_initDefaultValues() @@ -40,7 +42,6 @@ void Options::_initDefaultValues() field_240 = 1; field_1C = "Default"; field_19 = 1; - #ifdef ORIGINAL_CODE m_viewDistance.set(2); m_thirdPerson.set(0); @@ -53,6 +54,15 @@ void Options::_initDefaultValues() loadControls(); } +static UITheme GetDefaultUiTheme(Minecraft* mc) +{ +#if MC_PLATFORM_XBOX360 + return UI_CONSOLE; +#else + return mc->isTouchscreen() ? UI_POCKET : UI_JAVA; +#endif +} + Options::Options(Minecraft* mc, const std::string& folderPath) : m_pMinecraft(mc) , m_musicVolume("audio_music", "options.music", 1.0f) @@ -78,10 +88,13 @@ Options::Options(Minecraft* mc, const std::string& folderPath) : , m_splitControls("ctrl_split", "options.splitControls", false) , m_bUseController("ctrl_usecontroller", "options.useController", false) , m_dynamicHand("gfx_dynamichand", "options.dynamicHand", false) - , m_b2dTitleLogo("misc_oldtitle", "options.2dTitleLogo", false) , m_menuPanorama("misc_menupano", "options.menuPanorama", true) , m_guiScale("gfx_guiscale", "options.guiScale", 0, ValuesBuilder().add("options.guiScale.auto").add("options.guiScale.small").add("options.guiScale.normal").add(("options.guiScale.large"))) , m_lang("gfx_lang", "options.lang", "en_us") + , m_uiTheme("gfx_uitheme", "options.uiTheme", GetDefaultUiTheme(m_pMinecraft), ValuesBuilder().add("options.uiTheme.pocket").add("options.uiTheme.java").add("options.uiTheme.console")) + , m_logoType("gfx_logotype", "options.logoType", LOGO_AUTO, ValuesBuilder().add("options.logoType.auto").add("options.logoType.pocket").add("options.logoType.java").add("options.logoType.console").add("options.logoType.xbox360").add("options.logoType.logo3d")) + , m_hudSize("gfx_hudsize", "options.hudSize", HUD_SIZE_2) + , m_classicCrafting("gfx_classiccrafting", "options.classicCrafting", true) //, m_limitFramerate("gfx_fpslimit", "options.framerateLimit", 0, ValuesBuilder().add(performance.max").add("performance.balanced").add("performance.powersaver")) //, m_bMipmaps("gfx_mipmaps", "options.mipmaps") //, m_moreWorldOptions("misc_moreworldoptions", "options.moreWorldOptions", true) @@ -108,12 +121,15 @@ Options::Options(Minecraft* mc, const std::string& folderPath) : add(m_blockOutlines); add(m_dynamicHand); add(m_menuPanorama); - add(m_b2dTitleLogo); add(m_thirdPerson); add(m_hideGui); add(m_playerName); add(m_debugText); add(m_lang); + add(m_uiTheme); + add(m_logoType); + add(m_hudSize); + add(m_classicCrafting); _initDefaultValues(); if (folderPath.empty()) return; m_filePath = folderPath + "/options.txt"; @@ -130,6 +146,8 @@ void Options::_load() { std::vector strings = readPropertiesFromFile(m_filePath); + bool logo3d = false; + for (size_t i = 0; i < strings.size(); i += 2) { std::string key = strings[i], value = strings[i + 1]; @@ -137,9 +155,14 @@ void Options::_load() std::map::iterator opt = m_options.find(key); if (opt != m_options.end()) opt->second->load(value); + else if (key == "misc_oldtitle") + logo3d = !readBool(value); else if (key == "gfx_resourcepacks") readPackArray(value, m_resourcePacks); } + + if (logo3d) + m_logoType.set(LOGO_3D); } AsyncTask Options::_saveAsync() @@ -412,8 +435,11 @@ void Options::loadControls() KM(KM_MENU_DOWN, "key.menu.down", 0x28); // VK_DOWN KM(KM_MENU_LEFT, "key.menu.left", 0x25); // VK_LEFT KM(KM_MENU_RIGHT, "key.menu.right", 0x27); // VK_RIGHT + KM(KM_MENU_TAB_LEFT,"key.menu.tab.left", 0x25); // VK_LEFT + KM(KM_MENU_TAB_RIGHT, "key.menu.tab.right", 0x27);// VK_RIGHT KM(KM_MENU_OK, "key.menu.ok", 0x0D); // VK_RETURN KM(KM_MENU_CANCEL, "key.menu.cancel", 0x1B); // VK_ESCAPE, was 0x08 = VK_BACK + KM(KM_MENU_PAUSE, "key.menu.pause", 0x1B); // VK_ESCAPE KM(KM_SLOT_1, "key.slot.1", '1'); KM(KM_SLOT_2, "key.slot.2", '2'); KM(KM_SLOT_3, "key.slot.3", '3'); @@ -452,8 +478,11 @@ void Options::loadControls() KM(KM_MENU_DOWN, SDLVK_DOWN); KM(KM_MENU_LEFT, SDLVK_LEFT); KM(KM_MENU_RIGHT, SDLVK_RIGHT); + KM(KM_MENU_TAB_LEFT, SDLVK_LEFT); + KM(KM_MENU_TAB_RIGHT, SDLVK_RIGHT); KM(KM_MENU_OK, SDLVK_RETURN); KM(KM_MENU_CANCEL, SDLVK_ESCAPE); + KM(KM_MENU_PAUSE, SDLVK_ESCAPE); KM(KM_DROP, SDLVK_q); KM(KM_CHAT, SDLVK_t); KM(KM_FOG, SDLVK_f); @@ -511,10 +540,13 @@ void Options::loadControls() KM(KM_PLACE, AKEYCODE_C); KM(KM_MENU_UP, AKEYCODE_DPAD_UP); KM(KM_MENU_DOWN, AKEYCODE_DPAD_DOWN); - KM(KM_MENU_LEFT, AKEYCODE_BUTTON_L1); - KM(KM_MENU_RIGHT, AKEYCODE_BUTTON_R1); + KM(KM_MENU_LEFT, AKEYCODE_DPAD_LEFT); + KM(KM_MENU_RIGHT, AKEYCODE_DPAD_RIGHT); + KM(KM_MENU_TAB_LEFT, AKEYCODE_BUTTON_L1); + KM(KM_MENU_TAB_RIGHT, AKEYCODE_BUTTON_R1); KM(KM_MENU_OK, AKEYCODE_ENTER); - KM(KM_MENU_CANCEL, AKEYCODE_BUTTON_START); + KM(KM_MENU_CANCEL, AKEYCODE_BUTTON_B); + KM(KM_MENU_PAUSE, AKEYCODE_BUTTON_START); // custom KM(KM_SLOT_L, AKEYCODE_BUTTON_L1); KM(KM_SLOT_R, AKEYCODE_BUTTON_R1); @@ -553,8 +585,10 @@ void Options::loadControls() KM(KM_JUMP, SDL_CONTROLLER_BUTTON_A); KM(KM_MENU_UP, SDL_CONTROLLER_BUTTON_DPAD_UP); KM(KM_MENU_DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN); - KM(KM_MENU_LEFT, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); - KM(KM_MENU_RIGHT, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + KM(KM_MENU_LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT); + KM(KM_MENU_RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); + KM(KM_MENU_TAB_LEFT, SDL_CONTROLLER_BUTTON_LEFTSHOULDER); + KM(KM_MENU_TAB_RIGHT, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); KM(KM_MENU_OK, SDL_CONTROLLER_BUTTON_A); KM(KM_MENU_CANCEL, SDL_CONTROLLER_BUTTON_B); KM(KM_DROP, SDL_CONTROLLER_BUTTON_B); @@ -573,10 +607,13 @@ void Options::loadControls() KM(KM_JUMP, GameController::BUTTON_A); KM(KM_MENU_UP, GameController::BUTTON_DPAD_UP); KM(KM_MENU_DOWN, GameController::BUTTON_DPAD_DOWN); - KM(KM_MENU_LEFT, GameController::BUTTON_LEFTSHOULDER); - KM(KM_MENU_RIGHT, GameController::BUTTON_RIGHTSHOULDER); + KM(KM_MENU_LEFT, GameController::BUTTON_DPAD_LEFT); + KM(KM_MENU_RIGHT, GameController::BUTTON_DPAD_RIGHT); + KM(KM_MENU_TAB_LEFT, GameController::BUTTON_LEFTSHOULDER); + KM(KM_MENU_TAB_RIGHT, GameController::BUTTON_RIGHTSHOULDER); KM(KM_MENU_OK, GameController::BUTTON_A); KM(KM_MENU_CANCEL, GameController::BUTTON_B); + KM(KM_MENU_PAUSE, GameController::BUTTON_START); KM(KM_DROP, GameController::BUTTON_B); KM(KM_CHAT, GameController::BUTTON_BACK); KM(KM_INVENTORY, GameController::BUTTON_Y); @@ -593,6 +630,43 @@ void Options::loadControls() } } +void Options::reset() +{ + for (std::map::iterator it = m_options.begin(); it != m_options.end(); ++it) + { + it->second->reset(); + } +} + +UITheme Options::getUiTheme() const +{ + return UITheme(m_uiTheme.get()); +} + +LogoType Options::getLogoType() const +{ + if (m_logoType.get() == LOGO_AUTO) + { + switch (m_uiTheme.get()) + { + case UI_POCKET: + return LOGO_POCKET; + case UI_JAVA: + return LOGO_JAVA; + case UI_CONSOLE: +#if MC_PLATFORM_XBOX360 + return LOGO_XBOX360; +#else + return LOGO_CONSOLE; +#endif + default: + return (LogoType) m_logoType.get(); + } + } + else + return (LogoType) m_logoType.get(); +} + void Options::initResourceDependentOptions() { if (!GrassColor::isAvailable() && !FoliageColor::isAvailable()) @@ -602,9 +676,9 @@ void Options::initResourceDependentOptions() m_menuPanorama.set(false); } -const std::string& OptionEntry::getName() const +const std::string& OptionEntry::getDisplayName() const { - return Language::get(m_name); + return Language::get(getName()); } std::string OptionEntry::getDisplayValue() const @@ -616,12 +690,12 @@ std::string OptionEntry::getDisplayValue() const std::string OptionEntry::getMessage() const { - return Util::format(Language::get("options.value").c_str(), getName().c_str(), getDisplayValue().c_str()); + return Util::format(Language::get("options.value").c_str(), getDisplayName().c_str(), getDisplayValue().c_str()); } -void OptionEntry::addGuiElement(std::vector& elements, const std::string& text) +void OptionEntry::addGuiElement(std::vector& elements, UITheme uiTheme) { - elements.push_back(new SmallButton(0, 0, 0, this, text)); + elements.push_back(new SmallButton(0, 0, this, getMessage())); } void AOOption::apply() @@ -646,9 +720,9 @@ std::string FloatOption::getDisplayValue() const return get() == 0.0f ? Language::get("options.off") : Options::saveInt(get() * 100) + "%"; } -void FloatOption::addGuiElement(std::vector& elements, const std::string& text) +void FloatOption::addGuiElement(std::vector& elements, UITheme uiTheme) { - elements.push_back(new SliderButton(0, 0, 0, this, getMessage(), get())); + elements.push_back(new SliderButton(0, 0, 200, uiTheme == UI_CONSOLE ? 32 : 20, this, getMessage(), toFloat())); } void BoolOption::load(const std::string& value) @@ -666,14 +740,25 @@ std::string BoolOption::getDisplayValue() const return Language::get(get() ? "options.on" : "options.off"); } -void BoolOption::addGuiElement(std::vector& elements, const std::string& text) +void BoolOption::addGuiElement(std::vector& elements, UITheme uiTheme) { - elements.push_back(new SwitchButton(0, 0, 0, this, text)); + if (uiTheme == UI_CONSOLE) + elements.push_back(new TickBox(0, 0, this, getDisplayName())); + else + elements.push_back(new SwitchButton(0, 0, this, getDisplayName())); } -void ValuesOption::addGuiElement(std::vector& elements, const std::string& text) +std::string ValuesOption::getDisplayValue() const { - elements.push_back(new SwitchValuesButton(0, 0, 0, this, text)); + return Language::get(getValue()); +} + +void MinMaxOption::addGuiElement(std::vector& elements, UITheme uiTheme) +{ + if (uiTheme == UI_CONSOLE) + elements.push_back(new SliderButton(0, 0, 200, 32, this, getMessage(), toFloat())); + else + elements.push_back(new SwitchValuesButton(0, 0, this, getDisplayName())); } void GraphicsOption::apply() @@ -696,3 +781,25 @@ void IntOption::load(const std::string& value) { set(Options::readInt(value)); } + +void LogoTypeOption::apply() +{ + if (m_pMinecraft->getOptions()) + { + LogoRenderer::singleton().init(m_pMinecraft); + LogoRenderer::singleton().build(); + } +} + +std::string HUDSizeOption::getDisplayValue() const +{ + return Options::saveInt(get() - 1); +} + +void UIThemeOption::apply() +{ + if (m_pMinecraft->getOptions() && m_pMinecraft->getOptions()->m_logoType.get() == LOGO_AUTO) + { + m_pMinecraft->getOptions()->m_logoType.apply(); + } +} diff --git a/source/client/options/Options.hpp b/source/client/options/Options.hpp index fcf50d448..99bacdf1a 100644 --- a/source/client/options/Options.hpp +++ b/source/client/options/Options.hpp @@ -36,8 +36,11 @@ enum eKeyMappingIndex KM_MENU_DOWN, KM_MENU_LEFT, KM_MENU_RIGHT, + KM_MENU_TAB_LEFT, + KM_MENU_TAB_RIGHT, KM_MENU_OK, KM_MENU_CANCEL, KM_BACK = KM_MENU_CANCEL, + KM_MENU_PAUSE, KM_SLOT_1, KM_SLOT_2, KM_SLOT_3, @@ -71,6 +74,32 @@ struct KeyMapping KeyMapping(const char* keyName, int keyCode) : key(keyName), value(keyCode) {} }; +enum UITheme +{ + UI_POCKET, + UI_JAVA, + UI_CONSOLE +}; + +enum LogoType +{ + LOGO_AUTO, + LOGO_POCKET, + LOGO_JAVA, + LOGO_CONSOLE, + LOGO_XBOX360, + LOGO_3D +}; + +//@NOTE: Used only for the UI_CONSOLE UITheme for now +enum HUDSize +{ + HUD_SIZE_1 = 2, + HUD_SIZE_2 = 3, + HUD_SIZE_3 = 4 +}; + +class Minecraft; class GuiElement; class Minecraft; @@ -80,14 +109,19 @@ class OptionEntry OptionEntry(const std::string& key, const std::string& name) : m_key(key), m_name(name), m_pMinecraft(nullptr) {} virtual const std::string& getKey() const { return m_key; } - virtual const std::string& getName() const; + virtual const std::string& getName() const { return m_name; } + virtual const std::string& getDisplayName() const; virtual std::string getDisplayValue() const; virtual void save(std::stringstream&) const = 0; virtual std::string getMessage() const; virtual void load(const std::string& value) = 0; - virtual void toggle() = 0; + virtual void toggle() {} + virtual void addUnit(int mul) {} + virtual void fromFloat(float) {} + virtual float toFloat() const { return 0.0f; } + virtual void reset() {}; - virtual void addGuiElement(std::vector&, const std::string&); + virtual void addGuiElement(std::vector&, UITheme uiTheme); private: std::string m_key; @@ -107,7 +141,6 @@ class OptionInstance : public OptionEntry public: OptionInstance(const std::string& key, const std::string& name, V initial) : OptionEntry(key, name), m_value(initial), m_defaultValue(initial) {} - virtual void toggle() {} virtual void apply() {} void set(const V& v) @@ -118,8 +151,10 @@ class OptionInstance : public OptionEntry apply(); } - void reset() { set(m_defaultValue); } + void setDefault(const V& v) { m_defaultValue = v; } + void reset() override { set(m_defaultValue); } const V& get() const { return m_value; } + const V& getDefault() const { return m_defaultValue; } }; class BoolOption : public OptionInstance @@ -131,24 +166,34 @@ class BoolOption : public OptionInstance void save(std::stringstream& ss) const override; void toggle() override { set(get() ^ 1); } std::string getDisplayValue() const override; - void addGuiElement(std::vector&, const std::string&) override; + void addGuiElement(std::vector&, UITheme uiTheme) override; }; class FloatOption : public OptionInstance { public: - FloatOption(const std::string& key, const std::string& name, float initial = 0.0f) : OptionInstance(key, name, initial) {} + FloatOption(const std::string& key, const std::string& name, float initial = 0.0f, float unit = 0.01f) : + OptionInstance(key, name, initial), + m_unit(unit) + { + } void load(const std::string& value) override; void save(std::stringstream& ss) const override { ss << get(); } + void addUnit(int mul) override { set(Mth::clamp(get() + mul * m_unit, 0.0f, 1.0f)); } + void fromFloat(float v) override { set(v); } + float toFloat() const override { return get(); } std::string getDisplayValue() const override; - void addGuiElement(std::vector&, const std::string&) override; + void addGuiElement(std::vector&, UITheme uiTheme) override; + +public: + float m_unit; }; class SensitivityOption : public FloatOption { public: - SensitivityOption(const std::string& key, const std::string& name, float initial = 0.0f) : FloatOption(key, name, initial) {} + SensitivityOption(const std::string& key, const std::string& name, float initial = 0.0f) : FloatOption(key, name, initial, 0.005f) {} std::string getDisplayValue() const override; }; @@ -208,16 +253,33 @@ class ValuesBuilder std::vector m_values; }; -class ValuesOption : public IntOption +class MinMaxOption : public IntOption { public: - ValuesOption(const std::string& key, const std::string& name, int initial, const ValuesBuilder& values) : IntOption(key, name, initial), m_values(values.m_values) + MinMaxOption(const std::string& key, const std::string& name, int initial, int min, int max) : IntOption(key, name, initial), m_min(min), m_max(max) { } - void toggle() override { set((get() + 1) % m_values.size()); } - std::string getDisplayValue() const override { return m_values[Mth::Min(get(), int(m_values.size()))]; } - void addGuiElement(std::vector&, const std::string&) override; + void toggle() override { set(Mth::Max(m_min, (get() + 1) % m_max)); } + void addUnit(int mul) override { set(Mth::clamp(get() + mul, m_min, m_max - 1)); } + void fromFloat(float v) override { set(Mth::round(m_min + (m_max - 1 - m_min) * v)); } + float toFloat() const override { return (get() - m_min) / float(m_max - 1 - m_min); } + void addGuiElement(std::vector&, UITheme uiTheme) override; + +public: + int m_min, m_max; +}; + + +class ValuesOption : public MinMaxOption +{ +public: + ValuesOption(const std::string& key, const std::string& name, int initial, const ValuesBuilder& values) : MinMaxOption(key, name, initial, 0, values.m_values.size()), m_values(values.m_values) + { + } + + const std::string& getValue() const { return m_values[Mth::clamp(get(), m_min, m_max - 1)]; } + std::string getDisplayValue() const override; public: std::vector m_values; @@ -233,6 +295,36 @@ class GuiScaleOption : public ValuesOption void apply() override; }; +class LogoTypeOption : public ValuesOption +{ +public: + LogoTypeOption(const std::string& key, const std::string& name, int initial, const ValuesBuilder& values) : ValuesOption(key, name, initial, values) + { + } + + void apply() override; +}; + +class UIThemeOption : public ValuesOption +{ +public: + UIThemeOption(const std::string& key, const std::string& name, int initial, const ValuesBuilder& values) : ValuesOption(key, name, initial, values) + { + } + + void apply() override; +}; + +class HUDSizeOption : public MinMaxOption +{ +public: + HUDSizeOption(const std::string& key, const std::string& name, int initial) : MinMaxOption(key, name, initial, HUD_SIZE_1, HUD_SIZE_3 + 1) + { + } + + std::string getDisplayValue() const override; +}; + class Options { public: @@ -277,8 +369,12 @@ class Options bool isKey(eKeyMappingIndex idx, int keyCode) const { return getKey(idx) == keyCode; } void loadControls(); + void reset(); void initResourceDependentOptions(); + UITheme getUiTheme() const; + LogoType getLogoType() const; + private: Minecraft* m_pMinecraft; std::map m_options; @@ -291,6 +387,7 @@ class Options friend class FloatOption; friend class SensitivityOption; friend class IntOption; + friend class HUDSizeOption; FloatOption m_musicVolume; FloatOption m_masterVolume; @@ -324,10 +421,67 @@ class Options BoolOption m_splitControls; BoolOption m_bUseController; BoolOption m_dynamicHand; - BoolOption m_b2dTitleLogo; BoolOption m_menuPanorama; GuiScaleOption m_guiScale; StringOption m_lang; + UIThemeOption m_uiTheme; + LogoTypeOption m_logoType; + HUDSizeOption m_hudSize; + BoolOption m_classicCrafting; ResourcePackStack m_resourcePacks; }; + +#define OPTIONS_LIST_GAMEPLAY_GAME \ + HEADER("Game"); \ + OPTION(m_difficulty); \ + OPTION(m_thirdPerson); \ + OPTION(m_serverVisibleDefault); \ + +#define OPTIONS_LIST_GAMEPLAY_AUDIO \ + HEADER("Audio"); \ + OPTION(m_musicVolume); \ + OPTION(m_masterVolume); \ + +#define OPTIONS_LIST_CONTROLS_CONTROLS \ + HEADER("Controls"); \ + OPTION(m_sensitivity); \ + OPTION(m_invertMouse); \ + OPTION(m_splitControls); idxSplit = currentIndex; \ + /*OPTION(m_swapJumpSneak);*/ \ + /*OPTION(m_buttonSize);*/ \ + OPTION(m_autoJump); \ + OPTION(m_bUseController); idxController = currentIndex; \ + +#define OPTIONS_LIST_CONTROLS_FEEDBACK \ + /*HEADER("Feedback");*/ \ + /*OPTION(m_vibrate);*/ \ + +#define OPTIONS_LIST_CONTROLS_EXPERIMENTAL \ + HEADER("Experimental"); \ + OPTION(m_flightHax); \ + +#define OPTIONS_LIST_VIDEO_GRAPHICS \ + HEADER("Graphics"); \ + /*OPTION(m_brightness);*/ \ + OPTION(m_viewDistance); \ + /*OPTION(m_antiAliasing);*/ \ + /*OPTION(m_guiScale);*/ \ + /*OPTION(m_fov);*/ \ + OPTION(m_ambientOcclusion); \ + OPTION(m_fancyGraphics); \ + OPTION(m_viewBobbing); \ + OPTION(m_anaglyphs); \ + OPTION(m_blockOutlines); \ + OPTION(m_fancyGrass); \ + OPTION(m_biomeColors); \ + OPTION(m_dynamicHand); \ + OPTION(m_uiTheme); \ + OPTION(m_logoType); \ + +#define OPTIONS_LIST_VIDEO_EXPERIMENTAL \ + HEADER("Experimental"); \ + OPTION(m_hideGui); \ + OPTION(m_debugText); \ + OPTION(m_menuPanorama); idxPano = currentIndex; \ + diff --git a/source/client/player/LocalPlayer.cpp b/source/client/player/LocalPlayer.cpp index 7c6444928..ec62ed15b 100644 --- a/source/client/player/LocalPlayer.cpp +++ b/source/client/player/LocalPlayer.cpp @@ -46,7 +46,7 @@ LocalPlayer::LocalPlayer(Minecraft* pMinecraft, Level* pLevel, User* pUser, Game m_pMoveInput = nullptr; m_pMinecraft = pMinecraft; - m_name = pUser->field_0; + m_name = pUser->m_name; m_dimension = dimensionId; _init(); @@ -131,8 +131,7 @@ void LocalPlayer::swing() void LocalPlayer::startCrafting(const TilePos& pos) { - // PE 0.3.2 doesn't let you craft in creative mode - m_pMinecraft->setScreen(new CraftingScreen(m_pInventory, pos, m_pLevel)); + m_pMinecraft->getScreenChooser()->pushCraftingScreen(this, pos); } /*void LocalPlayer::openFurnace(FurnaceTileEntity* furnace) @@ -144,7 +143,7 @@ void LocalPlayer::startCrafting(const TilePos& pos) void LocalPlayer::openContainer(Container* container) { // PE 0.3.2 doesn't let you open chests in creative mode - m_pMinecraft->setScreen(new ChestScreen(m_pInventory, container)); + m_pMinecraft->getScreenChooser()->pushChestScreen(this, container); } void LocalPlayer::closeContainer() diff --git a/source/client/player/input/ControllerMoveInput.cpp b/source/client/player/input/ControllerMoveInput.cpp index c44f65e38..cf813abe8 100644 --- a/source/client/player/input/ControllerMoveInput.cpp +++ b/source/client/player/input/ControllerMoveInput.cpp @@ -39,6 +39,8 @@ void ControllerMoveInput::tick(Player* player) m_keys[INPUT_LEFT] = m_keys[INPUT_FORWARD] || m_keys[INPUT_BACKWARD]; if (m_keys[INPUT_LEFT]) m_vertInput = 0.0f; + + IMoveInput::tick(player); } void ControllerMoveInput::setKey(int eventKey, bool eventKeyState) diff --git a/source/client/player/input/IMoveInput.cpp b/source/client/player/input/IMoveInput.cpp index 0b47833c1..7b646287f 100644 --- a/source/client/player/input/IMoveInput.cpp +++ b/source/client/player/input/IMoveInput.cpp @@ -40,4 +40,9 @@ void IMoveInput::setScreenSize(int width, int height) void IMoveInput::tick(Player* pPlayer) { + if (m_bSneaking) + { + m_horzInput = m_horzInput * 0.3f; + m_vertInput = m_vertInput * 0.3f; + } } diff --git a/source/client/player/input/KeyboardInput.cpp b/source/client/player/input/KeyboardInput.cpp index 21c942c95..739a8106f 100644 --- a/source/client/player/input/KeyboardInput.cpp +++ b/source/client/player/input/KeyboardInput.cpp @@ -60,9 +60,5 @@ void KeyboardInput::tick(Player* pPlayer) m_bFlyUp = m_bJumping; m_bSneaking = m_keys[INPUT_SNEAK]; - if (m_keys[INPUT_SNEAK] && (!pPlayer->isCreative() || !pPlayer->m_bFlying)) - { - m_horzInput = m_horzInput * 0.3f; - m_vertInput = m_vertInput * 0.3f; - } + IMoveInput::tick(pPlayer); } diff --git a/source/client/player/input/TouchscreenInput_TestFps.cpp b/source/client/player/input/TouchscreenInput_TestFps.cpp index a9897a0d5..af67bd4f8 100644 --- a/source/client/player/input/TouchscreenInput_TestFps.cpp +++ b/source/client/player/input/TouchscreenInput_TestFps.cpp @@ -266,6 +266,8 @@ void TouchscreenInput_TestFps::tick(Player* pPlayer) m_horzInput -= 1.0f; break; } + + IMoveInput::tick(pPlayer); } m_bForwardBeingHeld = bForwardPressed; @@ -327,8 +329,8 @@ static void RenderTouchButton(Tesselator* t, PolygonArea* pArea, int srcX, int s for (int i = 0; i < pArea->m_count; i++) { t->vertexUV( - Gui::InvGuiScale * pArea->m_xPos[i], - Gui::InvGuiScale * pArea->m_yPos[i], + Gui::GuiScale * pArea->m_xPos[i], + Gui::GuiScale * pArea->m_yPos[i], 0.0f, tc[(2 * i) % 8], tc[(2 * i + 1) % 8] diff --git a/source/client/player/input/User.hpp b/source/client/player/input/User.hpp index 3df3abf13..0e56db1b9 100644 --- a/source/client/player/input/User.hpp +++ b/source/client/player/input/User.hpp @@ -15,11 +15,11 @@ class User public: User(const std::string& a, const std::string& b) { - field_0 = a; + m_name = a; field_18 = b; } public: - std::string field_0; + std::string m_name; std::string field_18; }; diff --git a/source/client/renderer/Font.cpp b/source/client/renderer/Font.cpp index 93a33266a..6ec81196f 100644 --- a/source/client/renderer/Font.cpp +++ b/source/client/renderer/Font.cpp @@ -11,6 +11,7 @@ #include "client/renderer/renderer/Tesselator.hpp" #include "renderer/ShaderConstants.hpp" #include "renderer/MatrixStack.hpp" +#include constexpr char COLOR_START_CHAR = '\xa7'; @@ -96,6 +97,72 @@ void Font::drawShadow(const std::string& str, int x, int y, const Color& color) draw(str, x, y, color, false); } +void Font::drawScalable(const std::string& str, int x, int y, const Color& color, float scale, bool shadow) +{ + MatrixStack::Ref matrix = MatrixStack::World.push(); + matrix->translate(Vec3(x, y, 0)); + matrix->scale(scale); + draw(str, 0, 0, color, shadow); +} + +void Font::drawScalableShadow(const std::string& str, int x, int y, const Color& color, float scale) +{ + drawScalable(str, x + 1, y + 1, color, scale, true); + drawScalable(str, x, y, color, scale); +} + +void Font::drawString(const std::string& str, int x, int y, const Color& color, bool hasShadow, bool isConsole) +{ + if (hasShadow) + { + if (isConsole) + drawScalableShadow(str, x, y, color); + else + drawShadow(str, x, y, color); + } + else + { + if (isConsole) + drawScalable(str, x, y, color); + else + draw(str, x, y, color); + } +} + +void Font::drawOutlinedString(const std::string& str, int x, int y, const Color& color, const Color& outlineColor, float scale, int thickness) +{ + int translations[] = {0, thickness, -thickness}; + for (int xi = 0; xi < 3; ++xi) + { + int t = translations[xi]; + for (int yi = 0; yi < 3; ++yi) + { + int t1 = translations[yi]; + if (t != 0 || t1 != 0) { + MatrixStack::Ref matrix = MatrixStack::World.push(); + matrix->translate(Vec3(t, t1, 0)); + drawScalable(str, x, y, outlineColor, scale, false); + } + } + } + + drawScalable(str, x, y, color, scale, false); +} + +void Font::drawWordWrap(const std::string& str, int x, int y, const Color& color, int width, int lineHeight, bool shadow, bool isConsole) +{ + drawWordWrap(split(str, width), x, y, color, lineHeight, shadow, isConsole); +} + +void Font::drawWordWrap(const std::vector& lines, int x, int y, const Color& color, int lineHeight, bool shadow, bool isConsole) +{ + for (std::vector::const_iterator it = lines.begin(); it != lines.end(); ++it) + { + drawString(*it, x, y, color, shadow, isConsole); + y += lineHeight; + } +} + void Font::draw(const std::string& str, int x, int y, const Color& color, bool bShadow) { drawSlow(str, x, y, color, bShadow); @@ -159,24 +226,16 @@ void Font::onGraphicsReset() init(m_pOptions); } -int Font::height(const std::string& str) +int Font::height(const std::string& str, int maxWidth) { - if (str.empty()) return 0; - - int res = 0; // note: starting at 0 looks wrong - - for (size_t i = 0; i < str.size(); i++) - if (str[i] == '\n') - res += 12; - - return res; + return split(str, maxWidth).size() * 8; } int Font::width(const std::string& str) { int maxLineWidth = 0, currentLineWidth = 0; - for (size_t i = 0; i < str.size(); i++) + for (int i = 0; i < int(str.size()); i++) { char chr = str[i]; @@ -201,3 +260,80 @@ int Font::width(const std::string& str) return maxLineWidth; } + +std::vector Font::split(const std::string& text, int maxWidth) +{ + std::vector lines; + + std::vector paragraphs; + size_t start = 0; + size_t newlinePos = text.find('\n'); + while (newlinePos != std::string::npos) + { + paragraphs.push_back(text.substr(start, newlinePos - start)); + start = newlinePos + 1; + newlinePos = text.find('\n', start); + } + paragraphs.push_back(text.substr(start)); + + for (std::vector::iterator it = paragraphs.begin(); it != paragraphs.end(); ++it) + { + std::string& paragraph = *it; + + if (paragraph.empty()) + { + lines.push_back(""); + continue; + } + + std::string currentLine; + std::istringstream iss(paragraph); + std::string word; + + while (iss >> word) { + std::string testLine = currentLine.empty() ? word : currentLine + " " + word; + + if (width(testLine) <= maxWidth) + currentLine = testLine; + else + { + if (!currentLine.empty()) + { + lines.push_back(currentLine); + currentLine.clear(); + } + + while (!word.empty() && width(word) > maxWidth) + { + size_t breakPos = 0; + for (size_t j = 1; j <= word.length(); ++j) + { + if (width(word.substr(0, j)) <= maxWidth) + breakPos = j; + else + break; + } + + if (breakPos == 0) breakPos = 1; + + std::string chunk = word.substr(0, breakPos); + lines.push_back(chunk); + word = word.substr(breakPos); + } + + currentLine = word; + } + } + + if (!currentLine.empty()) + lines.push_back(currentLine); + } + + while (!lines.empty() && lines.back().empty()) + lines.pop_back(); + + if (lines.empty()) + lines.push_back(""); + + return lines; +} \ No newline at end of file diff --git a/source/client/renderer/Font.hpp b/source/client/renderer/Font.hpp index 7fb4c3291..92020c250 100644 --- a/source/client/renderer/Font.hpp +++ b/source/client/renderer/Font.hpp @@ -32,16 +32,18 @@ class Font void draw(const std::string&, int x, int y, const Color& color, bool bShadow); void drawSlow(const std::string&, int x, int y, const Color& color, bool bShadow); void drawShadow(const std::string&, int x, int y, const Color& color); - - //int Font::drawWordWrap(Font *this, const StlString *a2, int a3, int a4, int a5, int a6). - // +- I probably won't actually implement this because - // +- 1. It does not seem to have any cross references - // +- 2. It appears to even be broken + void drawScalable(const std::string&, int x, int y, const Color& color, float scale = 2.0f, bool shadow = false); + void drawScalableShadow(const std::string&, int x, int y, const Color& color, float scale = 2.0f); + void drawString(const std::string&, int x, int y, const Color& color, bool hasShadow, bool isConsole = false); + void drawOutlinedString(const std::string&, int x, int y, const Color& color, const Color& outlineColor, float scale = 4.0f, int thickness = 2); + void drawWordWrap(const std::string&, int x, int y, const Color& color, int width, int lineHeight = 8, bool shadow = false, bool isConsole = false); + void drawWordWrap(const std::vector&, int x, int y, const Color& color, int lineHeight = 8, bool shadow = false, bool isConsole = false); void onGraphicsReset(); int width(const std::string& str); - int height(const std::string& str); + std::vector split(const std::string& str, int width); + int height(const std::string& str, int maxWidth); private: int field_0; diff --git a/source/client/renderer/GameRenderer.cpp b/source/client/renderer/GameRenderer.cpp index 9707194d5..d71fd3d4e 100644 --- a/source/client/renderer/GameRenderer.cpp +++ b/source/client/renderer/GameRenderer.cpp @@ -185,7 +185,7 @@ void GameRenderer::_renderDebugOverlay(float a) extern int g_nVertices; // Tesselator.cpp debugText << "\nverts: " << g_nVertices; - _renderVertexGraph(g_nVertices, int(Minecraft::height * Gui::InvGuiScale)); + _renderVertexGraph(g_nVertices, int(Minecraft::height * Gui::GuiScale)); #endif /*debugText << "\nGameControllerManager::stickValuesX[1]: " << GameControllerManager::stickValuesX[1]; @@ -389,11 +389,8 @@ void GameRenderer::saveMatrices() void GameRenderer::setupGuiScreen() { - float x = Gui::InvGuiScale * Minecraft::width; - float y = Gui::InvGuiScale * Minecraft::height; - Matrix& projMtx = MatrixStack::Projection.getTop(); - projMtx.setOrtho(0, x, y, 0, 1000.0f, 3000.0f); // 1000 for the znear is accurate to the original b1.7.3, and causes less depth problems + projMtx.setOrtho(0, Gui::GuiWidth, Gui::GuiHeight, 0, 1000.0f, 3000.0f); // 1000 for the znear is accurate to the original b1.7.3, and causes less depth problems Matrix& viewMtx = MatrixStack::View.getTop(); viewMtx = Matrix::IDENTITY; @@ -578,7 +575,7 @@ void GameRenderer::renderFramedItems(const Vec3& camPos, LevelRenderer& levelRen } } -void GameRenderer::render(float f) +void GameRenderer::render(const Timer& timer) { if (m_pMinecraft->m_pLocalPlayer && m_pMinecraft->m_bGrabbedMouse) { @@ -599,7 +596,7 @@ void GameRenderer::render(float f) Vec2 d = pMC->m_mouseHandler.m_delta * (4.0f * mult1); float old_field_84 = field_84; - field_84 = float(field_C) + f; + field_84 = float(field_C) + timer.m_renderTicks; diff_field_84 = field_84 - old_field_84; m_smoothTurnDelta += d; @@ -651,19 +648,22 @@ void GameRenderer::render(float f) int pointerId = Multitouch::getFirstActivePointerIdExThisUpdate(); if (pointerId >= 0) { - mouseX = int(float(Multitouch::getX(pointerId)) * Gui::InvGuiScale); - mouseY = int(float(Multitouch::getY(pointerId)) * Gui::InvGuiScale); + mouseX = int(float(Multitouch::getX(pointerId)) * Gui::GuiScale); + mouseY = int(float(Multitouch::getY(pointerId)) * Gui::GuiScale); bMouseData = true; } } else if (m_pMinecraft->useController()) { - // do nothing + if (m_pMinecraft->m_pScreen) + { + m_pMinecraft->m_pScreen->controllerEvent(1, timer.m_deltaTime); + } } else { - mouseX = int(Mouse::getX() * Gui::InvGuiScale); - mouseY = int(Mouse::getY() * Gui::InvGuiScale); + mouseX = int(Mouse::getX() * Gui::GuiScale); + mouseY = int(Mouse::getY() * Gui::GuiScale); bMouseData = true; } @@ -671,14 +671,16 @@ void GameRenderer::render(float f) { if (m_keepPic < 0) { - renderLevel(f); + renderLevel(timer.m_renderTicks); + currentShaderColor = Color::WHITE; + currentShaderDarkColor = Color::WHITE; if (m_pMinecraft->getOptions()->m_hideGui.get()) { if (!m_pMinecraft->m_pScreen) return; } - m_pMinecraft->m_pGui->render(f, m_pMinecraft->m_pScreen != nullptr, mouseX, mouseY); + m_pMinecraft->m_pGui->render(timer.m_renderTicks, m_pMinecraft->m_pScreen != nullptr, mouseX, mouseY); } } else @@ -694,7 +696,7 @@ void GameRenderer::render(float f) LocalPlayer* pLocalPlayer = m_pMinecraft->m_pLocalPlayer; if (pLocalPlayer && pLocalPlayer->m_pMoveInput) - pLocalPlayer->m_pMoveInput->render(f); + pLocalPlayer->m_pMoveInput->render(timer.m_renderTicks); Screen* pScreen = m_pMinecraft->m_pScreen; if (pScreen) @@ -705,12 +707,12 @@ void GameRenderer::render(float f) pScreen->handlePointerLocation(mouseX, mouseY); pScreen->handlePointerPressed(Mouse::getButtonState(MOUSE_BUTTON_LEFT)); } - pScreen->onRender(f); + pScreen->onRender(timer.m_partialTicks); } if (m_pMinecraft->getOptions()->m_debugText.get()) { - _renderDebugOverlay(f); + _renderDebugOverlay(timer.m_partialTicks); } int timeMs = getTimeMs(); @@ -849,10 +851,13 @@ void GameRenderer::renderPointer(const MenuPointer& pointer) { Textures& textures = *m_pMinecraft->m_pTextures; - Vec3 pos(pointer.x - (C_MENU_POINTER_WIDTH / 2), pointer.y - (C_MENU_POINTER_HEIGHT / 2), 0); - MatrixStack::Ref mtx = MatrixStack::World.push(); - mtx->translate(pos); + mtx->translate(Vec3(pointer.x, pointer.y, 0)); + + if (m_pMinecraft->m_pScreen && m_pMinecraft->m_pScreen->m_uiTheme == UI_CONSOLE) + mtx->scale(2.0f); + + mtx->translate(Vec3(-(C_MENU_POINTER_WIDTH / 2), -(C_MENU_POINTER_HEIGHT / 2), 0)); textures.loadAndBindTexture("gui/pointer.png", true); m_pointerMesh.render(ScreenRenderer::singleton().m_materials.ui_textured); diff --git a/source/client/renderer/GameRenderer.hpp b/source/client/renderer/GameRenderer.hpp index 99ebe9985..932acdf0d 100644 --- a/source/client/renderer/GameRenderer.hpp +++ b/source/client/renderer/GameRenderer.hpp @@ -14,6 +14,7 @@ #include "renderer/hal/interface/DepthStencilState.hpp" class Minecraft; +class Timer; class Entity; class LevelRenderer; @@ -48,7 +49,7 @@ class GameRenderer void renderLevel(float); void renderFramedItems(const Vec3& camPos, LevelRenderer& levelRenderer, const Entity& camera, float f, ParticleEngine& particleEngine, float i); - void render(float); + void render(const Timer&); void renderWeather(float f); void renderPointer(const MenuPointer& pointer); void setLevel(Level* pLevel, Dimension* pDimension); diff --git a/source/client/renderer/LevelRenderer.cpp b/source/client/renderer/LevelRenderer.cpp index 24f6deb0f..c7202fe54 100644 --- a/source/client/renderer/LevelRenderer.cpp +++ b/source/client/renderer/LevelRenderer.cpp @@ -1378,7 +1378,7 @@ void LevelRenderer::takePicture(TripodCamera* pCamera, Entity* pOwner) m_pMinecraft->m_pCameraEntity = pCamera; m_pMinecraft->getOptions()->m_hideGui.set(true); m_pMinecraft->getOptions()->m_thirdPerson.set(false); // really from the perspective of the camera - m_pMinecraft->m_pGameRenderer->render(0.0f); + m_pMinecraft->m_pGameRenderer->render(m_pMinecraft->m_timer); m_pMinecraft->m_pCameraEntity = pOldMob; m_pMinecraft->getOptions()->m_hideGui.set(bOldDontRenderGui); m_pMinecraft->getOptions()->m_thirdPerson.set(bOldThirdPerson); diff --git a/source/client/renderer/LogoRenderer.cpp b/source/client/renderer/LogoRenderer.cpp new file mode 100644 index 000000000..c5dac8dc3 --- /dev/null +++ b/source/client/renderer/LogoRenderer.cpp @@ -0,0 +1,458 @@ +#include "LogoRenderer.hpp" +#include "client/app/Minecraft.hpp" +#include "client/renderer/renderer/RenderMaterialGroup.hpp" +#include "renderer/RenderContextImmediate.hpp" +#include "renderer/ShaderConstants.hpp" +#include "client/renderer/Textures.hpp" + +// special mode so that we can crop out the title: +//#define TITLE_CROP_MODE + +#define C_TITLE_PATH_DEFAULT "title/mclogo.png" +#define C_TITLE_PATH_FALLBACK "gui/title.png" // everyone should have this +#define C_TITLE_PATH_POCKET "gui/title_pe.png" +#define C_TITLE_PATH_XBOX360 "gui/title_xbox360.png" +#define C_TITLE_PATH_CONSOLE "gui/title_console.png" + +const char gLogoLine1[] = "??? ??? # # # # # ### ### ### ### ### ### $$$ $$$"; +const char gLogoLine2[] = "? ? ? ## ## # ## # # # # # # # # # $ $ $ "; +const char gLogoLine3[] = "?? ?? # # # # # # # ## # ## ### ## # $$ $$ "; +const char gLogoLine4[] = "? ? ? # # # # ## # # # # # # # # $ $ "; +const char gLogoLine5[] = "? ? ??? # # # # # ### ### # # # # # # $ $$$"; + +const char* gLogoLines[] = { + gLogoLine1, + gLogoLine2, + gLogoLine3, + gLogoLine4, + gLogoLine5, +}; + +LogoRenderer* LogoRenderer::instance = nullptr; + +void LogoRenderer::init(Minecraft* mc) +{ + m_pMinecraft = mc; + _initTextures(); + + TitleTile::regenerate(); +} + +LogoRenderer::LogoRenderer() +{ + m_pTiles = nullptr; + m_pMinecraft = nullptr; +} + +LogoRenderer::~LogoRenderer() +{ + SAFE_DELETE_ARRAY(m_pTiles); +} + +void LogoRenderer::build(int width) +{ + m_width = width; + build(); +} + +void LogoRenderer::build() +{ + _build2dTitleMesh(); +} + +void LogoRenderer::tick() +{ + if (m_pTiles) + { + int Width = int(sizeof gLogoLine1 - 1); + int Height = int(sizeof gLogoLines / sizeof * gLogoLines); + for (int i = 0; i < Width * Height; i++) + m_pTiles[i]->tick(); + } +} + +void LogoRenderer::render(float f) +{ + if (m_pMinecraft->getOptions()->getLogoType() == LOGO_3D) + render3d(f); + else + render2d(); +} + +void LogoRenderer::_initTextures() +{ + Textures* tx = m_pMinecraft->m_pTextures; + std::string path; + + switch (m_pMinecraft->getOptions()->getLogoType()) + { + case LOGO_POCKET: + path = C_TITLE_PATH_POCKET; + break; + case LOGO_JAVA: + path = C_TITLE_PATH_DEFAULT; + break; + case LOGO_CONSOLE: + path = C_TITLE_PATH_CONSOLE; + break; + case LOGO_XBOX360: + path = C_TITLE_PATH_XBOX360; + break; + default: + break; + } + + if (!tx->getTextureData(path, false)) + { + path = C_TITLE_PATH_FALLBACK; + // "preload" texture data + tx->getTextureData(path, true); + } + + m_p2dTitleTexPath = path; +} + +void LogoRenderer::_build2dTitleMesh() +{ + // bool crampedMode = false; + + int yPos, width, height, left; + + TextureData* pTex = m_pMinecraft->m_pTextures->getTextureData(m_p2dTitleTexPath, true); + if (!pTex) + return; + + UITheme uiTheme = m_pMinecraft->getUiTheme(); + bool isConsole = uiTheme == UI_CONSOLE; + + switch (m_pMinecraft->getOptions()->getLogoType()) + { + case LOGO_POCKET: + { + yPos = 15; + width = pTex->m_imageData.m_width; + height = pTex->m_imageData.m_height; + + if (isConsole) + { + yPos = 56; + width *= 2; + height *= 2; + } + + left = (m_width - width) / 2; + + if (m_width * 3 / 4 < m_2dTitleBounds.w) + { + // crampedMode = true; + yPos = 4; + } + + m_2dTitleBounds.x = left; + m_2dTitleBounds.y = yPos; + m_2dTitleBounds.w = width; + m_2dTitleBounds.h = height; + + blit(m_2dTitleMesh, m_2dTitleBounds); + break; + } + case LOGO_JAVA: + { + yPos = 30; + width = 274; + int halfWidth = 155; + height = 44; + + if (isConsole) + { + yPos = 56; + width *= 2; + halfWidth *= 2; + height *= 2; + } + + left = m_width / 2 - width / 2; + + if (m_width * 3 / 4 < m_2dTitleBounds.w) + { + // crampedMode = true; + yPos = 4; + } + + Tesselator& t = Tesselator::instance; + t.begin(8); + t.vertexUV(left, yPos + height, 0, 0.0f, 44.0f / 256.0f); + t.vertexUV(left + halfWidth, yPos + height, 0, 155.0f / 256.0f, 44.0f / 256.0f); + t.vertexUV(left + halfWidth, yPos, 0, 155.0f / 256.0f, 0.0f); + t.vertexUV(left, yPos, 0, 0.0f, 0.0f); + t.vertexUV(left + halfWidth, yPos + height, 0, 0.0f, (45.0f + 44.0f) / 256.0f); + t.vertexUV(left + halfWidth * 2, yPos + height, 0, 155.0f / 256.0f, (45.0f + 44.0f) / 256.0f); + t.vertexUV(left + halfWidth * 2, yPos, 0, 155.0f / 256.0f, 45.0f / 256.0f); + t.vertexUV(left + halfWidth, yPos, 0, 0.0f, 45.0f / 256.0f); + m_2dTitleMesh = t.end(); + break; + } + case LOGO_CONSOLE: + case LOGO_XBOX360: + { + yPos = 56; + width = 571; + height = 138; + + if (!isConsole) + { + yPos = 15; + width /= 2; + height /= 2; + } + + left = (m_width - width) / 2; + + + m_2dTitleBounds.x = left; + m_2dTitleBounds.y = yPos; + m_2dTitleBounds.w = width; + m_2dTitleBounds.h = height; + + blit(m_2dTitleMesh, m_2dTitleBounds); + break; + } + default: + break; + } +} + +void LogoRenderer::render2d() +{ + currentShaderColor = Color::WHITE; + m_pMinecraft->m_pTextures->loadAndBindTexture(m_p2dTitleTexPath); + m_2dTitleMesh.render(m_materials.ui_textured); +} + +void LogoRenderer::render3d(float f) +{ + UITheme uiTheme = m_pMinecraft->getUiTheme(); + bool isConsole = uiTheme == UI_CONSOLE; + + int Width = int(sizeof gLogoLine1 - 1); + int Height = int(sizeof gLogoLines / sizeof * gLogoLines); + + if (!m_pTiles) + { + m_pTiles = new TitleTile * [Width * Height]; + + for (int y = 0; y < Height; y++) + for (int x = 0; x < Width; x++) + m_pTiles[y * Width + x] = new TitleTile(m_random, x, y); + } + + int titleHeight = int(120 / Gui::GuiScale); + + if (m_width * 3 / 4 < 256) // cramped mode + titleHeight = int(80 / Gui::GuiScale); + + if (isConsole) + titleHeight *= 2; + + MatrixStack::Ref projMtx = MatrixStack::Projection.pushIdentity(); + projMtx->setPerspective(70.0f, float(Minecraft::width) / titleHeight, 0.05f, 100.0f); + + mce::RenderContext& renderContext = mce::RenderContextImmediate::get(); + + mce::ViewportOrigin viewportOrigin; + { + viewportOrigin.leftX = 0; + viewportOrigin.bottomLeftY = Minecraft::height - titleHeight; + viewportOrigin.topLeftY = 0; + } + renderContext.setViewport(Minecraft::width, titleHeight, 0.0f, 0.7f, viewportOrigin); + + MatrixStack::Ref viewMtx = MatrixStack::View.pushIdentity(); + + mce::MaterialPtr* pMaterial; + + for (int i = 0; i < 2; i++) + { + MatrixStack::Ref matrix = MatrixStack::World.push(); + matrix->translate(Vec3(0.4f, 0.6f, -12.0f)); + switch (i) + { + case 0: // shadow + //glClear(GL_DEPTH_BUFFER_BIT); + renderContext.clearDepthStencilBuffer(); + matrix->translate(Vec3(0.0f, -0.5f, -0.5f)); + //glEnable(GL_BLEND); + //force set alpha + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // default + break; + + case 1: // tiles + //glDisable(GL_BLEND); + //glClear(GL_DEPTH_BUFFER_BIT); + renderContext.clearDepthStencilBuffer(); + //revert + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // default + break; + + case 2: // tiles again + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_COLOR, GL_ONE); + break; + } + + matrix->scale(Vec3(1.0f, -1.0f, 1.0f)); + matrix->rotate(8.0f, Vec3::UNIT_X); + //matrix->rotate(15.0f, Vec3::UNIT_X); + matrix->scale(Vec3(0.89f, 1.0f, 0.4f)); + matrix->translate(Vec3(-Width * 0.5f, -Height * 0.5f, 0.0f)); + + m_pMinecraft->m_pTextures->loadAndBindTexture(C_TERRAIN_NAME); + if (i == 0) + { + m_pMinecraft->m_pTextures->loadAndBindTexture("gui/black.png"); + pMaterial = &m_screenMaterials.ui_title_tile_shadow; + //currentShaderColor = Color(0, 0, 0, 100); + } + else + { + pMaterial = &m_screenMaterials.ui_title_tile; + currentShaderColor = Color::WHITE; + } + + for (int y = 0; y < Height; y++) + { + for (int x = 0; x < Width; x++) + { + if (gLogoLines[y][x] == ' ') + continue; + + Tile* pTile = TitleTile::getTileFromChar(gLogoLines[y][x]); + + MatrixStack::Ref matrix = MatrixStack::World.push(); + + TitleTile* pTTile = m_pTiles[y * Width + x]; + float z = Mth::Lerp(pTTile->lastHeight, pTTile->height, f); + float scale = 1.0f; + float bright = 1.0f; + float rotation = 180.0f; + + if (i == 0) + { + scale = z * 0.04f + 1.0f; + bright = 1.0f / scale; + z = 0.0f; + } + + matrix->translate(Vec3(x, y, z)); + matrix->scale(scale); + matrix->scale(Vec3(-1.0f, 1.0f, 1.0f)); + matrix->rotate(rotation, Vec3::UNIT_Z); + + // rotate 90 deg on the X axis to correct lighting + matrix->rotate(90.0f, Vec3::UNIT_X); + + m_tileRenderer.renderTile(FullTile(pTile, i == 0 ? 255 : 0), *pMaterial, bright, true); + } + } + } + + renderContext.setViewport(Minecraft::width, Minecraft::height, 0.0f, 0.7f); +} + +Tile* TitleTile::_tiles[3]; +Random TitleTile::_random; +bool TitleTile::_firstTimeInit = true; + +TitleTile::TitleTile(Random& random, int x, int y) +{ + height = float(10 + y) + 32.0f * random.nextFloat() + float(y); + lastHeight = height; + dropVel = 0; +} + +void TitleTile::tick() +{ + lastHeight = height; + + if (height > 0.0f) + dropVel -= 0.6f; + + height += dropVel; + dropVel *= 0.9f; + + if (height < 0.0f) + { + height = 0.0f; + dropVel = 0.0f; + } +} + +Tile* TitleTile::getTileFromChar(char c) +{ + switch (c) + { + case '?': return _tiles[1]; + case '$': return _tiles[2]; + default: return _tiles[0]; + } +} + +// NOTE: Using the tile enum instead of Tile::tileName->id, may want to.. not? +static const int _tileBlockList[] = { + TILE_BOOKSHELF, + TILE_TOPSNOW, + TILE_GRASS, + TILE_INFO_UPDATEGAME1, + TILE_INFO_UPDATEGAME2, + TILE_LEAVES_CARRIED +}; +static const int _tileBlockListSize = sizeof _tileBlockList / sizeof(int); + +Tile* TitleTile::getRandomTile(Tile* except1, Tile* except2) +{ + TileID id; + for (;;) + { + id = _random.nextInt(256); + for (int i = 0; i < _tileBlockListSize; i++) { + if (_tileBlockList[i] == id) { + // N.B. Air does not have a tile + id = TILE_AIR; + break; + } + } + + if (!Tile::tiles[id]) + continue; + + // If found a tile, check if it can be rendered + Tile* pTile = Tile::tiles[id]; + eRenderShape renderShape = pTile->getRenderShape(); + if (!TileRenderer::canRender(renderShape) || renderShape != SHAPE_SOLID) + continue; + + if (pTile == except1 || pTile == except2) + continue; + + return pTile; + } +} + +void TitleTile::regenerate() +{ + if (_firstTimeInit) + { + _firstTimeInit = false; + _random.setSeed(getTimeMs()); + } + + _tiles[0] = getRandomTile(nullptr, nullptr); + _tiles[1] = getRandomTile(_tiles[0], nullptr); + _tiles[2] = getRandomTile(_tiles[0], _tiles[1]); +} + +LogoRenderer::Materials::Materials() +{ + MATERIAL_PTR(common, ui_title_tile); + MATERIAL_PTR(common, ui_title_tile_shadow); +} \ No newline at end of file diff --git a/source/client/renderer/LogoRenderer.hpp b/source/client/renderer/LogoRenderer.hpp new file mode 100644 index 000000000..ec9564c7e --- /dev/null +++ b/source/client/renderer/LogoRenderer.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include "client/options/Options.hpp" +#include "client/gui/IntRectangle.hpp" +#include "client/renderer/TileRenderer.hpp" +#include "client/gui/GuiComponent.hpp" + +class LogoRenderer; + +class TitleTile +{ +public: + TitleTile(Random&, int x, int y); + void tick(); + + static Tile* getTileFromChar(char c); + static void regenerate(); + +protected: + float height; + float lastHeight; + float dropVel; + +private: + friend class LogoRenderer; + static Tile* _tiles[3]; + static bool _firstTimeInit; + static Random _random; + static Tile* getRandomTile(Tile* except1, Tile* except2); +}; + +class LogoRenderer : public GuiComponent +{ +private: + void _initTextures(); + void _build2dTitleMesh(); + +public: + LogoRenderer(); + ~LogoRenderer(); + + void init(Minecraft*); + + void build(int width); + void build(); + + void tick(); + + void render(float f); + + void render2d(); + void render3d(float f); + + static LogoRenderer& singleton() + { + if (!instance) + { + instance = new LogoRenderer; + } + + return *instance; + } + +private: + class Materials + { + public: + mce::MaterialPtr ui_title_tile; + mce::MaterialPtr ui_title_tile_shadow; + + Materials(); + }; + + Minecraft* m_pMinecraft; + + int m_width; + std::string m_p2dTitleTexPath; + mce::Mesh m_2dTitleMesh; + IntRectangle m_2dTitleBounds; + Random m_random; + TileRenderer m_tileRenderer; + TitleTile** m_pTiles; + Materials m_screenMaterials; + static LogoRenderer* instance; +}; \ No newline at end of file diff --git a/source/client/renderer/ScreenRenderer.cpp b/source/client/renderer/ScreenRenderer.cpp index 13da2afb9..f7081f3de 100644 --- a/source/client/renderer/ScreenRenderer.cpp +++ b/source/client/renderer/ScreenRenderer.cpp @@ -3,11 +3,28 @@ #include "renderer/RenderMaterialGroup.hpp" #include "renderer/ShaderConstants.hpp" #include "client/renderer/renderer/Tesselator.hpp" +#include "client/resources/Resource.hpp" #ifdef _MSC_VER #pragma warning (disable : 4244) #endif +std::string ScreenRenderer::PANEL_SLICES[] = { "gui/console/Graphics/Panel_TL.png", "gui/console/Graphics/Panel_TM.png", "gui/console/Graphics/Panel_TR.png", + "gui/console/Graphics/Panel_ML.png", "gui/console/Graphics/Panel_MM.png", "gui/console/Graphics/Panel_MR.png", + "gui/console/Graphics/Panel_BL.png", "gui/console/Graphics/Panel_BM.png", "gui/console/Graphics/Panel_BR.png" }; + +std::string ScreenRenderer::SMALL_PANEL_SLICES[] = { "gui/console/Panel_Top_L.png", "gui/console/Panel_Top_M.png", "gui/console/Panel_Top_R.png", + "gui/console/Panel_Mid_L.png", "gui/console/Panel_Mid_M.png", "gui/console/Panel_Mid_R.png", + "gui/console/Panel_Bot_L.png", "gui/console/Panel_Bot_M.png", "gui/console/Panel_Bot_R.png" }; + +std::string ScreenRenderer::PANEL_RECESS_SLICES[] = { "gui/console/Graphics/Panel_Recess_Top_L.png", "gui/console/Graphics/Panel_Recess_Top_M.png", "gui/console/Graphics/Panel_Recess_Top_R.png", + "gui/console/Graphics/Panel_Recess_Mid_L.png", "gui/console/Graphics/Panel_Recess_Mid_M.png", "gui/console/Graphics/Panel_Recess_Mid_R.png", + "gui/console/Graphics/Panel_Recess_Bot_L.png", "gui/console/Graphics/Panel_Recess_Bot_M.png", "gui/console/Graphics/Panel_Recess_Bot_R.png" }; + +std::string ScreenRenderer::POINTER_TEXT_PANEL_SLICES[] = { "gui/console/Graphics/PointerTextPanel_TL.png", "gui/console/Graphics/PointerTextPanel_TM.png", "gui/console/Graphics/PointerTextPanel_TR.png", + "gui/console/Graphics/PointerTextPanel_ML.png", "gui/console/Graphics/PointerTextPanel_MM.png", "gui/console/Graphics/PointerTextPanel_MR.png", + "gui/console/Graphics/PointerTextPanel_BL.png", "gui/console/Graphics/PointerTextPanel_BM.png", "gui/console/Graphics/PointerTextPanel_BR.png" }; + ScreenRenderer::Materials::Materials() { MATERIAL_PTR(common, ui_textured); @@ -75,6 +92,55 @@ void ScreenRenderer::blit(int dx, int dy, int sx, int sy, int tw, int th, int sw t.draw(materialPtr ? *materialPtr : m_materials.ui_textured); } +void ScreenRenderer::blitTexture(Textures& textures, const std::string& texture, int x, int y, float u, float v, int width, int height, int uvWidth, int uvHeight, int textureWidth, int textureHeight, mce::MaterialPtr* materialPtr) +{ + textures.loadAndBindTexture(texture); + Tesselator& t = Tesselator::instance; + t.begin(4); + t.vertexUV(x, y + height, m_blitOffset, u / textureWidth, (v + uvHeight) / textureHeight); + t.vertexUV(x + width, y + height, m_blitOffset, (u + uvWidth) / textureWidth, (v + uvHeight) / textureHeight); + t.vertexUV(x + width, y, m_blitOffset, (u + uvWidth) / textureWidth, v / textureHeight); + t.vertexUV(x, y, m_blitOffset, u / textureWidth, v / textureHeight); + t.draw(materialPtr ? *materialPtr : m_materials.ui_textured); +} + +void ScreenRenderer::blitTexture(Textures& textures, const std::string& texture, int x, int y, float u, float v, int width, int height, int textureWidth, int textureHeight, mce::MaterialPtr* materialPtr) +{ + blitTexture(textures, texture, x, y, u, v, width, height, width, height, textureWidth, textureHeight, materialPtr); +} + +void ScreenRenderer::blitTexture(Textures& textures, const std::string& texture, int x, int y, float u, float v, int width, int height, mce::MaterialPtr* materialPtr) +{ + blitTexture(textures, texture, x, y, u, v, width, height, width, height, width, height, materialPtr); +} + +void ScreenRenderer::blitSprite(Textures& textures, const std::string& texture, int x, int y, int width, int height, mce::MaterialPtr* materialPtr, float u, float v, int uvWidth, int uvHeight) +{ + blitSprite(textures, textures.getGuiSprite(texture), x, y, width, height, materialPtr, u, v, uvWidth, uvHeight); +} + +void ScreenRenderer::blitSprite(Textures& textures, const TextureAtlasSprite* sprite, int x, int y, int width, int height, mce::MaterialPtr* materialPtr, float u, float v, int uvWidth, int uvHeight) +{ + if (!sprite || !sprite->m_pAtlas) return; + + TextureAtlas& atlas = *sprite->m_pAtlas; + + + float u0 = u ? sprite->minU + u / atlas.getWidth() : sprite->minU; + float u1 = u || uvWidth ? sprite->minU + (u + uvWidth) / atlas.getWidth() : sprite->maxU; + float v0 = v ? sprite->minV + v / atlas.getHeight() : sprite->minV; + float v1 = v || uvHeight ? sprite->minV + (v + uvHeight) / atlas.getHeight() : sprite->maxV; + + textures.loadAndBindTexture(sprite->m_pAtlas->m_name); + Tesselator& t = Tesselator::instance; + t.begin(4); + t.vertexUV(x, y + height, m_blitOffset, u0, v1); + t.vertexUV(x + width, y + height, m_blitOffset, u1, v1); + t.vertexUV(x + width, y, m_blitOffset, u1, v0); + t.vertexUV(x, y, m_blitOffset, u0, v0); + t.draw(materialPtr ? *materialPtr : m_materials.ui_textured); +} + void ScreenRenderer::blitRaw(float x1, float x2, float y1, float y2, float z, float u1, float u2, float v1, float v2) { Tesselator& t = Tesselator::instance; @@ -87,11 +153,64 @@ void ScreenRenderer::blitRaw(float x1, float x2, float y1, float y2, float z, fl t.draw(m_materials.ui_textured_and_glcolor); } +void ScreenRenderer::blitNineSlice(Textures& textures, const std::string* slices, int x, int y, int width, int height, int border, mce::MaterialPtr* materialPtr) +{ + blitSprite(textures, slices[0], x, y, border, border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[1], x + border, y, width - 2 * border, border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[2], x + width - border, y, border, border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[3], x, y + border, border, height - 2 * border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[4], x + border, y + border, width - 2 * border, height - 2 * border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[5], x + width - border, y + border, border, height - 2 * border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[6], x, y + height - border, border, border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[7], x + border, y + height - border, width - 2 * border, border, materialPtr, 0, 0, border, border); + blitSprite(textures, slices[8], x + width - border, y + height - border, border, border, materialPtr, 0, 0, border, border); +} + +void ScreenRenderer::blitNineSlice(Textures& textures, const std::string& spriteName, int x, int y, int width, int height, int border, mce::MaterialPtr* materialPtr) +{ + const TextureAtlasSprite* sprite = textures.getGuiSprite(spriteName); + if (!sprite || !sprite->m_pAtlas) return; + + int iw = sprite->w; + int ih = sprite->h; + + if (iw == width && ih == height) + { + blitSprite(textures, spriteName, x, y, width, height, materialPtr); + return; + } + + if (iw == width) + { + blitSprite(textures, sprite, x, y, width, border, materialPtr); + blitSprite(textures, sprite, x, y + border, width, height - border * 2, materialPtr, 0, border, width, border); + blitSprite(textures, sprite, x, y + height - border, width, border, materialPtr, 0, ih - border); + return; + } + + if (iw == height) + { + blitSprite(textures, sprite, x, y, border, height, materialPtr); + blitSprite(textures, sprite, x + border, y, width - 2 * border, height, materialPtr, border, 0, border, height); + blitSprite(textures, sprite, x + width - border, y, border, height, materialPtr, iw - border); + return; + } + + blitSprite(textures, sprite, x, y, border, border, materialPtr, 0, 0, border, border); + blitSprite(textures, sprite, x + border, y, width - 2 * border, border, materialPtr, border, 0, border, border); + blitSprite(textures, sprite, x + width - border, y, border, border, materialPtr, iw - border, 0, border, border); + blitSprite(textures, sprite, x, y + border, border, height - 2 * border, materialPtr, 0, border, border, border); + blitSprite(textures, sprite, x + border, y + border, width - 2 * border, height - 2 * border, materialPtr, border, border, border, border); + blitSprite(textures, sprite, x + width - border, y + border, border, height - 2 * border, materialPtr, iw - border, border, border, border); + blitSprite(textures, sprite, x, y + height - border, border, border, materialPtr, 0, ih - border, border, border); + blitSprite(textures, sprite, x + border, y + height - border, width - 2 * border, border, materialPtr, border, ih - border, border, border); + blitSprite(textures, sprite, x + width - border, y + height - border, border, border, materialPtr, iw - border, ih - border, border, border); +} + void ScreenRenderer::drawCenteredString(Font& font, const std::string& str, int cx, int cy, const Color& color) { int width = font.width(str); - int height = font.height(str); - font.drawShadow(str, cx - width / 2, cy - height / 2, color); + font.drawShadow(str, cx - width / 2, cy, color); } void ScreenRenderer::drawString(Font& font, const std::string& str, int cx, int cy, const Color& color) diff --git a/source/client/renderer/ScreenRenderer.hpp b/source/client/renderer/ScreenRenderer.hpp index a0312c128..2bfe8effa 100644 --- a/source/client/renderer/ScreenRenderer.hpp +++ b/source/client/renderer/ScreenRenderer.hpp @@ -38,7 +38,14 @@ class ScreenRenderer void blit(const IntRectangle& rect); void blit(mce::Mesh& mesh, const IntRectangle& rect); void blit(int dstX, int dstY, int srcX, int srcY, int dstWidth, int dstHeight, int srcWidth, int srcHeight, mce::MaterialPtr* materialPtr = nullptr); + void blitTexture(Textures&, const std::string&, int x, int y, float u, float v, int width, int height, int uvWidth, int uvHeight, int textureWidth, int textureHeight, mce::MaterialPtr* materialPtr = nullptr); + void blitTexture(Textures&, const std::string&, int x, int y, float u, float v, int width, int height, int textureWidth, int textureHeight, mce::MaterialPtr* materialPtr = nullptr); + void blitTexture(Textures&, const std::string&, int x, int y, float u, float v, int width, int height, mce::MaterialPtr* materialPtr = nullptr); + void blitSprite(Textures&, const std::string&, int x, int y, int width, int height, mce::MaterialPtr* materialPtr = nullptr, float u = 0, float v = 0, int uvWidth = 0, int uvHeight = 0); + void blitSprite(Textures&, const TextureAtlasSprite*, int x, int y, int width, int height, mce::MaterialPtr* materialPtr = nullptr, float u = 0, float v = 0, int uvWidth = 0, int uvHeight = 0); void blitRaw(float x1, float x2, float y1, float y2, float z, float u1, float u2, float v1, float v2); + void blitNineSlice(Textures&, const std::string* slices, int x, int y, int width, int height, int tileSize, mce::MaterialPtr* materialPtr = nullptr); + void blitNineSlice(Textures&, const std::string&, int x, int y, int width, int height, int border, mce::MaterialPtr* materialPtr = nullptr); void drawCenteredString(Font& font, const std::string& str, int cx, int cy, const Color& color = Color::WHITE); void drawString(Font& font, const std::string& str, int cx, int cy, const Color& color = Color::WHITE); void fill(float left, float top, float right, float bottom, const Color& color); @@ -51,5 +58,10 @@ class ScreenRenderer float m_blitOffset; public: Materials m_materials; + + static std::string PANEL_SLICES[]; + static std::string SMALL_PANEL_SLICES[]; + static std::string PANEL_RECESS_SLICES[]; + static std::string POINTER_TEXT_PANEL_SLICES[]; }; diff --git a/source/client/renderer/Textures.cpp b/source/client/renderer/Textures.cpp index 8bccb497f..8cb8198bb 100644 --- a/source/client/renderer/Textures.cpp +++ b/source/client/renderer/Textures.cpp @@ -11,6 +11,7 @@ #include "common/Utils.hpp" #include "client/resources/Resource.hpp" #include "renderer/RenderContextImmediate.hpp" +#include "ScreenRenderer.hpp" #define MIP_TAG "_mip" #define MIP_TAG_SIZE 4 @@ -136,12 +137,52 @@ void Textures::clear() m_currBoundTex = -1; } -Textures::Textures() +Textures::Textures() : + m_guiAtlas("gui_atlas"), + m_filteredGuiAtlas("filtered_gui_atlas", true) { m_bClamp = false; m_bBlur = false; m_currBoundTex = -1; + + addSprite("gui/console/Graphics/IconHolder.png", m_guiAtlas); + //addSprite("gui/console/Graphics/IconHolderRed.png", m_guiAtlas); + addSprite("gui/console/Graphics/Armour_Slot_Head.png", m_guiAtlas); + addSprite("gui/console/Graphics/Armour_Slot_Body.png", m_guiAtlas); + addSprite("gui/console/Graphics/Armour_Slot_Legs.png", m_guiAtlas); + addSprite("gui/console/Graphics/Armour_Slot_Feet.png", m_guiAtlas); + addSprite("gui/console/Graphics/Arrow_Off.png", m_guiAtlas); + addSprite("gui/console/Graphics/Arrow_Small_Off.png", m_guiAtlas); + addSprite("gui/console/Graphics/MainMenuButton_Norm.png", m_filteredGuiAtlas); + addSprite("gui/console/Graphics/MainMenuButton_Over.png", m_filteredGuiAtlas); + addSprite("gui/console/Graphics/ListButton_Norm.png", m_filteredGuiAtlas); + addSprite("gui/console/Graphics/ListButton_Over.png", m_filteredGuiAtlas); + addSprite("gui/console/Graphics/Tickbox_Norm.png", m_guiAtlas); + addSprite("gui/console/Graphics/Tickbox_Over.png", m_guiAtlas); + addSprite("gui/console/Graphics/Tick.png", m_guiAtlas); + addSprite("gui/console/Graphics/Slider_Track.png", m_guiAtlas); + addSprite("gui/console/Graphics/Slider_Button.png", m_guiAtlas); + addSprite("gui/console/scrollDown.png", m_guiAtlas); + addSprite("gui/console/scrollUp.png", m_guiAtlas); + addSprite("gui/loading_block.png", m_guiAtlas); + addSprite("gui/container/entity_slot.png", m_guiAtlas); + addSprite("gui/slider_highlight.png", m_guiAtlas); + addSprite("gui/text_field.png", m_guiAtlas); + addSprite("gui/text_field_highlighted.png", m_guiAtlas); + //addSprite("gui/loading_bar.png", m_guiAtlas); + //addSprite("gui/loading_background.png", m_guiAtlas); + + for (int i = 0; i < 9; ++i) + { + addSprite(ScreenRenderer::PANEL_SLICES[i], m_guiAtlas); + addSprite(ScreenRenderer::SMALL_PANEL_SLICES[i], m_guiAtlas); + addSprite(ScreenRenderer::PANEL_RECESS_SLICES[i], m_guiAtlas); + addSprite(ScreenRenderer::POINTER_TEXT_PANEL_SLICES[i], m_guiAtlas); + } + + setupAtlas(m_guiAtlas); + setupAtlas(m_filteredGuiAtlas); } Textures::~Textures() @@ -220,3 +261,20 @@ void Textures::addDynamicTexture(DynamicTexture* pTexture) m_dynamicTextures.push_back(pTexture); pTexture->tick(); } + +void Textures::addSprite(const std::string& name, TextureAtlas& atlas) +{ + atlas.addSprite(name, Resource::loadTexture(name)); +} + +void Textures::setupAtlas(TextureAtlas& atlas) +{ + atlas.build(); + uploadTexture(atlas.m_name, atlas.m_texture); +} + +const TextureAtlasSprite* Textures::getGuiSprite(const std::string& spriteTexture) +{ + const TextureAtlasSprite* sprite = m_guiAtlas.getSprite(spriteTexture); + return sprite ? sprite : m_filteredGuiAtlas.getSprite(spriteTexture); +} diff --git a/source/client/renderer/Textures.hpp b/source/client/renderer/Textures.hpp index 581b71210..eb7a15a80 100644 --- a/source/client/renderer/Textures.hpp +++ b/source/client/renderer/Textures.hpp @@ -12,6 +12,7 @@ #include "client/options/Options.hpp" #include "client/app/AppPlatform.hpp" #include "DynamicTexture.hpp" +#include "texture/TextureAtlas.hpp" #define C_TERRAIN_NAME "terrain.png" #define C_ITEMS_NAME "gui/items.png" @@ -28,10 +29,15 @@ class Textures TextureData* loadTexture(const std::string& name, bool bRequired); TextureData* loadAndBindTexture(const std::string& name, bool isRequired = true, unsigned int textureUnit = 0); TextureData* getTextureData(const std::string& name, bool isRequired); + TextureData* uploadTexture(const std::string& name, TextureData& t); void unloadAll(); void clear(); void tick(); void addDynamicTexture(DynamicTexture* pTexture); + void addSprite(const std::string& name, TextureAtlas& atlas); + void setupAtlas(TextureAtlas&); + + const TextureAtlasSprite* getGuiSprite(const std::string&); // set smoothing for next texture to be loaded void setSmoothing(bool b) @@ -51,14 +57,14 @@ class Textures private: static bool MIPMAP; - TextureData* uploadTexture(const std::string& name, TextureData& t); - protected: TextureMap m_textures; int m_currBoundTex; bool m_bClamp; bool m_bBlur; std::vector m_dynamicTextures; + TextureAtlas m_guiAtlas; + TextureAtlas m_filteredGuiAtlas; // Why? friend class StartMenuScreen; diff --git a/source/client/renderer/entity/ItemRenderer.cpp b/source/client/renderer/entity/ItemRenderer.cpp index 83875e047..aa3d9973f 100644 --- a/source/client/renderer/entity/ItemRenderer.cpp +++ b/source/client/renderer/entity/ItemRenderer.cpp @@ -216,9 +216,9 @@ void ItemRenderer::renderGuiItemOverlay(Font* font, Textures* textures, ItemStac ss << item.m_count; std::string amtstr = ss.str(); - int width = font->width(amtstr), height = font->height(amtstr) + 8; + int width = font->width(amtstr); - font->drawShadow(amtstr, x + 17 - width, y + 17 - height, 0xFFFFFF); + font->drawShadow(amtstr, x + 17 - width, y + 6 + 3, 0xFFFFFF); } void ItemRenderer::renderGuiItem(Font* font, Textures* textures, ItemStack& item, int x, int y, bool b) diff --git a/source/client/renderer/texture/TextureAtlas.cpp b/source/client/renderer/texture/TextureAtlas.cpp new file mode 100644 index 000000000..d2fc5e27b --- /dev/null +++ b/source/client/renderer/texture/TextureAtlas.cpp @@ -0,0 +1,176 @@ +#include +#include +#include "TextureAtlas.hpp" +#include "common/Utils.hpp" + +TextureAtlas::TextureAtlas(const std::string& name, bool enableFiltering) : + m_currentX(0), + m_currentY(0), + m_shelfHeight(0), + m_name(name), + m_texture(DEFAULT_ATLAS_SIZE, DEFAULT_ATLAS_SIZE, enableFiltering) +{ + _init(); +} + +TextureAtlas::TextureAtlas(const std::string& name, int initialSize, bool enableFiltering) : + m_currentX(0), + m_currentY(0), + m_shelfHeight(0), + m_name(name), + m_texture(initialSize, initialSize, enableFiltering) +{ + _init(); +} + +void TextureAtlas::addSprite(const std::string& name, uint8_t* data, int width, int height) +{ + PendingSprite sprite; + sprite.name = name; + sprite.data = data; + sprite.width = width; + sprite.height = height; + m_pendingSprites.push_back(sprite); +} + +void TextureAtlas::addSprite(const std::string& name, const TextureData& texture) +{ + if (texture.isEmpty()) return; + + int size = texture.m_imageData.m_width * texture.m_imageData.m_height * 4; + uint8_t* data = new uint8_t[size]; + memcpy(data, texture.m_imageData.m_data, size); + addSprite(name, data, texture.m_imageData.m_width, texture.m_imageData.m_height); +} + +class SpriteSorter +{ +public: + bool operator()(const PendingSprite& a, const PendingSprite& b) + { + return a.height > b.height; + } +}; + +bool TextureAtlas::build() +{ + std::sort(m_pendingSprites.begin(), m_pendingSprites.end(), SpriteSorter()); + + while (!pack()) + { + if (!grow()) + return false; + } + + for (size_t i = 0; i < m_pendingSprites.size(); ++i) + { + delete[] m_pendingSprites[i].data; + } + + m_pendingSprites.clear(); + return true; +} + +void TextureAtlas::_init() +{ + SAFE_DELETE_ARRAY(m_texture.m_imageData.m_data); + + int size = getWidth() * getHeight() * 4; + m_texture.m_imageData.m_data = new uint8_t[size]; + memset(m_texture.m_imageData.m_data, 0, size); +} + +bool TextureAtlas::pack() +{ + m_currentX = 0; + m_currentY = 0; + m_shelfHeight = 0; + m_sprites.clear(); + + for (size_t i = 0; i < m_pendingSprites.size(); ++i) + { + const PendingSprite& pending = m_pendingSprites[i]; + + if (pending.width > getWidth()) + return false; + + if (m_currentX + pending.width > getWidth()) + { + m_currentX = 0; + m_currentY += m_shelfHeight; + m_shelfHeight = 0; + } + + if (m_currentY + pending.height > getHeight()) + return false; + + blitSprite(pending.data, pending.width, pending.height, m_currentX, m_currentY); + + m_sprites[pending.name] = TextureAtlasSprite( + pending.name, + m_currentX, m_currentY, + pending.width, pending.height, + this + ); + + m_currentX += pending.width; + if (pending.height > m_shelfHeight) + m_shelfHeight = pending.height; + } + + return true; +} + +void TextureAtlas::blitSprite(uint8_t* src, int srcWidth, int srcHeight, int destX, int destY) +{ + for (int y = 0; y < srcHeight; ++y) + { + memcpy( + m_texture.m_imageData.m_data + ((destY + y) * getWidth() + destX) * 4, + src + (y * srcWidth) * 4, + srcWidth * 4 + ); + } +} + +bool TextureAtlas::grow() +{ + int newWidth = getWidth() + DEFAULT_ATLAS_SIZE; + + if (newWidth > MAX_ATLAS_SIZE) + return false; + + m_texture.m_imageData.m_width = newWidth; + + _init(); + return true; +} + +const TextureAtlasSprite* TextureAtlas::getSprite(const std::string& name) const +{ + std::map::const_iterator it = m_sprites.find(name); + if (it != m_sprites.end()) + return &it->second; + return nullptr; +} + +int TextureAtlas::getWidth() const +{ + return m_texture.m_imageData.m_width; +} + +int TextureAtlas::getHeight() const +{ + return m_texture.m_imageData.m_height; +} + +TextureAtlasSprite::TextureAtlasSprite(const std::string& name, int x, int y, int width, int height, TextureAtlas* atlas) : + IntRectangle(x, y, width, height), + name(name), + m_pAtlas(atlas) +{ + minU = float(x) / atlas->getWidth(); + minV = float(y) / atlas->getHeight(); + maxU = float(x + width) / atlas->getWidth(); + maxV = float(y + height) / atlas->getHeight(); +} \ No newline at end of file diff --git a/source/client/renderer/texture/TextureAtlas.hpp b/source/client/renderer/texture/TextureAtlas.hpp new file mode 100644 index 000000000..9cf063257 --- /dev/null +++ b/source/client/renderer/texture/TextureAtlas.hpp @@ -0,0 +1,72 @@ +#pragma once +#include +#include +#include +#include +#include "TextureData.hpp" +#include "client/gui/IntRectangle.hpp" + +#define DEFAULT_ATLAS_SIZE (256) +#define MAX_ATLAS_SIZE (16384) + +class TextureAtlas; + +struct TextureAtlasSprite : IntRectangle +{ + std::string name; + float minU, minV, maxU, maxV; + TextureAtlas* m_pAtlas; + + TextureAtlasSprite() : + IntRectangle(0, 0, 0, 0), + minU(0.0f), + minV(0.0f), + maxU(0.0f), + maxV(0.0f), + m_pAtlas(nullptr) + { + } + + TextureAtlasSprite(const std::string& name, int x, int y, int width, int height, TextureAtlas* atlas); +}; + +struct PendingSprite +{ + std::string name; + uint8_t* data; + int width; + int height; +}; + +class TextureAtlas +{ +public: + TextureAtlas(const std::string& name, bool enableFiltering = false); + TextureAtlas(const std::string& name, int initialSize, bool enableFiltering = false); + +public: + void addSprite(const std::string& name, uint8_t* data, int width, int height); + void addSprite(const std::string& name, const TextureData&); + bool build(); + const TextureAtlasSprite* getSprite(const std::string& name) const; + int getWidth() const; + int getHeight() const; + +private: + void _init(); + bool pack(); + void blitSprite(uint8_t* src, int srcWidth, int srcHeight, int destX, int destY); + bool grow(); + +private: + std::vector m_pendingSprites; + std::map m_sprites; + + int m_currentX; + int m_currentY; + int m_shelfHeight; + +public: + std::string m_name; + TextureData m_texture; +}; \ No newline at end of file diff --git a/source/client/resources/LoadingTipManager.cpp b/source/client/resources/LoadingTipManager.cpp new file mode 100644 index 000000000..354115620 --- /dev/null +++ b/source/client/resources/LoadingTipManager.cpp @@ -0,0 +1,81 @@ +#include "LoadingTipManager.hpp" +#include "Resource.hpp" +#include "common/Util.hpp" +#include "client/locale/Language.hpp" +#include "thirdparty/rapidjson/document.h" + +LoadingTip LoadingTip::EMPTY(""); // can't use EMPTY_STRING here, race condition + +LoadingTipManager* LoadingTipManager::instance = nullptr; + +LoadingTipManager::LoadingTipManager() : + m_actual(LoadingTip::EMPTY), + m_actualTime(0) +{ +} + +void LoadingTipManager::init() +{ + m_all.clear(); + m_using.clear(); + + using namespace rapidjson; + + std::string file; + if (!Resource::load("texts/tips.json", file)) return; + Document d; + d.Parse(file.c_str()); + + if (d.Empty()) return; + + for (Value::ConstValueIterator it = d.Begin(); it != d.End(); ++it) + { + if (it->IsString()) + m_all.push_back(LoadingTip(it->GetString())); + else if (it->IsObject()) + { + Value::ConstObject translateValue = it->GetObj(); + Value::ConstMemberIterator translate = translateValue.FindMember("translate"); + Value::ConstMemberIterator time = translateValue.FindMember("time"); + + if (translate != translateValue.MemberEnd()) + { + std::string translation = Language::singleton().get(translate->value.GetString()); + if (time == translateValue.MemberEnd()) + m_all.push_back(LoadingTip(translation)); + else + m_all.push_back(LoadingTip(translation, time->value.GetInt())); + } + } + } +} + +const LoadingTip& LoadingTipManager::getActual() +{ + if (m_using.empty()) + { + if (m_all.empty()) return LoadingTip::EMPTY; + else + { + for (std::vector::iterator it = m_all.begin(); it != m_all.end(); ++it) + { + m_using.push_back(&(*it)); + } + } + } + + if (m_actual.text.empty()) + { + int i = m_random.nextInt(m_using.size()); + m_actual = *m_using[i]; + m_actualTime = getTimeMs(); + } + else if (getTimeMs() - m_actualTime >= m_actual.timeOnScreen) + { + m_actual = LoadingTip::EMPTY; + m_actualTime = 0; + return getActual(); + } + + return m_actual; +} diff --git a/source/client/resources/LoadingTipManager.hpp b/source/client/resources/LoadingTipManager.hpp new file mode 100644 index 000000000..a3fe841e7 --- /dev/null +++ b/source/client/resources/LoadingTipManager.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include "common/Random.hpp" + +struct LoadingTip +{ + std::string text; + int timeOnScreen; + + LoadingTip(const std::string text, int timeOnScreen) : + text(text), + timeOnScreen(timeOnScreen) + { + } + + LoadingTip(const std::string text) : + text(text), + timeOnScreen(text.size() * 80) + { + } + + bool operator==(const LoadingTip& other) const { + return text == other.text && timeOnScreen == other.timeOnScreen; + } + + static LoadingTip EMPTY; +}; + +class LoadingTipManager +{ +public: + LoadingTipManager(); + + void init(); + + const LoadingTip& getActual(); + + static LoadingTipManager& singleton() + { + if (!instance) + { + instance = new LoadingTipManager; + } + + return *instance; + } + +private: + Random m_random; + LoadingTip m_actual; + int m_actualTime; + +public: + std::vector m_all; + std::vector m_using; + + static LoadingTipManager* instance; +}; \ No newline at end of file diff --git a/source/client/resources/SplashManager.cpp b/source/client/resources/SplashManager.cpp new file mode 100644 index 000000000..85589e0b1 --- /dev/null +++ b/source/client/resources/SplashManager.cpp @@ -0,0 +1,51 @@ +#include +#include "SplashManager.hpp" +#include "Resource.hpp" +#include "common/Util.hpp" + +SplashManager* SplashManager::instance = nullptr; + +void SplashManager::init(const std::string& user) +{ + m_splashes.clear(); + std::string file; + if (!Resource::load("title/splashes.txt", file)) return; + std::istringstream stream(file); + std::string line; + + while (std::getline(stream, line)) + { + if (line.empty()) + continue; + + if (line[line.size() - 1] == '\r') + line.erase(line.size() - 1); + + if (line.compare(0, 2, "//") == 0) + continue; + + m_splashes.push_back(line); + } + +#if MCE_GFX_API_OGL +#ifdef USE_GLES + m_splashes.push_back("OpenGL ES 1.1!"); +#else + m_splashes.push_back("OpenGL 1.5!"); +#endif +#elif MCE_GFX_API_D3D11 + m_splashes.push_back("Direct3D 11.1!"); +#elif MCE_GFX_API_D3D9 + m_splashes.push_back("Direct3D 9!"); +#endif + + m_isYouSplash = Util::format("%s IS YOU", user.c_str()); +} + +const std::string& SplashManager::getSplash() +{ + //Add splashes for holidays? + if (m_random.nextInt(m_splashes.size()) == 42) return m_isYouSplash; + + return m_splashes[m_random.nextInt(m_splashes.size())]; +} diff --git a/source/client/resources/SplashManager.hpp b/source/client/resources/SplashManager.hpp new file mode 100644 index 000000000..f762f8c24 --- /dev/null +++ b/source/client/resources/SplashManager.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include "common/Random.hpp" + +class SplashManager +{ +public: + void init(const std::string&); + const std::string& getSplash(); + + static SplashManager& singleton() + { + if (!instance) + { + instance = new SplashManager; + } + return *instance; + } + +private: + Random m_random; + std::vector m_splashes; + std::string m_isYouSplash; + static SplashManager* instance; +}; \ No newline at end of file diff --git a/source/common/Mth.cpp b/source/common/Mth.cpp index 9236bf704..d3a20ddb0 100644 --- a/source/common/Mth.cpp +++ b/source/common/Mth.cpp @@ -102,6 +102,17 @@ float Mth::clamp(float x, float min, float max) return max; } +int Mth::clamp(int x, int min, int max) +{ + if (x > max) + return max; + if (x > min) + return x; + else + return min; + return max; +} + int Mth::floor(float f) { int result = int(f); @@ -112,6 +123,11 @@ int Mth::floor(float f) return result; } +int Mth::round(float f) +{ + return floor(f + 0.5f); +} + float Mth::atan(float f) { return atanf(f); diff --git a/source/common/Mth.hpp b/source/common/Mth.hpp index 5cb3355ca..797401f9f 100644 --- a/source/common/Mth.hpp +++ b/source/common/Mth.hpp @@ -33,7 +33,9 @@ class Mth static float atan2(float y, float x); static float cos(float); static float clamp(float x, float min, float max); + static int clamp(int x, int min, int max); static int floor(float); + static int round(float); static void initMth(); static int intFloorDiv(int, int); static float invSqrt(float); diff --git a/source/common/Timer.cpp b/source/common/Timer.cpp index f819da31f..3d1101bfd 100644 --- a/source/common/Timer.cpp +++ b/source/common/Timer.cpp @@ -38,7 +38,7 @@ double getAccurateTimeMs() } #endif -void Timer::advanceTime() +void Timer::advanceTime(bool paused) { double timeS = getTimeS(); double timeMs = timeS * 1000.0;// = getAccurateTimeMs(); @@ -57,17 +57,18 @@ void Timer::advanceTime() m_tickAdjustment += ((diff1 / diff2) - m_tickAdjustment) * 0.2f; } - double diff = timeS - m_lastUpdateTime; + m_deltaTime = timeS - m_lastUpdateTime; m_lastUpdateTime = timeS; - float x1 = diff * m_tickAdjustment; + float x1 = m_deltaTime * m_tickAdjustment; if (x1 > 1) x1 = 1; if (x1 < 0) x1 = 0; float x2 = m_partialTicks + x1 * m_timerSpeed * m_ticksPerSecond; m_ticks = int(x2); m_partialTicks = x2 - m_ticks; - m_renderTicks = x2 - m_ticks; + if (!paused) + m_renderTicks = m_partialTicks; if (m_ticks > 10) m_ticks = 10; } @@ -77,6 +78,7 @@ Timer::Timer() m_lastUpdateTime = 0; m_lastSyncTime = 0; m_unprocessedTime = 0; + m_deltaTime = 0; m_tickAdjustment = 1.0f; m_ticksPerSecond = 20.0f; m_ticks = 0; diff --git a/source/common/Timer.hpp b/source/common/Timer.hpp index 38ea952cc..d56f76fd0 100644 --- a/source/common/Timer.hpp +++ b/source/common/Timer.hpp @@ -17,18 +17,13 @@ class Timer public: Timer(); - void advanceTime(); + void advanceTime(bool paused); public: -#ifndef USE_ACCURATE_TIMER - float m_lastUpdateTime; - int m_lastSyncTime; - int m_unprocessedTime; -#else double m_lastUpdateTime; double m_lastSyncTime; double m_unprocessedTime; -#endif + double m_deltaTime; float m_tickAdjustment; float m_ticksPerSecond; int m_ticks; diff --git a/source/common/math/Color.cpp b/source/common/math/Color.cpp index 9774f3f35..139677930 100644 --- a/source/common/math/Color.cpp +++ b/source/common/math/Color.cpp @@ -18,6 +18,8 @@ Color Color::BLACK = Color(0.0f, 0.0f, 0.0f); Color Color::GREY = Color(0.5f, 0.5f, 0.5f); Color Color::WHITE = Color(1.0f, 1.0f, 1.0f); +Color Color::TEXT_GREY = Color(0x404040); + void Color::fromHSB(float h, float s, float b) { if (s == 0.0f) diff --git a/source/common/math/Color.hpp b/source/common/math/Color.hpp index c6c60e349..b215311a7 100644 --- a/source/common/math/Color.hpp +++ b/source/common/math/Color.hpp @@ -127,4 +127,6 @@ struct Color static Color BLACK; static Color GREY; static Color WHITE; + + static Color TEXT_GREY; }; diff --git a/source/renderer/hal/ogl/TextureOGL.cpp b/source/renderer/hal/ogl/TextureOGL.cpp index 81994ce0e..5048cd9ac 100644 --- a/source/renderer/hal/ogl/TextureOGL.cpp +++ b/source/renderer/hal/ogl/TextureOGL.cpp @@ -155,32 +155,31 @@ void TextureOGL::createTexture(RenderContext& context, const TextureDescription& ErrorHandlerOGL::checkForErrors(); createMipMap(context, nullptr, description.width, description.height, 0); - switch (description.filteringLevel) + + if (description.bWrap) + { + glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + else { - case TEXTURE_FILTERING_BILINEAR: // @NOTE: Need GL 1.2 for GL_CLAMP_TO_EDGE glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + switch (description.filteringLevel) + { + case TEXTURE_FILTERING_BILINEAR: + glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; case TEXTURE_FILTERING_POINT: - if (description.bWrap) - { - glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - else - { - glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; case TEXTURE_FILTERING_MIPMAP_BILINEAR: - glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); glTexParameteri(m_state.m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; diff --git a/source/server/ServerSideNetworkHandler.cpp b/source/server/ServerSideNetworkHandler.cpp index 6567b3d55..840207710 100644 --- a/source/server/ServerSideNetworkHandler.cpp +++ b/source/server/ServerSideNetworkHandler.cpp @@ -857,7 +857,7 @@ void ServerSideNetworkHandler::commandStats(OnlinePlayer* player, const std::vec std::stringstream ss; ss << "Server uptime: " << getTimeS() << " seconds.\n"; - ss << "Host's name: " << m_pMinecraft->m_pUser->field_0 << "\n"; + ss << "Host's name: " << m_pMinecraft->m_pUser->m_name << "\n"; size_t nPlayers = m_onlinePlayers.size(); if (nPlayers == 1) diff --git a/source/world/entity/Mob.cpp b/source/world/entity/Mob.cpp index 68c8a47a0..a336c5654 100644 --- a/source/world/entity/Mob.cpp +++ b/source/world/entity/Mob.cpp @@ -16,7 +16,7 @@ void Mob::_init() { // only sets 19 fields on 0.2.1 - m_invulnerableDuration = 10; + m_invulnerableDuration = 20; m_yBodyRot = 0.0f; m_yBodyRotO = 0.0f; m_oAttackAnim = 0.0f; diff --git a/source/world/inventory/ArmorSlot.cpp b/source/world/inventory/ArmorSlot.cpp index 79055621c..f0545a935 100644 --- a/source/world/inventory/ArmorSlot.cpp +++ b/source/world/inventory/ArmorSlot.cpp @@ -2,8 +2,8 @@ #include "world/tile/Tile.hpp" #include "world/item/Item.hpp" -ArmorSlot::ArmorSlot(Container* container, Item::EquipmentSlot equipmentSlot, int slotIndex, int x, int y) : - Slot(container, slotIndex, x, y), +ArmorSlot::ArmorSlot(Container* container, Item::EquipmentSlot equipmentSlot, int slotIndex) : + Slot(container, slotIndex, ARMOR), m_equipmentSlot(equipmentSlot) { } @@ -21,8 +21,3 @@ int ArmorSlot::getMaxStackSize() const { return 1; } - -int ArmorSlot::getNoItemIcon() const -{ - return 16 * ((Item::SLOT_HEAD - m_equipmentSlot) + 1) - 1; -} diff --git a/source/world/inventory/ArmorSlot.hpp b/source/world/inventory/ArmorSlot.hpp index a41d899a6..2b679e8d9 100644 --- a/source/world/inventory/ArmorSlot.hpp +++ b/source/world/inventory/ArmorSlot.hpp @@ -6,11 +6,10 @@ class ArmorSlot : public Slot { public: - ArmorSlot(Container* container, Item::EquipmentSlot equipmentSlot, int slotIndex, int x, int y); + ArmorSlot(Container* container, Item::EquipmentSlot equipmentSlot, int slotIndex); bool mayPlace(const ItemStack& item) const override; int getMaxStackSize() const override; - int getNoItemIcon() const override; public: Item::EquipmentSlot m_equipmentSlot; diff --git a/source/world/inventory/ChestMenu.cpp b/source/world/inventory/ChestMenu.cpp index 2cf424810..95a78894f 100644 --- a/source/world/inventory/ChestMenu.cpp +++ b/source/world/inventory/ChestMenu.cpp @@ -6,36 +6,22 @@ ChestMenu::ChestMenu(Container* inventory, Container* container) , m_pContainer(container) { int rows = m_pContainer->getContainerSize() / 9; - int verticalOffset = (rows - 4) * 18; for (int row = 0; row < rows; ++row) { for (int col = 0; col < 9; ++col) - { - int index = col + row * 9; - int x = 8 + col * 18; - int y = 18 + row * 18; - addSlot(new Slot(m_pContainer, index, x, y)); - } + addSlot(new Slot(m_pContainer, col + row * 9)); } for (int row = 0; row < 3; ++row) { for (int col = 0; col < 9; ++col) - { - int index = col + row * 9 + 9; - int x = 8 + col * 18; - int y = 103 + row * 18 + verticalOffset; - addSlot(new Slot(inventory, index, x, y)); - } + addSlot(new Slot(inventory, col + row * 9 + 9)); } for (int col = 0; col < 9; ++col) { - int index = col; - int x = 8 + col * 18; - int y = 161 + verticalOffset; - addSlot(new Slot(inventory, index, x, y)); + addSlot(new Slot(inventory, col, Slot::HOTBAR)); } } diff --git a/source/world/inventory/CraftingMenu.cpp b/source/world/inventory/CraftingMenu.cpp index fd94c2458..aeb9d016b 100644 --- a/source/world/inventory/CraftingMenu.cpp +++ b/source/world/inventory/CraftingMenu.cpp @@ -12,23 +12,23 @@ CraftingMenu::CraftingMenu(Inventory* inventory, const TilePos& tilePos, Level* m_pCraftSlots = new CraftingContainer(this, 3, 3); m_pResultSlots = new ResultContainer(); - addSlot(new ResultSlot(inventory->m_pPlayer, m_pCraftSlots, m_pResultSlots, 0, 124, 35)); + addSlot(new ResultSlot(inventory->m_pPlayer, m_pCraftSlots, m_pResultSlots, 0)); for (int y = 0; y < 3; ++y) { for (int x = 0; x < 3; ++x) - addSlot(new Slot(m_pCraftSlots, x + y * 3, 30 + x * 18, 17 + y * 18)); + addSlot(new Slot(m_pCraftSlots, x + y * 3, Slot::INPUT)); } for (int y = 0; y < 3; ++y) { for (int x = 0; x < 9; ++x) - addSlot(new Slot(inventory, x + (y + 1) * 9, 8 + x * 18, 84 + y * 18)); + addSlot(new Slot(inventory, x + (y + 1) * 9, Slot::INVENTORY)); } for (int i = 0; i < 9; ++i) { - addSlot(new Slot(inventory, i, 8 + i * 18, 142)); + addSlot(new Slot(inventory, i, Slot::HOTBAR)); } slotsChanged(m_pCraftSlots); @@ -64,7 +64,7 @@ bool CraftingMenu::stillValid(Player* player) const if (m_pLevel->getTile(m_pos) != Tile::craftingTable->m_ID) return false; else - return !(player->distanceToSqr(Vec3(m_pos.x + 0.5f, m_pos.y + 0.5f, m_pos.z + 0.5)) > 64.0f); + return !(player->distanceToSqr(Vec3(m_pos.x + 0.5f, m_pos.y + 0.5f, m_pos.z + 0.5f)) > 64.0f); } ItemStack CraftingMenu::quickMoveStack(int index) diff --git a/source/world/inventory/InventoryMenu.cpp b/source/world/inventory/InventoryMenu.cpp index 569d9261a..6c5d2a76f 100644 --- a/source/world/inventory/InventoryMenu.cpp +++ b/source/world/inventory/InventoryMenu.cpp @@ -13,28 +13,28 @@ InventoryMenu::InventoryMenu(Inventory* inventory, bool active) m_pCraftSlots = new CraftingContainer(this, 2, 2); m_pResultSlots = new ResultContainer; - addSlot(new ResultSlot(inventory->m_pPlayer, m_pCraftSlots, m_pResultSlots, 0, 144, 36)); + addSlot(new ResultSlot(inventory->m_pPlayer, m_pCraftSlots, m_pResultSlots, 0)); for (int y = 0; y < 2; ++y) { for (int x = 0; x < 2; ++x) - addSlot(new Slot(m_pCraftSlots, x + y * 2, 88 + x * 18, 26 + y * 18)); + addSlot(new Slot(m_pCraftSlots, x + y * 2, Slot::INPUT)); } for (int i = Item::SLOT_FEET; i <= Item::SLOT_HEAD; ++i) { - addSlot(new ArmorSlot(inventory, Item::EquipmentSlot(Item::SLOT_HEAD - i), inventory->getContainerSize() - 1 - i, 8, 8 + i * 18)); + addSlot(new ArmorSlot(inventory, Item::EquipmentSlot(Item::SLOT_HEAD - i), inventory->getContainerSize() - 1 - i)); } for (int y = 0; y < 3; ++y) { for (int x = 0; x < 9; ++x) - addSlot(new Slot(inventory, x + (y + 1) * 9, 8 + x * 18, 84 + y * 18)); + addSlot(new Slot(inventory, x + (y + 1) * 9, Slot::INVENTORY)); } for (int i = 0; i < 9; ++i) { - addSlot(new Slot(inventory, i, 8 + i * 18, 142)); + addSlot(new Slot(inventory, i, Slot::HOTBAR)); } slotsChanged(m_pCraftSlots); diff --git a/source/world/inventory/ResultSlot.cpp b/source/world/inventory/ResultSlot.cpp index 22eb00a8c..e031887df 100644 --- a/source/world/inventory/ResultSlot.cpp +++ b/source/world/inventory/ResultSlot.cpp @@ -3,8 +3,8 @@ #include "world/entity/Player.hpp" //#include "stats/Achievement.hpp" -ResultSlot::ResultSlot(Player* player, Container* craftSlots, Container* resultSlots, int slotIndex, int x, int y) : - Slot(resultSlots, slotIndex, x, y), +ResultSlot::ResultSlot(Player* player, Container* craftSlots, Container* resultSlots, int slotIndex) : + Slot(resultSlots, slotIndex, OUTPUT), m_pPlayer(player), m_pCraftSlots(craftSlots) { diff --git a/source/world/inventory/ResultSlot.hpp b/source/world/inventory/ResultSlot.hpp index a3e31a534..92dd109e6 100644 --- a/source/world/inventory/ResultSlot.hpp +++ b/source/world/inventory/ResultSlot.hpp @@ -6,7 +6,7 @@ class ResultSlot : public Slot { public: - ResultSlot(Player* player, Container* craftSlots, Container* resultSlots, int slotIndex, int x, int y); + ResultSlot(Player* player, Container* craftSlots, Container* resultSlots, int slotIndex); bool mayPlace(const ItemStack& item) const override; bool canSync() const override; diff --git a/source/world/inventory/Slot.cpp b/source/world/inventory/Slot.cpp index ffc0a3d2f..81beb469a 100644 --- a/source/world/inventory/Slot.cpp +++ b/source/world/inventory/Slot.cpp @@ -1,10 +1,9 @@ #include "Slot.hpp" -Slot::Slot(Container* container, int slot, int x, int y) : +Slot::Slot(Container* container, int slot, Group group) : m_pContainer(container), m_slot(slot), - m_x(x), - m_y(y) + m_group(group) { } diff --git a/source/world/inventory/Slot.hpp b/source/world/inventory/Slot.hpp index a5423ba65..12a033823 100644 --- a/source/world/inventory/Slot.hpp +++ b/source/world/inventory/Slot.hpp @@ -7,7 +7,17 @@ class ItemStack; class Slot { public: - Slot(Container* container, int slot, int x, int y); + enum Group + { + CONTAINER, + INVENTORY, + HOTBAR, + INPUT, + OUTPUT, + ARMOR + }; + + Slot(Container* container, int slot, Group group = CONTAINER); virtual ~Slot(); virtual bool canSync() const; @@ -26,8 +36,6 @@ class Slot virtual int getMaxStackSize() const { return m_pContainer->getMaxStackSize(); } - virtual int getNoItemIcon() const { return -1; } - virtual ItemStack remove(int count) { return m_pContainer->removeItem(m_slot, count); } virtual bool isAt(Container* cont, int s) { return cont == m_pContainer && s == m_slot; } @@ -36,6 +44,5 @@ class Slot Container* m_pContainer; int m_slot; int m_index; - int m_x; - int m_y; + Group m_group; }; \ No newline at end of file