mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-08 05:34:58 +00:00
Anim Editor: added interpolation editing
This commit is contained in:
@@ -41,8 +41,8 @@ module GameData
|
|||||||
"None" => :none,
|
"None" => :none,
|
||||||
"Linear" => :linear,
|
"Linear" => :linear,
|
||||||
"EaseIn" => :ease_in,
|
"EaseIn" => :ease_in,
|
||||||
"EaseOut" => :ease_out,
|
"EaseBoth" => :ease_both,
|
||||||
"EaseBoth" => :ease_both
|
"EaseOut" => :ease_out
|
||||||
}
|
}
|
||||||
USER_AND_TARGET_SEPARATION = [200, -200, -100] # x, y, z (from user to target)
|
USER_AND_TARGET_SEPARATION = [200, -200, -100] # x, y, z (from user to target)
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ module GameData
|
|||||||
# change during the animation.
|
# change during the animation.
|
||||||
# TODO: If more "SetXYZ"/"MoveXYZ" properties are added, ensure the "SetXYZ"
|
# TODO: If more "SetXYZ"/"MoveXYZ" properties are added, ensure the "SetXYZ"
|
||||||
# ones are given a duration of 0 in def validate_compiled_animation.
|
# ones are given a duration of 0 in def validate_compiled_animation.
|
||||||
# Also add display names to def property_display_name.
|
# Also add display names to def self.property_display_name.
|
||||||
SUB_SCHEMA = {
|
SUB_SCHEMA = {
|
||||||
# These properties cannot be changed partway through the animation.
|
# These properties cannot be changed partway through the animation.
|
||||||
# NOTE: "Name" isn't a property here, because the particle's name comes
|
# NOTE: "Name" isn't a property here, because the particle's name comes
|
||||||
@@ -162,6 +162,30 @@ module GameData
|
|||||||
:target_cry => nil
|
:target_cry => nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def self.property_display_name(property)
|
||||||
|
return {
|
||||||
|
:frame => _INTL("Frame"),
|
||||||
|
:blending => _INTL("Blending"),
|
||||||
|
:flip => _INTL("Flip"),
|
||||||
|
:x => _INTL("X"),
|
||||||
|
:y => _INTL("Y"),
|
||||||
|
:z => _INTL("Priority"),
|
||||||
|
:zoom_x => _INTL("Zoom X"),
|
||||||
|
:zoom_y => _INTL("Zoom Y"),
|
||||||
|
:angle => _INTL("Angle"),
|
||||||
|
:visible => _INTL("Visible"),
|
||||||
|
:opacity => _INTL("Opacity")
|
||||||
|
}[property] || property.capitalize
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.property_can_interpolate?(property)
|
||||||
|
return false if !property
|
||||||
|
SUB_SCHEMA.each_value do |prop|
|
||||||
|
return true if prop[0] == property && prop[5] && prop[5] == INTERPOLATION_TYPES
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
@@cmd_to_pbs_name = nil # Used for writing animation PBS files
|
@@cmd_to_pbs_name = nil # Used for writing animation PBS files
|
||||||
|
|
||||||
extend ClassMethodsIDNumbers
|
extend ClassMethodsIDNumbers
|
||||||
|
|||||||
@@ -296,6 +296,9 @@ class AnimationEditor
|
|||||||
# Move particle up/down the list?
|
# Move particle up/down the list?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: :keyframe_pane is currently inaccessible (intentionally). If it will
|
||||||
|
# have its own commands and should be accessible again, change def
|
||||||
|
# on_mouse_release in ParticleList.
|
||||||
def set_keyframe_pane_contents
|
def set_keyframe_pane_contents
|
||||||
keyframe_pane = @components[:keyframe_pane]
|
keyframe_pane = @components[:keyframe_pane]
|
||||||
keyframe_pane.add_header_label(:header, _INTL("Edit keyframe"))
|
keyframe_pane.add_header_label(:header, _INTL("Edit keyframe"))
|
||||||
@@ -810,6 +813,24 @@ class AnimationEditor
|
|||||||
@components[:particle_list].set_particles(@anim[:particles])
|
@components[:particle_list].set_particles(@anim[:particles])
|
||||||
@components[:particle_list].particle_index = idx2
|
@components[:particle_list].particle_index = idx2
|
||||||
refresh
|
refresh
|
||||||
|
when :cycle_interpolation
|
||||||
|
# value is [particle index, property, keyframe]
|
||||||
|
# Get current interpolation type
|
||||||
|
interp_type = nil
|
||||||
|
@anim[:particles][value[0]][value[1]].each do |cmd|
|
||||||
|
next if cmd[0] != value[2]
|
||||||
|
interp_type = cmd[3] if !interp_type
|
||||||
|
end
|
||||||
|
interp_type ||= :none
|
||||||
|
# Get the interpolation type to change to
|
||||||
|
interps = GameData::Animation::INTERPOLATION_TYPES.values
|
||||||
|
idx = (interps.index(interp_type) + 1) % interps.length
|
||||||
|
interp_type = interps[idx]
|
||||||
|
# Set the new interpolation type
|
||||||
|
AnimationEditor::ParticleDataHelper.set_interpolation(@anim[:particles][value[0]], value[1], value[2], interp_type)
|
||||||
|
@components[:particle_list].change_particle_commands(value[0])
|
||||||
|
refresh_component(:commands_pane)
|
||||||
|
refresh_component(:canvas)
|
||||||
end
|
end
|
||||||
when :animation_properties
|
when :animation_properties
|
||||||
# TODO: Will changes here need to refresh any other components (e.g. side
|
# TODO: Will changes here need to refresh any other components (e.g. side
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module AnimationEditor::ParticleDataHelper
|
|||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_keyframe_particle_value(particle, frame, property)
|
def get_keyframe_particle_value(particle, property, frame)
|
||||||
if !GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES.include?(property)
|
if !GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES.include?(property)
|
||||||
raise _INTL("Couldn't get default value for property {1} for particle {2}.",
|
raise _INTL("Couldn't get default value for property {1} for particle {2}.",
|
||||||
property, particle[:name])
|
property, particle[:name])
|
||||||
@@ -81,7 +81,7 @@ module AnimationEditor::ParticleDataHelper
|
|||||||
def get_all_keyframe_particle_values(particle, frame)
|
def get_all_keyframe_particle_values(particle, frame)
|
||||||
ret = {}
|
ret = {}
|
||||||
GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES.each_pair do |prop, default|
|
GameData::Animation::PARTICLE_KEYFRAME_DEFAULT_VALUES.each_pair do |prop, default|
|
||||||
ret[prop] = get_keyframe_particle_value(particle, frame, prop)
|
ret[prop] = get_keyframe_particle_value(particle, prop, frame)
|
||||||
end
|
end
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
@@ -151,7 +151,7 @@ module AnimationEditor::ParticleDataHelper
|
|||||||
# 0 - SetXYZ
|
# 0 - SetXYZ
|
||||||
# [+/- duration, interpolation type] --- MoveXYZ (duration's sign is whether
|
# [+/- duration, interpolation type] --- MoveXYZ (duration's sign is whether
|
||||||
# it makes the value higher or lower)
|
# it makes the value higher or lower)
|
||||||
def get_particle_property_commands_timeline(particle, commands, property)
|
def get_particle_property_commands_timeline(particle, property, commands)
|
||||||
return nil if !commands || commands.length == 0
|
return nil if !commands || commands.length == 0
|
||||||
if particle[:name] == "SE"
|
if particle[:name] == "SE"
|
||||||
ret = []
|
ret = []
|
||||||
@@ -188,6 +188,93 @@ module AnimationEditor::ParticleDataHelper
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_command(particle, property, frame, value)
|
def add_command(particle, property, frame, value)
|
||||||
|
# Return a new set of commands if there isn't one
|
||||||
|
if !particle[property] || particle[property].empty?
|
||||||
|
return [[frame, 0, value]]
|
||||||
|
end
|
||||||
|
# Find all relevant commands
|
||||||
|
set_now = nil
|
||||||
|
move_ending_now = nil
|
||||||
|
move_overlapping_now = nil
|
||||||
|
particle[property].each do |cmd|
|
||||||
|
if cmd[1] == 0
|
||||||
|
set_now = cmd if cmd[0] == frame
|
||||||
|
else
|
||||||
|
move_ending_now = cmd if cmd[0] + cmd[1] == frame
|
||||||
|
move_overlapping_now = cmd if cmd[0] < frame && cmd[0] + cmd[1] > frame
|
||||||
|
end
|
||||||
|
end
|
||||||
|
new_command_needed = true
|
||||||
|
# Replace existing command at frame if it has a duration of 0
|
||||||
|
if set_now
|
||||||
|
set_now[2] = value
|
||||||
|
new_command_needed = false
|
||||||
|
end
|
||||||
|
# If a command has a duration >0 and ends at frame, replace its value
|
||||||
|
if move_ending_now
|
||||||
|
move_ending_now[2] = value
|
||||||
|
new_command_needed = false
|
||||||
|
end
|
||||||
|
return particle[property] if !new_command_needed
|
||||||
|
# Add a new command
|
||||||
|
new_cmd = [frame, 0, value]
|
||||||
|
particle[property].push(new_cmd)
|
||||||
|
# If the new command interrupts an interpolation, split that interpolation
|
||||||
|
if move_overlapping_now
|
||||||
|
end_frame = move_overlapping_now[0] + move_overlapping_now[1]
|
||||||
|
new_cmd[1] = end_frame - frame # Duration
|
||||||
|
new_cmd[2] = move_overlapping_now[2] # Value
|
||||||
|
new_cmd[3] = move_overlapping_now[3] # Interpolation type
|
||||||
|
move_overlapping_now[1] = frame - move_overlapping_now[0] # Duration
|
||||||
|
move_overlapping_now[2] = value # Value
|
||||||
|
end
|
||||||
|
# Sort and return the commands
|
||||||
|
particle[property].sort! { |a, b| a[0] == b[0] ? a[1] == b[1] ? 0 : a[1] <=> b[1] : a[0] <=> b[0] }
|
||||||
|
return particle[property]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Cases:
|
||||||
|
# * SetXYZ - delete it
|
||||||
|
# * MoveXYZ start - turn into a SetXYZ at the end point
|
||||||
|
# * MoveXYZ end - delete it (this may happen to remove the start diamond too)
|
||||||
|
# * MoveXYZ end and start - merge both together (use first's type)
|
||||||
|
# * SetXYZ and MoveXYZ start - delete SetXYZ (leave MoveXYZ alone)
|
||||||
|
# * SetXYZ and MoveXYZ end - (unlikely) delete both
|
||||||
|
# * SetXYZ and MoveXYZ start and end - (unlikely) delete SetXYZ, merge Moves together
|
||||||
|
def delete_command(particle, property, frame)
|
||||||
|
# Find all relevant commands
|
||||||
|
set_now = nil
|
||||||
|
move_ending_now = nil
|
||||||
|
move_starting_now = nil
|
||||||
|
particle[property].each do |cmd|
|
||||||
|
if cmd[1] == 0
|
||||||
|
set_now = cmd if cmd[0] == frame
|
||||||
|
else
|
||||||
|
move_starting_now = cmd if cmd[0] == frame
|
||||||
|
move_ending_now = cmd if cmd[0] + cmd[1] == frame
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Delete SetXYZ if it is at frame
|
||||||
|
particle[property].delete(set_now) if set_now
|
||||||
|
# Edit/delete MoveXYZ commands starting/ending at frame
|
||||||
|
if move_ending_now && move_starting_now # Merge both MoveXYZ commands
|
||||||
|
move_ending_now[1] += move_starting_now[1] # Duration
|
||||||
|
move_ending_now[2] = move_starting_now[2] # Value
|
||||||
|
particle[property].delete(move_starting_now)
|
||||||
|
elsif move_ending_now # Delete MoveXYZ ending now
|
||||||
|
particle[property].delete(move_ending_now)
|
||||||
|
elsif move_starting_now && !set_now # Turn into SetXYZ at its end point
|
||||||
|
move_starting_now[0] += move_starting_now[1]
|
||||||
|
move_starting_now[1] = 0
|
||||||
|
move_starting_now[3] = nil
|
||||||
|
move_starting_now.compact!
|
||||||
|
end
|
||||||
|
return (particle[property].empty?) ? nil : particle[property]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Removes commands for the particle's given property if they don't make a
|
||||||
|
# difference. Returns the resulting set of commands.
|
||||||
|
def optimize_commands(particle, property)
|
||||||
# Split particle[property] into values and interpolation arrays
|
# Split particle[property] into values and interpolation arrays
|
||||||
set_points = [] # All SetXYZ commands (the values thereof)
|
set_points = [] # All SetXYZ commands (the values thereof)
|
||||||
end_points = [] # End points of MoveXYZ commands (the values thereof)
|
end_points = [] # End points of MoveXYZ commands (the values thereof)
|
||||||
@@ -202,14 +289,6 @@ module AnimationEditor::ParticleDataHelper
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# Add new command to points (may replace an existing command)
|
|
||||||
interp = :none
|
|
||||||
(frame + 1).times do |i|
|
|
||||||
interp = :none if set_points[i] || end_points[i]
|
|
||||||
interp = interps[i] if interps[i]
|
|
||||||
end
|
|
||||||
interps[frame] = interp if interp != :none
|
|
||||||
set_points[frame] = value
|
|
||||||
# For visibility only, set the keyframe with the first command (of any kind)
|
# For visibility only, set the keyframe with the first command (of any kind)
|
||||||
# to be visible, unless the command being added overwrites it. Also figure
|
# to be visible, unless the command being added overwrites it. Also figure
|
||||||
# out the first keyframe that has a command, and the first keyframe that has
|
# out the first keyframe that has a command, and the first keyframe that has
|
||||||
@@ -264,42 +343,60 @@ module AnimationEditor::ParticleDataHelper
|
|||||||
return (ret.empty?) ? nil : ret
|
return (ret.empty?) ? nil : ret
|
||||||
end
|
end
|
||||||
|
|
||||||
# Cases:
|
# SetXYZ at frame
|
||||||
# * SetXYZ - delete it
|
# - none: Do nothing.
|
||||||
# * MoveXYZ start - turn into a SetXYZ at the end point
|
# - interp: Add MoveXYZ (calc duration/value at end).
|
||||||
# * MoveXYZ end - delete it (this may happen to remove the start diamond too)
|
# MoveXYZ at frame
|
||||||
# * MoveXYZ end and start - merge both together (use first's type)
|
# - none: Turn into two SetXYZ (MoveXYZ's value for end point, calc value
|
||||||
# * SetXYZ and MoveXYZ start - delete SetXYZ (leave MoveXYZ alone)
|
# for start point).
|
||||||
# * SetXYZ and MoveXYZ end - (unlikely) delete both
|
# - interp: Change type.
|
||||||
# * SetXYZ and MoveXYZ start and end - (unlikely) delete SetXYZ, merge Moves together
|
# SetXYZ and MoveXYZ at frame
|
||||||
def delete_command(particle, property, frame)
|
# - none: Turn MoveXYZ into SetXYZ at the end point.
|
||||||
# Find all relevant commands
|
# - interp: Change MoveXYZ's type.
|
||||||
|
# End of earlier MoveXYZ (or nothing) at frame
|
||||||
|
# - none: Do nothing.
|
||||||
|
# - interp: Add MoveXYZ (calc duration/value at end).
|
||||||
|
def set_interpolation(particle, property, frame, type)
|
||||||
|
# Find relevant command
|
||||||
set_now = nil
|
set_now = nil
|
||||||
move_ending_now = nil
|
|
||||||
move_starting_now = nil
|
move_starting_now = nil
|
||||||
particle[property].each do |cmd|
|
particle[property].each do |cmd|
|
||||||
if cmd[1] == 0
|
next if cmd[0] != frame
|
||||||
set_now = cmd if cmd[0] == frame
|
set_now = cmd if cmd[1] == 0
|
||||||
|
move_starting_now = cmd if cmd[1] != 0
|
||||||
|
end
|
||||||
|
if move_starting_now
|
||||||
|
# If a MoveXYZ command exists at frame, amend it
|
||||||
|
if type == :none
|
||||||
|
old_end_point = move_starting_now[0] + move_starting_now[1]
|
||||||
|
old_value = move_starting_now[2]
|
||||||
|
# Turn the MoveXYZ command into a SetXYZ (or just delete it if a SetXYZ
|
||||||
|
# already exists at frame)
|
||||||
|
if set_now
|
||||||
|
particle[property].delete(move_starting_now)
|
||||||
|
else
|
||||||
|
move_starting_now[1] = 0
|
||||||
|
move_starting_now[2] = get_keyframe_particle_value(particle, property, frame)[0]
|
||||||
|
move_starting_now[3] = nil
|
||||||
|
move_starting_now.compact!
|
||||||
|
end
|
||||||
|
# Add a new SetXYZ at the end of the (former) interpolation
|
||||||
|
add_command(particle, property, old_end_point, old_value)
|
||||||
else
|
else
|
||||||
move_starting_now = cmd if cmd[0] == frame
|
# Simply change the type
|
||||||
move_ending_now = cmd if cmd[0] + cmd[1] == frame
|
move_starting_now[3] = type
|
||||||
|
end
|
||||||
|
elsif type != :none
|
||||||
|
# If no MoveXYZ command exists at frame, make one (if type isn't :none)
|
||||||
|
particle[property].each do |cmd| # Assumes commands are sorted by keyframe
|
||||||
|
next if cmd[0] <= frame
|
||||||
|
val_at_end = get_keyframe_particle_value(particle, property, cmd[0])[0]
|
||||||
|
particle[property].push([frame, cmd[0] - frame, val_at_end, type])
|
||||||
|
particle[property].sort! { |a, b| a[0] == b[0] ? a[1] == b[1] ? 0 : a[1] <=> b[1] : a[0] <=> b[0] }
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# Delete SetXYZ if it is at frame
|
return particle[property]
|
||||||
particle[property].delete(set_now) if set_now
|
|
||||||
# Edit/delete MoveXYZ commands starting/ending at frame
|
|
||||||
if move_ending_now && move_starting_now # Merge both MoveXYZ commands
|
|
||||||
move_ending_now[1] += move_starting_now[1]
|
|
||||||
particle[property].delete(move_starting_now)
|
|
||||||
elsif move_ending_now # Delete MoveXYZ ending now
|
|
||||||
particle[property].delete(move_ending_now)
|
|
||||||
elsif move_starting_now && !set_now # Turn into SetXYZ at its end point
|
|
||||||
move_starting_now[0] += move_starting_now[1]
|
|
||||||
move_starting_now[1] = 0
|
|
||||||
move_starting_now[3] = nil
|
|
||||||
move_starting_now.compact!
|
|
||||||
end
|
|
||||||
return (particle[property].empty?) ? nil : particle[property]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -8,10 +8,15 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
LIST_X = 0
|
LIST_X = 0
|
||||||
LIST_Y = TIMELINE_HEIGHT + VIEWPORT_SPACING
|
LIST_Y = TIMELINE_HEIGHT + VIEWPORT_SPACING
|
||||||
LIST_WIDTH = 180 - VIEWPORT_SPACING
|
LIST_WIDTH = 180 - VIEWPORT_SPACING
|
||||||
|
EXPAND_BUTTON_X = VIEWPORT_SPACING
|
||||||
|
EXPAND_BUTTON_WIDTH = 19
|
||||||
|
LIST_BOX_X = EXPAND_BUTTON_X + EXPAND_BUTTON_WIDTH + VIEWPORT_SPACING
|
||||||
|
LIST_INDENT = 8
|
||||||
COMMANDS_X = LIST_WIDTH + VIEWPORT_SPACING
|
COMMANDS_X = LIST_WIDTH + VIEWPORT_SPACING
|
||||||
COMMANDS_Y = LIST_Y
|
COMMANDS_Y = LIST_Y
|
||||||
|
|
||||||
ROW_HEIGHT = 24
|
ROW_HEIGHT = 24
|
||||||
|
ROW_SPACING = 1 # Gap at top of each row
|
||||||
DIAMOND_SIZE = 3
|
DIAMOND_SIZE = 3
|
||||||
TIMELINE_LEFT_BUFFER = DIAMOND_SIZE + 1 # Allows diamonds at keyframe 0 to be drawn fully
|
TIMELINE_LEFT_BUFFER = DIAMOND_SIZE + 1 # Allows diamonds at keyframe 0 to be drawn fully
|
||||||
TIMELINE_TEXT_SIZE = 16
|
TIMELINE_TEXT_SIZE = 16
|
||||||
@@ -19,6 +24,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
INTERP_LINE_HEIGHT = KEYFRAME_SPACING - ((DIAMOND_SIZE * 2) + 3)
|
INTERP_LINE_HEIGHT = KEYFRAME_SPACING - ((DIAMOND_SIZE * 2) + 3)
|
||||||
INTERP_LINE_Y = (ROW_HEIGHT / 2) - (INTERP_LINE_HEIGHT / 2)
|
INTERP_LINE_Y = (ROW_HEIGHT / 2) - (INTERP_LINE_HEIGHT / 2)
|
||||||
DURATION_BUFFER = 20 # Extra keyframes shown after the animation's end
|
DURATION_BUFFER = 20 # Extra keyframes shown after the animation's end
|
||||||
|
PROPERTY_BG_COLOR = Color.new(224, 224, 224)
|
||||||
CONTROL_BG_COLORS = {
|
CONTROL_BG_COLORS = {
|
||||||
:foreground => Color.new(128, 160, 248), # Blue
|
:foreground => Color.new(128, 160, 248), # Blue
|
||||||
:midground => Color.new(128, 160, 248), # Blue
|
:midground => Color.new(128, 160, 248), # Blue
|
||||||
@@ -32,7 +38,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
:target_side_background => Color.new(128, 248, 248) # Cyan
|
:target_side_background => Color.new(128, 248, 248) # Cyan
|
||||||
}
|
}
|
||||||
SE_CONTROL_BG_COLOR = Color.gray
|
SE_CONTROL_BG_COLOR = Color.gray
|
||||||
TIME_AFTER_ANIMATION_COLOR = Color.new(224, 224, 224)
|
TIME_AFTER_ANIMATION_COLOR = Color.new(160, 160, 160)
|
||||||
|
|
||||||
attr_reader :keyframe # The selected keyframe
|
attr_reader :keyframe # The selected keyframe
|
||||||
attr_reader :values
|
attr_reader :values
|
||||||
@@ -312,10 +318,14 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
end
|
end
|
||||||
|
|
||||||
def busy?
|
def busy?
|
||||||
return true if @controls.any? { |c| c[1].busy? }
|
return true if controls_busy?
|
||||||
return super
|
return super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def controls_busy?
|
||||||
|
return @controls.any? { |c| c[1].busy? }
|
||||||
|
end
|
||||||
|
|
||||||
def changed?
|
def changed?
|
||||||
return @changed
|
return @changed
|
||||||
end
|
end
|
||||||
@@ -366,7 +376,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
overall_commands = []
|
overall_commands = []
|
||||||
@particles[index].each_pair do |property, value|
|
@particles[index].each_pair do |property, value|
|
||||||
next if !value.is_a?(Array)
|
next if !value.is_a?(Array)
|
||||||
cmds = AnimationEditor::ParticleDataHelper.get_particle_property_commands_timeline(@particles[index], value, property)
|
cmds = AnimationEditor::ParticleDataHelper.get_particle_property_commands_timeline(@particles[index], property, value)
|
||||||
@commands[[index, property]] = cmds
|
@commands[[index, property]] = cmds
|
||||||
cmds.each_with_index do |cmd, i|
|
cmds.each_with_index do |cmd, i|
|
||||||
next if !cmd
|
next if !cmd
|
||||||
@@ -468,22 +478,6 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
def property_display_name(property)
|
|
||||||
return {
|
|
||||||
:frame => _INTL("Frame"),
|
|
||||||
:blending => _INTL("Blending"),
|
|
||||||
:flip => _INTL("Flip"),
|
|
||||||
:x => _INTL("X"),
|
|
||||||
:y => _INTL("Y"),
|
|
||||||
:z => _INTL("Priority"),
|
|
||||||
:zoom_x => _INTL("Zoom X"),
|
|
||||||
:zoom_y => _INTL("Zoom Y"),
|
|
||||||
:angle => _INTL("Angle"),
|
|
||||||
:visible => _INTL("Visible"),
|
|
||||||
:opacity => _INTL("Opacity")
|
|
||||||
}[property] || property.capitalize
|
|
||||||
end
|
|
||||||
|
|
||||||
def repaint
|
def repaint
|
||||||
@list_scrollbar.repaint if @list_scrollbar.invalid?
|
@list_scrollbar.repaint if @list_scrollbar.invalid?
|
||||||
@time_scrollbar.repaint if @time_scrollbar.invalid?
|
@time_scrollbar.repaint if @time_scrollbar.invalid?
|
||||||
@@ -503,21 +497,23 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
@time_bg_sprite.bitmap.fill_rect(draw_x, TIMELINE_HEIGHT, greyed_width, VIEWPORT_SPACING, Color.black)
|
@time_bg_sprite.bitmap.fill_rect(draw_x, TIMELINE_HEIGHT, greyed_width, VIEWPORT_SPACING, Color.black)
|
||||||
end
|
end
|
||||||
# Draw hover highlight
|
# Draw hover highlight
|
||||||
hover_color = nil
|
if !controls_busy?
|
||||||
if @captured_keyframe && !@captured_row
|
hover_color = nil
|
||||||
if @hover_keyframe && @hover_keyframe == @captured_keyframe && !@hover_row
|
if @captured_keyframe && !@captured_row
|
||||||
|
if @hover_keyframe && @hover_keyframe == @captured_keyframe && !@hover_row
|
||||||
|
hover_color = HOVER_COLOR
|
||||||
|
else
|
||||||
|
hover_color = CAPTURE_COLOR
|
||||||
|
end
|
||||||
|
draw_x = TIMELINE_LEFT_BUFFER + (@captured_keyframe * KEYFRAME_SPACING) - @left_pos
|
||||||
|
@timeline_sprite.bitmap.fill_rect(draw_x - (KEYFRAME_SPACING / 2), 0,
|
||||||
|
KEYFRAME_SPACING, TIMELINE_HEIGHT - 1, hover_color)
|
||||||
|
elsif !@captured_keyframe && !@captured_row && @hover_keyframe && !@hover_row
|
||||||
hover_color = HOVER_COLOR
|
hover_color = HOVER_COLOR
|
||||||
else
|
draw_x = TIMELINE_LEFT_BUFFER + (@hover_keyframe * KEYFRAME_SPACING) - @left_pos
|
||||||
hover_color = CAPTURE_COLOR
|
@timeline_sprite.bitmap.fill_rect(draw_x - (KEYFRAME_SPACING / 2), 0,
|
||||||
|
KEYFRAME_SPACING, TIMELINE_HEIGHT - 1, hover_color)
|
||||||
end
|
end
|
||||||
draw_x = TIMELINE_LEFT_BUFFER + (@captured_keyframe * KEYFRAME_SPACING) - @left_pos
|
|
||||||
@timeline_sprite.bitmap.fill_rect(draw_x - (KEYFRAME_SPACING / 2), 0,
|
|
||||||
KEYFRAME_SPACING, TIMELINE_HEIGHT - 1, hover_color)
|
|
||||||
elsif !@captured_keyframe && !@captured_row && @hover_keyframe && !@hover_row
|
|
||||||
hover_color = HOVER_COLOR
|
|
||||||
draw_x = TIMELINE_LEFT_BUFFER + (@hover_keyframe * KEYFRAME_SPACING) - @left_pos
|
|
||||||
@timeline_sprite.bitmap.fill_rect(draw_x - (KEYFRAME_SPACING / 2), 0,
|
|
||||||
KEYFRAME_SPACING, TIMELINE_HEIGHT - 1, hover_color)
|
|
||||||
end
|
end
|
||||||
# Draw timeline markings
|
# Draw timeline markings
|
||||||
each_visible_keyframe(true) do |i|
|
each_visible_keyframe(true) do |i|
|
||||||
@@ -551,37 +547,81 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
spr = @list_sprites[index]
|
spr = @list_sprites[index]
|
||||||
return if !spr
|
return if !spr
|
||||||
spr.bitmap.clear
|
spr.bitmap.clear
|
||||||
box_x = (@particle_list[index].is_a?(Array)) ? 16 : 0
|
# Get useful information
|
||||||
# Get the background color
|
is_property = @particle_list[index].is_a?(Array)
|
||||||
p_index = (@particle_list[index].is_a?(Array)) ? @particle_list[index][0] : @particle_list[index]
|
p_index = (is_property) ? @particle_list[index][0] : @particle_list[index]
|
||||||
particle_data = @particles[p_index]
|
particle_data = @particles[p_index]
|
||||||
|
box_x = LIST_BOX_X
|
||||||
|
box_x += LIST_INDENT if is_property
|
||||||
|
# Get the background color
|
||||||
if particle_data[:name] == "SE"
|
if particle_data[:name] == "SE"
|
||||||
bg_color = SE_CONTROL_BG_COLOR
|
bg_color = SE_CONTROL_BG_COLOR
|
||||||
|
elsif is_property
|
||||||
|
bg_color = PROPERTY_BG_COLOR
|
||||||
else
|
else
|
||||||
bg_color = CONTROL_BG_COLORS[@particles[p_index][:focus]] || Color.magenta
|
bg_color = CONTROL_BG_COLORS[@particles[p_index][:focus]] || Color.magenta
|
||||||
end
|
end
|
||||||
# Draw hover highlight
|
# Draw hover highlight
|
||||||
hover_color = nil
|
if !controls_busy? && !@captured_keyframe
|
||||||
if @captured_row && !@captured_keyframe
|
hover_color = nil
|
||||||
if @captured_row == index
|
if @captured_row
|
||||||
if @hover_row && @hover_row == index && !@hover_keyframe
|
if @captured_row == index
|
||||||
hover_color = HOVER_COLOR
|
if !@hover_keyframe && @hover_row && @hover_row == index &&
|
||||||
else
|
@captured_row_button && @hover_row_button == @captured_row_button
|
||||||
hover_color = CAPTURE_COLOR
|
hover_color = HOVER_COLOR
|
||||||
|
else
|
||||||
|
hover_color = CAPTURE_COLOR
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elsif @hover_row && @hover_row == index && !@hover_keyframe
|
||||||
|
hover_color = HOVER_COLOR
|
||||||
|
end
|
||||||
|
if hover_color
|
||||||
|
case @captured_row_button || @hover_row_button
|
||||||
|
when :expand
|
||||||
|
spr.bitmap.fill_rect(EXPAND_BUTTON_X, (ROW_HEIGHT - EXPAND_BUTTON_WIDTH + 1) / 2,
|
||||||
|
EXPAND_BUTTON_WIDTH, EXPAND_BUTTON_WIDTH, hover_color)
|
||||||
|
when :row
|
||||||
|
spr.bitmap.fill_rect(box_x, ROW_SPACING, spr.width - box_x, spr.height - ROW_SPACING, hover_color)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif !@captured_row && !@captured_keyframe && @hover_row && @hover_row == index && !@hover_keyframe
|
|
||||||
hover_color = HOVER_COLOR
|
|
||||||
end
|
end
|
||||||
spr.bitmap.fill_rect(box_x, 1, spr.width - box_x, spr.height - 1, hover_color) if hover_color
|
|
||||||
# Draw outline
|
# Draw outline
|
||||||
spr.bitmap.outline_rect(box_x, 1, spr.width - box_x, spr.height - 1, bg_color, 2)
|
spr.bitmap.outline_rect(box_x, ROW_SPACING, spr.width - box_x, spr.height - ROW_SPACING, bg_color, 2)
|
||||||
# Draw text
|
# Draw text
|
||||||
if @particle_list[index].is_a?(Array)
|
if is_property
|
||||||
draw_text(spr.bitmap, box_x + 4, 0, "→") # ►
|
draw_text(spr.bitmap, box_x + 4, 3, GameData::Animation.property_display_name(@particle_list[index][1]) + ":")
|
||||||
draw_text(spr.bitmap, box_x + 4 + 17, 3, property_display_name(@particle_list[index][1]))
|
|
||||||
else
|
else
|
||||||
draw_text(spr.bitmap, 4, 3, @particles[p_index][:name] || "Unnamed")
|
draw_text(spr.bitmap, box_x + 4, 3, @particles[p_index][:name] || "Unnamed")
|
||||||
|
end
|
||||||
|
# Draw expand/collapse arrow or dotted lines
|
||||||
|
if is_property
|
||||||
|
6.times do |j|
|
||||||
|
spr.bitmap.fill_rect(10, j * 2, 1, 1, Color.black)
|
||||||
|
end
|
||||||
|
9.times do |i|
|
||||||
|
spr.bitmap.fill_rect(10 + (i * 2), 12, 1, 1, Color.black)
|
||||||
|
end
|
||||||
|
elsif @expanded_particles.include?(p_index)
|
||||||
|
11.times do |i|
|
||||||
|
j = (i == 0 || i == 10) ? 1 : 0
|
||||||
|
h = [2, 4, 5, 6, 7, 8, 7, 6, 5, 4, 2][i]
|
||||||
|
h = ((i > 5) ? 10 - i : i) + 3 - j
|
||||||
|
spr.bitmap.fill_rect(5 + i, 9 + j, 1, h, Color.black)
|
||||||
|
end
|
||||||
|
elsif particle_data[:name] != "SE"
|
||||||
|
11.times do |j|
|
||||||
|
i = (j == 0 || j == 10) ? 1 : 0
|
||||||
|
w = [2, 4, 5, 6, 7, 8, 7, 6, 5, 4, 2][j]
|
||||||
|
w = ((j > 5) ? 10 - j : j) + 3 - i
|
||||||
|
spr.bitmap.fill_rect(7 + i, 7 + j, w, 1, Color.black)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Draw dotted line leading to the next property line
|
||||||
|
if @particle_list[index + 1]&.is_a?(Array)
|
||||||
|
5.times do |j|
|
||||||
|
spr.bitmap.fill_rect(10, 14 + (j * 2), 1, 1, Color.black)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -589,11 +629,14 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
bg_spr = @commands_bg_sprites[index]
|
bg_spr = @commands_bg_sprites[index]
|
||||||
return if !bg_spr
|
return if !bg_spr
|
||||||
bg_spr.bitmap.clear
|
bg_spr.bitmap.clear
|
||||||
p_index = (@particle_list[index].is_a?(Array)) ? @particle_list[index][0] : @particle_list[index]
|
is_property = @particle_list[index].is_a?(Array)
|
||||||
|
p_index = (is_property) ? @particle_list[index][0] : @particle_list[index]
|
||||||
particle_data = @particles[p_index]
|
particle_data = @particles[p_index]
|
||||||
# Get the background color
|
# Get the background color
|
||||||
if particle_data[:name] == "SE"
|
if particle_data[:name] == "SE"
|
||||||
bg_color = SE_CONTROL_BG_COLOR
|
bg_color = SE_CONTROL_BG_COLOR
|
||||||
|
elsif is_property
|
||||||
|
bg_color = PROPERTY_BG_COLOR
|
||||||
else
|
else
|
||||||
bg_color = CONTROL_BG_COLORS[@particles[p_index][:focus]] || Color.magenta
|
bg_color = CONTROL_BG_COLORS[@particles[p_index][:focus]] || Color.magenta
|
||||||
end
|
end
|
||||||
@@ -604,33 +647,53 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
draw_x = TIMELINE_LEFT_BUFFER + (i * KEYFRAME_SPACING) - @left_pos
|
draw_x = TIMELINE_LEFT_BUFFER + (i * KEYFRAME_SPACING) - @left_pos
|
||||||
# Draw bg
|
# Draw bg
|
||||||
if i < @duration - DURATION_BUFFER && visible_cmds[i]
|
if i < @duration - DURATION_BUFFER && visible_cmds[i]
|
||||||
bg_spr.bitmap.fill_rect(draw_x, 1, KEYFRAME_SPACING, ROW_HEIGHT - 2, bg_color)
|
bg_spr.bitmap.fill_rect(draw_x, ROW_SPACING, KEYFRAME_SPACING, ROW_HEIGHT - ROW_SPACING, bg_color)
|
||||||
end
|
end
|
||||||
# Draw hover highlight
|
# Draw hover highlight
|
||||||
hover_color = nil
|
hover_color = nil
|
||||||
if @captured_row && @captured_keyframe
|
if !controls_busy?
|
||||||
if @captured_row == index && @captured_keyframe == i
|
earlier_captured_keyframe = @captured_keyframe
|
||||||
if @hover_row && @hover_row == index && @hover_keyframe && @hover_keyframe == i
|
later_captured_keyframe = (earlier_captured_keyframe || -1) + 1
|
||||||
hover_color = HOVER_COLOR
|
earlier_hovered_keyframe = @hover_keyframe
|
||||||
else
|
later_hovered_keyframe = (earlier_hovered_keyframe || -1) + 1
|
||||||
hover_color = CAPTURE_COLOR
|
if is_property
|
||||||
end
|
later_captured_keyframe = @captured_row_button || 0
|
||||||
|
later_hovered_keyframe = @hover_row_button || 0
|
||||||
|
end
|
||||||
|
if @captured_row && @captured_keyframe
|
||||||
|
if @captured_row == index && i >= earlier_captured_keyframe && i < later_captured_keyframe
|
||||||
|
if @hover_row && @hover_row == index && @hover_keyframe && i >= earlier_hovered_keyframe && i < later_hovered_keyframe
|
||||||
|
hover_color = HOVER_COLOR
|
||||||
|
else
|
||||||
|
hover_color = CAPTURE_COLOR
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elsif !@captured_row && !@captured_keyframe && @hover_row && @hover_keyframe &&
|
||||||
|
@hover_row == index && i >= earlier_hovered_keyframe && i < later_hovered_keyframe
|
||||||
|
hover_color = HOVER_COLOR
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if hover_color
|
||||||
|
if is_property
|
||||||
|
bg_spr.bitmap.fill_rect(draw_x, 2, KEYFRAME_SPACING, ROW_HEIGHT - 3, hover_color)
|
||||||
|
else
|
||||||
|
bg_spr.bitmap.fill_rect(draw_x - (KEYFRAME_SPACING / 2), 2, KEYFRAME_SPACING, ROW_HEIGHT - 3, hover_color)
|
||||||
end
|
end
|
||||||
elsif !@captured_row && !@captured_keyframe &&
|
|
||||||
@hover_row && @hover_row == index && @hover_keyframe && @hover_keyframe == i
|
|
||||||
hover_color = HOVER_COLOR
|
|
||||||
end
|
end
|
||||||
bg_spr.bitmap.fill_rect(draw_x - (KEYFRAME_SPACING / 2), 2, KEYFRAME_SPACING, ROW_HEIGHT - 3, hover_color) if hover_color
|
|
||||||
next if i >= @duration - DURATION_BUFFER
|
next if i >= @duration - DURATION_BUFFER
|
||||||
next if !visible_cmds[i]
|
next if !visible_cmds[i]
|
||||||
# Draw outline
|
# Draw outline
|
||||||
bg_spr.bitmap.fill_rect(draw_x, 1, KEYFRAME_SPACING, 1, Color.black) # Top
|
outline_color = Color.black
|
||||||
bg_spr.bitmap.fill_rect(draw_x, ROW_HEIGHT - 1, KEYFRAME_SPACING, 1, Color.black) # Bottom
|
if is_property
|
||||||
|
outline_color = CONTROL_BG_COLORS[@particles[p_index][:focus]] || Color.magenta
|
||||||
|
end
|
||||||
|
bg_spr.bitmap.fill_rect(draw_x, ROW_SPACING, KEYFRAME_SPACING, 1, outline_color) # Top
|
||||||
|
bg_spr.bitmap.fill_rect(draw_x, ROW_HEIGHT - 1, KEYFRAME_SPACING, 1, outline_color) # Bottom
|
||||||
if i <= 0 || !visible_cmds[i - 1]
|
if i <= 0 || !visible_cmds[i - 1]
|
||||||
bg_spr.bitmap.fill_rect(draw_x, 1, 1, ROW_HEIGHT - 1, Color.black) # Left
|
bg_spr.bitmap.fill_rect(draw_x, ROW_SPACING, 1, ROW_HEIGHT - ROW_SPACING, outline_color) # Left
|
||||||
end
|
end
|
||||||
if i == @duration - DURATION_BUFFER - 1 || (i < @duration - 1 && !visible_cmds[i + 1])
|
if i == @duration - DURATION_BUFFER - 1 || (i < @duration - 1 && !visible_cmds[i + 1])
|
||||||
bg_spr.bitmap.fill_rect(draw_x + KEYFRAME_SPACING, 1, 1, ROW_HEIGHT - 1, Color.black) # Right
|
bg_spr.bitmap.fill_rect(draw_x + KEYFRAME_SPACING, ROW_SPACING, 1, ROW_HEIGHT - ROW_SPACING, outline_color) # Right
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -714,17 +777,47 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
listed_element = @particle_list[new_hover_row]
|
listed_element = @particle_list[new_hover_row]
|
||||||
p_index = listed_element.is_a?(Array) ? listed_element[0] : listed_element
|
p_index = listed_element.is_a?(Array) ? listed_element[0] : listed_element
|
||||||
break if @particles[p_index][:name] == "SE"
|
break if @particles[p_index][:name] == "SE"
|
||||||
ret = [area, nil, new_hover_row]
|
mouse_y_in_row = mouse_y + @top_pos - (new_hover_row * ROW_HEIGHT) - rect.y
|
||||||
|
case mouse_x
|
||||||
|
when EXPAND_BUTTON_X...(EXPAND_BUTTON_X + EXPAND_BUTTON_WIDTH)
|
||||||
|
next if listed_element.is_a?(Array)
|
||||||
|
next if mouse_y_in_row < (ROW_HEIGHT - EXPAND_BUTTON_WIDTH + 1) / 2
|
||||||
|
next if mouse_y_in_row >= ((ROW_HEIGHT - EXPAND_BUTTON_WIDTH + 1) / 2) + EXPAND_BUTTON_WIDTH
|
||||||
|
ret = [area, nil, new_hover_row, :expand]
|
||||||
|
when LIST_BOX_X...(@list_viewport.rect.width)
|
||||||
|
next if listed_element.is_a?(Array)
|
||||||
|
next if mouse_y_in_row < ROW_SPACING
|
||||||
|
ret = [area, nil, new_hover_row, :row]
|
||||||
|
end
|
||||||
when :timeline
|
when :timeline
|
||||||
new_hover_keyframe = (mouse_x + @left_pos - rect.x - TIMELINE_LEFT_BUFFER + (KEYFRAME_SPACING / 2) - 1) / KEYFRAME_SPACING
|
new_hover_keyframe = (mouse_x + @left_pos - rect.x - TIMELINE_LEFT_BUFFER + (KEYFRAME_SPACING / 2) - 1) / KEYFRAME_SPACING
|
||||||
break if new_hover_keyframe < 0 || new_hover_keyframe >= @duration
|
break if new_hover_keyframe < 0 || new_hover_keyframe >= @duration
|
||||||
ret = [area, new_hover_keyframe, nil]
|
ret = [area, new_hover_keyframe, nil]
|
||||||
when :commands
|
when :commands
|
||||||
new_hover_row = (mouse_y + @top_pos - rect.y) / ROW_HEIGHT
|
new_hover_row = (mouse_y + @top_pos - rect.y) / ROW_HEIGHT
|
||||||
new_hover_keyframe = (mouse_x + @left_pos - rect.x - TIMELINE_LEFT_BUFFER + (KEYFRAME_SPACING / 2) - 1) / KEYFRAME_SPACING
|
|
||||||
break if new_hover_row >= @particle_list.length
|
break if new_hover_row >= @particle_list.length
|
||||||
|
listed_element = @particle_list[new_hover_row]
|
||||||
|
if listed_element.is_a?(Array)
|
||||||
|
new_hover_keyframe = (mouse_x + @left_pos - rect.x - TIMELINE_LEFT_BUFFER - 1) / KEYFRAME_SPACING
|
||||||
|
else
|
||||||
|
new_hover_keyframe = (mouse_x + @left_pos - rect.x - TIMELINE_LEFT_BUFFER + (KEYFRAME_SPACING / 2) - 1) / KEYFRAME_SPACING
|
||||||
|
end
|
||||||
break if new_hover_keyframe < 0 || new_hover_keyframe >= @duration
|
break if new_hover_keyframe < 0 || new_hover_keyframe >= @duration
|
||||||
ret = [area, new_hover_keyframe, new_hover_row]
|
if listed_element.is_a?(Array)
|
||||||
|
break if !GameData::Animation.property_can_interpolate?(listed_element[1])
|
||||||
|
cmds = @commands[listed_element]
|
||||||
|
break if !cmds
|
||||||
|
earlier_keyframe = nil
|
||||||
|
later_keyframe = nil
|
||||||
|
cmds.each_with_index do |cmd, i|
|
||||||
|
earlier_keyframe = i if cmd && i <= new_hover_keyframe
|
||||||
|
later_keyframe = i if cmd && !later_keyframe && i > new_hover_keyframe
|
||||||
|
end
|
||||||
|
break if !earlier_keyframe || !later_keyframe
|
||||||
|
ret = [area, earlier_keyframe, new_hover_row, later_keyframe]
|
||||||
|
else
|
||||||
|
ret = [area, new_hover_keyframe, new_hover_row]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@@ -738,6 +831,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
@captured_area = hover_element[0]
|
@captured_area = hover_element[0]
|
||||||
@captured_keyframe = hover_element[1]
|
@captured_keyframe = hover_element[1]
|
||||||
@captured_row = hover_element[2]
|
@captured_row = hover_element[2]
|
||||||
|
@captured_row_button = hover_element[3]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -748,19 +842,38 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
if hover_element.is_a?(Array)
|
if hover_element.is_a?(Array)
|
||||||
if @captured_area == hover_element[0] &&
|
if @captured_area == hover_element[0] &&
|
||||||
@captured_keyframe == hover_element[1] &&
|
@captured_keyframe == hover_element[1] &&
|
||||||
@captured_row == hover_element[2]
|
@captured_row == hover_element[2] &&
|
||||||
if @captured_row && @particle_list[@captured_row].is_a?(Array)
|
@captured_row_button == hover_element[3]
|
||||||
# TODO: If I want to be able to select individual property rows and/or
|
if @captured_area == :commands && @captured_row && @particle_list[@captured_row].is_a?(Array)
|
||||||
# diamonds, I shouldn't have this line.
|
set_changed
|
||||||
@captured_row = @particle_list.index(@particle_list[@captured_row][0])
|
@values[:cycle_interpolation] = [*@particle_list[@captured_row], @captured_keyframe]
|
||||||
|
else
|
||||||
|
case @captured_row_button
|
||||||
|
when :expand
|
||||||
|
particle_index = @particle_list[@captured_row]
|
||||||
|
particle_index = particle_index[0] if particle_index.is_a?(Array)
|
||||||
|
if @expanded_particles.include?(particle_index) # Contract
|
||||||
|
@expanded_particles.delete(particle_index)
|
||||||
|
else # Expand
|
||||||
|
@expanded_particles.push(particle_index)
|
||||||
|
end
|
||||||
|
set_particles(@particles)
|
||||||
|
else # :row button or somewhere in the commands area or timeline, just change selection
|
||||||
|
if @captured_row && @particle_list[@captured_row].is_a?(Array)
|
||||||
|
@captured_row = @particle_list.index(@particle_list[@captured_row][0])
|
||||||
|
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
|
end
|
||||||
set_changed if @keyframe != @captured_keyframe || @row_index != @captured_row
|
|
||||||
@keyframe = @captured_keyframe || -1
|
|
||||||
@row_index = @captured_row || -1
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@captured_keyframe = nil
|
@captured_keyframe = nil
|
||||||
@captured_row = nil
|
@captured_row = nil
|
||||||
|
@captured_row_button = nil
|
||||||
super # Make this control not busy again
|
super # Make this control not busy again
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -778,6 +891,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
@hover_area = nil
|
@hover_area = nil
|
||||||
@hover_keyframe = nil
|
@hover_keyframe = nil
|
||||||
@hover_row = nil
|
@hover_row = nil
|
||||||
|
@hover_row_button = nil
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
# Check each interactive area for whether the mouse is hovering over it, and
|
# Check each interactive area for whether the mouse is hovering over it, and
|
||||||
@@ -787,7 +901,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
invalidate if @hover_area != hover_element[0] # Moved to a different region
|
invalidate if @hover_area != hover_element[0] # Moved to a different region
|
||||||
case hover_element[0]
|
case hover_element[0]
|
||||||
when :list
|
when :list
|
||||||
invalidate_rows if @hover_row != hover_element[2]
|
invalidate_rows if @hover_row != hover_element[2] || @hover_row_button != hover_element[3]
|
||||||
when :timeline
|
when :timeline
|
||||||
invalidate_time if @hover_keyframe != hover_element[1]
|
invalidate_time if @hover_keyframe != hover_element[1]
|
||||||
when :commands
|
when :commands
|
||||||
@@ -797,6 +911,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
@hover_area = hover_element[0]
|
@hover_area = hover_element[0]
|
||||||
@hover_keyframe = hover_element[1]
|
@hover_keyframe = hover_element[1]
|
||||||
@hover_row = hover_element[2]
|
@hover_row = hover_element[2]
|
||||||
|
@hover_row_button = hover_element[3]
|
||||||
elsif hover_element
|
elsif hover_element
|
||||||
if @hover_area == hover_element
|
if @hover_area == hover_element
|
||||||
case @hover_area
|
case @hover_area
|
||||||
@@ -813,11 +928,13 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
@hover_area = hover_element
|
@hover_area = hover_element
|
||||||
@hover_keyframe = nil
|
@hover_keyframe = nil
|
||||||
@hover_row = nil
|
@hover_row = nil
|
||||||
|
@hover_row_button = nil
|
||||||
else
|
else
|
||||||
invalidate if @hover_area
|
invalidate if @hover_area
|
||||||
@hover_area = nil
|
@hover_area = nil
|
||||||
@hover_keyframe = nil
|
@hover_keyframe = nil
|
||||||
@hover_row = nil
|
@hover_row = nil
|
||||||
|
@hover_row_button = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -825,7 +942,9 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
|
|||||||
return if !self.visible
|
return if !self.visible
|
||||||
@list_scrollbar.update
|
@list_scrollbar.update
|
||||||
@time_scrollbar.update
|
@time_scrollbar.update
|
||||||
@controls.each { |c| c[1].update }
|
if !@captured_area
|
||||||
|
@controls.each { |c| c[1].update }
|
||||||
|
end
|
||||||
super
|
super
|
||||||
# Refresh sprites if a scrollbar has been moved
|
# Refresh sprites if a scrollbar has been moved
|
||||||
self.top_pos = @list_scrollbar.position
|
self.top_pos = @list_scrollbar.position
|
||||||
|
|||||||
Reference in New Issue
Block a user