Anim Editor: improved NumberTextBox entry, added "FoeInvertX/Y" particle properties, tidied up

This commit is contained in:
Maruno17
2024-04-15 22:42:46 +01:00
parent a548a1ae9d
commit 15033d6114
18 changed files with 271 additions and 279 deletions

View File

@@ -39,7 +39,6 @@ class AnimationEditor::Canvas < Sprite
def initialize_background
self.z = -200
# NOTE: The background graphic is self.bitmap.
# TODO: Add second (flipped) background graphic, for screen shake commands.
player_base_pos = Battle::Scene.pbBattlerPosition(0)
@player_base = IconSprite.new(*player_base_pos, viewport)
@player_base.z = -199
@@ -231,7 +230,6 @@ class AnimationEditor::Canvas < Sprite
AnimationPlayer::Helper.apply_z_focus_to_sprite(@battler_sprites[idx], 0, focus_z)
end
end
# TODO: Also add background/bases and so on.
hide_all_sprites
@sel_frame_sprite.visible = false
@playing = true
@@ -249,9 +247,6 @@ class AnimationEditor::Canvas < Sprite
def refresh_bg_graphics
return if @bg_name && @bg_name == @settings[:canvas_bg]
@bg_name = @settings[:canvas_bg]
# TODO: Make the choice of background graphics match the in-battle one in
# def pbCreateBackdropSprites. Ideally make that method a class method
# so the canvas can use it rather than duplicate it.
self.bitmap = RPG::Cache.load_bitmap("Graphics/Battlebacks/", @bg_name + "_bg")
@player_base.setBitmap("Graphics/Battlebacks/" + @bg_name + "_base0")
@player_base.ox = @player_base.bitmap.width / 2
@@ -292,12 +287,11 @@ class AnimationEditor::Canvas < Sprite
end
end
# TODO: Create shadow sprites?
# TODO: Make this also refresh if the layout of the battle changes (i.e. which
# battlers are the user/target).
def ensure_battler_sprites
if @sides_swapped.nil? || @sides_swapped != sides_swapped? ||
!@side_size0 || @side_size0 != side_size(0)
should_ensure = @sides_swapped.nil? || @sides_swapped != sides_swapped? ||
@settings_user_index.nil? || @settings_user_index != @settings[:user_index] ||
@settings_target_indices.nil? || @settings_target_indices != @settings[:target_indices]
if should_ensure || !@side_size0 || @side_size0 != side_size(0)
@battler_sprites.each_with_index { |s, i| s.dispose if i.even? && s && !s.disposed? }
@battler_frame_sprites.each_with_index { |s, i| s.dispose if i.even? && s && !s.disposed? }
@side_size0 = side_size(0)
@@ -312,8 +306,7 @@ class AnimationEditor::Canvas < Sprite
@battler_frame_sprites[i * 2] = frame_sprite
end
end
if @sides_swapped.nil? || @sides_swapped != sides_swapped? ||
!@side_size1 || @side_size1 != side_size(1)
if should_ensure || !@side_size1 || @side_size1 != side_size(1)
@battler_sprites.each_with_index { |s, i| s.dispose if i.odd? && s && !s.disposed? }
@battler_frame_sprites.each_with_index { |s, i| s.dispose if i.odd? && s && !s.disposed? }
@side_size1 = side_size(1)
@@ -328,7 +321,11 @@ class AnimationEditor::Canvas < Sprite
@battler_frame_sprites[(i * 2) + 1] = frame_sprite
end
end
@sides_swapped = sides_swapped?
if should_ensure
@sides_swapped = sides_swapped?
@settings_user_index = @settings[:user_index]
@settings_target_indices = @settings[:target_indices].clone
end
end
def refresh_battler_graphics
@@ -429,6 +426,14 @@ class AnimationEditor::Canvas < Sprite
def refresh_sprite(index, target_idx = -1)
particle = @anim[:particles][index]
return if !particle || particle[:name] == "SE"
relative_to_index = -1
if particle[:focus] != :user_and_target
if GameData::Animation::FOCUS_TYPES_WITH_USER.include?(particle[:focus])
relative_to_index = user_index
elsif GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus])
relative_to_index = target_idx
end
end
# Get sprite
spr, frame = get_sprite_and_frame(index, target_idx)
# Calculate all values of particle at the current keyframe
@@ -443,10 +448,16 @@ class AnimationEditor::Canvas < Sprite
# Set opacity
spr.opacity = values[:opacity]
# Set coordinates
base_x = values[:x]
base_y = values[:y]
if relative_to_index >= 0 && relative_to_index.odd?
base_x *= -1 if particle[:foe_invert_x]
base_y *= -1 if particle[:foe_invert_y]
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)
AnimationPlayer::Helper.apply_xy_focus_to_sprite(spr, :x, base_x, focus_xy)
AnimationPlayer::Helper.apply_xy_focus_to_sprite(spr, :y, base_y, focus_xy)
# Set graphic and ox/oy (may also alter y coordinate)
AnimationPlayer::Helper.set_bitmap_and_origin(particle, spr, user_index, target_idx,
[@user_bitmap_front_name, @user_bitmap_back_name],
@@ -455,8 +466,6 @@ class AnimationEditor::Canvas < Sprite
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)
focus_z = AnimationPlayer::Helper.get_z_focus(particle, user_index, target_idx)
@@ -627,6 +636,15 @@ class AnimationEditor::Canvas < Sprite
base_coords = Battle::Scene.pbBattlerPosition(first_target_index)
new_pos -= base_coords[0]
end
relative_to_index = -1
if particle[:focus] != :user_and_target
if GameData::Animation::FOCUS_TYPES_WITH_USER.include?(particle[:focus])
relative_to_index = user_index
elsif GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus])
relative_to_index = target_idx
end
end
new_pos *= -1 if relative_to_index >= 0 && relative_to_index.odd? && particle[:foe_invert_x]
@values ||= {}
@values[:x] = new_pos
@captured[0] = new_canvas_x
@@ -655,6 +673,15 @@ class AnimationEditor::Canvas < Sprite
base_coords = Battle::Scene.pbBattlerPosition(first_target_index)
new_pos -= base_coords[1]
end
relative_to_index = -1
if particle[:focus] != :user_and_target
if GameData::Animation::FOCUS_TYPES_WITH_USER.include?(particle[:focus])
relative_to_index = user_index
elsif GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus])
relative_to_index = target_idx
end
end
new_pos *= -1 if relative_to_index >= 0 && relative_to_index.odd? && particle[:foe_invert_y]
@values ||= {}
@values[:y] = new_pos
@captured[1] = new_canvas_y

View File

@@ -33,25 +33,68 @@ class AnimationEditor::PlayControls < UIControls::ControlsContainer
@looping = false
end
def dispose
@bitmaps.each { |b| b&.dispose }
super
end
#-----------------------------------------------------------------------------
def generate_button_bitmaps
@bitmaps = {}
play_button = Bitmap.new(PLAY_BUTTON_SIZE, PLAY_BUTTON_SIZE)
(PLAY_BUTTON_SIZE - 2).times do |j|
play_button.fill_rect(PLAY_BUTTON_SIZE / 4, j + 1, (j >= (PLAY_BUTTON_SIZE - 2) / 2) ? PLAY_BUTTON_SIZE - j : j + 3, 1, ICON_COLOR)
end
@bitmaps[:play_button] = play_button
stop_button = Bitmap.new(PLAY_BUTTON_SIZE, PLAY_BUTTON_SIZE)
stop_button.fill_rect(4, 4, PLAY_BUTTON_SIZE - 8, PLAY_BUTTON_SIZE - 8, ICON_COLOR)
@bitmaps[:stop_button] = stop_button
# Loop button
play_once_button = Bitmap.new(LOOP_BUTTON_SIZE, LOOP_BUTTON_SIZE)
play_once_button.fill_rect(1, 7, 11, 2, ICON_COLOR)
play_once_button.fill_rect(8, 5, 2, 6, ICON_COLOR)
play_once_button.fill_rect(10, 6, 1, 4, ICON_COLOR)
play_once_button.fill_rect(13, 1, 2, 14, ICON_COLOR)
@bitmaps[:play_once_button] = play_once_button
looping_button = 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.fill_rect(1 + (i % 14), 1 + (i / 14), 1, 1, ICON_COLOR)
end
@bitmaps[:looping_button] = looping_button
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 = UIControls::BitmapButton.new(PLAY_BUTTON_X, PLAY_BUTTON_Y, self.viewport, @bitmaps[:play_button])
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 = UIControls::BitmapButton.new(PLAY_BUTTON_X, PLAY_BUTTON_Y, self.viewport, @bitmaps[:stop_button])
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 = UIControls::BitmapButton.new(LOOP_BUTTON_X, LOOP_BUTTON_Y, self.viewport, @bitmaps[:play_once_button])
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 = UIControls::BitmapButton.new(LOOP_BUTTON_X, LOOP_BUTTON_Y, self.viewport, @bitmaps[:looping_button])
unloop_button.set_interactive_rects
unloop_button.visible = false if !@looping
@controls.push([:unloop, unloop_button])
@@ -83,47 +126,6 @@ class AnimationEditor::PlayControls < UIControls::ControlsContainer
@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)

View File

@@ -135,31 +135,35 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
def initialize_controls
generate_button_bitmaps
@controls = []
add_particle_button = UIControls::BitmapButton.new(x + 1, y + 1, viewport, @add_button_bitmap)
add_particle_button = UIControls::BitmapButton.new(x + 1, y + 1, viewport, @bitmaps[:add_button])
add_particle_button.set_interactive_rects
@controls.push([:add_particle, add_particle_button])
up_particle_button = UIControls::BitmapButton.new(x + 22, y + 1, viewport, @up_button_bitmap)
up_particle_button = UIControls::BitmapButton.new(x + 22, y + 1, viewport, @bitmaps[:up_button])
up_particle_button.set_interactive_rects
@controls.push([:move_particle_up, up_particle_button])
down_particle_button = UIControls::BitmapButton.new(x + 43, y + 1, viewport, @down_button_bitmap)
down_particle_button = UIControls::BitmapButton.new(x + 43, y + 1, viewport, @bitmaps[:down_button])
down_particle_button.set_interactive_rects
@controls.push([:move_particle_down, down_particle_button])
end
def generate_button_bitmaps
@add_button_bitmap = Bitmap.new(12, 12)
@add_button_bitmap.fill_rect(1, 5, 10, 2, TEXT_COLOR)
@add_button_bitmap.fill_rect(5, 1, 2, 10, TEXT_COLOR)
@up_button_bitmap = Bitmap.new(12, 12)
@bitmaps = {}
add_button = Bitmap.new(12, 12)
add_button.fill_rect(1, 5, 10, 2, TEXT_COLOR)
add_button.fill_rect(5, 1, 2, 10, TEXT_COLOR)
@bitmaps[:add_button] = add_button
up_button = Bitmap.new(12, 12)
5.times do |i|
@up_button_bitmap.fill_rect(1 + i, 7 - i, 1, (i == 0) ? 2 : 3, TEXT_COLOR)
@up_button_bitmap.fill_rect(10 - i, 7 - i, 1, (i == 0) ? 2 : 3, TEXT_COLOR)
up_button.fill_rect(1 + i, 7 - i, 1, (i == 0) ? 2 : 3, TEXT_COLOR)
up_button.fill_rect(10 - i, 7 - i, 1, (i == 0) ? 2 : 3, TEXT_COLOR)
end
@down_button_bitmap = Bitmap.new(12, 12)
@bitmaps[:up_button] = up_button
down_button = Bitmap.new(12, 12)
5.times do |i|
@down_button_bitmap.fill_rect(1 + i, 2 + i + (i == 0 ? 1 : 0), 1, (i == 0) ? 2 : 3, TEXT_COLOR)
@down_button_bitmap.fill_rect(10 - i, 2 + i + (i == 0 ? 1 : 0), 1, (i == 0) ? 2 : 3, TEXT_COLOR)
down_button.fill_rect(1 + i, 2 + i + (i == 0 ? 1 : 0), 1, (i == 0) ? 2 : 3, TEXT_COLOR)
down_button.fill_rect(10 - i, 2 + i + (i == 0 ? 1 : 0), 1, (i == 0) ? 2 : 3, TEXT_COLOR)
end
@bitmaps[:down_button] = down_button
end
def dispose
@@ -171,9 +175,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
@particle_line_sprite.dispose
@controls.each { |c| c[1].dispose }
@controls.clear
@add_button_bitmap.dispose
@up_button_bitmap.dispose
@down_button_bitmap.dispose
@bitmaps.each { |b| b&.dispose }
dispose_listed_sprites
@list_viewport.dispose
@commands_bg_viewport.dispose
@@ -436,9 +438,6 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
@duration += DURATION_BUFFER
end
# TODO: Call this only from set_particles and when changes are made to
# @particles by the main editor scene. If we can be specific about which
# particle was changed, recalculate only that particle's commands.
def calculate_all_commands_and_durations
calculate_duration
calculate_all_commands
@@ -956,8 +955,6 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
end
set_changed if @keyframe != @captured_keyframe || @row_index != @captured_row
@keyframe = @captured_keyframe || -1
# TODO: If :keyframe_pane should be accessible by clicking on the
# timeline, change the below line to = @captured_row || -1.
@row_index = @captured_row if @captured_row
end
end