Added canvas to new animation editor (isn't interactive yet), improved example animations

This commit is contained in:
Maruno17
2024-01-25 21:07:16 +00:00
parent 94f0a9c8d0
commit 4455c093b8
245 changed files with 22085 additions and 14046 deletions

View File

@@ -135,7 +135,7 @@ module Compiler
case particle[:name]
when "User" then particle[:focus] = :user
when "Target" then particle[:focus] = :target
else particle[:focus] = :screen
else particle[:focus] = GameData::Animation::PARTICLE_DEFAULT_VALUES[:focus]
end
end
# Ensure user/target particles have a default graphic if not given
@@ -145,9 +145,11 @@ module Compiler
when "Target" then particle[:graphic] = "TARGET"
end
end
# TODO: Ensure that particles don't have a focus involving a user if the
# animation itself doesn't involve a user.
# Ensure that particles don't have a focus involving a target if the
# animation itself doesn't involve a target
if hash[:no_target] && [:target, :user_and_target].include?(particle[:focus])
if hash[:no_target] && GameData::Animation::FOCUS_TYPES_WITH_TARGET.include?(particle[:focus])
raise _INTL("Particle \"{1}\" can't have a \"Focus\" that involves a target if property \"NoTarget\" is set to true.",
particle[:name]) + "\n" + FileLineData.linereport
end

View File

@@ -1,3 +1,6 @@
# TODO: OppMove animations have their user and target swapped, and will need
# them swapping back.
module AnimationConverter
module_function
@@ -50,6 +53,7 @@ module AnimationConverter
}
add_frames_to_new_anim_hash(anim, new_anim)
add_bg_fg_commands_to_new_anim_hash(anim, new_anim)
add_se_commands_to_new_anim_hash(anim, new_anim)
new_anim[:particles].compact!
@@ -60,6 +64,9 @@ module AnimationConverter
end
def add_frames_to_new_anim_hash(anim, hash)
# Lookup array for particle index using cel index
index_lookup = []
max_index = -1
# Set up previous frame's values
default_frame = []
default_frame[AnimFrame::X] = -999
@@ -77,30 +84,70 @@ module AnimationConverter
default_frame[AnimFrame::TONEGREEN] = 0
default_frame[AnimFrame::TONEBLUE] = 0
default_frame[AnimFrame::TONEGRAY] = 0
default_frame[AnimFrame::PATTERN] = 0
default_frame[AnimFrame::PRIORITY] = 0 # 0=back, 1=front, 2=behind focus, 3=before focus
default_frame[AnimFrame::VISIBLE] = 1 # Boolean
default_frame[AnimFrame::MIRROR] = 0 # Boolean
default_frame[AnimFrame::FOCUS] = 4 # 1=target, 2=user, 3=user and target, 4=screen
default_frame[99] = anim.graphic
last_frame_values = []
# Go through each frame
anim.length.times do |frame_num|
frame = anim[frame_num]
had_particles = []
changed_particles = []
frame.each_with_index do |cel, i|
next if !cel
# If the particle from the previous frame for this cel had a different
# focus, start a new particle.
if i > 1 && frame_num > 0 && index_lookup[i] && index_lookup[i] >= 0 &&
last_frame_values[index_lookup[i]]
this_graphic = (cel[AnimFrame::PATTERN] == -1) ? "USER" : (cel[AnimFrame::PATTERN] == -2) ? "TARGET" : anim.graphic
if last_frame_values[index_lookup[i]][AnimFrame::FOCUS] != cel[AnimFrame::FOCUS] ||
last_frame_values[index_lookup[i]][99] != this_graphic # Graphic
index_lookup[i] = -1
end
end
# Get the particle index for this cel
if !index_lookup[i] || index_lookup[i] < 0
max_index += 1
index_lookup[i] = max_index
end
idx = index_lookup[i]
had_particles.push(idx)
# i=0 for "User", i=1 for "Target"
hash[:particles][i] ||= {
:name => "Particle #{i}"
}
particle = hash[:particles][i]
if i == 0
hash[:particles][idx] ||= { :name => "Particle #{idx}" }
particle = hash[:particles][idx]
last_frame = last_frame_values[idx] || default_frame.clone
# User and target particles have specific names
if idx == 0
particle[:name] = "User"
elsif i == 1
elsif idx == 1
particle[:name] = "Target"
else
# Set graphic
case cel[AnimFrame::PATTERN]
when -1 # User's sprite
particle[:graphic] = "USER"
last_frame[99] = "USER"
when -2 # Target's sprite
particle[:graphic] = "TARGET"
last_frame[99] = "TARGET"
else
particle[:graphic] = anim.graphic
last_frame[99] = anim.graphic
end
end
# Set focus for non-User/non-Target
if idx > 1
particle[:focus] = [:foreground, :target, :user, :user_and_target, :foreground][cel[AnimFrame::FOCUS]]
last_frame[AnimFrame::FOCUS] = cel[AnimFrame::FOCUS]
end
last_frame = last_frame_values[i] || default_frame.clone
# Copy commands across
[
[AnimFrame::X, :x],
@@ -118,25 +165,182 @@ module AnimationConverter
[AnimFrame::TONEGREEN, :tone_green],
[AnimFrame::TONEBLUE, :tone_blue],
[AnimFrame::TONEGRAY, :tone_gray],
[AnimFrame::PATTERN, :frame],
[AnimFrame::PRIORITY, :z],
[AnimFrame::VISIBLE, :visible], # Boolean
[AnimFrame::MIRROR, :flip], # Boolean
].each do |property|
next if cel[property[0]] == last_frame[property[0]]
particle[property[1]] ||= []
val = cel[property[0]].to_i
val = (val == 1) if [:visible, :flip].include?(property[1])
case property[1]
when :x
# TODO: What if the animation is an OppMove one? I think this should
# be the other way around.
if particle[:focus] == :user_and_target
fraction = (val - Battle::Scene::FOCUSUSER_X).to_f / (Battle::Scene::FOCUSTARGET_X - Battle::Scene::FOCUSUSER_X)
val = (fraction * GameData::Animation::USER_AND_TARGET_SEPARATION[0]).to_i
end
when :y
# TODO: What if the animation is an OppMove one? I think this should
# be the other way around.
if particle[:focus] == :user_and_target
fraction = (val - Battle::Scene::FOCUSUSER_Y).to_f / (Battle::Scene::FOCUSTARGET_Y - Battle::Scene::FOCUSUSER_Y)
val = (fraction * GameData::Animation::USER_AND_TARGET_SEPARATION[1]).to_i
end
when :visible, :flip
val = (val == 1) # Boolean
when :z
next if idx <= 1 # User or target
case val
when 0 then val = -50 + i # Back
when 1 then val = 25 + i # Front
when 2 then val = -25 + i # Behind focus
when 3 then val = i # Before focus
end
when :frame
next if val < 0 # -1 is user, -2 is target
end
# TODO: Come up with a better way to set a particle's graphic being
# the user or target. Probably can't, due to overlapping cel
# numbers and user/target being the :graphic property which
# doesn't change.
particle[property[1]].push([frame_num, 0, val])
last_frame[property[0]] = cel[property[0]]
end
# Set graphic
particle[:graphic] = anim.graphic
# Set focus for non-User/non-Target
if i > 1
particle[:focus] = [:screen, :target, :user, :user_and_target, :screen][cel[AnimFrame::FOCUS]]
changed_particles.push(idx) if !changed_particles.include?(idx)
end
# Remember this cel's values at this frame
last_frame_values[i] = last_frame
last_frame_values[idx] = last_frame
end
# End every particle lifetime that didn't have a corresponding cel this
# frame
hash[:particles].each_with_index do |particle, idx|
next if !particle || had_particles.include?(idx)
next if ["User", "Target"].include?(particle[:name])
if last_frame_values[idx][AnimFrame::VISIBLE] == 1
particle[:visible] ||= []
particle[:visible].push([frame_num, 0, false])
changed_particles.push(idx) if !changed_particles.include?(idx)
end
last_frame_values[idx][AnimFrame::VISIBLE] = 0
next if !index_lookup.include?(idx)
lookup_idx = index_lookup.index(idx)
index_lookup[lookup_idx] = -1
end
# Add a dummy command to the user particle in the last frame if that frame
# doesn't have any commands
if frame_num == anim.length - 1 && changed_particles.empty?
hash[:particles].each_with_index do |particle, idx|
next if !particle || idx <= 1 # User or target
# TODO: Making all non-user non-target particles invisible in the last
# frame isn't a perfect solution, but it's good enough to get
# example animation data.
next if last_frame_values[idx][AnimFrame::VISIBLE] == 0
particle[:visible] ||= []
particle[:visible].push([frame_num + 1, 0, false])
end
end
end
hash[:particles][0][:focus] = :user
hash[:particles][1][:focus] = :target
# Adjust all x/y positions based on particle[:focus]
hash[:particles].each do |particle|
next if !particle
offset_x = 0
offset_y = 0
case particle[:focus]
when :user
offset_x = -Battle::Scene::FOCUSUSER_X
offset_y = -Battle::Scene::FOCUSUSER_Y
when :target
offset_x = -Battle::Scene::FOCUSTARGET_X
offset_y = -Battle::Scene::FOCUSTARGET_Y
when :user_and_target
# NOTE: No change, done above.
end
next if offset_x == 0 && offset_y == 0
particle[:x].each { |cmd| cmd[2] += offset_x }
particle[:y].each { |cmd| cmd[2] += offset_y }
end
end
# TODO: Haven't tested this as no Essentials animations use them.
def add_bg_fg_commands_to_new_anim_hash(anim, new_anim)
bg_particle = { :name => "Background", :focus => :background }
fg_particle = { :name => "Foreground", :focus => :foreground }
first_bg_frame = 999
first_fg_frame = 999
anim.timing.each do |cmd|
case cmd.timingType
when 1, 2, 3, 4 # BG graphic (set, move/recolour), FG graphic (set, move/recolour)
is_bg = (cmd.timingType <= 2)
particle = (is_bg) ? bg_particle : fg_particle
duration = (cmd.timingType == 2) ? cmd.duration : 0
added = false
if cmd.name && cmd.name != ""
particle[:graphic] ||= []
particle[:graphic].push([cmd.frame, duration, cmd.name])
added = true
end
if cmd.colorRed
particle[:color_red] ||= []
particle[:color_red].push([cmd.frame, duration, cmd.colorRed])
added = true
end
if cmd.colorGreen
particle[:color_green] ||= []
particle[:color_green].push([cmd.frame, duration, cmd.colorGreen])
added = true
end
if cmd.colorBlue
particle[:color_blue] ||= []
particle[:color_blue].push([cmd.frame, duration, cmd.colorBlue])
added = true
end
if cmd.colorAlpha
particle[:color_alpha] ||= []
particle[:color_alpha].push([cmd.frame, duration, cmd.colorAlpha])
added = true
end
if cmd.opacity
particle[:opacity] ||= []
particle[:opacity].push([cmd.frame, duration, cmd.opacity])
added = true
end
if cmd.bgX
particle[:x] ||= []
particle[:x].push([cmd.frame, duration, cmd.bgX])
added = true
end
if cmd.bgY
particle[:y] ||= []
particle[:y].push([cmd.frame, duration, cmd.bgY])
added = true
end
if added
if is_bg
first_bg_frame = [first_bg_frame, cmd.frame].min
else
first_fg_frame = [first_fg_frame, cmd.frame].min
end
end
end
end
if bg_particle.keys.length > 2
if !bg_particle[:graphic]
particle[:graphic] ||= []
particle[:graphic].push([first_bg_frame, 0, "black_screen"])
end
new_anim[:particles].push(bg_particle)
end
if fg_particle.keys.length > 2
if !fg_particle[:graphic]
particle[:graphic] ||= []
particle[:graphic].push([first_fg_frame, 0, "black_screen"])
end
new_anim[:particles].push(fg_particle)
end
end