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