Mithran

Window Selectable Max

Mar 30th, 2012
269
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.28 KB | None | 0 0
  1. # Window Selectable Max
  2. # v 2.0
  3. # By Mithran
  4. # corrects an error when creating the contents of a huge window selectable file
  5. # this will prevent those crashes occured when the party possesses more than ~682
  6. # items and attempts to look at them in the menu. Included in this script is a
  7. # simple draw optimizer for all subclasses of window selectable that use the methods
  8. # refresh and draw_item, which will signifincaly reduce startup lag on windows
  9. # with a large amount of selections
  10.  
  11. # This script is free to use in any project, including commerical projects.
  12. # Just don't repost and claim you made it. Credit must remain intact in the script.
  13. # Credit not required for the project as a whole.
  14.  
  15. # Install: Place above main, below anything that alters or uses windows.
  16. # Place the bitmap forwarding script below this one.
  17.  
  18. module WSHuge
  19. Optimize = true # turns on optomomization. no items will be drawn offscreen
  20. # draws will be queued as they come onto the screen
  21. # Change to false to see the difference in how long windows take to refresh!
  22.  
  23. DRAW_AHEAD_RATE = 2 # number of frames between draw-aheads in a scrolling window
  24. # the lower the faster
  25. # setting to 0 disables
  26. # draw aheads use some processing while the window is not scrolling, but may
  27. # increase performance while it is scrolling
  28.  
  29. # DO NOT MESS WITH BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING
  30.  
  31. UP = Rect.new(88, 8, 16, 16) # rect for up arrow in the windowskin
  32. LEFT = Rect.new(72, 24, 16, 16) # rect for left arrow in the windowskin
  33. DOWN = Rect.new(88, 40, 16, 16) # rect for down arrow in the windowskin
  34. RIGHT = Rect.new(104, 24, 16, 16) # rect for right arrow in the windowskin
  35.  
  36. CONTENTS_HEIGHT_MAX = 8184 # the maximum height of a single bitmap.
  37. # do not raise this, anything higher will cause the error this script
  38. # is intended to fix
  39. # must be lowered if the resolution is increased
  40.  
  41. end
  42.  
  43. class Window_Selectable
  44.  
  45. attr_reader :subwindows
  46.  
  47. alias initialize_wshuge initialize
  48. def initialize(*args)
  49. @subwindows = []
  50. initialize_wshuge(*args)
  51. @draw_queue = {} # creates a hash to store draw queues in
  52. ws_optimizer if WSHuge::Optimize
  53. # run optimizer
  54. end
  55.  
  56. def create_contents
  57. self.contents.dispose
  58. contents.fake_height = nil # clears fake height
  59. contents.fake_width = nil # clears fake height
  60. @huge_contents = false # resets the huge flag, which handles arrow pointers when the
  61. # window is really really big
  62. @subwindows.each {|w| w.dispose}
  63. @subwindows = []
  64. cw = width - 32 # get the desired contents width
  65. ch = [height - 32, row_max * WLH].max # get the desired contents height
  66. if ch > WSHuge::CONTENTS_HEIGHT_MAX
  67. self.contents = Bitmap.new(width - 32, height - 32)
  68. self.contents.fake_height = ch # set the fake height attribute, for if
  69. # contents.height is looked up from the window, the desired height is returned
  70. self.contents.fake_width = cw # set the fake width attribute, for if
  71. # self.ox = self.oy = 1 # enable all arrows for the main contents
  72. @huge_contents = true # set the huge flag
  73. # seperate_windowskin # seperate the arrows from the windowskin
  74. contents.window_callback = self
  75. while ch > 0
  76. window = Window_Contents.new(self.x, self.y, self.width, self.height)
  77. window.contents.dispose
  78. window.contents = Bitmap.new(cw, WSHuge::CONTENTS_HEIGHT_MAX)
  79. window.opacity = 0
  80. window.seperate_windowskin
  81. @subwindows.push(window)
  82. ch -= WSHuge::CONTENTS_HEIGHT_MAX
  83. end
  84. if @front_window == nil
  85. @front_window = Window_Front.new(self.x, self.y, self.width, self.height)
  86. @front_window.contents.dispose
  87. @front_window.contents = Bitmap.new(width - 30, height - 30)
  88. @front_window.seperate_windowskin
  89. @front_window.opacity = 0
  90. @front_window.ox = @front_window.oy = 1
  91. end
  92. sync_windows
  93. else # otherwise,
  94. @front_window.dispose if @front_window # get rid of front window if it exists
  95. @front_window = nil
  96. self.contents = Bitmap.new(cw, ch) # create a blank bitmap normally
  97. end
  98. end
  99.  
  100. def ws_optimizer # optimizer method
  101. instance_eval{ # set current scope to the calling instance
  102. class << self # defining in the metaclass of the current window, following methods are singletons
  103. # draw item does not exist at the window_selectable level, but this implementation will alter
  104. # all windows where it is defined that are subclasses of Window_Selectable
  105. if method_defined?(:draw_item) && !method_defined?(:draw_item_wshuge)
  106. # if draw item method exists, add a hook to it
  107. alias draw_item_wshuge draw_item
  108. def draw_item(*args)
  109. index = args[0] # get the index
  110. if onscreen?(index) or @drawahead
  111. # if the item will be drawn on the current screen or drawing ahead
  112. draw_item_wshuge(*args) # draw item
  113. else # otherwise
  114. @draw_queue[index] = args #queue the draw
  115. end # end if
  116. end # end def
  117. end # end if method defined?
  118. if method_defined?(:refresh) && !method_defined?(:refresh_wshuge)
  119. # if refresh method exists, add a hook to it
  120. alias refresh_wshuge refresh
  121. def refresh(*args)
  122. @draw_queue.clear # clear the draw queue
  123. refresh_wshuge(*args) # run original method
  124. end
  125. end
  126. end
  127. @optimized = true # set the optimized flag
  128. } # end instance eval
  129. end # end optimizer method
  130.  
  131. def onscreen?(index)
  132. return screen_indexes.to_a.include?(index) # tests if the index is on the
  133. # current screen
  134. end
  135.  
  136. def screen_indexes
  137. n = (top_row * @column_max) - 1
  138. return n..(n + page_item_max + @column_max) # the index of every item
  139. # that can be drawn on the current screen
  140. end
  141.  
  142. def refresh_screen # draws ONLY queued items for the current screen
  143. return unless visible
  144. for i in screen_indexes
  145. draw = @draw_queue[i]
  146. @draw_queue.delete(i)
  147. draw_item(*draw) unless draw.nil?
  148. end
  149. end
  150.  
  151. alias update_cursor_wshuge update_cursor
  152. def update_cursor
  153. update_cursor_wshuge
  154. update_arrows if @huge_contents # update the windowskin arrow bitmaps if huge
  155. refresh_screen if @optimized # refreshes ONLY the queued draw methods
  156. end
  157.  
  158. alias update_wshuge update
  159. def update
  160. update_wshuge
  161. update_subwindows if @huge_contents
  162. if @optimized && self.visible && WSHuge::DRAW_AHEAD_RATE != 0 && (Graphics.frame_count % Graphics.frame_rate) % WSHuge::DRAW_AHEAD_RATE == 0
  163. i = @draw_queue.keys.sort.first
  164. if i != nil
  165. @drawahead = true
  166. draw = @draw_queue[i]
  167. @draw_queue.delete(i)
  168. draw_item(*draw) unless draw.nil?
  169. @drawahead = false
  170. end
  171. end
  172.  
  173. end
  174.  
  175. def update_subwindows
  176. subwindows.each { |w| w.update }
  177. @front_window.update
  178. end
  179.  
  180. def update_arrows
  181. if @index < 0 or @index > @item_max
  182. # if the index is out of range
  183. @front_window.window_uparrow(false)
  184. @front_window.window_downarrow(false)
  185. @front_window.window_rightarrow(false)
  186. @front_window.window_leftarrow(false)
  187. return
  188. end
  189. if top_row == 0 # top page
  190. @front_window.window_uparrow(false)
  191. else
  192. @front_window.window_uparrow(true)
  193. end
  194. if bottom_row >= row_max - 1 # bottom page
  195. @front_window.window_downarrow(false)
  196. else
  197. @front_window.window_downarrow(true)
  198. end
  199. @front_window.window_rightarrow(false)
  200. @front_window.window_leftarrow(false)
  201. end
  202.  
  203. # below - totally irrelevant to this issue, but fixes a very annoying issue
  204. # where the skill window still scrolls by L & R input in the skill scene,
  205. # even though L and R are used to switch actors
  206. alias cursor_pageup_disable cursor_pageup
  207. def cursor_pageup
  208. return if self.instance_of?(Window_Skill) && $scene.instance_of?(Scene_Skill)
  209. cursor_pageup_disable
  210. end
  211.  
  212. alias cursor_pagedown_disable cursor_pagedown
  213. def cursor_pagedown
  214. return if self.instance_of?(Window_Skill) && $scene.instance_of?(Scene_Skill)
  215. cursor_pagedown_disable
  216. end
  217.  
  218. def sync_windows
  219. subwindows.each_with_index { |w, i|
  220. w.x, w.y, w.width, w.height, w.viewport, w.visible, w.openness = x, y, width, height, viewport, visible, openness
  221. w.oy = self.oy - i * w.contents.height
  222. w.ox = self.ox
  223. }
  224. f = @front_window
  225. f.x, f.y, f.width, f.height, f.viewport, f.visible, f.openness = x, y, width, height, viewport, visible, openness
  226. end
  227.  
  228. def get_subwindow_ids(y, height)
  229. ids = []
  230. subwindows.each_with_index { |w, i|
  231. if y < (i + 1) * w.contents.height
  232. ids.push(i)
  233. if y + height > (i + 1) * w.contents.height
  234. ids.push(i + 1)
  235. end
  236. break
  237. end
  238. }
  239. return ids.compact
  240. end
  241.  
  242. end
  243.  
  244. # Bitmap Forwarding
  245.  
  246. class Bitmap
  247. def fake_height=(n) # assignment - assign fake height
  248. @fake_height = n
  249. end
  250.  
  251. def fake_width=(n) # assignment - assign fake width
  252. @fake_width = n
  253. end
  254.  
  255. alias height_wfake height unless $@
  256. def height # attribute wrapper - when height is looked up, if @fake_height
  257. # exists, it will instead return @fake_height. This makes it much more
  258. # natural for cursor rects and the like to fit how they should.
  259. return @fake_height unless @fake_height.nil?
  260. return height_wfake
  261. end
  262.  
  263. alias width_wfake width unless $@
  264. def width # attribute wrapper - when height is looked up, if @fake_width
  265. # exists, it will instead return @fake_width. This makes it much more
  266. # natural for cursor rects and the like to fit how they should.
  267. return @fake_width unless @fake_width.nil?
  268. return width_wfake
  269. end
  270.  
  271.  
  272. end
  273.  
  274. class Window
  275. alias ox_set_WSHuge ox= unless $@
  276. def ox=(ox_new)
  277. return if ox == ox_new
  278. ox_set_WSHuge(ox_new)
  279. refresh_screen if @optimized # refreshes ONLY the queued draw methods
  280. end
  281.  
  282. alias oy_set_WSHuge oy= unless $@
  283. def oy=(oy_new)
  284. oy_set_WSHuge(oy_new)
  285. return if oy == oy_new
  286. refresh_screen if @optimized # refreshes ONLY the queued draw methods
  287. end
  288.  
  289. def seperate_windowskin
  290. windowskin_new_wshuge(windowskin.clone) # make a clone of the skin for current window
  291. @up_bmp = Bitmap.new(16,16)
  292. @down_bmp = Bitmap.new(16,16)
  293. @left_bmp = Bitmap.new(16,16)
  294. @right_bmp = Bitmap.new(16,16)
  295. # create four bitmaps for the four pointer arrows
  296. @up_bmp.blt(0, 0, self.windowskin, WSHuge::UP)
  297. @down_bmp.blt(0, 0, self.windowskin, WSHuge::DOWN)
  298. @left_bmp.blt(0, 0, self.windowskin, WSHuge::LEFT)
  299. @right_bmp.blt(0, 0, self.windowskin, WSHuge::RIGHT)
  300. # copy the respective arrows into the bitmaps
  301. windowskin.clear_rect(WSHuge::UP)
  302. windowskin.clear_rect(WSHuge::DOWN)
  303. windowskin.clear_rect(WSHuge::LEFT)
  304. windowskin.clear_rect(WSHuge::RIGHT)
  305. # clear out the arrows
  306. end
  307.  
  308. alias windowskin_new_wshuge windowskin= unless $@
  309. # hook into windowskin assignment
  310. def windowskin=(new)
  311. if self.windowskin != new
  312. windowskin_new_wshuge(new)
  313. seperate_windowskin if @huge_contents # perform arrow seperation if using a huge window
  314. end
  315. end
  316.  
  317. ['x', 'y', 'width', 'height', 'viewport', 'visible', 'openness'].each { |m|
  318. aStr = %Q(
  319. alias assign_autoalias_wshuge_#{m} #{m}= unless $@
  320. def #{m}=(*args)
  321. assign_autoalias_wshuge_#{m}(*args)
  322. if @huge_contents
  323. subwindows.each { |w| w.assign_autoalias_wshuge_#{m}(*args) }
  324. @front_window.assign_autoalias_wshuge_#{m}(*args)
  325. end
  326. end
  327. )
  328. module_eval(aStr)
  329. }
  330.  
  331. alias assign_autoalias_wshuge_oy oy= unless $@
  332. def oy=(new_oy)
  333. assign_autoalias_wshuge_oy(new_oy)
  334. return unless @huge_contents
  335. subwindows.each_with_index { |w, i|
  336. w.oy = self.oy - i * w.contents.height
  337. }
  338. end
  339.  
  340. alias assign_autoalias_wshuge_ox ox= unless $@
  341. def ox=(new_ox)
  342. assign_autoalias_wshuge_ox(new_ox)
  343. return unless @huge_contents
  344. subwindows.each { |w| w.ox = self.ox }
  345. end
  346.  
  347. alias dispose_wshuge dispose unless $@
  348. def dispose
  349. if @huge_contents
  350. subwindows.each { |w| w.dispose }
  351. @front_window.dispose
  352. end
  353. dispose_wshuge
  354. end
  355.  
  356. # below - iterator method
  357. # creates the window_xxarrow methods for each of the given parameters
  358.  
  359. ['up', 'down', 'left', 'right'].each { |direct|
  360. aStr = %Q(
  361. def window_#{direct}arrow(bool)
  362. if bool != @window_#{direct}arrow
  363. @window_#{direct}arrow = bool
  364. unless bool
  365. windowskin.clear_rect(WSHuge::#{direct.upcase})
  366. else
  367. windowskin.blt(WSHuge::#{direct.upcase}.x, WSHuge::#{direct.upcase}.y, @#{direct}_bmp, @#{direct}_bmp.rect)
  368. end
  369. end
  370. end
  371. )
  372. module_eval(aStr)
  373. }
  374.  
  375. end
  376.  
  377. class Window_Base
  378. ['open', 'close', ].each { |m|
  379. aStr = %Q(
  380. alias autoalias_wshuge_#{m} #{m} unless $@
  381. def #{m}(*args)
  382. autoalias_wshuge_#{m}(*args)
  383. if @huge_contents
  384. subwindows.each { |w| w.autoalias_wshuge_#{m}(*args) }
  385. @front_window.autoalias_wshuge_#{m}(*args)
  386. end
  387. end
  388. )
  389. module_eval(aStr)
  390. }
  391.  
  392. end
  393.  
  394. class Window_Contents < Window_Base; end
  395. class Window_Front < Window_Base; end
Advertisement
Add Comment
Please, Sign In to add comment