#===============================================================================
# 
# OriginalWij and Yanfly Collaboration - Keyboard Input
# Last Date Updated: 2010.06.12
# Level: Normal
# 
# This is a utility script that provides the functionality to return inputs
# from the keyboard as well as free up more keys to be used in the Input module.
# This script will also replace Scene_Name and allow for direct keyboard input
# to type in an actor's name as well as fix the maximum characters shown from
# the default base script.
# 
#===============================================================================
# Updates
# -----------------------------------------------------------------------------
# o 2010.06.12 - Started and Finished Script.
#===============================================================================
# Instructions
# -----------------------------------------------------------------------------
# To install this script, open up your script editor and copy/paste this script
# to an open slot below ▼ Materials but above ▼ Main. Remember to save.
# 
# For users:
#   The Name Input event has been now replaced. It not longer takes you to the
#   name entry scene, but instead, allows the player to enter in the name of
#   the desired actor right in the current screen itself without needing to
#   change the scene altogether.
# 
# For scripters:
#   For those curious as to how to retrieve certain letters while coding their
#   Input commands, use the following as reference
#   
#   LETTERS['A'] through LETTERS['Z']
#     This returns true if the respective letter from A through Z is pressed.
#   
#   NUMBERS[0] through NUMBERS[9]
#     This returns true if the respective number on the top row of the keyboard
#     is pressed. This does not include the numberpad.
#   
#   NUMPAD[0] through NUMPAD[9]
#     This returns true if the respective number in the number pad is pressed.
#     This does not include the numbers found at the top row of the keyboard.
#   
#   Symbol Keys
#     
#     USCORE  - This returns true if the - key is pressed.
#     EQUALS  - This returns true if the = key is pressed.
#     SCOLON  - This returns true if the ; key is pressed.
#     QUOTE   - This returns true if the ' key is pressed.
#     COMMA   - This returns true if the , key is pressed.
#     PERIOD  - This returns true if the . key is pressed.
#     SLASH   - This returns true if the / key is pressed.
#     BSLASH  - This returns true if the \ key is pressed.
#     LBRACE  - This returns true if the [ key is pressed.
#     RBRACE  - This returns true if the ] key is pressed.
#     TILDE   - This returns true if the ~ key is pressed.
#   
#   Command Keys
#     
#     BACK    - This returns true if the backspace key is pressed.
#     ENTER   - This returns true if the enter/return key is pressed.
#     SPACE   - This returns true if the space bar is pressed.
#     ESC     - This returns true if the escape key is pressed.
#   
#   Module Methods
#     
#     Input.typing?
#       To check if typing is occurring. Returns true or false.
#     
#     Input.key_type
#       Returns whatever key is being used to type as a string.
#   
#   Example:
#   
#     if Input.typing?
#       string = Input.key_type
#     end
# 
#===============================================================================

$imported = {} if $imported == nil
$imported["KeyboardInput"] = true

#===============================================================================
# Editting anything past this point may potentially result in causing computer
# damage, incontinence, explosion of user's head, coma, death, and/or halitosis.
# Therefore, edit at your own risk.
#===============================================================================

#===============================================================================
# Input
#===============================================================================

class << Input  
  #--------------------------------------------------------------------------
  # Aliases (Mods - Linked to Module) - Created by OriginalWij
  #--------------------------------------------------------------------------
  alias ow_dt_i_press press? unless $@
  alias ow_dt_i_trigger trigger? unless $@
  alias ow_dt_i_repeat repeat? unless $@
  alias ow_dt_i_update update unless $@
end

module Input
  #--------------------------------------------------------------------------
  # constants - Created by OriginalWij and Yanfly
  #--------------------------------------------------------------------------
  LETTERS = {}        
  LETTERS['A'] = 65; LETTERS['B'] = 66; LETTERS['C'] = 67; LETTERS['D'] = 68
  LETTERS['E'] = 69; LETTERS['F'] = 70; LETTERS['G'] = 71; LETTERS['H'] = 72
  LETTERS['I'] = 73; LETTERS['J'] = 74; LETTERS['K'] = 75; LETTERS['L'] = 76
  LETTERS['M'] = 77; LETTERS['N'] = 78; LETTERS['O'] = 79; LETTERS['P'] = 80
  LETTERS['Q'] = 81; LETTERS['R'] = 82; LETTERS['S'] = 83; LETTERS['T'] = 84
  LETTERS['U'] = 85; LETTERS['V'] = 86; LETTERS['W'] = 87; LETTERS['X'] = 88
  LETTERS['Y'] = 89; LETTERS['Z'] = 90
  NUMBERS = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57]
  NUMPAD = [96, 97, 98, 99, 100, 101, 102, 103, 104, 105] 
  BACK   = 138; ENTER  = 143; SPACE  = 32;  SCOLON = 186; ESC    = 157
  QUOTE  = 222; EQUALS = 187; COMMA  = 188; USCORE = 189; PERIOD = 190
  SLASH  = 191; LBRACE = 219; RBRACE = 221; BSLASH = 220; TILDE  = 192
  F10    = 121; F11    = 122; CAPS   = 20;  NMUL   = 106; NPLUS  = 107
  NSEP   = 108; NMINUS = 109; NDECI  = 110; NDIV   = 111; Extras = 
  [USCORE, EQUALS, LBRACE, RBRACE, BSLASH, SCOLON, QUOTE, COMMA, PERIOD, SLASH,
   NMUL, NPLUS, NSEP, NMINUS, NDECI, NDIV]

  #--------------------------------------------------------------------------
  # initial module settings - Created by OriginalWij and Yanfly
  #--------------------------------------------------------------------------
  GetKeyState = Win32API.new("user32", "GetAsyncKeyState", "i", "i") 
  GetCapState = Win32API.new("user32", "GetKeyState", "i", "i") 
  KeyRepeatCounter = {}
  module_function 
  #--------------------------------------------------------------------------
  # alias method: update - Created by OriginalWij
  #--------------------------------------------------------------------------
  def update
    ow_dt_i_update
    for key in KeyRepeatCounter.keys
      if (GetKeyState.call(key).abs & 0x8000 == 0x8000)
        KeyRepeatCounter[key] += 1
      else
        KeyRepeatCounter.delete(key)
      end
    end
  end
  
  #--------------------------------------------------------------------------
  # alias method: press? - Created by OriginalWij
  #--------------------------------------------------------------------------
  def press?(key)
    return ow_dt_i_press(key) if key < 30
    adjusted_key = adjust_key(key)
    return true unless KeyRepeatCounter[adjusted_key].nil?
    return key_pressed?(adjusted_key)
  end
  
  #--------------------------------------------------------------------------
  # alias method: trigger? - Created by OriginalWij
  #--------------------------------------------------------------------------
  def trigger?(key)
    return ow_dt_i_trigger(key) if key < 30
    adjusted_key = adjust_key(key)
    count = KeyRepeatCounter[adjusted_key]
    return ((count == 0) or (count.nil? ? key_pressed?(adjusted_key) : false))
  end
  
  #--------------------------------------------------------------------------
  # alias method: repeat? - Created by OriginalWij
  #--------------------------------------------------------------------------
  def repeat?(key)
    return ow_dt_i_repeat(key) if key < 30
    adjusted_key = adjust_key(key)
    count = KeyRepeatCounter[adjusted_key]
    return true if count == 0
    if count.nil?
      return key_pressed?(adjusted_key)
    else
      return (count >= 23 and (count - 23) % 6 == 0)
    end
  end
  
  #--------------------------------------------------------------------------
  # new method: adjust_key - Created by OriginalWij
  #--------------------------------------------------------------------------
  def adjust_key(key)
    key -= 130 if key.between?(130, 158)
    return key
  end
  
  #--------------------------------------------------------------------------
  # new method: key_pressed? - Created by OriginalWij
  #--------------------------------------------------------------------------
  def key_pressed?(key)
    if (GetKeyState.call(key).abs & 0x8000 == 0x8000)
      KeyRepeatCounter[key] = 0
      return true
    end
    return false
  end
  
  #--------------------------------------------------------------------------
  # new method: typing? - Created by Yanfly
  #--------------------------------------------------------------------------
  def typing?
    return true if repeat?(SPACE)
    for i in 'A'..'Z'
      return true if repeat?(LETTERS[i])
    end
    for i in 0...NUMBERS.size
      return true if repeat?(NUMBERS[i])
      return true if repeat?(NUMPAD[i])
    end
    for key in Extras
      return true if repeat?(key)
    end
    return false
  end
  
  #--------------------------------------------------------------------------
  # new method: key_type - Created by Yanfly
  #--------------------------------------------------------------------------
  def key_type
    return " " if repeat?(SPACE)
    for i in 'A'..'Z'
      next unless repeat?(LETTERS[i])
      return upcase? ? i.upcase : i.downcase
    end
    for i in 0...NUMBERS.size
      return i.to_s if repeat?(NUMPAD[i])
      if !press?(SHIFT)
        return i.to_s if repeat?(NUMBERS[i])
      elsif repeat?(NUMBERS[i])
        case i
        when 1; return "!"
        when 2; return "@"
        when 3; return "#"
        when 4; return "$"
        when 5; return "%"
        when 6; return "^"
        when 7; return "&"
        when 8; return "*"
        when 9; return "("
        when 0; return ")"
        end
      end
    end
    for key in Extras
      next unless repeat?(key)
      case key
      when USCORE; return press?(SHIFT) ? "_" : "-"
      when EQUALS; return press?(SHIFT) ? "+" : "="
      when LBRACE; return press?(SHIFT) ? "{" : "["
      when RBRACE; return press?(SHIFT) ? "}" : "]"
      when BSLASH; return press?(SHIFT) ? "|" : "\\"
      when SCOLON; return press?(SHIFT) ? ":" : ";"
      when QUOTE;  return press?(SHIFT) ? '"' : "'"
      when COMMA;  return press?(SHIFT) ? "<" : ","
      when PERIOD; return press?(SHIFT) ? ">" : "."
      when SLASH;  return press?(SHIFT) ? "?" : "/"
      when NMUL;   return "*"
      when NPLUS;  return "+"
      when NSEP;   return ","
      when NMINUS; return "-"
      when NDECI;  return "."
      when NDIV;   return "/"
      end
    end
    return ""
  end
  
  #--------------------------------------------------------------------------
  # new method: upcase? - Created by Yanfly
  #--------------------------------------------------------------------------
  def upcase?
    return !press?(SHIFT) if GetCapState.call(CAPS) == 1
    return true if press?(SHIFT)
    return false
  end
  
end # Input

#===============================================================================
# Game_Interpreter
#===============================================================================

class Game_Interpreter
  
  #--------------------------------------------------------------------------
  # overwrite method: command_303 (Name Input Processing)
  #--------------------------------------------------------------------------
  def command_303
    if $data_actors[@params[0]] != nil
      $scene.name_entry(@params[0], @params[1])
    end
    @index += 1
    return false
  end
  
end # Game_Interpreter

#===============================================================================
# Window_NameEdit
#===============================================================================

class Window_NameEdit < Window_Base
  
  #--------------------------------------------------------------------------
  # overwrite method: initialize
  #--------------------------------------------------------------------------
  def initialize(actor, max_char)
    dw = Graphics.width - 176
    dy = (Graphics.height - 128) / 2
    if $game_message.visible
      difference = Graphics.height - 128
      case $game_message.position
      when 0; dy += 64
      when 1; dy += 0
      when 2; dy -= 64
      end
    end
    super(88, dy, dw, 128)
    @actor = actor
    @name = actor.name
    @max_char = max_char
    name_array = @name.split(//)[0...@max_char]
    @name = ""
    for i in 0...name_array.size
      @name += name_array[i]
    end
    @default_name = @name
    @index = name_array.size
    self.active = false
    refresh
    update_cursor
  end
  
  #--------------------------------------------------------------------------
  # overwrite method: item_rect
  #--------------------------------------------------------------------------
  def item_rect(index)
    if index == @max_char
      rect = Rect.new(0, 0, 0, 0)
    else
      rect = Rect.new(0, 0, 0, 0)
      rect.x = 112 + index * 12
      rect.y = 36
      rect.width = 24
      rect.height = WLH
    end
    return rect
  end
  
end # Window_NameEdit

#===============================================================================
# Scene_Base
#===============================================================================

class Scene_Base
  
  #--------------------------------------------------------------------------
  # new method: name_entry
  #--------------------------------------------------------------------------
  def name_entry(actor_id, max_char)
    @name_actor_id = actor_id
    @name_entry_max = max_char
    start_name_entry
    end_name_entry
  end
  
  #--------------------------------------------------------------------------
  # new method: start_name_entry
  #--------------------------------------------------------------------------
  def start_name_entry
    Graphics.freeze
    actor = $game_actors[@name_actor_id]
    @edit_window = Window_NameEdit.new(actor, @name_entry_max)
    Graphics.transition(10)
    loop do
      update_name_entry
      if Input.repeat?(Input::BACK) and @edit_window.index > 0
        Sound.play_cancel
        @edit_window.back
      elsif Input.typing? and @edit_window.index != @edit_window.max_char
        Sound.play_cursor
        @edit_window.add(Input.key_type)
      elsif Input.trigger?(Input::ENTER)
        Sound.play_decision
        actor.name = @edit_window.name
        break
      elsif Input.trigger?(Input::ESC)
        Sound.play_cancel
        break
      end
    end
  end
  
  #--------------------------------------------------------------------------
  # new method: update_name_entry
  #--------------------------------------------------------------------------
  def update_name_entry
    update_menu_background
    Graphics.update
    Input.update
    if $scene.is_a?(Scene_Map)
      $game_map.update
      @spriteset.update
    elsif $scene.is_a?(Scene_Battle)
      Graphics.update
      Input.update
      $game_system.update
      $game_troop.update
      @spriteset.update
      @message_window.update
    end
    @edit_window.update
  end
  
  #--------------------------------------------------------------------------
  # end_name_entry
  #--------------------------------------------------------------------------
  def end_name_entry
    @edit_window.dispose
    @edit_window = nil
    @name_actor_id = nil
    @name_entry_max = nil
  end
  
end # Scene_Base

#===============================================================================
# 
# END OF FILE
# 
#===============================================================================