Added animation editor's particle list

This commit is contained in:
Maruno17
2023-10-18 16:48:28 +01:00
parent 193f01f70b
commit 7031698d85
10 changed files with 900 additions and 79 deletions

View File

@@ -34,11 +34,14 @@ class AnimationEditor
SIDE_PANE_Y = CANVAS_Y
SIDE_PANE_WIDTH = WINDOW_WIDTH - SIDE_PANE_X - BORDER_THICKNESS
SIDE_PANE_HEIGHT = CANVAS_HEIGHT + (32 * 2)
PARTICLE_LIST_X = 0
PARTICLE_LIST_Y = SIDE_PANE_Y + SIDE_PANE_HEIGHT + (BORDER_THICKNESS * 2)
PARTICLE_LIST_WIDTH = WINDOW_WIDTH
PARTICLE_LIST_HEIGHT = WINDOW_HEIGHT - PARTICLE_LIST_Y
def initialize(anim_id, anim)
@anim_id = anim_id
@anim = anim
@keyframe = 0
@particle = -1
@viewport = Viewport.new(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
@viewport.z = 99999
@@ -50,7 +53,7 @@ class AnimationEditor
@canvas.y = CANVAS_Y
@canvas.bitmap = RPG::Cache.load_bitmap("Graphics/Battlebacks/", "field_bg")
# Side panes
@keyframe_particle_pane = ControlPane.new(SIDE_PANE_X, SIDE_PANE_Y, SIDE_PANE_WIDTH, SIDE_PANE_HEIGHT)
@keyframe_particle_pane = UIControls::ControlsContainer.new(SIDE_PANE_X, SIDE_PANE_Y, SIDE_PANE_WIDTH, SIDE_PANE_HEIGHT)
# TODO: Make more side panes for:
# - colour/tone editor (accessed from keyframe_particle_pane via a
# button; has Apply/Cancel buttons to only apply all its values at
@@ -63,7 +66,14 @@ class AnimationEditor
# shake, etc.)
# - keyframe properties (shift all later particle commands forward/
# backward).
# Timeline/particle list
@particle_list = UIControls::AnimationParticleList.new(
PARTICLE_LIST_X, PARTICLE_LIST_Y, PARTICLE_LIST_WIDTH, PARTICLE_LIST_HEIGHT, @viewport
)
@particle_list.set_interactive_rects
@captured = nil
set_side_panes_contents
set_particle_list_contents
refresh
end
@@ -71,9 +81,18 @@ class AnimationEditor
@screen_bitmap.dispose
@canvas.dispose
@keyframe_particle_pane.dispose
@particle_list.dispose
@viewport.dispose
end
def keyframe
return @particle_list.keyframe
end
def particle_index
return @particle_list.particle_index
end
#-----------------------------------------------------------------------------
def set_keyframe_particle_pane_contents
@@ -116,6 +135,10 @@ class AnimationEditor
set_keyframe_particle_pane_contents
end
def set_particle_list_contents
@particle_list.set_particles(@anim[:particles])
end
#-----------------------------------------------------------------------------
def draw_editor_background
@@ -131,79 +154,39 @@ class AnimationEditor
@screen_bitmap.bitmap.outline_rect(SIDE_PANE_X - 1, SIDE_PANE_Y - 1, SIDE_PANE_WIDTH + 2, SIDE_PANE_HEIGHT + 2, Color.white)
# Fill the side pane with white
@screen_bitmap.bitmap.fill_rect(SIDE_PANE_X, SIDE_PANE_Y, SIDE_PANE_WIDTH, SIDE_PANE_HEIGHT, Color.white)
end
def get_keyframe_particle_value(particle, frame, property)
if !GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES.include?(property)
raise _INTL("Couldn't get default value for property {1} for particle {2}.",
property, particle[:name])
end
ret = [GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES[property], false]
if particle[property]
# NOTE: The commands are already in keyframe order, so we can just run
# through them in order, applying their changes until we reach
# frame.
particle[property].each do |cmd|
break if cmd[0] > frame # Command is in the future; no more is needed
break if cmd[0] == frame && cmd[1] > 0 # Start of a "MoveXYZ" command; won't have changed yet
if cmd[0] + cmd[1] <= frame # Command has finished; use its end value
ret[0] = cmd[2]
next
end
# In a "MoveXYZ" command; need to interpolate
ret[0] = lerp(ret[0], cmd[2], cmd[1], cmd[0], frame).to_i
ret[1] = true # Interpolating
break
end
end
# NOTE: Particles are assumed to be not visible at the start of the
# animation, and automatically become visible when the particle has
# its first command. This does not apply to the "User" and "Target"
# particles, which start the animation visible.
if property == :visible
first_cmd = (["User", "Target"].include?(particle[:name])) ? 0 : -1
first_visible_cmd = -1
if first_cmd < 0
particle.each_pair do |prop, value|
next if !value.is_a?(Array) || value.length == 0
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
end
ret[0] = true if first_cmd >= 0 && first_cmd <= frame &&
(first_visible_cmd < 0 || frame < first_visible_cmd)
end
return ret
end
def get_all_keyframe_particle_values(particle, frame)
ret = {}
GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES.each_pair do |prop, default|
ret[prop] = get_keyframe_particle_value(particle, frame, prop)
end
return ret
# Outline around timeline/particle list
@screen_bitmap.bitmap.outline_rect(PARTICLE_LIST_X - 3, PARTICLE_LIST_Y - 3, PARTICLE_LIST_WIDTH + 6, PARTICLE_LIST_HEIGHT + 6, Color.white)
@screen_bitmap.bitmap.outline_rect(PARTICLE_LIST_X - 2, PARTICLE_LIST_Y - 2, PARTICLE_LIST_WIDTH + 4, PARTICLE_LIST_HEIGHT + 4, Color.black)
@screen_bitmap.bitmap.outline_rect(PARTICLE_LIST_X - 1, PARTICLE_LIST_Y - 1, PARTICLE_LIST_WIDTH + 2, PARTICLE_LIST_HEIGHT + 2, Color.white)
end
def refresh_keyframe_particle_pane
if @particle < 0 || !@anim[:particles][@particle]
if !keyframe || keyframe < 0 || !particle_index || particle_index < 0 ||
!@anim[:particles][particle_index]
@keyframe_particle_pane.visible = false
else
@keyframe_particle_pane.visible = true
new_vals = get_all_keyframe_particle_values(@anim[:particles][@particle], @keyframe)
new_vals = AnimationEditor::ParticleDataHelper.get_all_keyframe_particle_values(@anim[:particles][particle_index], keyframe)
# TODO: Need to do something special for :color, :tone and :graphic/:frame
# which all have button controls.
@keyframe_particle_pane.controls.each do |ctrl|
next if !new_vals.include?(ctrl[0])
ctrl.value = new_vals[ctrl[0]][0]
ctrl[1].value = new_vals[ctrl[0]][0] if ctrl[1].respond_to?("value=")
# TODO: new_vals[ctrl[0]][1] is whether the value is being interpolated,
# which should be indicated somehow in ctrl.
# which should be indicated somehow in ctrl[1].
end
end
end
def refresh_particle_list
@particle_list.refresh
end
def refresh
# Set all side pane controls to values from animation
refresh_keyframe_particle_pane
# Set particle list's contents
refresh_particle_list
end
#-----------------------------------------------------------------------------
@@ -216,6 +199,7 @@ class AnimationEditor
def update_keyframe_particle_pane
@keyframe_particle_pane.update
@captured = :keyframe_particle_pane if @keyframe_particle_pane.busy?
if @keyframe_particle_pane.changed?
# TODO: Make undo/redo snapshot.
values = @keyframe_particle_pane.values
@@ -233,9 +217,38 @@ class AnimationEditor
end
end
def update_particle_list
old_keyframe = keyframe
old_particle_index = particle_index
@particle_list.update
@captured = :particle_list if @particle_list.busy?
if @particle_list.changed?
refresh_keyframe_particle_pane if keyframe != old_keyframe || particle_index != old_particle_index
# TODO: Lots of stuff here.
@particle_list.clear_changed
end
@particle_list.repaint
end
def update
update_canvas
update_keyframe_particle_pane
if @captured
# TODO: There must be a better way to do this.
case @captured
when :canvas
update_canvas
@captured = nil if !@canvas.busy?
when :keyframe_particle_pane
update_keyframe_particle_pane
@captured = nil if !@keyframe_particle_pane.busy?
when :particle_list
update_particle_list
@captured = nil if !@particle_list.busy?
end
else
update_canvas
update_keyframe_particle_pane
update_particle_list
end
end
#-----------------------------------------------------------------------------