diff --git a/Data/Scripts/016b_UI redesign/000_UI_base.rb b/Data/Scripts/016b_UI redesign/000_UI_base.rb new file mode 100644 index 000000000..427fc773a --- /dev/null +++ b/Data/Scripts/016b_UI redesign/000_UI_base.rb @@ -0,0 +1,199 @@ +module UI + #============================================================================= + # The visuals class. + #============================================================================= + class BaseUIVisuals + GRAPHICS_FOLDER = "Graphics/UI/" + BACKGROUND_FILENAME = "bg" + BLACK_TEXT_COLOR = Color.new(72, 72, 72) + BLACK_TEXT_SHADOW_COLOR = Color.new(160, 160, 160) + + def initialize + @bitmaps = {} + @sprites = {} + initialize_viewport + initialize_bitmaps + initialize_background + initialize_overlay + # TODO: Initialize message box (and dialogue box?) for messages to use. + initialize_sprites + refresh + end + + def initialize_viewport + @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height) + @viewport.z = 99999 + end + + def initialize_bitmaps + end + + def initialize_background + addBackgroundPlane(@sprites, :background, GRAPHICS_FOLDER + background_filename, @viewport) + @sprites[:background].z = -1000 + end + + def background_filename + return gendered_filename(BACKGROUND_FILENAME) + end + + def initialize_overlay + @sprites[:overlay] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport) + @sprites[:overlay].z = 1000 + pbSetSystemFont(@sprites[:overlay].bitmap) + end + + def initialize_sprites + end + + #--------------------------------------------------------------------------- + + def add_icon_sprite(key, x, y, filename = nil) + @sprites[key] = IconSprite.new(x, y, :viewport) + @sprites[key].setBitmap(filename) if filename + end + + #--------------------------------------------------------------------------- + + def fade_in + pbFadeInAndShow(@sprites) { update_visuals } + end + + def fade_out + pbFadeOutAndHide(@sprites) { update_visuals } + end + + def dispose + @sprites.each_value { |s| s.dispose if s && !s.disposed? } + @sprites.clear + @bitmaps.each_value { |b| b.dispose if b && !b.disposed? } + @bitmaps.clear + @viewport.dispose + end + + #--------------------------------------------------------------------------- + + def gendered_filename(base_filename) + return filename_with_appendix(base_filename, "_f") if $player.female? + return base_filename + end + + def filename_with_appendix(base_filename, appendix) + if appendix && appendix != "" + trial_filename = base_filename + appendix + return trial_filename if pbResolveBitmap(GRAPHICS_FOLDER + trial_filename) + end + return base_filename + end + + #--------------------------------------------------------------------------- + + def show_message(text) + pbMessage(text) { update_visuals } + end + + def show_confirm_message(text) + return pbConfirmMessage(text) { update_visuals } + end + + def show_choice_message(text, options, cancel_index) + return pbMessage(text, options, cancel_index) { update_visuals } + end + + #--------------------------------------------------------------------------- + + # Redraw everything on the screen. + def refresh + refresh_overlay + end + + def refresh_overlay + @sprites[:overlay].bitmap.clear + end + + #--------------------------------------------------------------------------- + + def update_visuals + pbUpdateSpriteHash(@sprites) + end + + def update_input + if Input.trigger?(Input::BACK) + return :quit + end + return nil + end + + def update + update_visuals + return update_input + end + + #--------------------------------------------------------------------------- + + def navigate + ret = nil + loop do + Graphics.update + Input.update + ret = update + break if ret + end + return ret + end + end + + #============================================================================= + # The logic class. + #============================================================================= + class BaseUIScreen + def initialize + initialize_visuals + main + end + + def initialize_visuals + @visuals = UI::BaseUIVisuals.new + end + + def start_screen + @visuals.fade_in + end + + def end_screen + @visuals.fade_out + @visuals.dispose + end + + #----------------------------------------------------------------------------- + + def show_message(text) + @visuals.show_message(text) + end + + def show_confirm_message(text) + return @visuals.show_confirm_message(text) + end + + def show_choice_message(text, options, cancel_index) + return @visuals.show_choice_message(text, options, cancel_index) + end + + #----------------------------------------------------------------------------- + + def main + start_screen + loop do + command = @visuals.navigate + break if command == :quit + command = perform_action(command) + break if command == :quit + end + end_screen + end + + def perform_action(command) + return nil + end + end +end diff --git a/Data/Scripts/016b_UI redesign/001_UIRedesign_PauseMenu.rb b/Data/Scripts/016b_UI redesign/001_UIRedesign_PauseMenu.rb new file mode 100644 index 000000000..414eb081f --- /dev/null +++ b/Data/Scripts/016b_UI redesign/001_UIRedesign_PauseMenu.rb @@ -0,0 +1,140 @@ +# TODO: This code is incomplete, in that all the MenuHandlers for the pause menu +# assume the visuals class has def pbRefresh, def pbEndScene, def +# pbHideMenu and def pbShowMenu. + +#=============================================================================== +# +#=============================================================================== +class UI::PauseMenuVisuals < UI::BaseUIVisuals + def initialize + @info_state = false + # @help_state = false + super + end + + def initialize_background; end + def initialize_overlay; end + + def initialize_sprites + # Pause menu + @sprites[:commands] = Window_CommandPokemon.new([]) + @sprites[:commands].visible = false + @sprites[:commands].viewport = @viewport + # Info text box + @sprites[:info_text] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport) + @sprites[:info_text].visible = false + # Help text box + # @sprites[:help_text] = Window_UnformattedTextPokemon.newWithSize("", 0, 0, 32, 32, @viewport) + # @sprites[:help_text].visible = false + end + + #----------------------------------------------------------------------------- + + # commands is [[command IDs], [command names]]. + def set_commands(commands) + @commands = commands + cmd_window = @sprites[:commands] + cmd_window = @commands[1] + cmd_window.index = $game_temp.menu_last_choice + cmd_window.resizeToFit(@commands) + cmd_window.x = Graphics.width - cmd_window.width + cmd_window.y = 0 + cmd_window.visible = true + end + + #----------------------------------------------------------------------------- + + def show_menu + @sprites[:commands].visible = true + @sprites[:info_text].visible = @info_state + # @sprites[:help_text].visible = @help_state + end + + def hide_menu + @sprites[:commands].visible = false + @sprites[:info_text].visible = false + # @sprites[:help_text].visible = false + end + + # Used in Safari Zone and Bug-Catching Contest to show extra information. + def show_info(text) + @sprites[:info_text].resizeToFit(text, Graphics.height) + @sprites[:info_text].text = text + @sprites[:info_text].visible = true + @info_state = true + end + + # Unused. + # def show_help(text) + # @sprites[:help_text].resizeToFit(text, Graphics.height) + # @sprites[:help_text].text = text + # @sprites[:help_text].visible = true + # pbBottomLeft(@sprites[:help_text]) + # @help_state = true + # end + + #----------------------------------------------------------------------------- + + def update_visuals + pbUpdateSceneMap + super + end + + def update_input + if Input.trigger?(Input::BACK) || Input.trigger?(Input::ACTION) + return :quit + end + if Input.trigger?(Input::USE) + idx = @sprites[:commands].index + return @commands[0][idx] + end + return nil + end +end + +#=============================================================================== +# +#=============================================================================== +class UI::PauseMenuScreen < UI::BaseUIScreen + def initialize + raise _INTL("Tried to open the pause menu when $player was not defined.") if !$player + initialize_commands + super + end + + def initialize_commands + @commands ||= [[], []] + @commands.clear + @commands_hashes ||= {} + @commands_hashes.clear + MenuHandlers.each_available(:pause_menu) do |option, hash, name| + @commands[0].push(option) + @commands[1].push(name) + @commands_hashes[option] = hash + end + end + + def initialize_visuals + @visuals = UI::PauseMenuVisuals.new + @visuals.set_commands(@commands) + end + + def start_screen + pbSEPlay("GUI menu open") + end + + def end_screen + pbPlayCloseMenuSE if !@silent_quit + @visuals.dispose + end + + #----------------------------------------------------------------------------- + + def perform_action(command) + if @commands_hashes[command]["effect"].call(@visuals) + @silent_quit = true + return :quit + end + return nil + end +end diff --git a/Data/Scripts/016b_UI redesign/012_UIRedesign_TrainerCard.rb b/Data/Scripts/016b_UI redesign/012_UIRedesign_TrainerCard.rb new file mode 100644 index 000000000..edba150af --- /dev/null +++ b/Data/Scripts/016b_UI redesign/012_UIRedesign_TrainerCard.rb @@ -0,0 +1,126 @@ +#=============================================================================== +# +#=============================================================================== +class UI::TrainerCardVisuals < UI::BaseUIVisuals + GRAPHICS_FOLDER = "Graphics/UI/Trainer Card/" + BADGE_SIZE = [32, 32] # [width, height] of a Gym Badge + BADGE_SPACING = 16 # Size of gap between adjacent Gym Badges + FIRST_BADGE_X = 72 # Left edge of the first Gym Badge + FIRST_BADGE_Y = 310 # Top edge of the first Gym Badge + BADGE_COUNT = 8 # Number of Gym Badges to show + + def initialize_sprites + # Trainer card + add_icon_sprite(:card, 0, 0, GRAPHICS_FOLDER + gendered_filename(_INTL("trainer_card"))) + # Player sprite (coordinates are the bottom middle of the sprite) + add_icon_sprite(:player, 400, 240, GameData::TrainerType.player_front_sprite_filename($player.trainer_type)) + if !@sprites[:player].bitmap + raise _INTL("No trainer front sprite exists for the player character, expected a file at {1}.", + "Graphics/Trainers/" + $player.trainer_type.to_s + ".png") + end + @sprites[:player].x -= @sprites[:player].bitmap.width / 2 + @sprites[:player].y -= @sprites[:player].bitmap.height + @sprites[:player].z = 10 + end + + #----------------------------------------------------------------------------- + + def refresh_overlay + super + overlay = @sprites[:overlay].bitmap + draw_ID(overlay) + draw_stats(overlay) + draw_badges(overlay) + end + + # Draws the player's name and ID number onto the overlay. + def draw_ID(overlay) + pbDrawTextPositions(overlay, [ + [_INTL("Name"), 34, 70, :left, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [$player.name, 302, 70, :right, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [_INTL("ID No."), 332, 70, :left, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [sprintf("%05d", $player.public_ID), 468, 70, :right, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR] + ]) + end + + # Draws the player's money, Pokédex numbers, play time and start date onto the + # overlay. + def draw_stats(overlay) + # Create money text + money_text = _INTL("${1}", $player.money.to_s_formatted) + # Create Pokédex stats text + pokedex_text = sprintf("%d/%d", $player.pokedex.owned_count, $player.pokedex.seen_count) + # Create play time text + total_secs = $stats.play_time.to_i + hour = (total_secs / 60) / 60 + min = (total_secs / 60) % 60 + play_time = (hour > 0) ? _INTL("{1}h {2}m", hour, min) : _INTL("{1}m", min) + # Create start date text + $PokemonGlobal.startTime = Time.now if !$PokemonGlobal.startTime + # TODO: Put this date the proper way round for non-United States of Americans. + start_date = _INTL("{1} {2}, {3}", + pbGetAbbrevMonthName($PokemonGlobal.startTime.mon), + $PokemonGlobal.startTime.day, + $PokemonGlobal.startTime.year) + # Draw text + pbDrawTextPositions(overlay, [ + [_INTL("Money"), 34, 118, :left, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [money_text, 302, 118, :right, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [_INTL("Pokédex"), 34, 166, :left, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [pokedex_text, 302, 166, :right, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [_INTL("Time"), 34, 214, :left, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [play_time, 302, 214, :right, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [_INTL("Started"), 34, 262, :left, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR], + [start_date, 302, 262, :right, BLACK_TEXT_COLOR, BLACK_TEXT_SHADOW_COLOR] + ]) + end + + # Draws the player's owned Gym Badges onto the overlay. + def draw_badges(overlay) + x = FIRST_BADGE_X + region = pbGetCurrentRegion(0) # Get the current region + BADGE_COUNT.times do |i| + if $player.badges[i + (region * BADGE_COUNT)] + pbDrawImagePositions(overlay, [ + [GRAPHICS_FOLDER + "icon_badges", x, FIRST_BADGE_Y, i * BADGE_SIZE[0], region * BADGE_SIZE[1], *BADGE_SIZE] + ]) + end + x += BADGE_SIZE[0] + BADGE_SPACING + end + end +end + +#=============================================================================== +# +#=============================================================================== +class UI::TrainerCardScreen < UI::BaseUIScreen + def initialize_visuals + @visuals = UI::TrainerCardVisuals.new + end + + def start_screen + super + pbSEPlay("GUI trainer card open") + end + + def end_screen + pbPlayCloseMenuSE + super + end +end + +#=============================================================================== +# +#=============================================================================== +MenuHandlers.add(:pause_menu, :new_trainer_card, { + "name" => proc { next "New Trainer Card" }, + "order" => 55, + "effect" => proc { |menu| + pbPlayDecisionSE + pbFadeOutIn do + UI::TrainerCardScreen.new + menu.pbRefresh + end + next false + } +})