Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Window Selectable Max
- # v 2.0
- # By Mithran
- # corrects an error when creating the contents of a huge window selectable file
- # this will prevent those crashes occured when the party possesses more than ~682
- # items and attempts to look at them in the menu. Included in this script is a
- # simple draw optimizer for all subclasses of window selectable that use the methods
- # refresh and draw_item, which will signifincaly reduce startup lag on windows
- # with a large amount of selections
- # This script is free to use in any project, including commerical projects.
- # Just don't repost and claim you made it. Credit must remain intact in the script.
- # Credit not required for the project as a whole.
- # Install: Place above main, below anything that alters or uses windows.
- # Place the bitmap forwarding script below this one.
- module WSHuge
- Optimize = true # turns on optomomization. no items will be drawn offscreen
- # draws will be queued as they come onto the screen
- # Change to false to see the difference in how long windows take to refresh!
- DRAW_AHEAD_RATE = 2 # number of frames between draw-aheads in a scrolling window
- # the lower the faster
- # setting to 0 disables
- # draw aheads use some processing while the window is not scrolling, but may
- # increase performance while it is scrolling
- # DO NOT MESS WITH BELOW HERE UNLESS YOU KNOW WHAT YOU ARE DOING
- UP = Rect.new(88, 8, 16, 16) # rect for up arrow in the windowskin
- LEFT = Rect.new(72, 24, 16, 16) # rect for left arrow in the windowskin
- DOWN = Rect.new(88, 40, 16, 16) # rect for down arrow in the windowskin
- RIGHT = Rect.new(104, 24, 16, 16) # rect for right arrow in the windowskin
- CONTENTS_HEIGHT_MAX = 8184 # the maximum height of a single bitmap.
- # do not raise this, anything higher will cause the error this script
- # is intended to fix
- # must be lowered if the resolution is increased
- end
- class Window_Selectable
- attr_reader :subwindows
- alias initialize_wshuge initialize
- def initialize(*args)
- @subwindows = []
- initialize_wshuge(*args)
- @draw_queue = {} # creates a hash to store draw queues in
- ws_optimizer if WSHuge::Optimize
- # run optimizer
- end
- def create_contents
- self.contents.dispose
- contents.fake_height = nil # clears fake height
- contents.fake_width = nil # clears fake height
- @huge_contents = false # resets the huge flag, which handles arrow pointers when the
- # window is really really big
- @subwindows.each {|w| w.dispose}
- @subwindows = []
- cw = width - 32 # get the desired contents width
- ch = [height - 32, row_max * WLH].max # get the desired contents height
- if ch > WSHuge::CONTENTS_HEIGHT_MAX
- self.contents = Bitmap.new(width - 32, height - 32)
- self.contents.fake_height = ch # set the fake height attribute, for if
- # contents.height is looked up from the window, the desired height is returned
- self.contents.fake_width = cw # set the fake width attribute, for if
- # self.ox = self.oy = 1 # enable all arrows for the main contents
- @huge_contents = true # set the huge flag
- # seperate_windowskin # seperate the arrows from the windowskin
- contents.window_callback = self
- while ch > 0
- window = Window_Contents.new(self.x, self.y, self.width, self.height)
- window.contents.dispose
- window.contents = Bitmap.new(cw, WSHuge::CONTENTS_HEIGHT_MAX)
- window.opacity = 0
- window.seperate_windowskin
- @subwindows.push(window)
- ch -= WSHuge::CONTENTS_HEIGHT_MAX
- end
- if @front_window == nil
- @front_window = Window_Front.new(self.x, self.y, self.width, self.height)
- @front_window.contents.dispose
- @front_window.contents = Bitmap.new(width - 30, height - 30)
- @front_window.seperate_windowskin
- @front_window.opacity = 0
- @front_window.ox = @front_window.oy = 1
- end
- sync_windows
- else # otherwise,
- @front_window.dispose if @front_window # get rid of front window if it exists
- @front_window = nil
- self.contents = Bitmap.new(cw, ch) # create a blank bitmap normally
- end
- end
- def ws_optimizer # optimizer method
- instance_eval{ # set current scope to the calling instance
- class << self # defining in the metaclass of the current window, following methods are singletons
- # draw item does not exist at the window_selectable level, but this implementation will alter
- # all windows where it is defined that are subclasses of Window_Selectable
- if method_defined?(:draw_item) && !method_defined?(:draw_item_wshuge)
- # if draw item method exists, add a hook to it
- alias draw_item_wshuge draw_item
- def draw_item(*args)
- index = args[0] # get the index
- if onscreen?(index) or @drawahead
- # if the item will be drawn on the current screen or drawing ahead
- draw_item_wshuge(*args) # draw item
- else # otherwise
- @draw_queue[index] = args #queue the draw
- end # end if
- end # end def
- end # end if method defined?
- if method_defined?(:refresh) && !method_defined?(:refresh_wshuge)
- # if refresh method exists, add a hook to it
- alias refresh_wshuge refresh
- def refresh(*args)
- @draw_queue.clear # clear the draw queue
- refresh_wshuge(*args) # run original method
- end
- end
- end
- @optimized = true # set the optimized flag
- } # end instance eval
- end # end optimizer method
- def onscreen?(index)
- return screen_indexes.to_a.include?(index) # tests if the index is on the
- # current screen
- end
- def screen_indexes
- n = (top_row * @column_max) - 1
- return n..(n + page_item_max + @column_max) # the index of every item
- # that can be drawn on the current screen
- end
- def refresh_screen # draws ONLY queued items for the current screen
- return unless visible
- for i in screen_indexes
- draw = @draw_queue[i]
- @draw_queue.delete(i)
- draw_item(*draw) unless draw.nil?
- end
- end
- alias update_cursor_wshuge update_cursor
- def update_cursor
- update_cursor_wshuge
- update_arrows if @huge_contents # update the windowskin arrow bitmaps if huge
- refresh_screen if @optimized # refreshes ONLY the queued draw methods
- end
- alias update_wshuge update
- def update
- update_wshuge
- update_subwindows if @huge_contents
- if @optimized && self.visible && WSHuge::DRAW_AHEAD_RATE != 0 && (Graphics.frame_count % Graphics.frame_rate) % WSHuge::DRAW_AHEAD_RATE == 0
- i = @draw_queue.keys.sort.first
- if i != nil
- @drawahead = true
- draw = @draw_queue[i]
- @draw_queue.delete(i)
- draw_item(*draw) unless draw.nil?
- @drawahead = false
- end
- end
- end
- def update_subwindows
- subwindows.each { |w| w.update }
- @front_window.update
- end
- def update_arrows
- if @index < 0 or @index > @item_max
- # if the index is out of range
- @front_window.window_uparrow(false)
- @front_window.window_downarrow(false)
- @front_window.window_rightarrow(false)
- @front_window.window_leftarrow(false)
- return
- end
- if top_row == 0 # top page
- @front_window.window_uparrow(false)
- else
- @front_window.window_uparrow(true)
- end
- if bottom_row >= row_max - 1 # bottom page
- @front_window.window_downarrow(false)
- else
- @front_window.window_downarrow(true)
- end
- @front_window.window_rightarrow(false)
- @front_window.window_leftarrow(false)
- end
- # below - totally irrelevant to this issue, but fixes a very annoying issue
- # where the skill window still scrolls by L & R input in the skill scene,
- # even though L and R are used to switch actors
- alias cursor_pageup_disable cursor_pageup
- def cursor_pageup
- return if self.instance_of?(Window_Skill) && $scene.instance_of?(Scene_Skill)
- cursor_pageup_disable
- end
- alias cursor_pagedown_disable cursor_pagedown
- def cursor_pagedown
- return if self.instance_of?(Window_Skill) && $scene.instance_of?(Scene_Skill)
- cursor_pagedown_disable
- end
- def sync_windows
- subwindows.each_with_index { |w, i|
- w.x, w.y, w.width, w.height, w.viewport, w.visible, w.openness = x, y, width, height, viewport, visible, openness
- w.oy = self.oy - i * w.contents.height
- w.ox = self.ox
- }
- f = @front_window
- f.x, f.y, f.width, f.height, f.viewport, f.visible, f.openness = x, y, width, height, viewport, visible, openness
- end
- def get_subwindow_ids(y, height)
- ids = []
- subwindows.each_with_index { |w, i|
- if y < (i + 1) * w.contents.height
- ids.push(i)
- if y + height > (i + 1) * w.contents.height
- ids.push(i + 1)
- end
- break
- end
- }
- return ids.compact
- end
- end
- # Bitmap Forwarding
- class Bitmap
- def fake_height=(n) # assignment - assign fake height
- @fake_height = n
- end
- def fake_width=(n) # assignment - assign fake width
- @fake_width = n
- end
- alias height_wfake height unless $@
- def height # attribute wrapper - when height is looked up, if @fake_height
- # exists, it will instead return @fake_height. This makes it much more
- # natural for cursor rects and the like to fit how they should.
- return @fake_height unless @fake_height.nil?
- return height_wfake
- end
- alias width_wfake width unless $@
- def width # attribute wrapper - when height is looked up, if @fake_width
- # exists, it will instead return @fake_width. This makes it much more
- # natural for cursor rects and the like to fit how they should.
- return @fake_width unless @fake_width.nil?
- return width_wfake
- end
- end
- class Window
- alias ox_set_WSHuge ox= unless $@
- def ox=(ox_new)
- return if ox == ox_new
- ox_set_WSHuge(ox_new)
- refresh_screen if @optimized # refreshes ONLY the queued draw methods
- end
- alias oy_set_WSHuge oy= unless $@
- def oy=(oy_new)
- oy_set_WSHuge(oy_new)
- return if oy == oy_new
- refresh_screen if @optimized # refreshes ONLY the queued draw methods
- end
- def seperate_windowskin
- windowskin_new_wshuge(windowskin.clone) # make a clone of the skin for current window
- @up_bmp = Bitmap.new(16,16)
- @down_bmp = Bitmap.new(16,16)
- @left_bmp = Bitmap.new(16,16)
- @right_bmp = Bitmap.new(16,16)
- # create four bitmaps for the four pointer arrows
- @up_bmp.blt(0, 0, self.windowskin, WSHuge::UP)
- @down_bmp.blt(0, 0, self.windowskin, WSHuge::DOWN)
- @left_bmp.blt(0, 0, self.windowskin, WSHuge::LEFT)
- @right_bmp.blt(0, 0, self.windowskin, WSHuge::RIGHT)
- # copy the respective arrows into the bitmaps
- windowskin.clear_rect(WSHuge::UP)
- windowskin.clear_rect(WSHuge::DOWN)
- windowskin.clear_rect(WSHuge::LEFT)
- windowskin.clear_rect(WSHuge::RIGHT)
- # clear out the arrows
- end
- alias windowskin_new_wshuge windowskin= unless $@
- # hook into windowskin assignment
- def windowskin=(new)
- if self.windowskin != new
- windowskin_new_wshuge(new)
- seperate_windowskin if @huge_contents # perform arrow seperation if using a huge window
- end
- end
- ['x', 'y', 'width', 'height', 'viewport', 'visible', 'openness'].each { |m|
- aStr = %Q(
- alias assign_autoalias_wshuge_#{m} #{m}= unless $@
- def #{m}=(*args)
- assign_autoalias_wshuge_#{m}(*args)
- if @huge_contents
- subwindows.each { |w| w.assign_autoalias_wshuge_#{m}(*args) }
- @front_window.assign_autoalias_wshuge_#{m}(*args)
- end
- end
- )
- module_eval(aStr)
- }
- alias assign_autoalias_wshuge_oy oy= unless $@
- def oy=(new_oy)
- assign_autoalias_wshuge_oy(new_oy)
- return unless @huge_contents
- subwindows.each_with_index { |w, i|
- w.oy = self.oy - i * w.contents.height
- }
- end
- alias assign_autoalias_wshuge_ox ox= unless $@
- def ox=(new_ox)
- assign_autoalias_wshuge_ox(new_ox)
- return unless @huge_contents
- subwindows.each { |w| w.ox = self.ox }
- end
- alias dispose_wshuge dispose unless $@
- def dispose
- if @huge_contents
- subwindows.each { |w| w.dispose }
- @front_window.dispose
- end
- dispose_wshuge
- end
- # below - iterator method
- # creates the window_xxarrow methods for each of the given parameters
- ['up', 'down', 'left', 'right'].each { |direct|
- aStr = %Q(
- def window_#{direct}arrow(bool)
- if bool != @window_#{direct}arrow
- @window_#{direct}arrow = bool
- unless bool
- windowskin.clear_rect(WSHuge::#{direct.upcase})
- else
- windowskin.blt(WSHuge::#{direct.upcase}.x, WSHuge::#{direct.upcase}.y, @#{direct}_bmp, @#{direct}_bmp.rect)
- end
- end
- end
- )
- module_eval(aStr)
- }
- end
- class Window_Base
- ['open', 'close', ].each { |m|
- aStr = %Q(
- alias autoalias_wshuge_#{m} #{m} unless $@
- def #{m}(*args)
- autoalias_wshuge_#{m}(*args)
- if @huge_contents
- subwindows.each { |w| w.autoalias_wshuge_#{m}(*args) }
- @front_window.autoalias_wshuge_#{m}(*args)
- end
- end
- )
- module_eval(aStr)
- }
- end
- class Window_Contents < Window_Base; end
- class Window_Front < Window_Base; end
Advertisement
Add Comment
Please, Sign In to add comment