module DesignHUD # This HUD uses an easy to use format for configuration much like html # it has many types of tags, each inserting different information into the # HUD, such as icons, hp/sp/xp bars, and different information about the # actors. # # Tags: # # Formatting Elements: # * # - italicizes text # * # - bolds text # * # - changes the color to Color.new(R, G, B, A) (A is unnecessary) # * # - changes the font to NAME and the font size to SIZE # Graphical Elements: # * # - inserts the icon named FILENAME # * # - inserts the picture named FILENAME # * # - inserts the blizzart bar (if using blizzart bars) in style STYLE # and with colors corresponding to the stat TYPE with width WIDTH # - types: HP, SP, EXP # Positioning Elements: # * # - positions the contents at an x position of VALX and # at a y position of VALY # * # - adds VALX and VALY to the position of the contents # *
# - starts a table # * # - adds a row to a table # * # - adds a cell to a row of a table # * # - aligns the contents to the left # *
# - aligns the contents in the center # * # - aligns the contents to the right # * # - denotes one line in the HUD # * # - sets the width of the contents to VAL # * # - sets the height of the contents to VAL # HUD Properties: # * # - this tag has many properties, listed below # * windowskin='FILENAME' # - sets the windowskin of the HUD to the windowskin named FILENAME # * bg='FILENAME' # - sets the background image of the HUD to the picture named FILENAME # * align=ALIGN # - sets the align of the HUD to ALIGN # - possible aligns: TL, TC, TR, ML, MC, MR, BL, BC, BR (top-left, # top-center, top-right, middle-left, middle-center, middle-right, # bottom-left, bottom-center, bottom-right) # * offsetx=VAL # - sets the xoffset of the HUD to VAL # * offsety=VAL # - and the yoffset of the HUD to VAL # * width=VAL # - sets the width of the HUD to VAL # * height=VAL # - sets the height of the HUD to VAL # * back_opacity=VAL # - sets the back opacity of the HUD to VAL # * contents_opacity=VAL # - sets the contents opacity of the HUD to VAL # * opacity=VAL # - sets the opacity of the HUD to VAL HUD = <<-HUD G Test HUD NO_END = ['ico', 'pic', 'hud', 'var'] BLOCK_ELS = ['ln'] def self.var_expression(name) case name when 'gold' then return proc { $game_party.gold } else return proc {} end end end class HUD < Window_Base attr_accessor :tmp_attrs def initialize(text) super(0, 0, 33, 33) self.contents = Bitmap.new(1, 1) self.visible = false @align = 'TL' @xoffset, @yoffset = 0, 0 @tmp_attrs = {} @text = text Element.reset_id parse_text setup_hud setup_align @dom.delete_if { |el| el.el_type == 'hud' } self.contents = Bitmap.new(width - 32, height - 32) tmp = self.contents render_hud end def update redim = [] vars = [] redraw = [] @var_nodes.each { |el| val = el.val if val != el.attrs[:val] vars.push(el) redim |= [el.last_line] pos = el.attrs[:pos] rect = el.attrs[:size] rect.x, rect.y = *pos self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) el.attrs[:val] = val end } @dom.each { |el| comp = false el.each_child_ex2(proc { |child| comp = false }) { |child| if child.attrs[:size] and !comp pos = child.attrs[:pos] rect = child.attrs[:size] rect.x, rect.y = *pos if vars.select { |el| pos = el.attrs[:pos];tmp = el.attrs[:size];tmp.x, tmp.y = *pos;tmp.intersect?(rect) }.length > 0 redraw.push(child) comp = true end end } } redraw ||= vars redetermine_size(redim) if redim.length > 0 setup_align redraw_hud(redraw) if redraw.length > 0 end def redetermine_size(els) @tmp_attrs[:ox] = 0 @tmp_attrs[:oy] = 0 pos = [0, 0] @dom.each { |el| ln_height = ln_width = 0 if els.include?(el) pos = el.attrs[:pos].clone unless @tmp_attrs[:tmp] if @tmp_attrs[:tmp] @tmp_attrs[:tmp].push(true) else @tmp_attrs[:tmp] = [true] end end case el.el_type when 'ln' el.each_child_ex(proc { |child| if @tmp_attrs[:tmp] unless child.attrs[:size].nil? rect = child.attrs[:size] rect.x, rect.y = *child.attrs[:pos] self.contents.fill_rect(rect, Color.new(0, 0, 0, 0)) end if @tmp_attrs[:abs_pos] child.attrs[:pos] = [@tmp_attrs[:abs_pos].last[0] + @tmp_attrs[:ox], @tmp_attrs[:abs_pos].last[1] + @tmp_attrs[:oy]] else child.attrs[:pos] = [pos[0] + @tmp_attrs[:ox], pos[1] + @tmp_attrs[:oy]] end end if els.include?(child) pos = child.attrs[:pos].clone unless @tmp_attrs[:tmp] if @tmp_attrs[:tmp] @tmp_attrs[:tmp].push(true) else @tmp_attrs[:tmp] = [true] end end case child when FormatNode tmp = child.attrs[:start].call(child, self) child.attrs = tmp if tmp and tmp.is_a?(Hash) end }, proc { |child| case child when FormatNode tmp = child.attrs[:finish].call(child, self) child.attrs = tmp if tmp and tmp.is_a?(Hash) end if @tmp_attrs[:tmp] if els.include?(child) @tmp_attrs[:tmp].pop @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0 end end unless child.children.empty? resize(child) end }) { |child| if @tmp_attrs[:tmp] case child when TextNode size = self.contents.text_size(child.attrs[:val]) child.attrs[:size] = size ln_height = [size.height, ln_height].max if @tmp_attrs[:abs_pos] tmp = @tmp_attrs[:abs_pos] ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width else ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max pos[0] += size.width end when VariableNode size = self.contents.text_size(child.val.to_s) child.attrs[:size] = size ln_height = [size.height, ln_height].max if @tmp_attrs[:abs_pos] tmp = @tmp_attrs[:abs_pos] ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width else ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max pos[0] += size.width end when IconNode, PictureNode size = child.attrs[:bitmap].rect child.attrs[:size] = size ln_height = [size.height, ln_height].max if @tmp_attrs[:abs_pos] tmp = @tmp_attrs[:abs_pos] ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width else ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max pos[0] += size.width end end end } end if @tmp_attrs[:tmp] if els.include?(el) @tmp_attrs[:tmp].pop @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0 end end } @dom.each { |child| if child.block? child.attrs[:size].width = self.width - 32 end } end def redraw_hud(els) @tmp_attrs = {} @dom.each { |el| align = 0 case el.el_type when 'ln' if els.include?(el) pos = el.attrs[:pos].clone unless @tmp_attrs[:tmp] if @tmp_attrs[:tmp] @tmp_attrs[:tmp].push(true) else @tmp_attrs[:tmp] = [true] end end el.each_child_ex(proc { |child| if els.include?(child) pos = child.attrs[:pos].clone unless @tmp_attrs[:tmp] if @tmp_attrs[:tmp] @tmp_attrs[:tmp].push(true) else @tmp_attrs[:tmp] = [true] end end case child when FormatNode child.attrs[:start].call(child, self) end }, proc { |child| case child when FormatNode child.attrs[:finish].call(child, self) end if @tmp_attrs[:tmp] if els.include?(child) @tmp_attrs[:tmp].pop @tmp_attrs.delete(:tmp) if @tmp_attrs[:tmp].length == 0 end end }) { |child| if @tmp_attrs[:tmp] case child when TextNode pos = child.attrs[:pos] text = child.attrs[:val] size = child.attrs[:size] self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text) when VariableNode pos = child.attrs[:pos] text = child.val.to_s size = child.attrs[:size] self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text) when IconNode, PictureNode pos = child.attrs[:pos] bitmap = child.attrs[:bitmap] self.contents.blt(pos[0], pos[1], bitmap, bitmap.rect) end end } end } end def parse_text text = @text.clone @dom, @var_nodes = [], [] index = 0 current_id = -1 current_el = nil parent = nil parent_els = [] spattern = /<([\w\-]+)(?:\s*=\s*([\w\"\'\-\_\:\$\.\s]+))?((?:\s*\w+\s*=\s*[\w\"\'\-\_\:\$\.\s]+)*)>/ epattern = /<\/[\w\-]+>/ while text.length != 0 s_ind = text.index(spattern) if s_ind != nil contents = nil el_name = $1 el_val = $2 || '' el_attrs = {} tmp = $3.strip tmp.gsub(/(\w+)\s+=\s+([\w\"\'\-\:]+)/, "\\1=\\2").split(/\s+/).each { |el| el_attrs[el.split('=')[0].to_sym] = el.split('=')[1].gsub(/[\'\"]/, '') } el_val.gsub!(/[\'\"]/, '') if el_val el_attrs[:val] = el_val level, tmp_name, tmp_ind = 0, '', s_ind if !DesignHUD::NO_END.include?(el_name) loop do text.sub!(spattern, '') tmp = [text.index(/(<#{el_name}(?:=[\w\"\'\-\:]+)?(?:\s*\w+=[\w\"\'\-\:]+)*>)/, tmp_ind)] tmp.push(text.index(/<\/#{el_name}>/, tmp_ind)) if !tmp[1] contents = text[s_ind...text.length - 4 - el_name.length] text = '' elsif !tmp[0] contents = text[s_ind...text.length - 4 - el_name.length] text = '' elsif tmp[1] < tmp[0] contents = text[s_ind...tmp[1]] text = text[tmp[1]...text.length] else level += 1 tmp_ind = tmp[0] + 2 + el_name.length end break if contents != nil end case el_name when 'ln' element = ContainerNode.new('ln', el_attrs, nil, contents) @dom.push(element) end else text.sub!(spattern, '') case el_name when 'hud' element = HudNode.new('hud', el_attrs) @dom.push(element) end end end end end def setup_hud @dom.each { |el| el.each_child { |tmp| if tmp.el_type == 'hud' self.width = tmp.attrs[:width].to_i if tmp.attrs[:width] self.height = tmp.attrs[:height].to_i if tmp.attrs[:height] @align = tmp.attrs[:align] if tmp.attrs[:align] @xoffset = tmp.attrs[:offsetx].to_i if tmp.attrs[:offsetx] @yoffset = tmp.attrs[:offsety].to_i if tmp.attrs[:offsety] self.opacity = tmp.attrs[:opacity].to_i if tmp.attrs[:opacity] self.back_opacity = tmp.attrs[:back_opacity].to_i if tmp.attrs[:back_opacity] self.contents_opacity = tmp.attrs[:contents_opacity].to_i if tmp.attrs[:contents_opacity] begin self.windowskin = ((tmp.attrs[:windowskin] == '') ? Bitmap.new(1, 1) : RPG::Cache.windowskin(tmp.attrs[:windowskin])) if tmp.attrs[:windowskin] rescue self.windowskin = Bitmap.new(1, 1) end @bg = Sprite.new @bg.z = self.z - 1 if tmp.attrs[:bg] @bg.bitmap = RPG::Cache.picture(tmp.attrs[:bg]) else @bg.visible = false end end } } tmp_width, tmp_height = get_dimensions if self.width == 33 self.width = [tmp_width, 1].max + 32 end if self.height == 33 self.height = [tmp_height, 1].max + 32 end @dom.each { |child| if child.block? child.attrs[:size].width = self.width - 32 end } @align.downcase! xmod = (['l','c'].include?(@align[1..1]) ? 1 : -1) ymod = (['t','m'].include?(@align[0..0]) ? 1 : -1) xstrt = case @align[1..1] when 'l' then 0 when 'r' then 640 - self.width when 'c' then (640 - self.width) / 2 end ystrt = case @align[0..0] when 't' then 0 when 'b' then 480 - self.height when 'm' then (480 - self.height) / 2 end self.x = xstrt + xmod * @xoffset self.y = ystrt + ymod * @yoffset if @bg.visible @bg.x = self.x + (self.width - @bg.bitmap.width) / 2 @bg.y = self.y + (self.height - @bg.bitmap.height) / 2 end self.visible = true end def get_dimensions ln_widths = [] height = 0 @tmp_attrs[:ox] = 0 @tmp_attrs[:oy] = 0 @tmp_attrs[:align] = 0 pos = [0, 0] @dom.each { |el| pos[0] = 0 ln_width = 0 ln_height = 0 case el.el_type when 'ln' el.attrs[:pos] = pos.clone el.attrs[:align] = @tmp_attrs[:abs_pos] el.attrs[:abs] = 0 el.each_child_ex(proc { |child| # start proc child.attrs[:align] = (@tmp_attrs[:abs_pos] ? 0 : @tmp_attrs[:align]) if @tmp_attrs[:abs_pos] child.attrs[:pos] = [@tmp_attrs[:abs_pos].last[0] + @tmp_attrs[:ox], @tmp_attrs[:abs_pos].last[1] + @tmp_attrs[:oy]] child.attrs[:abs] = @tmp_attrs[:abs_pos].length else child.attrs[:pos] = [pos[0] + @tmp_attrs[:ox], pos[1] + @tmp_attrs[:oy]] child.attrs[:abs] = 0 end case child when FormatNode tmp = child.attrs[:start].call(child, self) child.attrs = tmp if tmp and tmp.is_a?(Hash) end }, proc { |child| # end proc case child when FormatNode tmp = child.attrs[:finish].call(child, self) child.attrs = tmp if tmp and tmp.is_a?(Hash) end if !child.children.empty? resize(child) elsif child.block? child.attrs[:size] = Rect.new(0, 0, 0, 0) end }) { |child| # main proc case child when TextNode size = self.contents.text_size(child.attrs[:val]) child.attrs[:size] = size ln_height = [size.height, ln_height].max if @tmp_attrs[:abs_pos] tmp = @tmp_attrs[:abs_pos] ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width else ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max pos[0] += size.width end when VariableNode size = self.contents.text_size(child.val.to_s) child.attrs[:size] = size ln_height = [size.height, ln_height].max if @tmp_attrs[:abs_pos] tmp = @tmp_attrs[:abs_pos] ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width else ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max pos[0] += size.width end @var_nodes.push(child) when IconNode, PictureNode size = child.attrs[:bitmap].rect child.attrs[:size] = size ln_height = [size.height, ln_height].max if @tmp_attrs[:abs_pos] tmp = @tmp_attrs[:abs_pos] ln_width = [tmp.last[0] + @tmp_attrs[:ox] + size.width, ln_width].max @tmp_attrs[:abs_pos][tmp.length - 1][0] += size.width else ln_width = [pos[0] + @tmp_attrs[:ox] + size.width, ln_width].max pos[0] += size.width end end } end pos[1] += ln_height + @tmp_attrs[:oy] ln_widths.push(ln_width) } height = pos[1] width = ln_widths.max return width, height end def resize(el) size = Rect.new(0, 0, 0, 0) x1, y1 = 640, 480 x2 = y2 = 0 len = el.attrs[:abs] el.children.each { |i| next if i.attrs[:abs] > len x, y = *i.attrs[:pos] ns = i.attrs[:size] x1 = [x1, x].min y1 = [y1, y].min x2 = [x2, x + ns.width].max y2 = [y2, y + ns.height].max } size.width = x2 - x1 size.height = y2 - y1 pos = [x1, y1] el.attrs[:pos], el.attrs[:size] = pos, size end def setup_align aligned = nil @dom.each { |el| case el.el_type when 'ln' el.each_child_ex(proc {|child|}, proc { |child| # end proc case child when FormatNode if child.attrs[:tmp] child.attrs.delete_at(:tmp) aligned.pop aligned = nil if aligned.empty? end end }) { |child| # main proc break unless aligned.nil? if ['right', 'left', 'center'].include?(child.el_type) child.attrs[:tmp] = true if aligned aligned.push(true) else aligned = [true] end end case child.attrs[:align] when 0 pos = child.attrs[:pos] fb = child.last_block np = fb.attrs[:pos] child.attrs[:pos] = np.clone child.each_child_ex(proc{},proc{}) { |i| i.attrs[:pos][0] += np[0] - pos[0] i.attrs[:pos][1] += np[1] - pos[1] } when 1 pos = child.attrs[:pos] fb = child.last_block fbw = fb.attrs[:size].width fbp = fb.attrs[:pos] w = child.attrs[:size].width np = [(fbw - w) / 2, pos[1]] child.attrs[:pos] = np.clone child.each_child_ex(proc{},proc{}) { |i| i.attrs[:pos][0] += np[0] - pos[0] i.attrs[:pos][1] += np[1] - pos[1] } when 2 pos = child.attrs[:pos] fb = child.last_block fbw = fb.attrs[:size].width fbp = fb.attrs[:pos] w = child.attrs[:size].width np = [fbw - w, pos[1]] child.attrs[:pos] = np.clone child.each_child_ex(proc{},proc{}) { |i| i.attrs[:pos][0] += np[0] - pos[0] i.attrs[:pos][1] += np[1] - pos[1] } end } end } end def render_hud @dom.each { |el| align = 0 case el.el_type when 'ln' el.each_child_ex(proc { |child| case child when FormatNode child.attrs[:start].call(child, self) end }, proc { |child| case child when FormatNode child.attrs[:finish].call(child, self) end }) { |child| case child when TextNode pos = child.attrs[:pos] text = child.attrs[:val] size = child.attrs[:size] self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text) when VariableNode pos = child.attrs[:pos] text = child.val.to_s size = child.attrs[:size] self.contents.draw_text(Rect.new(pos[0], pos[1], size.width, size.height), text) when IconNode, PictureNode pos = child.attrs[:pos] bitmap = child.attrs[:bitmap] self.contents.blt(pos[0], pos[1], bitmap, bitmap.rect) end } end } end def get_el(path) el = @dom[path[0]] if path.length > 1 path[1..path.length - 1].each { |tmp| el = el.children[tmp] } end el end end class Element @@id = 0 attr_accessor :children, :el_type, :attrs, :el_id, :parent def initialize(el_type, attrs, parent) @children = [] @el_type = el_type.downcase @attrs = attrs @parent = parent @contents = '' @el_id = @@id @@id += 1 end def block? return DesignHUD::BLOCK_ELS.include?(@el_type) end def inline? return !DesignHUD::BLOCK_ELS.include?(@el_type) end def self.reset_id @@id = 0 end def parents if @parent != nil parents = [@parent] parent = @parent while parent.parent != nil parents.push(parent.parent) parent = parent.parent end return parents else return [] end end def last_block if @parent != nil last = self parent = @parent while last.inline? last = parent parent = parent.parent break if parent.nil? end return last else return nil end end def last_line if @parent != nil last = self parent = @parent while last.el_type != 'ln' last = parent parent = parent.parent break if parent.nil? end return last else return nil end end def each_child(&block) block.call(self) path = [0] cur = self loop { child = cur.children[path.last] if child block.call(child) cur = child path.push(0) else cur = cur.parent path.pop break unless cur path[path.length - 1] += 1 end } end def each_child_ex(start, finish, &block) path = [0] cur = self loop { child = cur.children[path.last] if child start.call(child) block.call(child) cur = child path.push(0) else finish.call(cur) cur = cur.parent path.pop break unless cur and path.length > 0 path[path.length-1] += 1 end } end def each_child_ex2(finish, &block) block.call(self) path = [0] cur = self loop { child = cur.children[path.last] if child block.call(child) cur = child path.push(0) else finish.call(cur) cur = cur.parent path.pop break unless cur path[path.length - 1] += 1 end } end def parse_contents(text) @tmp_attrs = {} spattern = /<([\w\-]+)(?:\s*=\s*([\w\"\'\-\_\:\$\.\s]+))?((?:\s*\w+\s*=\s*[\w\"\'\-\_\:\$\.\s]+)*)>/ epattern = /<\/[\w\-]+>/ while text != '' s_ind = text.index(spattern) if s_ind != nil if s_ind > 0 contents = text[0...s_ind] text = text[s_ind...text.length] element = TextNode.new('', self, contents) @children.push(element) end contents = nil el_name = $1 el_val = $2 || '' el_attrs = {} tmp = $3.strip tmp.gsub(/(\w+)\s+=\s+([\w\"\'\-\:]+)/, "\\1=\\2").split(/\s+/).each { |el| el_attrs[el.split('=')[0].to_sym] = eval(el.split('=')[1]) } el_val.gsub!(/[\'\"]/, '') if el_val el_attrs[:val] = el_val level, tmp_name, tmp_ind = 0, '', 0 if !DesignHUD::NO_END.include?(el_name) text.sub!(spattern, '') last_ind = nil loop do tmp = [text.index(/(<#{el_name}(?:=[\w\"\'\-\:]+)?(?:\s*\w+=[\w\"\'\-\:]+)*>)/, tmp_ind)] tmp2 = tmp_ind (level+1).times { i = text.index(/<\/#{el_name}>/, tmp2) tmp2 = i + 2 + el_name.length unless i.nil? } tmp.push(tmp2 - 2 - el_name.length) if !tmp[1] contents = text[0...text.length] text = '' elsif !tmp[0] contents = text[0...tmp[1]] text = text[tmp[1] + 3 + el_name.length...text.length] level = [level - 1, 0].max elsif tmp[1] < tmp[0] contents = text[0...tmp[1]] text = text[tmp[1] + 3 + el_name.length...text.length] level = [level - 1, 0].max else level += 1 unless last_ind != nil and tmp[0] > last_ind[1] tmp_ind = tmp[0] + 2 + el_name.length end last_ind = tmp break if contents != nil end case el_name when 'ln' element = ContainerNode.new('ln', el_attrs, self, contents) @children.push(element) when 'b' element = FormatNode.new('b', self, contents, proc { |child, hud| if !@tmp_attrs[:tmpb] @tmp_attrs[:tmpb] = [hud.contents.font.bold] else @tmp_attrs[:tmpb].push(hud.contents.font.bold) end hud.contents.font.bold = true }, proc { |child, hud| hud.contents.font.bold = @tmp_attrs[:tmpb].pop }) @children.push(element) when 'i' element = FormatNode.new('i', self, contents, proc { |child, hud| if !@tmp_attrs[:tmpi] @tmp_attrs[:tmpi] = [hud.contents.font.italic] else @tmp_attrs[:tmpi].push(hud.contents.font.italic) end hud.contents.font.italic = true }, proc { |child, hud| hud.contents.font.italic = @tmp_attrs[:tmpi].pop }) @children.push(element) when 'c' element = FormatNode.new('c', self, contents, proc { |child, hud| if !hud.tmp_attrs[:tmpc] hud.tmp_attrs[:tmpc] = [hud.contents.font.color.clone] else hud.tmp_attrs[:tmpc].push(hud.contents.font.color.clone) end hud.contents.font.color = Color.new(*child.attrs[:val].split(':').map { |i| i.to_i }) }, proc { |child, hud| hud.contents.font.color = hud.tmp_attrs[:tmpc].pop }, el_val) @children.push(element) when 'font' element = FormatNode.new('font', self, contents, proc { |child, hud| if !@tmp_attrs[:tmpfn] hud.tmp_attrs[:tmpfn] = [[hud.contents.font.name.clone, hud.contents.font.size]] else hud.tmp_attrs[:tmpfn].push([hud.contents.font.name.clone, hud.contents.font.size]) end if Font.exist?(child.attrs[:val].split(':')[0]) hud.contents.font.name = child.attrs[:val].split(':')[0] hud.contents.font.size = child.attrs[:val].split(':')[1].to_i end }, proc { |child, hud| hud.contents.font.name, hud.contents.font.size = *hud.tmp_attrs[:tmpfn].pop }, el_val) @children.push(element) when 'pos' element = FormatNode.new('pos', self, contents, proc { |child, hud| if !hud.tmp_attrs[:abs_pos] hud.tmp_attrs[:abs_pos] = [[child.attrs[:x], child.attrs[:y]]] else hud.tmp_attrs[:abs_pos].push([child.attrs[:x], child.attrs[:y]]) end }, proc { |child, hud| hud.tmp_attrs[:abs_pos].pop hud.tmp_attrs.delete(:abs_pos) if hud.tmp_attrs[:abs_pos].length == 0 }, el_val, el_attrs) @children.push(element) when 'offset' element = FormatNode.new('offset', self, contents, proc { |child, hud| if !hud.tmp_attrs[:tmpofst] hud.tmp_attrs[:tmpofst] = [[hud.tmp_attrs[:ox], hud.tmp_attrs[:oy]]] else hud.tmp_attrs[:tmpofst].push([hud.tmp_attrs[:ox], hud.tmp_attrs[:oy]]) end hud.tmp_attrs[:ox], hud.tmp_attrs[:oy] = child.attrs[:x], child.attrs[:y] }, proc { |child, hud| hud.tmp_attrs[:ox], hud.tmp_attrs[:oy] = *hud.tmp_attrs[:tmpofst].pop }, el_val, el_attrs) @children.push(element) when 'right' element = FormatNode.new('right', self, contents, proc { |child, hud| if !hud.tmp_attrs[:tmpalign] hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]] else hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align]) end hud.tmp_attrs[:align] = 2 child.attrs[:align] = 2 }, proc { |child, hud| hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop }, el_val, el_attrs) @children.push(element) when 'center' element = FormatNode.new('center', self, contents, proc { |child, hud| if !hud.tmp_attrs[:tmpalign] hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]] else hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align]) end hud.tmp_attrs[:align] = 1 child.attrs[:align] = 1 }, proc { |child, hud| hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop }, el_val, el_attrs) @children.push(element) when 'left' element = FormatNode.new('left', self, contents, proc { |child, hud| if !hud.tmp_attrs[:tmpalign] hud.tmp_attrs[:tmpalign] = [hud.tmp_attrs[:align]] else hud.tmp_attrs[:tmpalign].push(hud.tmp_attrs[:align]) end hud.tmp_attrs[:align] = 0 child.attrs[:align] = 0 }, proc { |child, hud| hud.tmp_attrs[:align] = hud.tmp_attrs[:tmpalign].pop }, el_val, el_attrs) @children.push(element) end else text.sub!(spattern, '') case el_name when 'hud' element = HudNode.new('hud', el_attrs, self) @children.push(element) when 'var' element = VariableNode.new(self, el_val) @children.push(element) when 'ico' element = IconNode.new(self, el_val) @children.push(element) when 'pic' element = PictureNode.new(self, el_val) @children.push(element) end end else contents = text text = '' element = TextNode.new('', self, contents) @children.push(element) end end end end class TextNode < Element def initialize(type, parent, text) super(type, {}, parent) @attrs[:val] = text end end class PictureNode < Element def initialize(parent, val) super('pic', {}, parent) @attrs[:bitmap] = RPG::Cache.picture(val) end end class IconNode < Element def initialize(parent, val) super('ico', {}, parent) @attrs[:bitmap] = RPG::Cache.icon(el_val).clone end end class VariableNode < Element def initialize(parent, name) super('var', {}, parent) @attrs[:expr] = DesignHUD.var_expression(name) @attrs[:val] = @attrs[:expr].call || 0 end def val tmp = @attrs[:expr].call return (tmp.nil? ? 0 : tmp) end end class BarNode < Element end class HudNode < Element def initialize(type, attrs, parent = nil) super('hud', attrs, parent) end end class ContainerNode < Element def initialize(type, attrs, parent, contents) super(type, attrs, parent) parse_contents(contents) end end class FormatNode < Element def initialize(type, parent, contents, start, finish, val=nil, attrs = {}) super(type, attrs, parent) parse_contents(contents) @attrs[:val] = val if val @attrs[:start] = start @attrs[:finish] = finish end end class Rect def intersect?(rect) return false if rect.width * rect.height == 0 or self.width * self.height == 0 return true if (self.x.between?(rect.x - 1, rect.x + rect.width) or (self.x + self.width).between?(rect.x - 1, rect.x + rect.width)) and (self.y.between?(rect.y - 1, rect.y + rect.height) or (self.y + self.height).between?(rect.y - 1, rect.y + rect.height)) return false end end