#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=: # DRG - Custom Input # Version 1.00 # Author : LiTTleDRAgo #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=: # # How to use : # Keyboard.press?(KEY) # Keyboard.trigger?(KEY) # Keyboard.repeat?(KEY) # Keyboard.release?(KEY) # # KEY = Keyboard key (as a string or symbol), look at ASCII table below # # Example : # Keyboard.press?(:Enter) # Keyboard.press?('Enter') # #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=: ($imported ||= {})[:drg_custom_input] = 1.00 $imported[:drg_core_engine] || raise("This script needs Drago Core Engine") #============================================================================== # ** Keyboard #------------------------------------------------------------------------------ # #============================================================================== module Keyboard #---------------------------------------------------------------------------- # * Public Instance Variable #---------------------------------------------------------------------------- class << self attr_sec_reader :getkeysta, "Win32API.new('user32','GetKeyboardState','p','i')" attr_sec_reader :getkeylay, "Win32API.new('user32','GetKeyboardLayout','l','l')" attr_sec_reader :mapvirkey, "Win32API.new('user32','MapVirtualKeyEx','iil','i')" attr_sec_reader :tounicode, "Win32API.new('user32','ToUnicodeEx','llppill','l')" end #---------------------------------------------------------------------------- # * Simple ASCII table #---------------------------------------------------------------------------- Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70, 'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76, 'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82, 'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88, 'Y' => 89, 'Z' => 90, '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53, '6' => 54, '7' => 55, '8' => 56, '9' => 57, 'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40, 'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12, 'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38, 'NumberPad 9' => 33, 'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116, 'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121, 'F11' => 122, 'F12' => 123, ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220, '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192, 'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16, 'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162, 'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165, 'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33, 'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45, 'Delete' => 46, 'Arrow Left' => 37, 'Arrow Up' => 38, 'Left' => 37, 'Up' => 38, 'Arrow Right' => 39, 'Arrow Down' => 40, 'Right' => 39, 'Down' => 40, 'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4, 'Mouse 4' => 5, 'Mouse 5' => 6} #---------------------------------------------------------------------------- # * Constant #---------------------------------------------------------------------------- KEY_COUNT = 256 ALL_KEYS = (0...KEY_COUNT).to_a DOWN_STATE_MASK = 0x80 DEAD_KEY_MASK = 0x80000000 #---------------------------------------------------------------------------- # * Data #---------------------------------------------------------------------------- @state = "\0" * KEY_COUNT #---------------------------------------------------------------------------- # * update # Updates input. #---------------------------------------------------------------------------- def self.update @language_layout = getkeylay.call(0) getkeysta.call(@state) key = 0 @state.each_byte do |byte| if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK (@released||=[])[key] = false unless (@pressed||=[])[key] (@pressed||=[])[key] = (@triggered||=[])[key] = true @repeatedKey = key @repeatedCount = 0 else (@triggered||=[])[key] = false end if key == @repeatedKey (@repeatedCount||=0) < 17 ? @repeatedCount += 1 : @repeatedCount = 15 end elsif !(@released||=[])[key] if (@pressed||=[])[key] (@triggered||=[])[key] = (@pressed||=[])[key] = false (@released||=[])[key] = true key == @repeatedKey && (@repeatedKey = -1) && (@repeatedCount = 0) end else (@released||=[])[key] = false end key += 1 end end #---------------------------------------------------------------------------- # * dir4 # 4 direction check. #---------------------------------------------------------------------------- def self.dir4 return 2 if self.press?(:Down) return 4 if self.press?(:Left) return 6 if self.press?(:Right) return 8 if self.press?(:Up) return 0 end #---------------------------------------------------------------------------- # * dir8 # 8 direction check. #---------------------------------------------------------------------------- def self.dir8 down = self.press?(:Down) left = self.press?(:Left) return 1 if down && left right = self.press?(:Right) return 3 if down && right up = self.press?(:Up) return 7 if up && left return 9 if up && right return 2 if down return 4 if left return 6 if right return 8 if up return 0 end #---------------------------------------------------------------------------- # * trigger? # Test if key was triggered once. #---------------------------------------------------------------------------- def self.trigger?(keys) keys = [keys] unless keys.is_a?(Array) keys.collect! do |key| key.is_a?(String) || key.is_a?(Symbol) ? Key["#{key}"] : key end return keys.any? {|key| (@triggered||=[])[key]} end #---------------------------------------------------------------------------- # * press? # Test if key is being pressed. #---------------------------------------------------------------------------- def self.press?(keys) keys = [keys] unless keys.is_a?(Array) keys.collect! do |key| key.is_a?(String) || key.is_a?(Symbol) ? Key["#{key}"] : key end return keys.any? {|key| (@pressed||=[])[key]} end #---------------------------------------------------------------------------- # * pressed_any? # Test if any key is being pressed #---------------------------------------------------------------------------- def self.pressed_any? (@pressed||=[]).any? {|key| key == true} end #---------------------------------------------------------------------------- # * repeat? # Test if key is being pressed for repeating. #---------------------------------------------------------------------------- def self.repeat?(keys) keys = [keys] unless keys.is_a?(Array) keys.collect! do |key| key.is_a?(String) || key.is_a?(Symbol) ? Key["#{key}"] : key end return ((@repeatedKey||=-1) >= 0 && keys.include?(@repeatedKey) && (@repeatedCount == 1 || @repeatedCount == 16)) end #---------------------------------------------------------------------------- # * release? # Test if key was released. #---------------------------------------------------------------------------- def self.release?(keys) keys = [keys] unless keys.is_a?(Array) keys.collect! do |key| key.is_a?(String) || key.is_a?(Symbol) ? Key["#{key}"] : key end return keys.any? {|key| (@released||=[])[key]} end #---------------------------------------------------------------------------- # * get_character # vk - virtual key # Gets the character from keyboard input using the input locale identifier # (formerly called keyboard layout handles). #---------------------------------------------------------------------------- def self.get_character(vk) c = self.mapvirkey.call(vk, 2, @language_layout) return '' if c < 32 && (c & DEAD_KEY_MASK) != DEAD_KEY_MASK vsc = self.mapvirkey.call(vk, 0, @language_layout) length = self.tounicode.call(vk,vsc,@state,(r="\0"*4),4,0,@language_layout) return (length == 0 ? '' : r) end #---------------------------------------------------------------------------- # * get_input_string # Gets the string that was entered using the keyboard over the input locale # identifier (formerly called keyboard layout handles). #---------------------------------------------------------------------------- def self.get_input_string result = '' ALL_KEYS.each do |key| self.repeat?(key) && (c = self.get_character(key)) != '' && result += c end return '' if result == '' return self.unicode_to_utf8(result) end #---------------------------------------------------------------------------- # * unicode_to_utf8 # string - string in Unicode format # Converts a string from Unicode format to UTF-8 format as RGSS does not # support Unicode. #---------------------------------------------------------------------------- def self.unicode_to_utf8(string) result = '' string.unpack('L*').each {|c| if c < 0x0080 result += c.chr elsif c < 0x0800 result += (0xC0 | (c >> 6)).chr result += (0x80 | (c & 0x3F)).chr elsif c < 0x10000 result += (0xE0 | (c >> 12)).chr result += (0x80 | ((c >> 6) & 0x3F)).chr result += (0x80 | (c & 0x3F)).chr elsif c < 0x200000 result += (0xF0 | (c >> 18)).chr result += (0x80 | ((c >> 12) & 0x3F)).chr result += (0x80 | ((c >> 6) & 0x3F)).chr result += (0x80 | (c & 0x3F)).chr elsif c < 0x4000000 result += (0xF8 | (c >> 24)).chr result += (0x80 | ((c >> 18) & 0x3F)).chr result += (0x80 | ((c >> 12) & 0x3F)).chr result += (0x80 | ((c >> 6) & 0x3F)).chr result += (0x80 | (c & 0x3F)).chr elsif c < 0x80000000 result += (0xFC | (c >> 30)).chr result += (0x80 | ((c >> 24) & 0x3F)).chr result += (0x80 | ((c >> 18) & 0x3F)).chr result += (0x80 | ((c >> 12) & 0x3F)).chr result += (0x80 | ((c >> 6) & 0x3F)).chr result += (0x80 | (c & 0x3F)).chr end} return result end end #============================================================================== # ** Input #------------------------------------------------------------------------------ # This module handles all Input #============================================================================== class << Input #---------------------------------------------------------------------------- # * Alias Listing #---------------------------------------------------------------------------- alias_sec_method :drago_input_keyboard_update, :update #---------------------------------------------------------------------------- # * Frame Update #---------------------------------------------------------------------------- def update(*args) drago_input_keyboard_update(*args) Keyboard.update end end #============================================================================== # ** Kernel #------------------------------------------------------------------------------ # #============================================================================== module Kernel #------------------------------------------------------------------------- # * Overwriten method: press_any_key #------------------------------------------------------------------------- def press_any_key return true if Keyboard.pressed_any? end end