mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-09 22:24:58 +00:00
Anim Editor: added play functionality to battle and editor
This commit is contained in:
@@ -220,7 +220,7 @@ class AnimationEditor
|
||||
:canvas_bg => "indoor1",
|
||||
# NOTE: These sprite names are also used in Pokemon.play_cry and so should
|
||||
# be a species ID (being a string is fine).
|
||||
:user_sprite_name => "ARCANINE",
|
||||
:user_sprite_name => "DRAGONITE",
|
||||
:target_sprite_name => "CHARIZARD"
|
||||
}
|
||||
end
|
||||
@@ -285,7 +285,7 @@ class AnimationEditor
|
||||
].each_with_index do |tab, i|
|
||||
btn = UIControls::Button.new(100, 28, pane.viewport, tab[2])
|
||||
btn.set_fixed_size
|
||||
btn.disable if tab[0] == component
|
||||
btn.set_highlighted if tab[0] == component
|
||||
pane.add_control_at(tab[1], btn, next_pos_x, next_pos_y)
|
||||
next_pos_x += btn.width
|
||||
end
|
||||
@@ -313,6 +313,7 @@ class AnimationEditor
|
||||
end
|
||||
|
||||
def set_play_controls_contents
|
||||
@components[:play_controls].add_play_controls
|
||||
@components[:play_controls].duration = @components[:particle_list].duration
|
||||
end
|
||||
|
||||
@@ -330,7 +331,6 @@ class AnimationEditor
|
||||
move_ctrl.max_rows = 16
|
||||
anim_properties.add_labelled_number_text_box(:version, _INTL("Version"), 0, 99, 0)
|
||||
anim_properties.add_labelled_text_box(:name, _INTL("Name"), "")
|
||||
# TODO: Have two TextBoxes, one for folder and one for filename?
|
||||
anim_properties.add_labelled_text_box(:pbs_path, _INTL("PBS filepath"), "")
|
||||
anim_properties.add_labelled_checkbox(:has_user, _INTL("Involves a user?"), true)
|
||||
anim_properties.add_labelled_checkbox(:has_target, _INTL("Involves a target?"), true)
|
||||
@@ -420,6 +420,53 @@ class AnimationEditor
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def play_animation
|
||||
# TODO: Grey out the rest of the screen.
|
||||
play_controls = @components[:play_controls]
|
||||
# Set up canvas as a pseudo-battle screen
|
||||
@components[:canvas].prepare_to_play_animation
|
||||
play_controls.prepare_to_play_animation
|
||||
# Set up fake battlers for the animation player
|
||||
user_battler = nil
|
||||
if !@anim[:no_user]
|
||||
user_battler = AnimationPlayer::FakeBattler.new(@settings[:user_index], @settings[:user_sprite_name])
|
||||
end
|
||||
target_battlers = nil
|
||||
if !@anim[:no_target]
|
||||
target_battlers = []
|
||||
@settings[:target_indices].each do |idx|
|
||||
target_battlers.push(AnimationPlayer::FakeBattler.new(idx, @settings[:target_sprite_name]))
|
||||
end
|
||||
end
|
||||
# Create animation player
|
||||
anim_player = AnimationPlayer.new(@anim, user_battler, target_battlers, @components[:canvas])
|
||||
anim_player.looping = @components[:play_controls].looping
|
||||
anim_player.slowdown = @components[:play_controls].slowdown
|
||||
anim_player.set_up
|
||||
# Play animation
|
||||
anim_player.start
|
||||
loop do
|
||||
Graphics.update
|
||||
Input.update
|
||||
anim_player.update
|
||||
# TODO: Maybe get elapsed time from anim_player and pass it to
|
||||
# play_controls to be drawn?
|
||||
play_controls.update
|
||||
if play_controls.changed?
|
||||
if play_controls.values.keys.include?(:stop)
|
||||
play_controls.clear_changed
|
||||
break
|
||||
end
|
||||
end
|
||||
break if anim_player.finished?
|
||||
end
|
||||
anim_player.dispose
|
||||
@components[:canvas].end_playing_animation
|
||||
play_controls.end_playing_animation
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def refresh_component_visibility(component_sym)
|
||||
# Panes are all mutually exclusive
|
||||
side_pane = AnimationEditor::SidePanes.get_pane(component_sym)
|
||||
@@ -558,8 +605,10 @@ class AnimationEditor
|
||||
refresh
|
||||
end
|
||||
when :play_controls
|
||||
# TODO: Will the play controls ever signal themselves as changed? I don't
|
||||
# think so.
|
||||
case property
|
||||
when :play
|
||||
@ready_to_play = true
|
||||
end
|
||||
when :particle_list
|
||||
case property
|
||||
when :add_particle
|
||||
@@ -739,7 +788,10 @@ class AnimationEditor
|
||||
Graphics.update
|
||||
Input.update
|
||||
update
|
||||
if @captured.nil? && @quit
|
||||
if @ready_to_play
|
||||
play_animation
|
||||
@ready_to_play = false
|
||||
elsif @captured.nil? && @quit
|
||||
case message(_INTL("Do you want to save changes to the animation?"),
|
||||
[:yes, _INTL("Yes")], [:no, _INTL("No")], [:cancel, _INTL("Cancel")])
|
||||
when :yes
|
||||
|
||||
@@ -298,13 +298,13 @@ class AnimationEditor::AnimationSelector
|
||||
# Put the correct list into the moves list
|
||||
case @animation_type
|
||||
when 0
|
||||
@components.get_control(:moves).disable
|
||||
@components.get_control(:commons).enable
|
||||
@components.get_control(:moves).set_highlighted
|
||||
@components.get_control(:commons).set_not_highlighted
|
||||
@components.get_control(:moves_list).values = @move_list
|
||||
@components.get_control(:moves_label).text = _INTL("Moves")
|
||||
when 1
|
||||
@components.get_control(:moves).enable
|
||||
@components.get_control(:commons).disable
|
||||
@components.get_control(:moves).set_not_highlighted
|
||||
@components.get_control(:commons).set_highlighted
|
||||
@components.get_control(:moves_list).values = @common_list
|
||||
@components.get_control(:moves_label).text = _INTL("Common animations")
|
||||
end
|
||||
|
||||
@@ -4,18 +4,6 @@
|
||||
module AnimationEditor::ParticleDataHelper
|
||||
module_function
|
||||
|
||||
def get_duration(particles)
|
||||
ret = 0
|
||||
particles.each do |particle|
|
||||
particle.each_pair do |property, value|
|
||||
next if !value.is_a?(Array) || value.length == 0
|
||||
max = value.last[0] + value.last[1] # Keyframe + duration
|
||||
ret = max if ret < max
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
def get_keyframe_particle_value(particle, property, frame)
|
||||
if !GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES.include?(property)
|
||||
raise _INTL("Couldn't get default value for property {1} for particle {2}.",
|
||||
@@ -34,28 +22,9 @@ module AnimationEditor::ParticleDataHelper
|
||||
next
|
||||
end
|
||||
# In a "MoveXYZ" command; need to interpolate
|
||||
case (cmd[3] || :linear)
|
||||
when :linear
|
||||
ret[0] = lerp(ret[0], cmd[2], cmd[1], cmd[0], frame).to_i
|
||||
when :ease_in # Quadratic
|
||||
x = (frame - cmd[0]) / cmd[1].to_f
|
||||
ret[0] += (cmd[2] - ret[0]) * x * x
|
||||
ret[0] = ret[0].round
|
||||
when :ease_out # Quadratic
|
||||
x = (frame - cmd[0]) / cmd[1].to_f
|
||||
ret[0] += (cmd[2] - ret[0]) * (1 - ((1 - x) * (1 - x)))
|
||||
ret[0] = ret[0].round
|
||||
when :ease_both # Quadratic
|
||||
x = (frame - cmd[0]) / cmd[1].to_f
|
||||
if x < 0.5
|
||||
ret[0] += (cmd[2] - ret[0]) * x * x * 2
|
||||
else
|
||||
ret[0] += (cmd[2] - ret[0]) * (1 - (((-2 * x) + 2) * ((-2 * x) + 2) / 2))
|
||||
end
|
||||
ret[0] = ret[0].round
|
||||
else
|
||||
raise _INTL("Unknown interpolation method {1}.", cmd[3])
|
||||
end
|
||||
ret[0] = AnimationPlayer::Helper.interpolate(
|
||||
(cmd[3] || :linear), ret[0], cmd[2], cmd[1], cmd[0], frame
|
||||
)
|
||||
ret[1] = true # Interpolating
|
||||
break
|
||||
end
|
||||
@@ -68,7 +37,7 @@ module AnimationEditor::ParticleDataHelper
|
||||
first_cmd = (["User", "Target"].include?(particle[:name])) ? 0 : -1
|
||||
first_visible_cmd = -1
|
||||
particle.each_pair do |prop, value|
|
||||
next if !value.is_a?(Array) || value.length == 0
|
||||
next if !value.is_a?(Array) || value.empty?
|
||||
first_cmd = value[0][0] if first_cmd < 0 || first_cmd > value[0][0]
|
||||
first_visible_cmd = value[0][0] if prop == :visible && (first_visible_cmd < 0 || first_visible_cmd > value[0][0])
|
||||
end
|
||||
@@ -111,7 +80,7 @@ module AnimationEditor::ParticleDataHelper
|
||||
if !["User", "Target", "SE"].include?(particle[:name])
|
||||
earliest = duration
|
||||
particle.each_pair do |prop, value|
|
||||
next if !value.is_a?(Array) || value.length == 0
|
||||
next if !value.is_a?(Array) || value.empty?
|
||||
earliest = value[0][0] if earliest > value[0][0]
|
||||
end
|
||||
ret[earliest] = true
|
||||
@@ -152,7 +121,7 @@ module AnimationEditor::ParticleDataHelper
|
||||
# [+/- duration, interpolation type] --- MoveXYZ (duration's sign is whether
|
||||
# it makes the value higher or lower)
|
||||
def get_particle_property_commands_timeline(particle, property, commands)
|
||||
return nil if !commands || commands.length == 0
|
||||
return nil if !commands || commands.empty?
|
||||
if particle[:name] == "SE"
|
||||
ret = []
|
||||
commands.each { |cmd| ret[cmd[0]] = 0 }
|
||||
@@ -192,7 +161,7 @@ module AnimationEditor::ParticleDataHelper
|
||||
se_particle = particles.select { |particle| particle[:name] == "SE" }[0]
|
||||
if se_particle
|
||||
se_particle.each_pair do |property, values|
|
||||
next if !values.is_a?(Array) || values.length == 0
|
||||
next if !values.is_a?(Array) || values.empty?
|
||||
ret = values.any? { |value| value[0] == frame }
|
||||
break if ret
|
||||
end
|
||||
@@ -310,7 +279,7 @@ module AnimationEditor::ParticleDataHelper
|
||||
first_cmd = (["User", "Target", "SE"].include?(particle[:name])) ? 0 : -1
|
||||
first_non_visible_cmd = -1
|
||||
particle.each_pair do |prop, value|
|
||||
next if !value.is_a?(Array) || value.length == 0
|
||||
next if !value.is_a?(Array) || value.empty?
|
||||
next if prop == property && value[0][0] == frame
|
||||
first_cmd = value[0][0] if first_cmd < 0 || first_cmd > value[0][0]
|
||||
next if prop == :visible
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
# 9999+ = UI
|
||||
#===============================================================================
|
||||
class AnimationEditor::Canvas < Sprite
|
||||
attr_reader :sprites # Only used while playing the animation
|
||||
attr_reader :values
|
||||
|
||||
FRAME_SIZE = 48
|
||||
@@ -25,7 +26,6 @@ class AnimationEditor::Canvas < Sprite
|
||||
@captured = nil
|
||||
@user_coords = []
|
||||
@target_coords = []
|
||||
@playing = false # TODO: What should this affect? Is it needed?
|
||||
initialize_background
|
||||
initialize_battlers
|
||||
initialize_particle_sprites
|
||||
@@ -195,15 +195,40 @@ class AnimationEditor::Canvas < Sprite
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def prepare_to_play_animation
|
||||
# TODO: Hide particle sprites, set battler sprites to starting positions so
|
||||
# that the animation can play properly. Also need a way to end this
|
||||
# override after the animation finishes playing. This method does not
|
||||
# literally play the animation; the main editor screen or playback
|
||||
# control does that.
|
||||
@sprites = {}
|
||||
# Populate @sprites with sprites that are present during battle, and reset
|
||||
# their x/y/z values so the animation player knows where they start
|
||||
idx = user_index
|
||||
particle_idx = @anim[:particles].index { |particle| particle[:name] == "User" }
|
||||
@sprites["pokemon_#{idx}"] = @battler_sprites[idx]
|
||||
@battler_sprites[idx].x = @user_coords[0]
|
||||
@battler_sprites[idx].y = @user_coords[1]
|
||||
offset_xy = AnimationPlayer::Helper.get_xy_offset(@anim[:particles][particle_idx], @battler_sprites[idx])
|
||||
@battler_sprites[idx].x += offset_xy[0]
|
||||
@battler_sprites[idx].y += offset_xy[1]
|
||||
focus_z = AnimationPlayer::Helper.get_z_focus(@anim[:particles][particle_idx], idx, idx)
|
||||
AnimationPlayer::Helper.apply_z_focus_to_sprite(@battler_sprites[idx], 0, focus_z)
|
||||
@battler_sprites[idx].z = 0
|
||||
particle_idx = @anim[:particles].index { |particle| particle[:name] == "Target" }
|
||||
target_indices.each do |idx|
|
||||
@sprites["pokemon_#{idx}"] = @battler_sprites[idx]
|
||||
@battler_sprites[idx].x = @target_coords[idx][0]
|
||||
@battler_sprites[idx].y = @target_coords[idx][1]
|
||||
offset_xy = AnimationPlayer::Helper.get_xy_offset(@anim[:particles][particle_idx], @battler_sprites[idx])
|
||||
@battler_sprites[idx].x += offset_xy[0]
|
||||
@battler_sprites[idx].y += offset_xy[1]
|
||||
focus_z = AnimationPlayer::Helper.get_z_focus(@anim[:particles][particle_idx], idx, idx)
|
||||
AnimationPlayer::Helper.apply_z_focus_to_sprite(@battler_sprites[idx], 0, focus_z)
|
||||
end
|
||||
# TODO: Also add background/bases and so on.
|
||||
hide_all_sprites
|
||||
@sel_frame_sprite.visible = false
|
||||
@playing = true
|
||||
end
|
||||
|
||||
def end_playing_animation
|
||||
@sprites.clear
|
||||
@sprites = nil
|
||||
@playing = false
|
||||
refresh
|
||||
end
|
||||
@@ -298,17 +323,21 @@ class AnimationEditor::Canvas < Sprite
|
||||
def refresh_battler_graphics
|
||||
if !@user_sprite_name || !@user_sprite_name || @user_sprite_name != @settings[:user_sprite_name]
|
||||
@user_sprite_name = @settings[:user_sprite_name]
|
||||
@user_bitmap_front_name = GameData::Species.front_sprite_filename(@user_sprite_name)
|
||||
@user_bitmap_back_name = GameData::Species.back_sprite_filename(@user_sprite_name)
|
||||
@user_bitmap_front&.dispose
|
||||
@user_bitmap_back&.dispose
|
||||
@user_bitmap_front = RPG::Cache.load_bitmap("Graphics/Pokemon/Front/", @user_sprite_name)
|
||||
@user_bitmap_back = RPG::Cache.load_bitmap("Graphics/Pokemon/Back/", @user_sprite_name)
|
||||
@user_bitmap_front = RPG::Cache.load_bitmap("", @user_bitmap_front_name)
|
||||
@user_bitmap_back = RPG::Cache.load_bitmap("", @user_bitmap_back_name)
|
||||
end
|
||||
if !@target_bitmap_front || !@target_sprite_name || @target_sprite_name != @settings[:target_sprite_name]
|
||||
@target_sprite_name = @settings[:target_sprite_name]
|
||||
@target_bitmap_front_name = GameData::Species.front_sprite_filename(@target_sprite_name)
|
||||
@target_bitmap_back_name = GameData::Species.back_sprite_filename(@target_sprite_name)
|
||||
@target_bitmap_front&.dispose
|
||||
@target_bitmap_back&.dispose
|
||||
@target_bitmap_front = RPG::Cache.load_bitmap("Graphics/Pokemon/Front/", @target_sprite_name)
|
||||
@target_bitmap_back = RPG::Cache.load_bitmap("Graphics/Pokemon/Back/", @target_sprite_name)
|
||||
@target_bitmap_front = RPG::Cache.load_bitmap("", @target_bitmap_front_name)
|
||||
@target_bitmap_back = RPG::Cache.load_bitmap("", @target_bitmap_back_name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -403,108 +432,24 @@ class AnimationEditor::Canvas < Sprite
|
||||
# Set opacity
|
||||
spr.opacity = values[:opacity]
|
||||
# Set coordinates
|
||||
spr.x = values[:x]
|
||||
spr.y = values[:y]
|
||||
case particle[:focus]
|
||||
when :foreground, :midground, :background
|
||||
when :user
|
||||
spr.x += @user_coords[0]
|
||||
spr.y += @user_coords[1]
|
||||
when :target
|
||||
spr.x += @target_coords[target_idx][0]
|
||||
spr.y += @target_coords[target_idx][1]
|
||||
when :user_and_target
|
||||
user_pos = @user_coords
|
||||
target_pos = @target_coords[target_idx]
|
||||
distance = GameData::Animation::USER_AND_TARGET_SEPARATION
|
||||
spr.x = user_pos[0] + ((values[:x].to_f / distance[0]) * (target_pos[0] - user_pos[0])).to_i
|
||||
spr.y = user_pos[1] + ((values[:y].to_f / distance[1]) * (target_pos[1] - user_pos[1])).to_i
|
||||
when :user_side_foreground, :user_side_background
|
||||
base_coords = Battle::Scene.pbBattlerPosition(user_index)
|
||||
spr.x += base_coords[0]
|
||||
spr.y += base_coords[1]
|
||||
when :target_side_foreground, :target_side_background
|
||||
base_coords = Battle::Scene.pbBattlerPosition(target_idx)
|
||||
spr.x += base_coords[0]
|
||||
spr.y += base_coords[1]
|
||||
end
|
||||
focus_xy = AnimationPlayer::Helper.get_xy_focus(particle, user_index, target_idx,
|
||||
@user_coords, @target_coords[target_idx])
|
||||
AnimationPlayer::Helper.apply_xy_focus_to_sprite(spr, :x, values[:x], focus_xy)
|
||||
AnimationPlayer::Helper.apply_xy_focus_to_sprite(spr, :y, values[:y], focus_xy)
|
||||
# Set graphic and ox/oy (may also alter y coordinate)
|
||||
case particle[:graphic]
|
||||
when "USER", "USER_OPP", "USER_FRONT", "USER_BACK",
|
||||
"TARGET", "TARGET_OPP", "TARGET_FRONT", "TARGET_BACK"
|
||||
case particle[:graphic]
|
||||
when "USER"
|
||||
spr.bitmap = (user_index.even?) ? @user_bitmap_back : @user_bitmap_front
|
||||
when "USER_OPP"
|
||||
spr.bitmap = (user_index.even?) ? @user_bitmap_front : @user_bitmap_back
|
||||
when "USER_FRONT"
|
||||
spr.bitmap = @user_bitmap_front
|
||||
when "USER_BACK"
|
||||
spr.bitmap = @user_bitmap_back
|
||||
when "TARGET"
|
||||
spr.bitmap = (target_idx.even?) ? @target_bitmap_back : @target_bitmap_front
|
||||
when "TARGET_OPP"
|
||||
spr.bitmap = (target_idx.even?) ? @target_bitmap_front : @target_bitmap_back
|
||||
when "TARGET_FRONT"
|
||||
spr.bitmap = @target_bitmap_front
|
||||
when "TARGET_BACK"
|
||||
spr.bitmap = @target_bitmap_back
|
||||
end
|
||||
spr.ox = spr.bitmap.width / 2
|
||||
spr.oy = spr.bitmap.height
|
||||
spr.y += spr.bitmap.height / 2
|
||||
else
|
||||
spr.bitmap = RPG::Cache.load_bitmap("Graphics/Battle animations/", particle[:graphic])
|
||||
if [:foreground, :midground, :background].include?(particle[:focus]) &&
|
||||
spr.bitmap.width == AnimationEditor::CANVAS_WIDTH &&
|
||||
spr.bitmap.height >= AnimationEditor::CANVAS_HEIGHT - @message_bar_sprite.y
|
||||
spr.ox = 0
|
||||
spr.oy = 0
|
||||
elsif spr.bitmap.width > spr.bitmap.height * 2
|
||||
spr.src_rect.set(values[:frame] * spr.bitmap.height, 0, spr.bitmap.height, spr.bitmap.height)
|
||||
spr.ox = spr.bitmap.height / 2
|
||||
spr.oy = spr.bitmap.height / 2
|
||||
else
|
||||
spr.src_rect.set(0, 0, spr.bitmap.width, spr.bitmap.height)
|
||||
spr.ox = spr.bitmap.width / 2
|
||||
spr.oy = spr.bitmap.height / 2
|
||||
end
|
||||
if particle[:graphic][/\[\s*bottom\s*\]\s*$/i] # [bottom] at end of filename
|
||||
spr.oy = spr.bitmap.height
|
||||
end
|
||||
end
|
||||
AnimationPlayer::Helper.set_bitmap_and_origin(particle, spr, user_index, target_idx,
|
||||
[@user_bitmap_front_name, @user_bitmap_back_name],
|
||||
[@target_bitmap_front_name, @target_bitmap_back_name])
|
||||
offset_xy = AnimationPlayer::Helper.get_xy_offset(particle, spr)
|
||||
spr.x += offset_xy[0]
|
||||
spr.y += offset_xy[1]
|
||||
# Set frame
|
||||
# TODO: Should this always happens or only if the graphic is a spritesheet?
|
||||
# I don't think there's harm in it always being set.
|
||||
spr.src_rect.x = values[:frame].floor * spr.src_rect.width
|
||||
# Set z (priority)
|
||||
spr.z = values[:z]
|
||||
case particle[:focus]
|
||||
when :foreground
|
||||
spr.z += 2000
|
||||
when :midground
|
||||
spr.z += 1000
|
||||
when :background
|
||||
# NOTE: No change.
|
||||
when :user
|
||||
spr.z += 1000 + ((100 * ((user_index / 2) + 1)) * (user_index.even? ? 1 : -1))
|
||||
when :target
|
||||
spr.z += 1000 + ((100 * ((target_idx / 2) + 1)) * (target_idx.even? ? 1 : -1))
|
||||
when :user_and_target
|
||||
user_pos = 1000 + ((100 * ((user_index / 2) + 1)) * (user_index.even? ? 1 : -1))
|
||||
target_pos = 1000 + ((100 * ((target_idx / 2) + 1)) * (target_idx.even? ? 1 : -1))
|
||||
distance = GameData::Animation::USER_AND_TARGET_SEPARATION[2]
|
||||
if values[:z] >= 0
|
||||
spr.z += user_pos
|
||||
elsif values[:z] <= distance
|
||||
spr.z += target_pos
|
||||
else
|
||||
spr.z = user_pos + ((values[:z].to_f / distance) * (target_pos - user_pos)).to_i
|
||||
end
|
||||
when :user_side_foreground, :target_side_foreground
|
||||
this_idx = (particle[:focus] == :user_side_foreground) ? user_index : target_idx
|
||||
spr.z += 1000
|
||||
spr.z += 1000 if this_idx.even? # On player's side
|
||||
when :user_side_background, :target_side_background
|
||||
this_idx = (particle[:focus] == :user_side_background) ? user_index : target_idx
|
||||
spr.z += 1000 if this_idx.even? # On player's side
|
||||
end
|
||||
focus_z = AnimationPlayer::Helper.get_z_focus(particle, user_index, target_idx)
|
||||
AnimationPlayer::Helper.apply_z_focus_to_sprite(spr, values[:z], focus_z)
|
||||
# Set various other properties
|
||||
spr.zoom_x = values[:zoom_x] / 100.0
|
||||
spr.zoom_y = values[:zoom_y] / 100.0
|
||||
@@ -544,11 +489,7 @@ class AnimationEditor::Canvas < Sprite
|
||||
update_selected_particle_frame
|
||||
end
|
||||
|
||||
def refresh
|
||||
refresh_bg_graphics
|
||||
ensure_battler_sprites
|
||||
refresh_battler_graphics
|
||||
refresh_battler_positions
|
||||
def hide_all_sprites
|
||||
[@battler_sprites, @battler_frame_sprites].each do |sprites|
|
||||
sprites.each { |s| s.visible = false if s && !s.disposed? }
|
||||
end
|
||||
@@ -561,6 +502,14 @@ class AnimationEditor::Canvas < Sprite
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def refresh
|
||||
refresh_bg_graphics
|
||||
ensure_battler_sprites
|
||||
refresh_battler_graphics
|
||||
refresh_battler_positions
|
||||
hide_all_sprites
|
||||
@anim[:particles].each_with_index do |particle, i|
|
||||
if GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus])
|
||||
refresh_particle(i) # Because there can be multiple targets
|
||||
|
||||
@@ -1,25 +1,193 @@
|
||||
#===============================================================================
|
||||
# TODO
|
||||
#
|
||||
#===============================================================================
|
||||
class AnimationEditor::PlayControls < UIControls::BaseControl
|
||||
class AnimationEditor::PlayControls < UIControls::ControlsContainer
|
||||
attr_reader :slowdown, :looping
|
||||
|
||||
ROW_HEIGHT = 28
|
||||
PLAY_BUTTON_X = 241
|
||||
PLAY_BUTTON_Y = 13
|
||||
PLAY_BUTTON_SIZE = 22
|
||||
LOOP_BUTTON_X = PLAY_BUTTON_X + PLAY_BUTTON_SIZE + 12
|
||||
LOOP_BUTTON_Y = 16
|
||||
LOOP_BUTTON_SIZE = 16
|
||||
# NOTE: Slowdown label is centered horizontally over the buttons.
|
||||
SLOWDOWN_LABEL_Y = 0
|
||||
SLOWDOWN_BUTTON_X = 1
|
||||
SLOWDOWN_BUTTON_Y = ROW_HEIGHT - 1
|
||||
SLOWDOWN_BUTTON_WIDTH = 32
|
||||
SLOWDOWN_BUTTON_SPACING = -3
|
||||
# NOTE: Duration label and value are centered horizontally on DURATION_TEXT_X.
|
||||
DURATION_TEXT_X = 464
|
||||
DURATION_LABEL_Y = SLOWDOWN_LABEL_Y
|
||||
DURATION_VALUE_Y = ROW_HEIGHT
|
||||
SLOWDOWN_FACTORS = [1, 2, 4, 6, 8]
|
||||
ICON_COLOR = Color.black
|
||||
|
||||
def initialize(x, y, width, height, viewport)
|
||||
super(width, height, viewport)
|
||||
self.x = x
|
||||
self.y = y
|
||||
super(x, y, width, height)
|
||||
@viewport.z = viewport.z + 10
|
||||
generate_button_bitmaps
|
||||
@duration = 0
|
||||
@slowdown = SLOWDOWN_FACTORS[0]
|
||||
@looping = false
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def add_play_controls
|
||||
# Play button
|
||||
play_button = UIControls::BitmapButton.new(PLAY_BUTTON_X, PLAY_BUTTON_Y, self.viewport, @play_button_bitmap)
|
||||
play_button.set_interactive_rects
|
||||
play_button.disable
|
||||
@controls.push([:play, play_button])
|
||||
# Stop button
|
||||
stop_button = UIControls::BitmapButton.new(PLAY_BUTTON_X, PLAY_BUTTON_Y, self.viewport, @stop_button_bitmap)
|
||||
stop_button.set_interactive_rects
|
||||
stop_button.visible = false
|
||||
@controls.push([:stop, stop_button])
|
||||
# Loop buttons
|
||||
loop_button = UIControls::BitmapButton.new(LOOP_BUTTON_X, LOOP_BUTTON_Y, self.viewport, @play_once_button_bitmap)
|
||||
loop_button.set_interactive_rects
|
||||
loop_button.visible = false if @looping
|
||||
@controls.push([:loop, loop_button])
|
||||
unloop_button = UIControls::BitmapButton.new(LOOP_BUTTON_X, LOOP_BUTTON_Y, self.viewport, @looping_button_bitmap)
|
||||
unloop_button.set_interactive_rects
|
||||
unloop_button.visible = false if !@looping
|
||||
@controls.push([:unloop, unloop_button])
|
||||
# Slowdown label
|
||||
duration_label = UIControls::Label.new(200, ROW_HEIGHT, self.viewport, _INTL("Slowdown factor"))
|
||||
duration_label.x = SLOWDOWN_BUTTON_X + (SLOWDOWN_FACTORS.length * (SLOWDOWN_BUTTON_WIDTH - SLOWDOWN_BUTTON_SPACING) / 2)
|
||||
duration_label.x -= (duration_label.text_width / 2) + 5
|
||||
duration_label.y = SLOWDOWN_LABEL_Y
|
||||
@controls.push([:slowdown_label, duration_label])
|
||||
# Slowdown factor buttons
|
||||
SLOWDOWN_FACTORS.each_with_index do |value, i|
|
||||
button = UIControls::Button.new(SLOWDOWN_BUTTON_WIDTH, ROW_HEIGHT, self.viewport, value.to_s)
|
||||
button.set_fixed_size
|
||||
button.x = SLOWDOWN_BUTTON_X + ((SLOWDOWN_BUTTON_WIDTH - SLOWDOWN_BUTTON_SPACING) * i)
|
||||
button.y = SLOWDOWN_BUTTON_Y
|
||||
button.set_interactive_rects
|
||||
button.set_highlighted if value == @slowdown
|
||||
@controls.push([("slowdown" + value.to_s).to_sym, button])
|
||||
end
|
||||
# Duration label
|
||||
duration_label = UIControls::Label.new(200, ROW_HEIGHT, self.viewport, _INTL("Duration"))
|
||||
duration_label.x = DURATION_TEXT_X - (duration_label.text_width / 2)
|
||||
duration_label.y = DURATION_LABEL_Y
|
||||
@controls.push([:duration_label, duration_label])
|
||||
# Duration value
|
||||
duration_value = UIControls::Label.new(200, ROW_HEIGHT, self.viewport, _INTL("{1}s", 0.0))
|
||||
duration_value.x = DURATION_TEXT_X - (duration_value.text_width / 2)
|
||||
duration_value.y = DURATION_VALUE_Y
|
||||
@controls.push([:duration_value, duration_value])
|
||||
end
|
||||
|
||||
def generate_button_bitmaps
|
||||
@play_button_bitmap = Bitmap.new(PLAY_BUTTON_SIZE, PLAY_BUTTON_SIZE)
|
||||
(PLAY_BUTTON_SIZE - 2).times do |j|
|
||||
@play_button_bitmap.fill_rect(PLAY_BUTTON_SIZE / 4, j + 1, (j >= (PLAY_BUTTON_SIZE - 2) / 2) ? PLAY_BUTTON_SIZE - j : j + 3, 1, ICON_COLOR)
|
||||
end
|
||||
@stop_button_bitmap = Bitmap.new(PLAY_BUTTON_SIZE, PLAY_BUTTON_SIZE)
|
||||
@stop_button_bitmap.fill_rect(4, 4, PLAY_BUTTON_SIZE - 8, PLAY_BUTTON_SIZE - 8, ICON_COLOR)
|
||||
# Loop button
|
||||
@play_once_button_bitmap = Bitmap.new(LOOP_BUTTON_SIZE, LOOP_BUTTON_SIZE)
|
||||
@play_once_button_bitmap.fill_rect(1, 7, 11, 2, ICON_COLOR)
|
||||
@play_once_button_bitmap.fill_rect(8, 5, 2, 6, ICON_COLOR)
|
||||
@play_once_button_bitmap.fill_rect(10, 6, 1, 4, ICON_COLOR)
|
||||
@play_once_button_bitmap.fill_rect(13, 1, 2, 14, ICON_COLOR)
|
||||
@looping_button_bitmap = Bitmap.new(LOOP_BUTTON_SIZE, LOOP_BUTTON_SIZE)
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
|
||||
1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
|
||||
1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0].each_with_index do |val, i|
|
||||
next if val == 0
|
||||
@looping_button_bitmap.fill_rect(1 + (i % 14), 1 + (i / 14), 1, 1, ICON_COLOR)
|
||||
end
|
||||
end
|
||||
|
||||
def dispose
|
||||
@play_button_bitmap.dispose
|
||||
@stop_button_bitmap.dispose
|
||||
@play_once_button_bitmap.dispose
|
||||
@looping_button_bitmap.dispose
|
||||
super
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def duration=(new_val)
|
||||
return if @duration == new_val
|
||||
@duration = new_val
|
||||
if @duration == 0
|
||||
get_control(:play).disable
|
||||
else
|
||||
get_control(:play).enable
|
||||
end
|
||||
ctrl = get_control(:duration_value)
|
||||
ctrl.text = _INTL("{1}s", @duration / 20.0)
|
||||
ctrl.x = DURATION_TEXT_X - (ctrl.text_width / 2)
|
||||
refresh
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def refresh
|
||||
def prepare_to_play_animation
|
||||
get_control(:play).visible = false
|
||||
get_control(:stop).visible = true
|
||||
@controls.each { |ctrl| ctrl[1].disable if ctrl[0] != :stop }
|
||||
end
|
||||
|
||||
def end_playing_animation
|
||||
get_control(:stop).visible = false
|
||||
get_control(:play).visible = true
|
||||
@controls.each { |ctrl| ctrl[1].enable }
|
||||
end
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def update
|
||||
super
|
||||
draw_text(self.bitmap, 12, TEXT_OFFSET_Y + 14, _INTL("Play controls not added yet!"))
|
||||
draw_text(self.bitmap, width - 134, TEXT_OFFSET_Y, _INTL("Total length: {1}s", @duration / 20.0))
|
||||
if @values
|
||||
@values.keys.each do |key|
|
||||
case key
|
||||
when :loop
|
||||
get_control(:loop).visible = false
|
||||
get_control(:unloop).visible = true
|
||||
@looping = true
|
||||
@values.delete(key)
|
||||
when :unloop
|
||||
get_control(:unloop).visible = false
|
||||
get_control(:loop).visible = true
|
||||
@looping = false
|
||||
@values.delete(key)
|
||||
else
|
||||
if key.to_s[/slowdown/]
|
||||
# A slowdown button was pressed; apply its effect now
|
||||
@slowdown = key.to_s.sub("slowdown", "").to_i
|
||||
@controls.each do |ctrl|
|
||||
next if !ctrl[0].to_s[/slowdown\d+/]
|
||||
if ctrl[0].to_s.sub("slowdown", "").to_i == @slowdown
|
||||
ctrl[1].set_highlighted
|
||||
else
|
||||
ctrl[1].set_not_highlighted
|
||||
end
|
||||
end
|
||||
@values.delete(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
@values = nil if @values.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -177,6 +177,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
||||
@list_viewport.dispose
|
||||
@commands_bg_viewport.dispose
|
||||
@commands_viewport.dispose
|
||||
super
|
||||
end
|
||||
|
||||
def dispose_listed_sprites
|
||||
@@ -430,7 +431,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def calculate_duration
|
||||
@duration = AnimationEditor::ParticleDataHelper.get_duration(@particles)
|
||||
@duration = AnimationPlayer::Helper.get_duration(@particles)
|
||||
@duration += DURATION_BUFFER
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user