mkxp-sunshine/scripts/Window_NameInput.rb
2016-04-06 13:45:36 -04:00

258 lines
8.7 KiB
Ruby

#==============================================================================
# ** Window_NameInput
#------------------------------------------------------------------------------
# This window is used to select text characters on the input name screen.
#==============================================================================
class NameInputMode
attr_reader :names
attr_reader :size
attr_accessor :index
attr_accessor :count
def initialize(names, bitmap)
@names = names
@size = names.map { |n| bitmap.text_size(n).width }.max
@index = 0
@count = 0
end
def cycle
@index = (@index + 1) % @count
end
def label
@names[(@index + 1) % @count]
end
end
class Window_NameInput < Window_Base
BUTTON_BUFFER = 8
BUTTON_PADDING = 16
attr_accessor :index
attr_accessor :ok_text
attr_accessor :character_tables
attr_accessor :table_height
attr_accessor :char_w
attr_accessor :char_h
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 128, 640, 352)
self.contents = Bitmap.new(width - 32, height - 32)
@index = 0
@ok_text = "OK"
@char_w = 28
@char_h = 32
end
def init
# Create dimension information
@table_size = @character_tables.values.first.size
@table_width = @table_size / @table_height
@start_x = ((width - 32) - @table_width * @char_w) / 2
@start_y = ((height - 32) - (@table_height + 1) * @char_h + BUTTON_BUFFER) / 2
@ok_text_size = self.contents.text_size(@ok_text).width
# Initialize mode information
@character_tables.each_key do |key|
key.each_with_index do |new_max, i|
@modes[i].count = new_max + 1 if @modes[i].count < new_max + 1
end
end
refresh
update_cursor_rect
self
end
#--------------------------------------------------------------------------
# * Properties
#--------------------------------------------------------------------------
def set_mode_buttons(buttons)
@modes = buttons.map { |n| NameInputMode.new(n, self.contents) }
end
#--------------------------------------------------------------------------
# * Text Character Acquisition
#--------------------------------------------------------------------------
def character
return current_table[@index]
end
#--------------------------------------------------------------------------
# * Mode Button Cursor Positioning
#--------------------------------------------------------------------------
def mode_button_slot
pos = @index % @table_width
x = 0
@modes.each_with_index do |mode, i|
size = mode.size + BUTTON_PADDING * 2
if pos * @char_w >= x && pos * @char_w <= x + size
if (pos + 1) * @char_w - BUTTON_PADDING <= x + size || i < @modes.size - 1
return i
end
end
x += size
end
return -1
end
#--------------------------------------------------------------------------
# * Cycle Current Mode
#--------------------------------------------------------------------------
def cycle_mode(slot)
@modes[slot].cycle
refresh
end
#--------------------------------------------------------------------------
# * Get Character Table for Mode
#--------------------------------------------------------------------------
def current_table
@character_tables[@modes.map { |m| m.index }]
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
self.contents.clear
table = current_table
@table_size.times do |i|
x = @start_x + (i % @table_width) * @char_w
y = @start_y + (i / @table_width) * @char_h
self.contents.draw_text(x, y, @char_w, @char_h, table[i], 1)
end
# OK button
self.contents.draw_text(@start_x + @table_width * @char_w - @ok_text_size - BUTTON_PADDING,
@start_y + @table_height * @char_h + BUTTON_BUFFER,
@ok_text_size, @char_h, @ok_text, 1)
# Mode buttons
x = @start_x + BUTTON_PADDING
@modes.each do |mode|
self.contents.draw_text(x, @start_y + @table_height * @char_h + BUTTON_BUFFER,
mode.size, @char_h, mode.label, 1)
x += BUTTON_PADDING * 2 + mode.size
end
end
#--------------------------------------------------------------------------
# * Cursor Rectangle Update
#--------------------------------------------------------------------------
def update_cursor_rect
if @index >= @table_size
# Cursor is positioned on OK or mode buttons
slot = mode_button_slot
if slot >= 0
# Cursor is positioned on mode button
x = @start_x
@modes.each_with_index do |mode, i|
if slot == i
self.cursor_rect.set(x, @start_y + @table_height * @char_h + BUTTON_BUFFER,
mode.size + BUTTON_PADDING * 2, @char_h)
break
end
x += BUTTON_PADDING * 2 + mode.size
end
else
# Cursor is positioned on OK button
self.cursor_rect.set(@start_x + @table_width * @char_w - @ok_text_size - BUTTON_PADDING * 2,
@start_y + @table_height * @char_h + BUTTON_BUFFER,
@ok_text_size + 32, @char_h)
end
else
# Cursor is not positioned on OK or mode buttons
x = @start_x + (@index % @table_width) * @char_w
y = @start_y + (@index / @table_width) * @char_h
self.cursor_rect.set(x, y, @char_w, @char_h)
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
if @index >= @table_size
# Cursor is positioned on OK or mode buttons
if Input.repeat?(Input::LEFT)
# If directional button pressed down is not a repeat, or
# cursor is not positioned on the left edge
old_slot = mode_button_slot
if Input.trigger?(Input::LEFT) || old_slot != 0
$game_system.se_play($data_system.cursor_se)
if old_slot == 0
@index = @table_size + @table_width - 1
else
loop do
@index -= 1
break if old_slot != mode_button_slot
end
end
end
end
if Input.repeat?(Input::RIGHT)
# If directional button pressed down is not a repeat, or
# cursor is not positioned on the right edge
old_slot = mode_button_slot
if Input.trigger?(Input::RIGHT) || old_slot != -1
$game_system.se_play($data_system.cursor_se)
if old_slot == -1
@index = @table_size
else
loop do
@index += 1
break if old_slot != mode_button_slot
end
end
end
end
if Input.trigger?(Input::DOWN)
$game_system.se_play($data_system.cursor_se)
@index -= @table_size
end
if Input.repeat?(Input::UP)
$game_system.se_play($data_system.cursor_se)
@index -= @table_width
end
else
# Cursor is not positioned on OK or mode buttons
if Input.repeat?(Input::RIGHT)
# If directional button pressed down is not a repeat, or
# cursor is not positioned on the right edge
if Input.trigger?(Input::RIGHT) || @index % @table_width < @table_width - 1
$game_system.se_play($data_system.cursor_se)
if @index % @table_width < @table_width - 1
@index += 1
else
@index -= @table_width - 1
end
end
end
if Input.repeat?(Input::LEFT)
# If directional button pressed down is not a repeat, or
# cursor is not positioned on the left edge
if Input.trigger?(Input::LEFT) || @index % @table_width > 0
$game_system.se_play($data_system.cursor_se)
if @index % @table_width > 0
@index -= 1
else
@index += @table_width - 1
end
end
end
if Input.repeat?(Input::DOWN)
$game_system.se_play($data_system.cursor_se)
@index += @table_width
end
if Input.repeat?(Input::UP)
# If directional button pressed down is not a repeat, or
# cursor is not positioned on the upper edge
if Input.trigger?(Input::UP) || @index >= @table_width
$game_system.se_play($data_system.cursor_se)
if @index >= @table_width
@index -= @table_width
else
@index += @table_size
end
end
end
end
update_cursor_rect
end
end