class Window_RingCommand
OPEN_DURATION = 40
ROTATE_DURATION = 20
attr_reader :index
def initialize(commands, radius, x, y)
@commands = commands.map { |i| i[0] }
@icons = commands.map { |i| RPG::Cache.icon(i[1]) }
@angle = 270
@radius = 0
@opacity = 0
@dest_rad = radius
@pos = [x, y]
@spriteset = Spriteset_Ring.new(commands, radius, x, y)
@opening = false
@closing = false
@rotating = false
@index = 0
self.open(OPEN_DURATION, 180, 64)
update
end
def update
if Input.repeat?(Input::LEFT) and !@opening and !@closing and !@rotating
@index = (@index + 1) % @icons.length
angle = (270 + 360 * (@icons.length - @index) / @icons.length) % 360
duration = ROTATE_DURATION
self.rotate(duration, angle, false)
end
if Input.repeat?(Input::RIGHT) and !@opening and !@closing and !@rotating
@index = (@index + @icons.length - 1) % @icons.length
angle = (270 + 360 * (@icons.length - @index) / @icons.length) % 360
duration = ROTATE_DURATION
self.rotate(duration, angle, true)
end
if @opening
@frames += 1
@radius = @dest_rad * @frames / @duration
@angle = @s_angle + (270 - @s_angle) * @frames / @duration
@opacity = 255 * 2 * @frames / @duration
if @frames == @duration
@opening = false
end
elsif @closing
@frames += 1
@radius = @s_rad * (@duration - @frames) / @duration
@angle = @s_angle * @frames / @duration + @d_angle * (@duration - @frames) / @duration
@opacity = 255 * (@duration - @frames) * 2 / @duration
if @frames == @duration
@closing = false
end
elsif @rotating
@frames += 1
@angle = @d_angle * @frames / @duration + @s_angle * (@duration - @frames) / @duration
if @frames == @duration
@rotating = false
end
end
@spriteset.set(@radius, @angle, @pos, @opacity)
end
def open(duration, angle, radius)
@s_angle = @angle = @angle - angle
@dest_rad = radius
@radius = 0
@duration = duration
@frames = 0
@opening = true
end
def close(duration, angle)
@s_angle = @angle
@d_angle = @angle - angle
@s_rad = @radius
@duration = duration
@frames = 0
@closing = true
end
def rotate(duration, angle, right)
@s_angle = @angle
@d_angle = angle
if right
while @d_angle < @s_angle
@d_angle += 360
end
while @d_angle - @s_angle > 360
@d_angle -= 360
end
elsif !right
while @d_angle > @s_angle
@d_angle -= 360
end
while @s_angle - @d_angle > 360
@d_angle += 360
end
end
@duration = duration
@frames = 0
@rotating = true
end
def dispose
@icons.each { |i| i.dispose }
@spriteset.dispose
end
end
class Spriteset_Ring
def initialize(commands, radius, x, y)
@commands = commands.map { |i| i[0] }
@icons = commands.map { |i| RPG::Cache.icon(i[1]) }
@icon_sprites = @icons.map { |icon| s=Sprite.new;s.bitmap=icon;s }
@angle = 270
@radius = radius
@pos = [x, y]
@tsprites = @commands.map { |i|
s=Sprite.new
s.bitmap=Bitmap.new(1,1)
rect=s.bitmap.text_size(i)
s.bitmap=Bitmap.new(rect.width,rect.height)
s.bitmap.draw_text(rect,i,1)
s.ox=rect.width/2
s.oy=rect.height/2
s.x,s.y=*@pos
s
}
end
def set(radius, angle, pos, opacity)
@radius = radius
@angle = angle
@pos = pos
@icon_sprites.each { |i| i.opacity = opacity }
@tsprites.each { |s| s.x,s.y=*@pos }
update
end
def update
@icon_sprites.each_with_index { |icon, ind|
angle = (@angle + 360 * ind / @icons.length) % 360
d = 360 / @icons.length
if angle > 270 - d and angle < 270 + d
dist = (angle - 270).abs
vals = [-120 * dist / d, 100 * dist / d]
alpha = 255 * (d - dist) / d
icon.tone = Tone.new(vals[0], vals[0], vals[0], vals[1])
@tsprites[ind].opacity = alpha
else
icon.tone = Tone.new(-120, -120, -120, 100)
@tsprites[ind].opacity = 0
end
angle *= Math::PI / 180
x, y = Math.cos(angle) * @radius + @pos[0] - icon.bitmap.width / 2, Math.sin(angle) * @radius + @pos[1] - icon.bitmap.height / 2
icon.x, icon.y = x, y
}
end
def dispose
@icon_sprites.each { |i| i.dispose }
@icons.each { |i| i.dispose }
@tsprites.each { |i| i.dispose }
end
end