Advertisement
LiTTleDRAgo

[RGSS/2/3] Drago - Custom Input v2.00

Sep 4th, 2016
305
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 19.21 KB | None | 0 0
  1. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
  2. # DRG - Custom Input
  3. # Version 2.10
  4. # Author : LiTTleDRAgo
  5. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
  6. #
  7. # How to use :
  8. #   Keyboard.press?(KEY)
  9. #   Keyboard.trigger?(KEY)
  10. #   Keyboard.repeat?(KEY)
  11. #   Keyboard.release?(KEY)
  12. #   Mouse.press?(MKEY)
  13. #   Mouse.trigger?(MKEY)
  14. #   Mouse.repeat?(MKEY)
  15. #   Mouse.release?(MKEY)
  16. #
  17. #  KEY  = Keyboard key (as a string or symbol), look at ASCII table below
  18. #  MKEY = 'Mouse Left', 'Mouse Right', 'Mouse Middle'
  19. #
  20. #   Mouse.x              # returns x position of the mouse
  21. #   Mouse.y              # returns y position of the mouse
  22. #   Mouse.dragging?      # returns true if mouse is dragging
  23. #   Mouse.drag_rect      # returns as a rect if mouse is dragging
  24. #   Mouse.in_area?(RECT) # returns true if mouse position inside the area
  25. #   Mouse.scroll_up?     # returns true if mouse wheel is scrolled up
  26. #   Mouse.scroll_down?   # returns true if mouse wheel is scrolled down
  27. #
  28. # New in v 2.10
  29. #   Added MouseWheel.dll for smoother wheel scroll (Credit to KK20 for his dll)
  30. #   The DLL can be downloaded at forum chaos-project.
  31. #   (http://forum.chaos-project.com/index.php/topic,15450.0.html)
  32. #
  33. # Example :
  34. #   Keyboard.press?(:Enter)
  35. #   Keyboard.press?('Enter')
  36. #
  37. #:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
  38. ($imported ||= {})[:drg_custom_input] = 2.10
  39.  
  40. core_engine   = "This script needs Drago - Core Engine ver 1.51 or above"
  41. ($imported[:drg_core_engine] || 0) >= 1.51 || raise(core_engine)
  42.  
  43. #==============================================================================
  44. # ** Keyboard
  45. #------------------------------------------------------------------------------
  46. #  
  47. #==============================================================================
  48.  
  49. module Keyboard
  50.   #----------------------------------------------------------------------------
  51.   # * Public Instance Variable
  52.   #----------------------------------------------------------------------------
  53.   class << self
  54.     attr_sec_reader :getkeysta, 'LiTTleDRAgo.getkeysta'
  55.     attr_sec_reader :getkeylay, 'LiTTleDRAgo.getkeylay'
  56.     attr_sec_reader :mapvirkey, 'LiTTleDRAgo.mapvirkey'
  57.     attr_sec_reader :tounicode, 'LiTTleDRAgo.tounicode'
  58.   end
  59.   #----------------------------------------------------------------------------
  60.   # * Simple ASCII table
  61.   #----------------------------------------------------------------------------
  62.   Key = {'A' => 65, 'B' => 66, 'C' => 67, 'D' => 68, 'E' => 69, 'F' => 70,
  63.          'G' => 71, 'H' => 72, 'I' => 73, 'J' => 74, 'K' => 75, 'L' => 76,
  64.          'M' => 77, 'N' => 78, 'O' => 79, 'P' => 80, 'Q' => 81, 'R' => 82,
  65.          'S' => 83, 'T' => 84, 'U' => 85, 'V' => 86, 'W' => 87, 'X' => 88,
  66.          'Y' => 89, 'Z' => 90,
  67.          '0' => 48, '1' => 49, '2' => 50, '3' => 51, '4' => 52, '5' => 53,
  68.          '6' => 54, '7' => 55, '8' => 56, '9' => 57,
  69.          'NumberPad 0' => 45, 'NumberPad 1' => 35, 'NumberPad 2' => 40,
  70.          'NumberPad 3' => 34, 'NumberPad 4' => 37, 'NumberPad 5' => 12,
  71.          'NumberPad 6' => 39, 'NumberPad 7' => 36, 'NumberPad 8' => 38,
  72.          'NumberPad 9' => 33,
  73.          'F1' => 112, 'F2' => 113, 'F3' => 114, 'F4' => 115, 'F5' => 116,
  74.          'F6' => 117, 'F7' => 118, 'F8' => 119, 'F9' => 120, 'F10' => 121,
  75.          'F11' => 122, 'F12' => 123,
  76.          ';' => 186, '=' => 187, ',' => 188, '-' => 189, '.' => 190, '/' => 220,
  77.          '\\' => 191, '\'' => 222, '[' => 219, ']' => 221, '`' => 192,
  78.          'Backspace' => 8, 'Tab' => 9, 'Enter' => 13, 'Shift' => 16,
  79.          'Left Shift' => 160, 'Right Shift' => 161, 'Left Ctrl' => 162,
  80.          'Right Ctrl' => 163, 'Left Alt' => 164, 'Right Alt' => 165,
  81.          'Ctrl' => 17, 'Alt' => 18, 'Esc' => 27, 'Space' => 32, 'Page Up' => 33,
  82.          'Page Down' => 34, 'End' => 35, 'Home' => 36, 'Insert' => 45,
  83.          'Delete' => 46,
  84.          'Arrow Left'  => 37, 'Arrow Up'   => 38, 'Left' => 37,  'Up'   => 38,
  85.          'Arrow Right' => 39, 'Arrow Down' => 40, 'Right' => 39, 'Down' => 40,
  86.          'Mouse Left' => 1, 'Mouse Right' => 2, 'Mouse Middle' => 4,
  87.          'Mouse 4' => 5, 'Mouse 5' => 6}
  88.   #----------------------------------------------------------------------------
  89.   # * Constant
  90.   #----------------------------------------------------------------------------
  91.   KEY_COUNT       = 256
  92.   ALL_KEYS        = (0...KEY_COUNT).to_a
  93.   DOWN_STATE_MASK = 0x80
  94.   DEAD_KEY_MASK   = 0x80000000
  95.   #----------------------------------------------------------------------------
  96.   # * Data
  97.   #----------------------------------------------------------------------------
  98.   @state         = "\0" * KEY_COUNT
  99.   #----------------------------------------------------------------------------
  100.   # * update
  101.   #  Updates input.
  102.   #----------------------------------------------------------------------------
  103.   def self.update
  104.     @language_layout = getkeylay.call(0)
  105.     getkeysta.call(@state)
  106.     key = 0
  107.     @state.each_byte do |byte|
  108.       if (byte & DOWN_STATE_MASK) == DOWN_STATE_MASK  
  109.         (@released||=[])[key] = false                        
  110.         unless (@pressed||=[])[key]
  111.           @pressed[key] = (@triggered||=[])[key] = true
  112.           @repeatedKey = key
  113.           @repeatedCount = 0
  114.         else
  115.           (@triggered||=[])[key] = false
  116.         end
  117.         if key == @repeatedKey
  118.           (@repeatedCount||=0) < 17 ? @repeatedCount += 1 : @repeatedCount = 15
  119.         end
  120.       elsif !(@released||=[])[key]
  121.         if (@pressed||=[])[key]
  122.           (@triggered||=[])[key] = @pressed[key] = false
  123.           @released[key] = true
  124.           key == @repeatedKey && (@repeatedKey = -1) && (@repeatedCount = 0)
  125.         end
  126.       else
  127.         @released[key] = false
  128.       end
  129.       key += 1
  130.     end
  131.   end
  132.   #----------------------------------------------------------------------------
  133.   # * dir4
  134.   #  4 direction check.
  135.   #----------------------------------------------------------------------------
  136.   def self.dir4
  137.     return 2 if self.press?(:Down)
  138.     return 4 if self.press?(:Left)
  139.     return 6 if self.press?(:Right)
  140.     return 8 if self.press?(:Up)
  141.     return 0
  142.   end
  143.   #----------------------------------------------------------------------------
  144.   # * dir8
  145.   #  8 direction check.
  146.   #----------------------------------------------------------------------------
  147.   def self.dir8
  148.     left  = self.press?(:Left)
  149.     return 1 if (down  = self.press?(:Down)) && left
  150.     return 3 if (right = self.press?(:Right)) && down
  151.     return 7 if (up    = self.press?(:Up)) && left
  152.     return 9 if up && right
  153.     return 2 if down
  154.     return 4 if left
  155.     return 6 if right
  156.     return 8 if up
  157.     return 0
  158.   end
  159.   #----------------------------------------------------------------------------
  160.   # * trigger?
  161.   #  Test if key was triggered once.
  162.   #----------------------------------------------------------------------------
  163.   def self.trigger?(*keys)
  164.     keys_collect(keys).any? {|key| (@triggered ||= [])[key]}
  165.   end
  166.   #----------------------------------------------------------------------------
  167.   # * press?
  168.   #  Test if key is being pressed.
  169.   #----------------------------------------------------------------------------
  170.   def self.press?(*keys)
  171.     keys_collect(keys).any? {|key| (@pressed ||= [])[key]}
  172.   end
  173.   #----------------------------------------------------------------------------
  174.   # * pressed_any?
  175.   #  Test if any key is being pressed
  176.   #----------------------------------------------------------------------------
  177.   def self.pressed_any?
  178.     (@pressed ||= []).any? {|key| key == true}
  179.   end
  180.   #----------------------------------------------------------------------------
  181.   # * keys_collect
  182.   #  Collecting inputted keys into arrays
  183.   #----------------------------------------------------------------------------
  184.   def self.keys_collect(keys)
  185.     keys.collect! do |key|
  186.       key.is_a?(String) || key.is_a?(Symbol) ? Key["#{key}"] : key
  187.     end
  188.   end
  189.   #----------------------------------------------------------------------------
  190.   # * repeat?
  191.   #  Test if key is being pressed for repeating.
  192.   #----------------------------------------------------------------------------
  193.   def self.repeat?(*keys)
  194.     ((@repeatedKey ||= -1) >= 0 && keys_collect(keys).include?(@repeatedKey) &&
  195.         (@repeatedCount == 1 || @repeatedCount == 16))
  196.   end
  197.   #----------------------------------------------------------------------------
  198.   # * release?
  199.   #  Test if key was released.
  200.   #----------------------------------------------------------------------------
  201.   def self.release?(*keys)
  202.     keys_collect(keys).any? {|key| (@released ||= [])[key]}
  203.   end
  204.   #----------------------------------------------------------------------------
  205.   # * get_character
  206.   #  vk - virtual key
  207.   #  Gets the character from keyboard input using the input locale identifier
  208.   #  (formerly called keyboard layout handles).
  209.   #----------------------------------------------------------------------------
  210.   def self.get_character(vk)
  211.     c = self.mapvirkey.call(vk, 2, @language_layout)
  212.     return '' if c < 32 && (c & DEAD_KEY_MASK) != DEAD_KEY_MASK
  213.     vsc = self.mapvirkey.call(vk, 0, @language_layout)
  214.     length = self.tounicode.call(vk,vsc,@state,(r="\0"*4),4,0,@language_layout)
  215.     return (length == 0 ? '' : r)
  216.   end
  217. end
  218.  
  219. #==============================================================================
  220. # ** Mouse
  221. #------------------------------------------------------------------------------
  222. #  This module performs mouse input processing
  223. #==============================================================================
  224. module Mouse
  225.   #--------------------------------------------------------------------------
  226.   # * Declare Module Variables
  227.   #--------------------------------------------------------------------------
  228.   # Declare API calls
  229.   @getWindowRect = LiTTleDRAgo.winapi(2, 'GetWindowRect', 'lp', 'v')
  230.   @getMessage    = LiTTleDRAgo.winapi(2, 'GetMessage', 'plll', 'l')
  231.   @metrics       = LiTTleDRAgo.systemmetrix
  232.   @getCursorPos  = LiTTleDRAgo.cursorposition
  233.   # Get window thread
  234.   @window        = LiTTleDRAgo.hwnd
  235.   # Set up double click
  236.   @double_click  = false
  237.   @double_click_frames = 20
  238.   @double_click_pixels = 4
  239.   @double_click_counter = 0
  240.   # Set up wheel scroll
  241.   @wheel_scroll  = false
  242.   @wheel_scroll_frames = 10
  243.   @wheel_dll = File.exist?('MouseWheel.dll')
  244.   if @wheel_dll
  245.     StartWheel = Win32API.new('MouseWheel', 'Initialize', 'i', 'i')
  246.     StartWheel.call(1)
  247.     WheelDelta = Win32API.new('MouseWheel', 'WheelDelta', '', 'i')
  248.   end
  249.   # Set up drag
  250.   @drag_pixels   = 4
  251.   @drag_hold     = false
  252.   @mouse_drag    = [false, 0, 0, 0, 0]
  253.   # Set up last click
  254.   @last_click_x  = 0
  255.   @last_click_y  = 0
  256.   @@unpack_cache = {}
  257.   #----------------------------------------------------------------------------
  258.   # ● Redirect Listing
  259.   #----------------------------------------------------------------------------
  260.   redirect_method 'self.press?',       'Keyboard.press?'
  261.   redirect_method 'self.trigger?',     'Keyboard.trigger?'
  262.   redirect_method 'self.repeat?',      'Keyboard.repeat?'
  263.   redirect_method 'self.release?',     'Keyboard.release?'
  264.   redirect_method 'self.in_screen?',   '(@in_screen)'
  265.   redirect_method 'self.x',            '(@mouse_x)'
  266.   redirect_method 'self.y',            '(@mouse_y)'
  267.   redirect_method 'self.pos',          '([x, y])'
  268.   redirect_method 'self.dragging?',    '(@mouse_drag[0])'
  269.   #--------------------------------------------------------------------------
  270.   # * Mouse Keys
  271.   #--------------------------------------------------------------------------
  272.   SWAPBUTTON = @metrics.call(23) == 0 ? false : true # Buttons Swapped
  273.   LBUTTON    = 'Mouse Left'      # Physical Left Button
  274.   RBUTTON    = 'Mouse Right'     # Physical Right Button
  275.   MBUTTON    = 'Mouse Middle'    # Middle Mouse Button
  276.   XBUTTON1   = 'Mouse 4'         # X1 Mouse Button
  277.   XBUTTON2   = 'Mouse 5'         # X2 Mouse Button
  278.   PRIMARY    = !SWAPBUTTON ? LBUTTON : RBUTTON # Primary Mouse Button
  279.   SECONDARY  = !SWAPBUTTON ? RBUTTON : LBUTTON # Secondary Mouse Button
  280.   #--------------------------------------------------------------------------
  281.   # * Frame Update
  282.   #--------------------------------------------------------------------------
  283.   def self.update
  284.     @getWindowRect.call(@window, (rect = '0'*16))
  285.     left, top, right, bottom = rect.unpack("LLLL")
  286.     @window_x = left + (me5 = @metrics.call(5)) + (me45 = @metrics.call(45))
  287.     @window_y = top + (me6 = @metrics.call(6)) + (me46 = @metrics.call(46))
  288.     @window_y += (me4 = @metrics.call(4))
  289.     @window_width = (right - left) - ((me5 + me45) * 2)
  290.     @window_height = ((bottom - top) - ((me6 + me46) * 2)) - me4
  291.     @getCursorPos.call((cursor_position = '0'*8))
  292.     @mouse_x, @mouse_y = cursor_position.unpack('LL')
  293.     @mouse_x -= @window_x
  294.     @mouse_y -= @window_y
  295.     if (@mouse_x < 0 || @mouse_y < 0 || @mouse_x >= @window_width ||
  296.       @mouse_y >= @window_height)
  297.       @in_screen = false
  298.     else
  299.       @in_screen = true
  300.     end
  301.     @mouse_x = @mouse_x.clamp(0, @window_width  - 1)
  302.     @mouse_y = @mouse_y.clamp(0, @window_height - 1)
  303.     @double_click = false
  304.     x_deviance = (@last_click_x - @mouse_x).abs
  305.     y_deviance = (@last_click_y - @mouse_y).abs
  306.     if self.trigger?(PRIMARY)
  307.       deviance = @double_click_pixels
  308.       if (@double_click_counter > 0 && x_deviance <= deviance &&
  309.         y_deviance <= deviance)
  310.         @double_click = true
  311.       else
  312.         @double_click_counter = @double_click_frames
  313.       end
  314.       @drag_hold = true
  315.       @mouse_drag[1] = (@last_click_x = @mouse_x)
  316.       @mouse_drag[2] = (@last_click_y = @mouse_y)
  317.     elsif self.press?(PRIMARY)
  318.       if x_deviance >= @drag_pixels || y_deviance >= @drag_pixels
  319.         @mouse_drag[0] = true
  320.       end
  321.       if @mouse_drag[0] == true
  322.         @mouse_drag[3] = @mouse_x
  323.         @mouse_drag[4] = @mouse_y
  324.       end
  325.     elsif self.release?(PRIMARY)
  326.       @drag_hold = false
  327.       @mouse_drag[0] = false
  328.       @mouse_drag[1] = 0
  329.       @mouse_drag[2] = 0
  330.       @mouse_drag[3] = 0
  331.       @mouse_drag[4] = 0
  332.     end
  333.     @double_click_counter -= 1 if @double_click_counter > 0
  334.     @update_scroll_counter = (@update_scroll_counter || -1) + 1
  335.     @update_scroll_counter = update_scroll && 0 if self.scroll_can_update?  
  336.   end    
  337.   #--------------------------------------------------------------------------
  338.   # * scroll_can_update?
  339.   #--------------------------------------------------------------------------
  340.   def self.scroll_can_update?
  341.     return false unless @in_screen
  342.     return true if @wheel_dll
  343.     return false unless @wheel_scroll
  344.     return false unless @update_scroll_counter % @wheel_scroll_frames == 0
  345.     return false if Keyboard.pressed_any?
  346.     return false if @drag_hold || @mouse_drag[0]
  347.     return true
  348.   end
  349.   #--------------------------------------------------------------------------
  350.   # * unpack_dword
  351.   #--------------------------------------------------------------------------
  352.   def self.unpack_dword(buffer, offset = 0)
  353.     bitso = []
  354.     buffer.each_byte {|s| bitso << s }
  355.     ret = bitso[offset + 0] & 0x000000ff
  356.     ret |=(bitso[offset + 1] << (8 * 1)) & 0x0000ff00
  357.     ret |=(bitso[offset + 2] << (8 * 2)) & 0x00ff0000
  358.     ret |=(bitso[offset + 3] << (8 * 3)) & 0xff000000
  359.     return ret
  360.   end
  361.   #--------------------------------------------------------------------------
  362.   # * wmcallback
  363.   #--------------------------------------------------------------------------
  364.   def self.wmcallback(buffer)
  365.     @@unpack_cache[buffer] ||= (
  366.       message = unpack_dword(buffer,4 * 1)
  367.       if message == 0x0000020A
  368.         wparam = unpack_dword(buffer, 4 * 2)
  369.         wparam > 10000000 ? -1 : 1
  370.       else
  371.         0
  372.       end )
  373.     @@unpack_cache.shift! if @@unpack_cache.size > 500
  374.     return @@unpack_cache[buffer]  
  375.   end
  376.   #--------------------------------------------------------------------------
  377.   # * scroll_up?
  378.   #--------------------------------------------------------------------------
  379.   def self.scroll_up?
  380.     (@delta ||= self.update_scroll) > 0
  381.   end
  382.   #--------------------------------------------------------------------------
  383.   # * scroll_down?
  384.   #--------------------------------------------------------------------------
  385.   def self.scroll_down?
  386.     (@delta ||= self.update_scroll) < 0
  387.   end
  388.   #--------------------------------------------------------------------------
  389.   # * scroll?
  390.   #--------------------------------------------------------------------------
  391.   def self.scroll?
  392.     (@delta ||= 0) !=  0
  393.   end
  394.   #--------------------------------------------------------------------------
  395.   # * update_scroll
  396.   #--------------------------------------------------------------------------
  397.   def self.update_scroll
  398.     if @wheel_dll
  399.       @delta = WheelDelta.call
  400.       return
  401.     end
  402.     @getMessage.call((msg = "\0" * 32), @window, 0, 0)
  403.     @delta = wmcallback(msg)
  404.   end  
  405.   #--------------------------------------------------------------------------
  406.   # * Get Mouse Drag Rect
  407.   #--------------------------------------------------------------------------
  408.   def self.drag_rect
  409.     return Rect.new(0, 0, 0, 0) unless @mouse_drag[0]
  410.     x = @mouse_drag[1] <= @mouse_drag[3] ? @mouse_drag[1] : @mouse_drag[3]
  411.     y = @mouse_drag[2] <= @mouse_drag[4] ? @mouse_drag[2] : @mouse_drag[4]
  412.     width  = @mouse_drag[1] > @mouse_drag[3] ? @mouse_drag[1] : @mouse_drag[3]
  413.     height = @mouse_drag[2] > @mouse_drag[4] ? @mouse_drag[2] : @mouse_drag[4]
  414.     width  -= x
  415.     height -= y
  416.     return Rect.new(x, y, width, height)
  417.   end
  418.   #--------------------------------------------------------------------------
  419.   # * Get Mouse Drag Coordinates
  420.   #--------------------------------------------------------------------------
  421.   def self.drag_coor
  422.     return @mouse_drag[0] ? [@mouse_drag[1], @mouse_drag[2]] : self.pos
  423.   end
  424.   #--------------------------------------------------------------------------
  425.   # * Get Mouse in Area Flag
  426.   #--------------------------------------------------------------------------
  427.   def self.in_area?(*args)
  428.     return false if !@in_screen
  429.     if args[0].is_a?(Rect)
  430.       return (@mouse_x >= args[0].x && @mouse_y >= args[0].y &&
  431.         @mouse_x < args[0].x + args[0].width &&
  432.         @mouse_y < args[0].y + args[0].height)
  433.     else
  434.       return (@mouse_x >= args[0] && @mouse_y >= args[1] &&
  435.         @mouse_x < args[0] + args[2] && @mouse_y < args[1] + args[3])
  436.     end
  437.   end
  438.   #--------------------------------------------------------------------------
  439.   # * Initialize Module
  440.   #--------------------------------------------------------------------------
  441.   begin
  442.     self.update
  443.   end
  444. end
  445.  
  446. Input.auto_update.push([Keyboard,:update],[Mouse,:update])
  447. #==============================================================================
  448. # ** Kernel
  449. #------------------------------------------------------------------------------
  450. #  
  451. #==============================================================================
  452. module Kernel
  453.   #-------------------------------------------------------------------------
  454.   # * Overwriten method: press_any_key
  455.   #-------------------------------------------------------------------------
  456.   def press_any_key
  457.     return true if Keyboard.pressed_any? && Mouse.not.dragging?
  458.   end
  459. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement