Tidied up TODO comments, misc tweaks to Anim Editor

This commit is contained in:
Maruno17
2023-12-03 23:47:38 +00:00
parent b4e7b765d1
commit 2f231a25bb
203 changed files with 813 additions and 852 deletions

View File

@@ -1,16 +1,6 @@
#===============================================================================
# Controls are arranged in a list in self's bitmap. Each control is given an
# area of size "self's bitmap's width" x LINE_SPACING to draw itself in.
# TODO: The act of "capturing" a control makes other controls in this container
# not update themselves, i.e. they won't colour themselves with a hover
# highlight if the mouse happens to move over it while another control is
# captured. Is there a better way of dealing with this? I'm leaning
# towards the control itself deciding if it's captured, and it being
# treated as uncaptured once it says its value has changed, but I think
# this would require manually telling all other controls in this container
# that something else is captured and they shouldn't show a hover
# highlight when updated (perhaps as a parameter in def update), which I
# don't think is ideal.
#===============================================================================
class UIControls::ControlsContainer
attr_reader :x, :y
@@ -171,11 +161,6 @@ class UIControls::ControlsContainer
return if !@visible
# Update controls
if @captured
# TODO: Ideally all controls will be updated here, if only to redraw
# themselves if they happen to be invalidated somehow. But that
# involves telling each control whether any other control is busy,
# to ensure that they don't show their hover colours or anything,
# which is fiddly and I'm not sure if it's the best approach.
@captured.update
@captured = nil if !@captured.busy?
else

View File

@@ -10,6 +10,7 @@ class UIControls::BaseControl < BitmapSprite
TEXT_COLOR = Color.black
TEXT_SIZE = 18 # Default is 22 if size isn't explicitly set
TEXT_OFFSET_Y = 5
HOVER_COLOR = Color.cyan # For clickable area when hovering over it
CAPTURE_COLOR = Color.pink # For area you clicked in but aren't hovering over
DISABLED_COLOR = Color.gray
@@ -19,7 +20,6 @@ class UIControls::BaseControl < BitmapSprite
super(width, height, viewport)
self.bitmap.font.color = TEXT_COLOR
self.bitmap.font.size = TEXT_SIZE
@disabled = false
@hover_area = nil # Is a symbol from the keys for @interactions if the mouse is hovering over that interaction
@captured_area = nil # Is a symbol from the keys for @interactions (or :none) if this control is clicked in
@@ -51,10 +51,7 @@ class UIControls::BaseControl < BitmapSprite
return false if !@interactions || @interactions.empty?
mouse_x, mouse_y = mouse_pos
return false if !mouse_x || !mouse_y
@interactions.each_pair do |area, rect|
return true if rect.contains?(mouse_x, mouse_y)
end
return false
return @interactions.any? { |area, rect| rect.contains?(mouse_x, mouse_y) }
end
#-----------------------------------------------------------------------------
@@ -84,7 +81,7 @@ class UIControls::BaseControl < BitmapSprite
@invalid = true
end
# Makes the control no longer invalid.
# Makes the control no longer invalid. Called after repainting.
def validate
@invalid = false
end
@@ -125,7 +122,6 @@ class UIControls::BaseControl < BitmapSprite
end
def refresh
# Paint over control to erase contents (intentionally not using self.bitmap.clear)
self.bitmap.clear
draw_area_highlight
end
@@ -194,10 +190,8 @@ class UIControls::BaseControl < BitmapSprite
# Updates the logic on the control, invalidating it if necessary.
def update
return if !self.visible
return if disabled? && !busy?
return if disabled? && !busy? # This control still works if it becomes disabled while using it
update_hover_highlight
# Detect a mouse press/release
if @interactions && !@interactions.empty?
if Input.trigger?(Input::MOUSELEFT)
@@ -206,6 +200,5 @@ class UIControls::BaseControl < BitmapSprite
on_mouse_release
end
end
end
end

View File

@@ -4,9 +4,6 @@
class UIControls::Label < UIControls::BaseControl
attr_reader :text
LABEL_END_X = 80
TEXT_OFFSET_Y = 5
def initialize(width, height, viewport, text)
super(width, height, viewport)
@text = text
@@ -27,8 +24,10 @@ class UIControls::Label < UIControls::BaseControl
super
if @header
draw_text_centered(self.bitmap, 0, TEXT_OFFSET_Y, width, @text)
# Draw underline
text_size = self.bitmap.text_size(@text)
self.bitmap.fill_rect((width - text_size.width) / 2, TEXT_OFFSET_Y + text_size.height, text_size.width, 1, TEXT_COLOR)
self.bitmap.fill_rect((width - text_size.width) / 2, TEXT_OFFSET_Y + text_size.height,
text_size.width, 1, TEXT_COLOR)
else
draw_text(self.bitmap, 4, TEXT_OFFSET_Y, @text)
end

View File

@@ -1,20 +1,18 @@
#===============================================================================
# TODO: Support selecting part of the text by remembering the initial
# cursor position and using it and the current cursor position to
# decide which characters are selected. Maybe? Note that this method
# is only triggered upon the initial mouse press, and isn't repeated
# while it's still held down.
#
#===============================================================================
class UIControls::TextBox < UIControls::BaseControl
attr_accessor :box_width
TEXT_BOX_X = 2
TEXT_BOX_WIDTH = 200
TEXT_BOX_HEIGHT = 24
TEXT_BOX_PADDING = 4 # Gap between sides of text box and text
TEXT_OFFSET_Y = 5
def initialize(width, height, viewport, value = "")
super(width, height, viewport)
@value = value
@box_width = TEXT_BOX_WIDTH
@cursor_pos = -1
@display_pos = 0
@cursor_timer = nil
@@ -22,9 +20,13 @@ class UIControls::TextBox < UIControls::BaseControl
@blacklist = []
end
def value
return @value.dup
end
def value=(new_value)
return if @value == new_value
@value = new_value
@value = new_value.dup
invalidate
end
@@ -59,7 +61,7 @@ class UIControls::TextBox < UIControls::BaseControl
def set_interactive_rects
@text_box_rect = Rect.new(TEXT_BOX_X, (height - TEXT_BOX_HEIGHT) / 2,
[TEXT_BOX_WIDTH, width].min, TEXT_BOX_HEIGHT)
[@box_width, width - (TEXT_BOX_X * 2)].min, TEXT_BOX_HEIGHT)
@interactions = {
:text_box => @text_box_rect
}

View File

@@ -1,6 +1,5 @@
#===============================================================================
# TODO: Is there a better knob design than a big black rectangle? I'd rather
# it not be a different colour.
#
#===============================================================================
class UIControls::NumberSlider < UIControls::BaseControl
attr_reader :min_value
@@ -14,7 +13,6 @@ class UIControls::NumberSlider < UIControls::BaseControl
SLIDER_LENGTH = 128
PLUS_X = SLIDER_X + SLIDER_LENGTH + SLIDER_PADDING
VALUE_X = PLUS_X + PLUS_MINUS_SIZE + 5
TEXT_OFFSET_Y = 5
def initialize(width, height, viewport, min_value, max_value, value)
super(width, height, viewport)

View File

@@ -4,8 +4,8 @@
class UIControls::Button < UIControls::BaseControl
BUTTON_X = 2
BUTTON_Y = 2
BUTTON_PADDING = 10
BUTTON_HEIGHT = 28
BUTTON_PADDING = 10 # Used when @fixed_size is false
BUTTON_HEIGHT = 28 # Used when @fixed_size is false
# TODO: This will also depend on the font size.
TEXT_BASE_OFFSET_Y = 18 # Text is centred vertically in the button
@@ -20,6 +20,7 @@ class UIControls::Button < UIControls::BaseControl
end
def set_interactive_rects
@interactions&.clear
button_width = (@fixed_size) ? width - (BUTTON_X * 2) : self.bitmap.text_size(@text).width + (BUTTON_PADDING * 2)
button_height = (@fixed_size) ? height - (2 * BUTTON_Y) : BUTTON_HEIGHT
button_height = [button_height, height - (2 * BUTTON_Y)].min
@@ -29,10 +30,10 @@ class UIControls::Button < UIControls::BaseControl
}
end
# TODO: This won't change the button's size. This is probably okay.
def set_text(val)
return if @text == val
@text = val
set_interactive_rects if !@fixed_size
invalidate
end
@@ -60,12 +61,14 @@ class UIControls::Button < UIControls::BaseControl
self.bitmap.outline_rect(@button_rect.x, @button_rect.y,
@button_rect.width, @button_rect.height,
self.bitmap.font.color)
# TODO: Make buttons look more different to text boxes?
# shade = self.bitmap.font.color.clone
# shade.alpha = 96
# self.bitmap.outline_rect(@button_rect.x + 1, @button_rect.y + 1,
# @button_rect.width - 2, @button_rect.height - 2,
# shade, 3)
# Draw inner grey ring that shows this is a button rather than a text box
if !disabled?
shade = self.bitmap.font.color.clone
shade.alpha = 64
self.bitmap.outline_rect(@button_rect.x + 2, @button_rect.y + 2,
@button_rect.width - 4, @button_rect.height - 4,
shade, 1)
end
# Draw button text
draw_text_centered(self.bitmap, @button_rect.x,
@button_rect.y + (@button_rect.height - TEXT_BASE_OFFSET_Y) / 2,

View File

@@ -1,11 +1,5 @@
#===============================================================================
# TODO: Do I need to split self's bitmap into two (one for highlights and one
# for text)? This would be to reduce lag caused by redrawing text even if
# you're just waving the mouse over the control. There doesn't seem to be
# any lag at the moment with a tall list.
# TODO: Make a viewport for the list, and allow scrolling positions halfway
# through a line? Nah.
# TODO: This control cannot be disabled.
#
#===============================================================================
class UIControls::List < UIControls::BaseControl
LIST_X = 0

View File

@@ -2,22 +2,23 @@
#
#===============================================================================
class UIControls::DropdownList < UIControls::BaseControl
attr_accessor :box_width
attr_accessor :max_rows
TEXT_BOX_X = 2
TEXT_BOX_WIDTH = 200
TEXT_BOX_HEIGHT = 24
TEXT_BOX_PADDING = 4 # Gap between sides of text box and text
TEXT_OFFSET_Y = 5
MAX_LIST_ROWS = 8
attr_accessor :max_rows
# NOTE: options is a hash: keys are symbols, values are display names.
def initialize(width, height, viewport, options, value)
# NOTE: options is a hash: keys are symbols, values are display names.
super(width, height, viewport)
@options = options
@value = value
@options = options
@value = value
@box_width = TEXT_BOX_WIDTH
@toggling_dropdown_list = false
@max_rows = MAX_LIST_ROWS
@max_rows = MAX_LIST_ROWS
end
def dispose
@@ -33,7 +34,7 @@ class UIControls::DropdownList < UIControls::BaseControl
def set_interactive_rects
@button_rect = Rect.new(TEXT_BOX_X, (height - TEXT_BOX_HEIGHT) / 2,
[TEXT_BOX_WIDTH, width].min, TEXT_BOX_HEIGHT)
[@box_width, width - (TEXT_BOX_X * 2)].min, TEXT_BOX_HEIGHT)
@interactions = {
:button => @button_rect
}

View File

@@ -1,7 +1,5 @@
#===============================================================================
# TODO: Make the slider a separate sprite that moves, instead of redrawing this
# sprite's bitmap whenever it moves? Intended to reduce lag. There doesn't
# seem to be any lag at the moment with a tall scrollbar.
#
#===============================================================================
class UIControls::Scrollbar < UIControls::BaseControl
SLIDER_WIDTH = 16
@@ -122,9 +120,6 @@ class UIControls::Scrollbar < UIControls::BaseControl
return if !self.visible
super
if @captured_area == :slider
# TODO: Have a display y position for the slider bar which is in pixels,
# and round it to the nearest row when setting @top_row? This is
# just to make the slider bar movement smoother.
mouse_x, mouse_y = mouse_pos
return if !mouse_x || !mouse_y
long_coord = (@horizontal) ? mouse_x : mouse_y

View File

@@ -6,6 +6,15 @@ class Bitmap
fill_rect(x + width - thickness, y, thickness, height, color)
end
# Draws a series of concentric outline_rects around the defined area. From
# inside to outside, the color of each ring alternates.
def border_rect(x, y, width, height, thickness, color1, color2)
thickness.times do |i|
col = (i.even?) ? color1 : color2
outline_rect(x - i - 1, y - i - 1, width + (i * 2) + 2, height + (i * 2) + 2, col)
end
end
def fill_diamond(x, y, radius, color)
((radius * 2) + 1).times do |i|
height = (i <= radius) ? (i * 2) + 1 : (((radius * 2) - i) * 2) + 1

View File

@@ -25,7 +25,6 @@ module GameData
# Properties that apply to the animation in general, not to individual
# particles. They don't change during the animation.
SCHEMA = {
# TODO: Add support for overworld animations.
"SectionName" => [:id, "esU", {"Move" => :move, "OppMove" => :opp_move,
"Common" => :common, "OppCommon" => :opp_common}],
"Name" => [:name, "s"],
@@ -36,8 +35,6 @@ module GameData
# TODO: DamageFrame (keyframe at which the battle continues, i.e. damage
# animations start playing).
"Flags" => [:flags, "*s"],
# TODO: If this is changed to be more than just a string, edit the
# compiler's current_particle definition accordingly.
"Particle" => [:particles, "s"] # Is a subheader line like <text>
}
# For individual particles. Any property whose schema begins with "^" can
@@ -49,9 +46,9 @@ module GameData
# These properties cannot be changed partway through the animation.
# NOTE: "Name" isn't a property here, because the particle's name comes
# from the "Particle" property above.
"Graphic" => [:graphic, "s"],
# TODO: If more focus types are added, add ones that involve a target to
# the Compiler's check relating to "NoTarget".
"Graphic" => [:graphic, "s"],
"Focus" => [:focus, "e", {"User" => :user, "Target" => :target,
"UserAndTarget" => :user_and_target,
"Screen" => :screen}],
@@ -59,8 +56,8 @@ module GameData
# All properties below are "SetXYZ" or "MoveXYZ". "SetXYZ" has the
# keyframe and the value, and "MoveXYZ" has the keyframe, duration and the
# value. All are "^". "SetXYZ" is turned into "MoveXYZ" when compiling by
# inserting a duration (second value) of 0.
# value. All have "^" in their schema. "SetXYZ" is turned into "MoveXYZ"
# when compiling by inserting a duration (second value) of 0.
"SetFrame" => [:frame, "^uu"], # Frame within the graphic if it's a spritesheet
"MoveFrame" => [:frame, "^uuuE", nil, nil, nil, INTERPOLATION_TYPES],
"SetBlending" => [:blending, "^uu"], # 0, 1 or 2
@@ -144,7 +141,7 @@ module GameData
:target_cry => nil
}
@@cmd_to_pbs_name = nil # USed for writing animation PBS files
@@cmd_to_pbs_name = nil # Used for writing animation PBS files
extend ClassMethodsIDNumbers
include InstanceMethods
@@ -162,27 +159,6 @@ module GameData
DATA[(id_num >= 0) ? id_num : DATA.keys.length] = self.new(hash)
end
# TODO: Rewrite this to query animations from other criteria. Remember that
# multiple animations could have the same move/version. Odds are this
# method won't be used much at all.
# TODO: Separate exists? methods for move and common animations?
# def exists?(other)
# end
# TODO: Rewrite this to get animations from other criteria. Remember that
# multiple animations could have the same move/version. Odds are this
# method won't be used much at all.
# TODO: Separate get methods for move and common animations?
# def get(other)
# end
# TODO: Rewrite this to get animations from other criteria. Remember that
# multiple animations could have the same move/version. Odds are this
# method won't be used much at all.
# TODO: Separate try_get methods for move and common animations?
# def try_get(other)
# end
def initialize(hash)
# NOTE: hash has an :id entry, but it's unused here.
@type = hash[:type]
@@ -201,9 +177,9 @@ module GameData
def clone_as_hash
ret = {}
ret[:type] = @type
ret[:move] = @move.dup
ret[:version] = @version.dup
ret[:name] = @name.dup
ret[:move] = @move
ret[:version] = @version
ret[:name] = @name
ret[:particles] = [] # Clone the @particles array, which is nested hashes and arrays
@particles.each do |particle|
new_p = {}
@@ -254,10 +230,6 @@ module GameData
# The User and Target particles have hardcoded graphics/foci, so they
# don't need writing to PBS
ret = nil if ["User", "Target"].include?(@particles[index][:name])
when "Play"
# TODO: Turn volume/pitch of 100 into nil.
when "PlayUserCry", "PlayTargetCry"
# TODO: Turn volume/pitch of 100 into nil.
when "AllCommands"
# Get translations of all properties to their names as seen in PBS
# animation files
@@ -283,6 +255,14 @@ module GameData
new_cmd.pop if new_cmd.last == :linear # This is the default
ret.push([@@cmd_to_pbs_name[key][1]] + new_cmd) # ["MoveXYZ", keyframe, duration, value]
else
case key
when :se
new_cmd[4] = nil if new_cmd[4] == 100 # Pitch
new_cmd[3] = nil if new_cmd[4].nil? && new_cmd[3] == 100 # Volume
when :user_cry, :target_cry
new_cmd[3] = nil if new_cmd[3] == 100 # Pitch
new_cmd[2] = nil if new_cmd[3].nil? && new_cmd[2] == 100 # Volume
end
ret.push([@@cmd_to_pbs_name[key][0]] + new_cmd) # ["SetXYZ", keyframe, duration, value]
end
end

View File

@@ -1,20 +1,5 @@
# TODO: Should I split this code into visual and mechanical classes, a la the
# other UI screens?
#===============================================================================
# TODO: When creating a new particle, blacklist the names "User", "Target" and
# "SE". Make particles with those names undeletable.
# TODO: Remove the particle named "Target" if the animation's focus is changed
# to one that doesn't include a target, and vice versa. Do the same for
# "User"(?).
# TODO: Things that need pop-up windows (draws a semi-transparent grey over the
# whole screen behind the window):
# - animation properties (Move/OppMove/Common/OppCommon, move, version,
# extra name, target, filepath, flags, etc.)
# - editor settings (theme, canvas BG graphics, user/target graphics,
# display of canvas particle boxes, etc.)
# TODO: While playing the animation, draw a semi-transparent grey over the
# screen except for the canvas and playback controls. Can't edit anything
# while it's playing.
#
#===============================================================================
class AnimationEditor
WINDOW_WIDTH = Settings::SCREEN_WIDTH + (32 * 10)
@@ -22,6 +7,7 @@ class AnimationEditor
BORDER_THICKNESS = 4
# Components
MENU_BAR_WIDTH = WINDOW_WIDTH
MENU_BAR_HEIGHT = 30
@@ -45,15 +31,43 @@ class AnimationEditor
PARTICLE_LIST_WIDTH = WINDOW_WIDTH - (BORDER_THICKNESS * 2)
PARTICLE_LIST_HEIGHT = WINDOW_HEIGHT - PARTICLE_LIST_Y - BORDER_THICKNESS
ANIM_PROPERTIES_WIDTH = SIDE_PANE_WIDTH + 80
ANIM_PROPERTIES_HEIGHT = WINDOW_HEIGHT * 3 / 4
ANIM_PROPERTIES_X = (WINDOW_WIDTH - ANIM_PROPERTIES_WIDTH) / 2
ANIM_PROPERTIES_Y = (WINDOW_HEIGHT - ANIM_PROPERTIES_HEIGHT) / 2
# Pop-up windows
ANIM_PROPERTIES_LABEL_WIDTH = UIControls::ControlsContainer::OFFSET_FROM_LABEL_X + 80
ANIM_PROPERTIES_WIDTH = SIDE_PANE_WIDTH + 80 + 8
ANIM_PROPERTIES_HEIGHT = WINDOW_HEIGHT * 3 / 4
ANIM_PROPERTIES_X = (WINDOW_WIDTH - ANIM_PROPERTIES_WIDTH) / 2
ANIM_PROPERTIES_Y = (WINDOW_HEIGHT - ANIM_PROPERTIES_HEIGHT) / 2
MESSAGE_BOX_WIDTH = WINDOW_WIDTH * 3 / 4
MESSAGE_BOX_HEIGHT = 160
MESSAGE_BOX_BUTTON_WIDTH = 150
MESSAGE_BOX_BUTTON_HEIGHT = 32
MESSAGE_BOX_SPACING = 16
CHOOSER_BUTTON_WIDTH = 150
CHOOSER_BUTTON_HEIGHT = MESSAGE_BOX_BUTTON_HEIGHT
CHOOSER_FILE_LIST_X = 8
CHOOSER_FILE_LIST_Y = 32
CHOOSER_FILE_LIST_WIDTH = CHOOSER_BUTTON_WIDTH * 2
CHOOSER_FILE_LIST_HEIGHT = UIControls::List::ROW_HEIGHT * 15
GRAPHIC_CHOOSER_PREVIEW_SIZE = 320 # Square
GRAPHIC_CHOOSER_WINDOW_WIDTH = CHOOSER_FILE_LIST_X + CHOOSER_FILE_LIST_WIDTH + 10 + GRAPHIC_CHOOSER_PREVIEW_SIZE + 8 + (BORDER_THICKNESS * 2)
GRAPHIC_CHOOSER_WINDOW_HEIGHT = CHOOSER_FILE_LIST_Y + CHOOSER_FILE_LIST_HEIGHT + 10 + CHOOSER_BUTTON_HEIGHT + 8 + (BORDER_THICKNESS * 2)
GRAPHIC_CHOOSER_X = ((WINDOW_WIDTH - GRAPHIC_CHOOSER_WINDOW_WIDTH) / 2)
GRAPHIC_CHOOSER_Y = ((WINDOW_HEIGHT - GRAPHIC_CHOOSER_WINDOW_HEIGHT) / 2)
AUDIO_CHOOSER_LABEL_WIDTH = UIControls::ControlsContainer::OFFSET_FROM_LABEL_X
AUDIO_CHOOSER_SLIDER_WIDTH = (CHOOSER_BUTTON_WIDTH * 2) - AUDIO_CHOOSER_LABEL_WIDTH
AUDIO_CHOOSER_WINDOW_WIDTH = CHOOSER_FILE_LIST_X + CHOOSER_FILE_LIST_WIDTH + 8 + (CHOOSER_BUTTON_WIDTH * 2) + 4 + (BORDER_THICKNESS * 2)
AUDIO_CHOOSER_WINDOW_HEIGHT = CHOOSER_FILE_LIST_Y + CHOOSER_FILE_LIST_HEIGHT + 10 + CHOOSER_BUTTON_HEIGHT + 8 + (BORDER_THICKNESS * 2)
AUDIO_CHOOSER_X = ((WINDOW_WIDTH - AUDIO_CHOOSER_WINDOW_WIDTH) / 2)
AUDIO_CHOOSER_Y = ((WINDOW_HEIGHT - AUDIO_CHOOSER_WINDOW_HEIGHT) / 2)
def initialize(anim_id, anim)
@anim_id = anim_id
@anim = anim
@pbs_path = anim[:pbs_path].dup
@pbs_path = anim[:pbs_path]
@quit = false
# Viewports
@viewport = Viewport.new(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)
@@ -85,13 +99,10 @@ class AnimationEditor
[:commands_pane, :se_pane, :particle_pane, :keyframe_pane].each do |pane|
@components[pane] = UIControls::ControlsContainer.new(SIDE_PANE_X, SIDE_PANE_Y, SIDE_PANE_WIDTH, SIDE_PANE_HEIGHT)
end
# TODO: Make more side panes for:
# - colour/tone editor (accessed from @components[:commands_pane] via
# a button; has Apply/Cancel buttons to only apply all its values at
# the end of editing them, although canvas will be updated in real
# time to show the changes)
# - effects particle properties (depends on keyframe; for screen
# shake, etc.)
# TODO: Make a side pane for colour/tone editor (accessed from
# @components[:commands_pane] via a button; has Apply/Cancel buttons
# to retain/undo all its changes, although changes are made normally
# while in it and canvas is updated accordingly.
# Timeline/particle list
@components[:particle_list] = AnimationEditor::ParticleList.new(
PARTICLE_LIST_X, PARTICLE_LIST_Y, PARTICLE_LIST_WIDTH, PARTICLE_LIST_HEIGHT, @viewport
@@ -99,17 +110,25 @@ class AnimationEditor
@components[:particle_list].set_interactive_rects
# Animation properties pop-up window
@components[:animation_properties] = UIControls::ControlsContainer.new(
ANIM_PROPERTIES_X + 4, ANIM_PROPERTIES_Y + 4, ANIM_PROPERTIES_WIDTH - 8, ANIM_PROPERTIES_HEIGHT - 8
ANIM_PROPERTIES_X + BORDER_THICKNESS + 4, ANIM_PROPERTIES_Y + BORDER_THICKNESS,
ANIM_PROPERTIES_WIDTH - ((BORDER_THICKNESS + 4) * 2), ANIM_PROPERTIES_HEIGHT - (BORDER_THICKNESS * 2)
)
@components[:animation_properties].viewport.z = @pop_up_viewport.z + 1
@components[:animation_properties].label_offset_x = 170
# Graphic chooser pop-up window
@components[:graphic_chooser] = UIControls::ControlsContainer.new(
GRAPHIC_CHOOSER_X + BORDER_THICKNESS, GRAPHIC_CHOOSER_Y + BORDER_THICKNESS,
GRAPHIC_CHOOSER_WINDOW_WIDTH - (BORDER_THICKNESS * 2), GRAPHIC_CHOOSER_WINDOW_HEIGHT - (BORDER_THICKNESS * 2)
)
@components[:graphic_chooser].viewport.z = @pop_up_viewport.z + 1
# Audio chooser pop-up window
@components[:audio_chooser] = UIControls::ControlsContainer.new(
AUDIO_CHOOSER_X + BORDER_THICKNESS, AUDIO_CHOOSER_Y + BORDER_THICKNESS,
AUDIO_CHOOSER_WINDOW_WIDTH - (BORDER_THICKNESS * 2), AUDIO_CHOOSER_WINDOW_HEIGHT - (BORDER_THICKNESS * 2)
)
@components[:audio_chooser].viewport.z = @pop_up_viewport.z + 1
@captured = nil
set_menu_bar_contents
set_canvas_contents
set_play_controls_contents
set_side_panes_contents
set_particle_list_contents
set_animation_properties_contents
set_components_contents
refresh
end
@@ -121,6 +140,7 @@ class AnimationEditor
@components.clear
@viewport.dispose
@canvas_viewport.dispose
@pop_up_viewport.dispose
end
def keyframe
@@ -178,8 +198,12 @@ class AnimationEditor
# sprite, make this instead a choice of front/back/same as the main sprite/
# opposite of the main sprite. Probably need two controls in the same space
# and refresh_component(:commands_pane) makes the appropriate one visible.
commands_pane.add_labelled_number_text_box(:x, _INTL("X"), -128, CANVAS_WIDTH + 128, 64)
commands_pane.add_labelled_number_text_box(:y, _INTL("Y"), -128, CANVAS_HEIGHT + 128, 96)
commands_pane.add_labelled_number_text_box(:x, _INTL("X"), -(CANVAS_WIDTH + 128), CANVAS_WIDTH + 128, 0)
commands_pane.add_labelled_number_text_box(:y, _INTL("Y"), -(CANVAS_WIDTH + 128), CANVAS_HEIGHT + 128, 0)
# TODO: If the graphic is user's sprite/target's sprite, make :frame instead
# a choice of front/back/same as the main sprite/opposite of the main
# sprite. Will need two controls in the same space.
commands_pane.add_labelled_number_text_box(:frame, _INTL("Frame"), 0, 99, 0)
commands_pane.add_labelled_checkbox(:visible, _INTL("Visible"), true)
commands_pane.add_labelled_number_slider(:opacity, _INTL("Opacity"), 0, 255, 255)
commands_pane.add_labelled_number_text_box(:zoom_x, _INTL("Zoom X"), 0, 1000, 100)
@@ -273,12 +297,14 @@ class AnimationEditor
# Create "opp" variant
anim_properties.add_labelled_checkbox(:opp_variant, _INTL("User is opposing?"), false)
# Create move control
# TODO: Also make a TextBox here for common animations, and toggle these two
# controls' visibility depending on :type?
# TODO: Instead of having the :common_anim TextBox control, make this a
# TextBoxDropdownList control instead. Make it allow custom text
# as well as any option in the list. Its options will be changed
# depending on the animation's type. Also have a list of existing
# Common animation names for it.
move_list = []
GameData::Move.each { |m| move_list.push([m.id.to_s, m.name]) }
move_list.sort! { |a, b| a[1] <=> b[1] }
# TODO: Make this a TextBoxDropdownList instead.
anim_properties.add_labelled_dropdown_list(:move, _INTL("Move"), move_list.to_h, move_list[0][0])
move_ctrl = anim_properties.get_control(:move)
move_ctrl.max_rows = 16
@@ -297,11 +323,71 @@ class AnimationEditor
# TODO: List, TextBox and some Buttons to add/delete.
# Create "usable in battle" control
anim_properties.add_labelled_checkbox(:usable, _INTL("Can be used in battle?"), true)
# TODO: "Play if target is on the same side as the user".
anim_properties.add_button(:close, _INTL("Close"))
anim_properties.visible = false
end
def set_graphic_chooser_contents
graphic_chooser = @components[:graphic_chooser]
graphic_chooser.add_header_label(:header, _INTL("Choose a file"))
# List of files
list = UIControls::List.new(CHOOSER_FILE_LIST_WIDTH, CHOOSER_FILE_LIST_HEIGHT, graphic_chooser.viewport, [])
graphic_chooser.add_control_at(:list, list, CHOOSER_FILE_LIST_X, CHOOSER_FILE_LIST_Y)
# Buttons
[[:ok, _INTL("OK")], [:cancel, _INTL("Cancel")]].each_with_index do |option, i|
btn = UIControls::Button.new(CHOOSER_BUTTON_WIDTH, MESSAGE_BOX_BUTTON_HEIGHT, graphic_chooser.viewport, option[1])
btn.set_fixed_size
graphic_chooser.add_control_at(option[0], btn,
CHOOSER_FILE_LIST_X + (CHOOSER_BUTTON_WIDTH * i),
CHOOSER_FILE_LIST_Y + CHOOSER_FILE_LIST_HEIGHT + 4)
end
graphic_chooser.visible = false
end
def set_audio_chooser_contents
audio_chooser = @components[:audio_chooser]
audio_chooser.add_header_label(:header, _INTL("Choose a file"))
# List of files
list = UIControls::List.new(CHOOSER_FILE_LIST_WIDTH, CHOOSER_FILE_LIST_HEIGHT, audio_chooser.viewport, [])
audio_chooser.add_control_at(:list, list, CHOOSER_FILE_LIST_X, CHOOSER_FILE_LIST_Y)
# Buttons
[[:ok, _INTL("OK")], [:cancel, _INTL("Cancel")]].each_with_index do |option, i|
btn = UIControls::Button.new(CHOOSER_BUTTON_WIDTH, MESSAGE_BOX_BUTTON_HEIGHT, audio_chooser.viewport, option[1])
btn.set_fixed_size
audio_chooser.add_control_at(option[0], btn,
CHOOSER_FILE_LIST_X + (CHOOSER_BUTTON_WIDTH * i),
CHOOSER_FILE_LIST_Y + CHOOSER_FILE_LIST_HEIGHT + 4)
end
# Volume and pitch sliders
[[:volume, _INTL("Volume"), 0, 100], [:pitch, _INTL("Pitch"), 0, 200]].each_with_index do |option, i|
label = UIControls::Label.new(AUDIO_CHOOSER_LABEL_WIDTH, 28, audio_chooser.viewport, option[1])
audio_chooser.add_control_at((option[0].to_s + "_label").to_sym, label,
list.x + list.width + 8, list.y + (28 * i))
slider = UIControls::NumberSlider.new(AUDIO_CHOOSER_SLIDER_WIDTH, 28, audio_chooser.viewport, option[2], option[3], 100)
audio_chooser.add_control_at(option[0], slider, label.x + label.width, label.y)
end
# Playback buttons
[[:play, _INTL("Play")], [:stop, _INTL("Stop")]].each_with_index do |option, i|
btn = UIControls::Button.new(CHOOSER_BUTTON_WIDTH, MESSAGE_BOX_BUTTON_HEIGHT, audio_chooser.viewport, option[1])
btn.set_fixed_size
audio_chooser.add_control_at(option[0], btn,
list.x + list.width + 8 + (CHOOSER_BUTTON_WIDTH * i),
list.y + (28 * 2))
end
audio_chooser.visible = false
end
def set_components_contents
set_menu_bar_contents
set_canvas_contents
set_play_controls_contents
set_side_panes_contents
set_particle_list_contents
set_animation_properties_contents
set_graphic_chooser_contents
set_audio_chooser_contents
end
#-----------------------------------------------------------------------------
def save
@@ -320,19 +406,17 @@ class AnimationEditor
#-----------------------------------------------------------------------------
def draw_editor_background
draw_big_outline = lambda do |bitmap, x, y, width, height|
BORDER_THICKNESS.times do |i|
col = (i.even?) ? Color.white : Color.black
bitmap.outline_rect(x - i - 1, y - i - 1, width + (i * 2) + 2, height + (i * 2) + 2, col)
end
end
# Fill the whole screen with white
@screen_bitmap.bitmap.fill_rect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, Color.white)
# Outline around elements
draw_big_outline.call(@screen_bitmap.bitmap, CANVAS_X, CANVAS_Y, CANVAS_WIDTH, CANVAS_HEIGHT)
draw_big_outline.call(@screen_bitmap.bitmap, PLAY_CONTROLS_X, PLAY_CONTROLS_Y, PLAY_CONTROLS_WIDTH, PLAY_CONTROLS_HEIGHT)
draw_big_outline.call(@screen_bitmap.bitmap, SIDE_PANE_X, SIDE_PANE_Y, SIDE_PANE_WIDTH, SIDE_PANE_HEIGHT)
draw_big_outline.call(@screen_bitmap.bitmap, PARTICLE_LIST_X, PARTICLE_LIST_Y, PARTICLE_LIST_WIDTH, PARTICLE_LIST_HEIGHT)
@screen_bitmap.bitmap.border_rect(CANVAS_X, CANVAS_Y, CANVAS_WIDTH, CANVAS_HEIGHT,
BORDER_THICKNESS, Color.white, Color.black)
@screen_bitmap.bitmap.border_rect(PLAY_CONTROLS_X, PLAY_CONTROLS_Y, PLAY_CONTROLS_WIDTH, PLAY_CONTROLS_HEIGHT,
BORDER_THICKNESS, Color.white, Color.black)
@screen_bitmap.bitmap.border_rect(SIDE_PANE_X, SIDE_PANE_Y, SIDE_PANE_WIDTH, SIDE_PANE_HEIGHT,
BORDER_THICKNESS, Color.white, Color.black)
@screen_bitmap.bitmap.border_rect(PARTICLE_LIST_X, PARTICLE_LIST_Y, PARTICLE_LIST_WIDTH, PARTICLE_LIST_HEIGHT,
BORDER_THICKNESS, Color.white, Color.black)
# Draw box around SE list box in side pane
@se_list_box_bitmap.bitmap.outline_rect(SIDE_PANE_X + 3, SIDE_PANE_Y + 24 + 4,
SIDE_PANE_WIDTH - 6, (5 * UIControls::List::ROW_HEIGHT) + 4, Color.black)
@@ -365,14 +449,14 @@ class AnimationEditor
case component_sym
when :commands_pane
new_vals = AnimationEditor::ParticleDataHelper.get_all_keyframe_particle_values(@anim[:particles][particle_index], keyframe)
# TODO: Need to do something special for :color, :tone and :frame which
# all have button controls.
component.controls.each do |ctrl|
next if !new_vals.include?(ctrl[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[1].
end
# TODO: component.get_control(:frame).disable if the particle's graphic is
# not a spritesheet or is "USER"/"TARGET"/etc. (enable otherwise).
when :se_pane
se_particle = @anim[:particles].select { |p| p[:name] == "SE" }[0]
kyfrm = keyframe
@@ -428,18 +512,20 @@ class AnimationEditor
component.get_control(:graphic).enable
component.get_control(:focus).enable
end
# TODO: Set the possible focus options depending on whether the animation
# has a target/user.
when :animation_properties
case @anim[:type]
when :move, :opp_move
component.get_control(:move_label).text = _INTL("Move")
component.get_control(:move).visible = true
component.get_control(:move).value = @anim[:move].dup
component.get_control(:move).value = @anim[:move]
component.get_control(:common_anim).visible = false
when :common, :opp_common
component.get_control(:move_label).text = _INTL("Common animation")
component.get_control(:move).visible = false
component.get_control(:common_anim).visible = true
component.get_control(:common_anim).value = @anim[:move].dup
component.get_control(:common_anim).value = @anim[:move]
end
# TODO: Maybe other things as well?
end
@@ -458,8 +544,6 @@ class AnimationEditor
#-----------------------------------------------------------------------------
# TODO: Every component that contains a button, etc. should respond to
# "values", which returns the changed elements.
def apply_changed_value(component_sym, property, value)
case component_sym
when :menu_bar
@@ -544,7 +628,7 @@ class AnimationEditor
if @anim[:particles][p_index][:graphic] != new_file
@anim[:particles][p_index][:graphic] = new_file
refresh_component(:particle_pane)
# TODO: refresh_component(:canvas)
refresh_component(:canvas)
end
else
particle = @anim[:particles][particle_index]
@@ -572,7 +656,7 @@ class AnimationEditor
when :common_anim
@anim[:move] = value
when :pbs_path
txt = value.dup.gsub!(/\.txt$/, "")
txt = value.gsub!(/\.txt$/, "")
@anim[property] = txt
when :has_target
@anim[:no_target] = !value

View File

@@ -2,20 +2,6 @@
#
#===============================================================================
class AnimationEditor
MESSAGE_BOX_WIDTH = WINDOW_WIDTH * 3 / 4
MESSAGE_BOX_HEIGHT = 160
MESSAGE_BOX_BUTTON_WIDTH = 150
MESSAGE_BOX_BUTTON_HEIGHT = 32
MESSAGE_BOX_SPACING = 16
GRAPHIC_CHOOSER_BUTTON_WIDTH = 150
GRAPHIC_CHOOSER_BUTTON_HEIGHT = MESSAGE_BOX_BUTTON_HEIGHT
GRAPHIC_CHOOSER_FILE_LIST_WIDTH = GRAPHIC_CHOOSER_BUTTON_WIDTH * 2
GRAPHIC_CHOOSER_FILE_LIST_HEIGHT = 15 * UIControls::List::ROW_HEIGHT
GRAPHIC_CHOOSER_PREVIEW_SIZE = 320
GRAPHIC_CHOOSER_WINDOW_WIDTH = GRAPHIC_CHOOSER_FILE_LIST_WIDTH + GRAPHIC_CHOOSER_PREVIEW_SIZE + (MESSAGE_BOX_SPACING * 2) + 8
GRAPHIC_CHOOSER_WINDOW_HEIGHT = GRAPHIC_CHOOSER_FILE_LIST_HEIGHT + GRAPHIC_CHOOSER_BUTTON_HEIGHT + 24 + (MESSAGE_BOX_SPACING * 2) + 2
def create_pop_up_window(width, height)
ret = BitmapSprite.new(width, height, @pop_up_viewport)
ret.x = (WINDOW_WIDTH - width) / 2
@@ -24,10 +10,9 @@ class AnimationEditor
ret.bitmap.font.color = Color.black
ret.bitmap.font.size = 18
# Draw message box border
BORDER_THICKNESS.times do |i|
col = (i.even?) ? Color.black : Color.white
ret.bitmap.outline_rect(i, i, ret.width - (i * 2), ret.height - (i * 2), col)
end
ret.bitmap.border_rect(BORDER_THICKNESS, BORDER_THICKNESS,
ret.width - (BORDER_THICKNESS * 2), ret.height - (BORDER_THICKNESS * 2),
BORDER_THICKNESS, Color.white, Color.black)
# Fill message box with white
ret.bitmap.fill_rect(BORDER_THICKNESS, BORDER_THICKNESS,
ret.width - (BORDER_THICKNESS * 2),
@@ -94,66 +79,64 @@ class AnimationEditor
#-----------------------------------------------------------------------------
# Generates a list of all files in the given folder which have a file
# extension that matches one in exts. Removes any files from the list whose
# filename is the same as one in prepends (case insensitive), and then adds
# all the files in prepends to the start of the list.
def get_all_files_in_folder_and_prepend(folder, exts, prepends)
ret = []
Dir.chdir(folder) do
exts.each do |type|
Dir.glob(type) { |f| ret.push([File.basename(f, ".*"), f]) }
end
end
ret.delete_if { |f| prepends.any? { |add| add[0] == f[0].upcase } }
ret.sort! { |a, b| a[0].downcase <=> b[0].downcase }
ret.prepend(*prepends)
return ret
end
def choose_graphic_file(selected)
selected ||= ""
sprite_folder = "Graphics/Battle animations/"
# Show pop-up window
@pop_up_bg_bitmap.visible = true
bg_bitmap = create_pop_up_window(GRAPHIC_CHOOSER_WINDOW_WIDTH, GRAPHIC_CHOOSER_WINDOW_HEIGHT)
graphic_chooser = @components[:graphic_chooser]
graphic_chooser.visible = true
# Draw box around list control
list = graphic_chooser.get_control(:list)
bg_bitmap.bitmap.outline_rect(list.x + BORDER_THICKNESS - 2, list.y + BORDER_THICKNESS - 2,
list.width + 4, list.height + 4, Color.black)
# Get a list of files
files = []
Dir.chdir(sprite_folder) do
Dir.glob("*.png") { |f| files.push([File.basename(f, ".*"), f]) }
Dir.glob("*.jpg") { |f| files.push([File.basename(f, ".*"), f]) }
Dir.glob("*.jpeg") { |f| files.push([File.basename(f, ".*"), f]) }
end
files.delete_if { |f| ["USER", "USER_OPP", "USER_FRONT", "USER_BACK",
"TARGET", "TARGET_OPP", "TARGET_FRONT",
"TARGET_BACK"].include?(f[0].upcase) }
files.sort! { |a, b| a[0].downcase <=> b[0].downcase }
files.prepend(["USER", _INTL("[[User's sprite]]")],
["USER_OPP", _INTL("[[User's other side sprite]]")],
["USER_FRONT", _INTL("[[User's front sprite]]")],
["USER_BACK", _INTL("[[User's back sprite]]")],
["TARGET", _INTL("[[Target's sprite]]")],
["TARGET_OPP", _INTL("[[Target's other side sprite]]")],
["TARGET_FRONT", _INTL("[[Target's front sprite]]")],
["TARGET_BACK", _INTL("[[Target's back sprite]]")])
files = get_all_files_in_folder_and_prepend(
sprite_folder, ["*.png", "*.jpg", "*.jpeg"],
[["USER", _INTL("[[User's sprite]]")],
["USER_OPP", _INTL("[[User's other side sprite]]")],
["USER_FRONT", _INTL("[[User's front sprite]]")],
["USER_BACK", _INTL("[[User's back sprite]]")],
["TARGET", _INTL("[[Target's sprite]]")],
["TARGET_OPP", _INTL("[[Target's other side sprite]]")],
["TARGET_FRONT", _INTL("[[Target's front sprite]]")],
["TARGET_BACK", _INTL("[[Target's back sprite]]")]]
)
idx = 0
files.each_with_index do |f, i|
next if f[0] != selected
idx = i
break
end
# Show pop-up window
@pop_up_bg_bitmap.visible = true
bg_bitmap = create_pop_up_window(GRAPHIC_CHOOSER_WINDOW_WIDTH, GRAPHIC_CHOOSER_WINDOW_HEIGHT)
text = _INTL("Choose a file...")
text_size = bg_bitmap.bitmap.text_size(text)
bg_bitmap.bitmap.draw_text(MESSAGE_BOX_SPACING, 11, bg_bitmap.width, text_size.height, text, 0)
# Create list of files
list = UIControls::List.new(GRAPHIC_CHOOSER_FILE_LIST_WIDTH, GRAPHIC_CHOOSER_FILE_LIST_HEIGHT, @pop_up_viewport, files)
list.x = bg_bitmap.x + MESSAGE_BOX_SPACING
list.y = bg_bitmap.y + MESSAGE_BOX_SPACING + 24
# Set control values
list.values = files
list.selected = idx
list.set_interactive_rects
list.repaint
bg_bitmap.bitmap.outline_rect(MESSAGE_BOX_SPACING - 2, MESSAGE_BOX_SPACING + 24 - 2,
GRAPHIC_CHOOSER_FILE_LIST_WIDTH + 4, GRAPHIC_CHOOSER_FILE_LIST_HEIGHT + 4, Color.black)
# Create buttons
buttons = []
[[:ok, _INTL("OK")], [:cancel, _INTL("Cancel")]].each_with_index do |option, i|
btn = UIControls::Button.new(GRAPHIC_CHOOSER_BUTTON_WIDTH, MESSAGE_BOX_BUTTON_HEIGHT, @pop_up_viewport, option[1])
btn.x = list.x + (GRAPHIC_CHOOSER_BUTTON_WIDTH * i)
btn.y = list.y + list.height + 2
btn.set_fixed_size
btn.set_interactive_rects
buttons.push([option[0], btn])
end
# Create sprite preview
bg_bitmap.bitmap.outline_rect(MESSAGE_BOX_SPACING + list.width + 6, MESSAGE_BOX_SPACING + 24 - 2,
bg_bitmap.bitmap.outline_rect(BORDER_THICKNESS + list.x + list.width + 10 - 2,
BORDER_THICKNESS + list.y - 2,
GRAPHIC_CHOOSER_PREVIEW_SIZE + 4, GRAPHIC_CHOOSER_PREVIEW_SIZE + 4,
Color.black)
preview_sprite = Sprite.new(@pop_up_viewport)
preview_sprite.x = list.x + list.width + 8 + (GRAPHIC_CHOOSER_PREVIEW_SIZE / 2)
preview_sprite.y = list.y + (GRAPHIC_CHOOSER_PREVIEW_SIZE / 2)
preview_sprite.x = graphic_chooser.x + list.x + list.width + 10 + (GRAPHIC_CHOOSER_PREVIEW_SIZE / 2)
preview_sprite.y = graphic_chooser.y + list.y + (GRAPHIC_CHOOSER_PREVIEW_SIZE / 2)
preview_bitmap = nil
set_preview_graphic = lambda do |sprite, filename|
preview_bitmap&.dispose
@@ -166,7 +149,7 @@ class AnimationEditor
else
preview_bitmap = AnimatedBitmap.new(sprite_folder + filename)
end
bg_bitmap.bitmap.fill_rect(MESSAGE_BOX_SPACING + list.width + 8, MESSAGE_BOX_SPACING + 24,
bg_bitmap.bitmap.fill_rect(BORDER_THICKNESS + list.x + list.width + 10, BORDER_THICKNESS + list.y,
GRAPHIC_CHOOSER_PREVIEW_SIZE, GRAPHIC_CHOOSER_PREVIEW_SIZE,
Color.white)
next if !preview_bitmap
@@ -176,52 +159,42 @@ class AnimationEditor
sprite.zoom_x = sprite.zoom_y = zoom
sprite.ox = sprite.width / 2
sprite.oy = sprite.height / 2
bg_bitmap.bitmap.fill_rect(MESSAGE_BOX_SPACING + list.width + 8 + (GRAPHIC_CHOOSER_PREVIEW_SIZE / 2) - (sprite.width * sprite.zoom_x / 2),
MESSAGE_BOX_SPACING + 24 + (GRAPHIC_CHOOSER_PREVIEW_SIZE / 2) - (sprite.height * sprite.zoom_y / 2),
bg_bitmap.bitmap.fill_rect(BORDER_THICKNESS + sprite.x - graphic_chooser.x - (sprite.width * sprite.zoom_x / 2),
BORDER_THICKNESS + sprite.y - graphic_chooser.y - (sprite.height * sprite.zoom_y / 2),
sprite.width * sprite.zoom_x, sprite.height * sprite.zoom_y,
Color.magenta)
end
set_preview_graphic.call(preview_sprite, list.value)
# Interaction loop
ret = nil
captured = nil
loop do
Graphics.update
Input.update
if captured
captured.update
captured = nil if !captured.busy?
else
list.update
captured = list if list.busy?
buttons.each do |btn|
btn[1].update
captured = btn[1] if btn[1].busy?
graphic_chooser.update
if graphic_chooser.changed?
graphic_chooser.values.each_pair do |ctrl, value|
case ctrl
when :ok
ret = list.value
when :cancel
ret = selected
when :list
set_preview_graphic.call(preview_sprite, list.value)
end
graphic_chooser.clear_changed
end
ret = selected if !graphic_chooser.busy? && Input.trigger?(Input::BACK)
break if ret
graphic_chooser.repaint
end
if list.changed?
set_preview_graphic.call(preview_sprite, list.value)
list.clear_changed
end
buttons.each do |btn|
next if !btn[1].changed?
ret = list.value if btn[0] == :ok
ret = selected if btn[0] == :cancel
break
end
ret = selected if Input.trigger?(Input::BACK)
break if ret
list.repaint
buttons.each { |btn| btn[1].repaint }
end
# Dispose and return
list.dispose
buttons.each { |btn| btn[1].dispose }
buttons.clear
bg_bitmap.dispose
preview_sprite.dispose
preview_bitmap&.dispose
@pop_up_bg_bitmap.visible = false
graphic_chooser.clear_changed
graphic_chooser.visible = false
return ret
end
@@ -229,119 +202,75 @@ class AnimationEditor
def choose_audio_file(selected, volume = 100, pitch = 100)
selected ||= ""
sprite_folder = "Audio/SE/Anim/"
audio_folder = "Audio/SE/Anim/"
# Show pop-up window
@pop_up_bg_bitmap.visible = true
bg_bitmap = create_pop_up_window(AUDIO_CHOOSER_WINDOW_WIDTH, AUDIO_CHOOSER_WINDOW_HEIGHT)
audio_chooser = @components[:audio_chooser]
audio_chooser.visible = true
# Draw box around list control
list = audio_chooser.get_control(:list)
bg_bitmap.bitmap.outline_rect(list.x + BORDER_THICKNESS - 2, list.y + BORDER_THICKNESS - 2,
list.width + 4, list.height + 4, Color.black)
# Get a list of files
files = []
Dir.chdir(sprite_folder) do
Dir.glob("*.wav") { |f| files.push([File.basename(f, ".*"), f]) }
Dir.glob("*.ogg") { |f| files.push([File.basename(f, ".*"), f]) }
Dir.glob("*.mp3") { |f| files.push([File.basename(f, ".*"), f]) }
Dir.glob("*.wma") { |f| files.push([File.basename(f, ".*"), f]) }
end
files.delete_if { |f| ["USER", "TARGET"].include?(f[0].upcase) }
files.sort! { |a, b| a[0].downcase <=> b[0].downcase }
files.prepend(["USER", _INTL("[[User's cry]]")],
["TARGET", _INTL("[[Target's cry]]")])
files = get_all_files_in_folder_and_prepend(
audio_folder, ["*.wav", "*.ogg", "*.mp3", "*.wma"],
[["USER", _INTL("[[User's cry]]")],
["TARGET", _INTL("[[Target's cry]]")]]
)
idx = 0
files.each_with_index do |f, i|
next if f[0] != selected
idx = i
break
end
# Show pop-up window
@pop_up_bg_bitmap.visible = true
bg_bitmap = create_pop_up_window(GRAPHIC_CHOOSER_WINDOW_WIDTH - 24, GRAPHIC_CHOOSER_WINDOW_HEIGHT)
text = _INTL("Choose a file...")
text_size = bg_bitmap.bitmap.text_size(text)
bg_bitmap.bitmap.draw_text(MESSAGE_BOX_SPACING, 11, bg_bitmap.width, text_size.height, text, 0)
# Create list of files
list = UIControls::List.new(GRAPHIC_CHOOSER_FILE_LIST_WIDTH, GRAPHIC_CHOOSER_FILE_LIST_HEIGHT, @pop_up_viewport, files)
list.x = bg_bitmap.x + MESSAGE_BOX_SPACING
list.y = bg_bitmap.y + MESSAGE_BOX_SPACING + 24
# Set control values
list.values = files
list.selected = idx
list.set_interactive_rects
list.repaint
bg_bitmap.bitmap.outline_rect(MESSAGE_BOX_SPACING - 2, MESSAGE_BOX_SPACING + 24 - 2,
GRAPHIC_CHOOSER_FILE_LIST_WIDTH + 4, GRAPHIC_CHOOSER_FILE_LIST_HEIGHT + 4, Color.black)
# Create buttons
buttons = []
[[:ok, _INTL("OK")], [:cancel, _INTL("Cancel")]].each_with_index do |option, i|
btn = UIControls::Button.new(GRAPHIC_CHOOSER_BUTTON_WIDTH, MESSAGE_BOX_BUTTON_HEIGHT, @pop_up_viewport, option[1])
btn.x = list.x + (GRAPHIC_CHOOSER_BUTTON_WIDTH * i)
btn.y = list.y + list.height + 2
btn.set_fixed_size
btn.set_interactive_rects
buttons.push([option[0], btn])
end
# Create audio player controls
[[:volume, _INTL("Volume"), 0, 100], [:pitch, _INTL("Pitch"), 0, 200]].each_with_index do |option, i|
label = UIControls::Label.new(90, 28, @pop_up_viewport, option[1])
label.x = list.x + list.width + 8
label.y = list.y + (28 * i)
label.set_interactive_rects
buttons.push([(option[0].to_s + "_label").to_sym, label])
slider = UIControls::NumberSlider.new(250, 28, @pop_up_viewport, option[2], option[3], (i == 0 ? volume : pitch))
slider.x = list.x + list.width + 8 + label.width
slider.y = list.y + (28 * i)
slider.set_interactive_rects
buttons.push([option[0], slider])
end
[[:play, _INTL("Play")], [:stop, _INTL("Stop")]].each_with_index do |option, i|
btn = UIControls::Button.new(GRAPHIC_CHOOSER_BUTTON_WIDTH, MESSAGE_BOX_BUTTON_HEIGHT, @pop_up_viewport, option[1])
btn.x = list.x + list.width + 8 + (GRAPHIC_CHOOSER_BUTTON_WIDTH * i)
btn.y = list.y + (28 * 2)
btn.set_fixed_size
btn.set_interactive_rects
buttons.push([option[0], btn])
end
audio_chooser.get_control(:volume).value = volume
audio_chooser.get_control(:pitch).value = pitch
# Interaction loop
ret = nil
captured = nil
cancel = false
loop do
Graphics.update
Input.update
if captured
captured.update
captured = nil if !captured.busy?
else
list.update
captured = list if list.busy?
buttons.each do |btn|
btn[1].update
captured = btn[1] if btn[1].busy?
audio_chooser.update
if audio_chooser.changed?
audio_chooser.values.each_pair do |ctrl, value|
case ctrl
when :ok
ret = list.value
when :cancel
ret = selected
cancel = true
when :play
vol = audio_chooser.get_control(:volume).value
ptch = audio_chooser.get_control(:pitch).value
# TODO: Play appropriate things if a cry is selected. See which
# battlers are defined in the editor's settings, and use their
# cries.
pbSEPlay(RPG::AudioFile.new("Anim/" + list.value, vol, ptch))
when :stop
pbSEStop
end
audio_chooser.clear_changed
end
end
buttons.each do |btn|
next if !btn[1].changed?
case btn[0]
when :ok
ret = list.value
when :cancel
if !audio_chooser.busy? && Input.trigger?(Input::BACK)
ret = selected
when :play
vol = buttons.select { |b| b[0] == :volume }[0][1].value
ptch = buttons.select { |b| b[0] == :pitch }[0][1].value
# TODO: Play appropriate things if a cry is selected.
pbSEPlay(RPG::AudioFile.new("Anim/" + list.value, vol, ptch))
when :stop
pbSEStop
cance = true
end
btn[1].clear_changed
break
break if ret
audio_chooser.repaint
end
ret = selected if Input.trigger?(Input::BACK)
break if ret
list.repaint
buttons.each { |btn| btn[1].repaint }
end
vol = buttons.select { |b| b[0] == :volume }[0][1].value
ptch = buttons.select { |b| b[0] == :pitch }[0][1].value
vol = (cancel) ? volume : audio_chooser.get_control(:volume).value
ptch = (cancel) ? pitch : audio_chooser.get_control(:pitch).value
# Dispose and return
list.dispose
buttons.each { |btn| btn[1].dispose }
buttons.clear
bg_bitmap.dispose
@pop_up_bg_bitmap.visible = false
audio_chooser.clear_changed
audio_chooser.visible = false
return [ret, vol, ptch]
end
@@ -352,9 +281,9 @@ class AnimationEditor
@pop_up_bg_bitmap.visible = true
bg_bitmap = create_pop_up_window(ANIM_PROPERTIES_WIDTH, ANIM_PROPERTIES_HEIGHT)
# TODO: Draw box around list control(s), i.e. flags.
@components[:animation_properties].visible = true
# Set control values
anim_properties = @components[:animation_properties]
anim_properties.visible = true
# Set control values
case @anim[:type]
when :move, :opp_move
anim_properties.get_control(:type).value = :move
@@ -371,7 +300,6 @@ class AnimationEditor
refresh_component(:animation_properties) # This sets the :move control's value
# Interaction loop
ret = nil
captured = nil
loop do
Graphics.update
Input.update

View File

@@ -66,11 +66,11 @@ class AnimationEditor::AnimationSelector
btn.set_fixed_size
@components.add_control_at(val[0], btn, TYPE_BUTTONS_X, TYPE_BUTTONS_Y + (i * TYPE_BUTTON_HEIGHT))
end
# TODO: Filter text box for :moves_list's contents. Applies the filter upon
# every change to the text box's value. Perhaps it should only do so
# after 0.5 seconds of non-typing. What exactly should the filter be
# applied to? Animation's name, move's name (if there is one), what
# else?
# TODO: Add filter text box for :moves_list's contents. Applies the filter
# upon every change to the text box's value. Perhaps it should only do
# so after 0.5 seconds of non-typing. What exactly should the filter
# be applied to? Animation's name, move's name (if there is one), what
# else? Flags?
# Moves list label
label = UIControls::Label.new(MOVES_LIST_WIDTH, TYPE_BUTTON_HEIGHT, @viewport, _INTL("Moves"))
label.header = true
@@ -190,7 +190,11 @@ class AnimationEditor::AnimationSelector
@quit = true
return # Don't need to refresh the screen
when :new
# TODO: New animation.
# TODO: New animation. Create a new animation hash with some default
# contents, go into the edit screen and immediately open the
# animation properties pop-up window. Use the first available ID
# number from GameData::Animation for it. Don't register the
# animation hash here, though.
when :moves
@animation_type = 0
@components.get_control(:moves_list).selected = -1
@@ -204,19 +208,17 @@ class AnimationEditor::AnimationSelector
if anim_id
screen = AnimationEditor.new(anim_id, GameData::Animation.get(anim_id).clone_as_hash)
screen.run
# TODO: Might want to select whichever options in each list get to
# the animation with ID anim_id.
generate_lists
end
when :copy
anim_id = selected_animation_id
if anim_id
# TODO: Copy animation.
# TODO: Copy animation. Append "(copy)" to its name.
end
when :delete
anim_id = selected_animation_id
if anim_id
# TODO: Delete animation.
# TODO: Delete animation. Ask the user if they're sure.
end
end
refresh

View File

@@ -146,7 +146,6 @@ module AnimationEditor::ParticleDataHelper
if cmd[1] > 0 # MoveXYZ
dur = cmd[1]
dur *= -1 if cmd[2] < val
# TODO: Support multiple interpolation types here (will be cmd[3]).
ret[cmd[0]] = [dur, cmd[3] || :linear]
ret[cmd[0] + cmd[1]] = 0
else # SetXYZ

View File

@@ -7,7 +7,6 @@ class AnimationEditor::Canvas < Sprite
def initialize(viewport)
super
@bg_val = ""
# TODO: Add a second bg sprite for screen shake purposes.
player_base_pos = Battle::Scene.pbBattlerPosition(0)
@player_base = IconSprite.new(*player_base_pos, viewport)
@player_base.z = 1
@@ -28,8 +27,9 @@ class AnimationEditor::Canvas < Sprite
def bg_name=(val)
return if @bg_name == val
@bg_name = val
# TODO: Come up with a better way to define the base filenames, based on
# which files actually exist.
# 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

View File

@@ -2,8 +2,6 @@
# TODO
#===============================================================================
class AnimationEditor::PlayControls < UIControls::BaseControl
TEXT_OFFSET_Y = 5
def initialize(x, y, width, height, viewport)
super(width, height, viewport)
self.x = x

View File

@@ -1,8 +1,5 @@
#===============================================================================
# TODO: Would be nice to make command sprites wider than their viewport and
# change @commands_viewport's ox to @left_pos, similar to how the vertical
# scrollbar works, i.e. every visible @commands_sprites isn't redrawn each
# time the horizontal scrollbar changes.
#
#===============================================================================
class AnimationEditor::ParticleList < UIControls::BaseControl
VIEWPORT_SPACING = 1
@@ -247,8 +244,6 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
#-----------------------------------------------------------------------------
def calculate_duration
# TODO: Refresh lots of things if the duration changed (e.g. SE command
# line).
@duration = AnimationEditor::ParticleDataHelper.get_duration(@particles)
@duration += DURATION_BUFFER
end
@@ -269,7 +264,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
end
def calculate_commands_for_particle(index)
# TODO: Delete everything from @commands that includes index.
@commands.delete_if { |cmd| cmd == index || (cmd.is_a?(Array) && cmd[0] == index) }
overall_commands = []
@particles[index].each_pair do |property, value|
next if !value.is_a?(Array)
@@ -290,8 +285,6 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
# Returns whether the sprites need replacing due to the addition or
# subtraction of one.
def ensure_sprites
# TODO: Check through @particle_list to ensure only ones are shown which
# correspond to something in @particles.
# Go through all @particles to ensure there are sprites for each of them
missing = false
@particles.each_with_index do |particle, index|
@@ -379,7 +372,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
def property_display_name(property)
return {
:frame => _INTL("Graphic frame"),
:frame => _INTL("Frame"),
:blending => _INTL("Blending"),
:flip => _INTL("Flip"),
:x => _INTL("X"),
@@ -438,7 +431,9 @@ class AnimationEditor::ParticleList < UIControls::BaseControl
end
end
# TODO: Add indicator that this is selected (if so).
# TODO: Add indicator that this is selected (if so). Some kind of arrow on the
# left, or a red horizontal line (like the keyframe's vertical line), or
# fill_rect with colour instead of outline_rect?
def refresh_particle_list_sprite(index)
spr = @list_sprites[index]
return if !spr

View File

@@ -1,9 +1,5 @@
#===============================================================================
# TODO: Ideally the menu buttons (add_button) will be replaced by a proper
# menu control (basically multiple DropdownList controls where the headers
# have fixed names and, while captured, hovering over a header changes
# which list is displayed). The menu control should go under UI controls
# rather than be unique to the Animation Editor.
#
#===============================================================================
class AnimationEditor::MenuBar < UIControls::ControlsContainer
MENU_BUTTON_WIDTH = 80

View File

@@ -109,4 +109,4 @@ Name = Attract
SetY = 17,-17
SetOpacity = 17,64
<SE>
Play = 0,infatuated,100,100
Play = 0,infatuated

View File

@@ -40,6 +40,6 @@ Name = Bind
SetX = 6,216
SetX = 7,264
<SE>
Play = 0,Slash10,80,100
Play = 3,Slash10,80,100
Play = 6,Slash10,80,100
Play = 0,Slash10,80
Play = 3,Slash10,80
Play = 6,Slash10,80

View File

@@ -16,4 +16,4 @@ Name = Burn
SetZoomX = 0,200
SetZoomY = 0,200
<SE>
Play = 0,Fire2,80,100
Play = 0,Fire2,80

View File

@@ -45,4 +45,4 @@ Name = Confusion
SetY = 17,39
SetOpacity = 17,154
<SE>
Play = 0,throw,80,100
Play = 0,throw,80

View File

@@ -109,4 +109,4 @@ Name = FireSpin
SetX = 5,415
SetY = 5,138
<SE>
Play = 0,throw,80,100
Play = 0,throw,80

View File

@@ -58,4 +58,4 @@ Name = Frozen
SetY = 14,134
SetOpacity = 14,255
<SE>
Play = 0,Ice5,80,100
Play = 0,Ice5,80

View File

@@ -30,6 +30,6 @@ Name = HealthUp
SetX = 11,344
SetY = 11,70
<SE>
Play = 0,Recovery,75,100
Play = 2,Recovery,80,100
Play = 5,Recovery,80,100
Play = 0,Recovery,75
Play = 2,Recovery,80
Play = 5,Recovery,80

View File

@@ -50,4 +50,4 @@ Name = Paralysis
SetX = 10,448
SetX = 11,312
<SE>
Play = 0,Paralyze3,80,100
Play = 0,Paralyze3,80

View File

@@ -18,4 +18,4 @@ Name = ParentalBond
SetOpacity = 8,150
SetOpacity = 9,100
<SE>
Play = 0,Blow1,80,100
Play = 0,Blow1,80

View File

@@ -14,4 +14,4 @@ Name = Poison
SetX = 1,384
SetY = 1,86
<SE>
Play = 0,Poison,80,100
Play = 0,Poison,80

View File

@@ -63,4 +63,4 @@ Name = Shadow
SetX = 10,416
SetY = 10,118
<SE>
Play = 0,Saint6,75,100
Play = 0,Saint6,75

View File

@@ -63,4 +63,4 @@ Name = Shiny
SetX = 10,416
SetY = 10,118
<SE>
Play = 0,Shiny sparkle,100,100
Play = 0,Shiny sparkle

View File

@@ -64,4 +64,4 @@ Name = Sleep
SetX = 10,309
SetY = 10,25
<SE>
Play = 0,Sleep,80,100
Play = 0,Sleep,80

View File

@@ -131,4 +131,4 @@ Name = StatDown
SetY = 2,58
SetOpacity = 2,126
<SE>
Play = 0,decrease,100,100
Play = 0,decrease

View File

@@ -102,4 +102,4 @@ Name = StatUp
SetY = 9,154
SetOpacity = 9,0
<SE>
Play = 0,increase,100,100
Play = 0,increase

View File

@@ -8,21 +8,6 @@ Name = SuperShiny
<Target>
SetX = 0,384
SetY = 0,96
<Particle 3>
Graphic = leech-seed
Focus = Target
SetX = 2,440
SetY = 2,126
SetX = 4,327
SetY = 4,78
SetX = 6,366
SetY = 6,129
SetX = 7,416
SetY = 7,54
SetX = 8,368
SetY = 8,67
SetX = 9,416
SetY = 9,118
<Particle 4>
Graphic = leech-seed
Focus = Target
@@ -62,5 +47,20 @@ Name = SuperShiny
SetY = 9,67
SetX = 10,416
SetY = 10,118
<Particle 3>
Graphic = leech-seed
Focus = Target
SetX = 2,440
SetY = 2,126
SetX = 4,327
SetY = 4,78
SetX = 6,366
SetY = 6,129
SetX = 7,416
SetY = 7,54
SetX = 8,368
SetY = 8,67
SetX = 9,416
SetY = 9,118
<SE>
Play = 0,Shiny sparkle,100,100
Play = 0,Shiny sparkle

View File

@@ -40,6 +40,6 @@ Name = Wrap
SetX = 6,216
SetX = 7,264
<SE>
Play = 0,Slash10,80,100
Play = 3,Slash10,80,100
Play = 6,Slash10,80,100
Play = 0,Slash10,80
Play = 3,Slash10,80
Play = 6,Slash10,80

View File

@@ -173,9 +173,9 @@ Name = ABSORB
SetX = 5,364
SetY = 5,98
<SE>
Play = 0,Absorb2,80,100
Play = 0,Absorb2,80,100
Play = 2,Absorb2,80,100
Play = 5,Absorb2,80,100
Play = 7,Absorb2,80,100
Play = 8,Saint7,80,100
Play = 0,Absorb2,80
Play = 0,Absorb2,80
Play = 2,Absorb2,80
Play = 5,Absorb2,80
Play = 7,Absorb2,80
Play = 8,Saint7,80

View File

@@ -46,5 +46,5 @@ Name = ACID
SetY = 4,110
SetOpacity = 12,100
<SE>
Play = 0,throw,80,100
Play = 3,Poison,80,100
Play = 0,throw,80
Play = 3,Poison,80

View File

@@ -18,6 +18,6 @@ Name = ACIDARMOR
SetX = 5,392
SetY = 6,78
<SE>
Play = 0,throw,80,100
Play = 0,Sound2,80,100
Play = 0,Pollen,80,100
Play = 0,throw,80
Play = 0,Sound2,80
Play = 0,Pollen,80

View File

@@ -124,4 +124,4 @@ Name = ACIDSPRAY
SetZoomY = 5,85
SetAngle = 5,180
<SE>
Play = 0,Substitute,80,100
Play = 0,Substitute,80

View File

@@ -85,4 +85,4 @@ Name = ACUPRESSURE
SetX = 8,395
SetY = 8,80
<SE>
Play = 0,Acupressure,100,100
Play = 0,Acupressure

View File

@@ -206,7 +206,7 @@ Name = AERIALACE
SetX = 9,487
SetY = 9,62
<SE>
Play = 0,Ace,80,100
Play = 0,Ace,80
#-------------------------------
[OppMove,AERIALACE]
Name = AERIALACE
@@ -352,4 +352,4 @@ Name = AERIALACE
SetX = 8,211
SetY = 8,284
<SE>
Play = 0,Ace,80,100
Play = 0,Ace,80

View File

@@ -48,4 +48,4 @@ Name = ALLYSWITCH
SetOpacity = 18,42
SetOpacity = 19,0
<SE>
Play = 0,Uproar,100,100
Play = 0,Uproar

View File

@@ -18,4 +18,4 @@ Name = AMNESIA
SetOpacity = 2,250
SetOpacity = 3,255
<SE>
Play = 0,Yawn,100,100
Play = 0,Yawn

View File

@@ -300,5 +300,5 @@ Name = ANCIENTPOWER
SetX = 28,432
SetY = 28,136
<SE>
Play = 0,Earth4,100,100
Play = 24,Earth5,100,100
Play = 0,Earth4
Play = 24,Earth5

View File

@@ -58,4 +58,4 @@ Name = AQUARING
SetX = 5,394
SetY = 5,104
<SE>
Play = 0,Weatherball,80,100
Play = 0,Weatherball,80

View File

@@ -143,4 +143,4 @@ Name = AROMATHERAPY
SetY = 5,-26
SetX = 6,368
<SE>
Play = 0,Saint8,80,100
Play = 0,Saint8,80

View File

@@ -214,5 +214,5 @@ Name = AURORABEAM
SetZoomX = 4,50
SetZoomY = 4,50
<SE>
Play = 1,Twine,80,100
Play = 10,Fire3,80,100
Play = 1,Twine,80
Play = 10,Fire3,80

View File

@@ -51,4 +51,4 @@ Name = BARRIER
SetX = 9,379
SetY = 9,85
<SE>
Play = 0,Flash2,80,100
Play = 0,Flash2,80

View File

@@ -34,7 +34,7 @@ Name = BEATUP
SetZoomY = 3,125
SetOpacity = 3,50
<SE>
Play = 0,Blow4,80,100
Play = 0,Blow4,80
#-------------------------------
[Move,BEATUP,1]
Name = Beat Up hit 2
@@ -70,7 +70,7 @@ Name = Beat Up hit 2
SetZoomY = 3,125
SetOpacity = 3,100
<SE>
Play = 0,Blow4,80,100
Play = 0,Blow4,80
#-------------------------------
[Move,BEATUP,2]
Name = Beat Up hit 3
@@ -106,7 +106,7 @@ Name = Beat Up hit 3
SetZoomY = 3,125
SetOpacity = 3,50
<SE>
Play = 0,Blow4,80,100
Play = 0,Blow4,80
#-------------------------------
[Move,BEATUP,3]
Name = Beat Up hit 4
@@ -142,7 +142,7 @@ Name = Beat Up hit 4
SetZoomY = 3,125
SetOpacity = 3,100
<SE>
Play = 0,Blow4,80,100
Play = 0,Blow4,80
#-------------------------------
[Move,BEATUP,4]
Name = Beat Up hit 5
@@ -178,7 +178,7 @@ Name = Beat Up hit 5
SetZoomY = 3,125
SetOpacity = 3,50
<SE>
Play = 0,Blow4,80,100
Play = 0,Blow4,80
#-------------------------------
[Move,BEATUP,5]
Name = Beat Up hit 6
@@ -214,4 +214,4 @@ Name = Beat Up hit 6
SetZoomY = 3,125
SetOpacity = 3,100
<SE>
Play = 0,Blow4,80,100
Play = 0,Blow4,80

View File

@@ -40,6 +40,6 @@ Name = BIND
SetX = 6,216
SetX = 7,264
<SE>
Play = 0,Slash10,80,100
Play = 3,Slash10,80,100
Play = 6,Slash10,80,100
Play = 0,Slash10,80
Play = 3,Slash10,80
Play = 6,Slash10,80

View File

@@ -20,4 +20,4 @@ Name = BITE
SetOpacity = 3,255
SetOpacity = 13,128
<SE>
Play = 9,Sword2,80,100
Play = 9,Sword2,80

View File

@@ -196,4 +196,4 @@ Name = BLASTBURN
SetX = 10,339
SetY = 10,179
<SE>
Play = 3,Fire2,80,100
Play = 3,Fire2,80

View File

@@ -14,4 +14,4 @@ Name = BLOCK
SetX = 0,385
SetY = 0,96
<SE>
Play = 0,buzzer,80,100
Play = 0,buzzer,80

View File

@@ -14,4 +14,4 @@ Name = BODYSLAM
SetX = 0,384
SetY = 0,94
<SE>
Play = 0,Damage1,80,100
Play = 0,Damage1,80

View File

@@ -32,4 +32,4 @@ Name = BRICKBREAK
SetX = 7,440
SetY = 7,166
<SE>
Play = 4,Blow7,80,100
Play = 4,Blow7,80

View File

@@ -207,4 +207,4 @@ Name = BUBBLE
SetY = 8,91
SetOpacity = 8,100
<SE>
Play = 0,Water5,80,100
Play = 0,Water5,80

View File

@@ -369,9 +369,9 @@ Name = BUBBLEBEAM
SetX = 10,153
SetY = 10,217
<SE>
Play = 0,Water5,80,100
Play = 3,Blow1,80,100
Play = 7,Blow1,80,100
Play = 9,Blow1,80,100
Play = 11,Blow1,80,100
Play = 13,Blow1,80,100
Play = 0,Water5,80
Play = 3,Blow1,80
Play = 7,Blow1,80
Play = 9,Blow1,80
Play = 11,Blow1,80
Play = 13,Blow1,80

View File

@@ -92,13 +92,13 @@ Name = BULLETSEED
SetX = 6,256
SetY = 6,161
<SE>
Play = 0,throw,80,100
Play = 2,throw,80,100
Play = 5,throw,80,100
Play = 5,Knock,80,100
Play = 7,Knock,80,100
Play = 8,throw,80,100
Play = 9,Knock,80,100
Play = 0,throw,80
Play = 2,throw,80
Play = 5,throw,80
Play = 5,Knock,80
Play = 7,Knock,80
Play = 8,throw,80
Play = 9,Knock,80
#-------------------------------
[Move,BULLETSEED,1]
Name = Bullet Seed hit 2
@@ -192,13 +192,13 @@ Name = Bullet Seed hit 2
SetY = 6,129
SetX = 7,313
<SE>
Play = 0,throw,80,100
Play = 2,throw,80,100
Play = 5,throw,80,100
Play = 5,Knock,80,100
Play = 7,Knock,80,100
Play = 8,throw,80,100
Play = 9,Knock,80,100
Play = 0,throw,80
Play = 2,throw,80
Play = 5,throw,80
Play = 5,Knock,80
Play = 7,Knock,80
Play = 8,throw,80
Play = 9,Knock,80
#-------------------------------
[Move,BULLETSEED,2]
Name = Bullet Seed hit 3
@@ -292,13 +292,13 @@ Name = Bullet Seed hit 3
SetX = 7,364
SetY = 8,110
<SE>
Play = 0,throw,80,100
Play = 2,throw,80,100
Play = 5,throw,80,100
Play = 5,Knock,80,100
Play = 7,Knock,80,100
Play = 8,throw,80,100
Play = 9,Knock,80,100
Play = 0,throw,80
Play = 2,throw,80
Play = 5,throw,80
Play = 5,Knock,80
Play = 7,Knock,80
Play = 8,throw,80
Play = 9,Knock,80
#-------------------------------
[Move,BULLETSEED,3]
Name = Bullet Seed hit 4
@@ -392,13 +392,13 @@ Name = Bullet Seed hit 4
SetX = 9,364
SetY = 9,79
<SE>
Play = 0,throw,80,100
Play = 2,throw,80,100
Play = 5,throw,80,100
Play = 5,Knock,80,100
Play = 7,Knock,80,100
Play = 8,throw,80,100
Play = 9,Knock,80,100
Play = 0,throw,80
Play = 2,throw,80
Play = 5,throw,80
Play = 5,Knock,80
Play = 7,Knock,80
Play = 8,throw,80
Play = 9,Knock,80
#-------------------------------
[Move,BULLETSEED,4]
Name = Bullet Seed hit 5
@@ -492,10 +492,10 @@ Name = Bullet Seed hit 5
SetX = 10,352
SetY = 10,47
<SE>
Play = 0,throw,80,100
Play = 2,throw,80,100
Play = 5,throw,80,100
Play = 5,Knock,80,100
Play = 7,Knock,80,100
Play = 8,throw,80,100
Play = 9,Knock,80,100
Play = 0,throw,80
Play = 2,throw,80
Play = 5,throw,80
Play = 5,Knock,80
Play = 7,Knock,80
Play = 8,throw,80
Play = 9,Knock,80

View File

@@ -92,8 +92,8 @@ Name = CHARGE
SetX = 7,176
SetY = 7,286
<SE>
Play = 0,Thunder3,80,100
Play = 2,Thunder3,80,100
Play = 4,Thunder3,80,100
Play = 5,Thunder3,80,100
Play = 7,Thunder3,80,100
Play = 0,Thunder3,80
Play = 2,Thunder3,80
Play = 4,Thunder3,80
Play = 5,Thunder3,80
Play = 7,Thunder3,80

View File

@@ -22,4 +22,4 @@ Name = CLEARSMOG
SetY = 5,101
SetX = 6,382
<SE>
Play = 0,Snore,86,100
Play = 0,Snore,86

View File

@@ -29,9 +29,9 @@ Name = COMETPUNCH
SetX = 6,432
SetY = 6,110
<SE>
Play = 0,Blow1,80,100
Play = 2,Blow1,80,100
Play = 5,Blow1,80,100
Play = 0,Blow1,80
Play = 2,Blow1,80
Play = 5,Blow1,80
#-------------------------------
[Move,COMETPUNCH,1]
Name = Comet Punch hit 2
@@ -62,9 +62,9 @@ Name = Comet Punch hit 2
SetX = 5,432
SetY = 5,110
<SE>
Play = 0,Blow1,80,100
Play = 2,Blow1,80,100
Play = 5,Blow1,80,100
Play = 0,Blow1,80
Play = 2,Blow1,80
Play = 5,Blow1,80
#-------------------------------
[Move,COMETPUNCH,2]
Name = Comet Punch hit 3
@@ -95,9 +95,9 @@ Name = Comet Punch hit 3
SetX = 6,432
SetY = 6,110
<SE>
Play = 0,Blow1,80,100
Play = 2,Blow1,80,100
Play = 5,Blow1,80,100
Play = 0,Blow1,80
Play = 2,Blow1,80
Play = 5,Blow1,80
#-------------------------------
[Move,COMETPUNCH,3]
Name = Comet Punch hit 4
@@ -128,9 +128,9 @@ Name = Comet Punch hit 4
SetX = 5,432
SetY = 5,110
<SE>
Play = 0,Blow1,80,100
Play = 2,Blow1,80,100
Play = 5,Blow1,80,100
Play = 0,Blow1,80
Play = 2,Blow1,80
Play = 5,Blow1,80
#-------------------------------
[Move,COMETPUNCH,4]
Name = Comet Punch hit 5
@@ -161,6 +161,6 @@ Name = Comet Punch hit 5
SetX = 6,432
SetY = 6,110
<SE>
Play = 0,Blow1,80,100
Play = 2,Blow1,80,100
Play = 5,Blow1,80,100
Play = 0,Blow1,80
Play = 2,Blow1,80
Play = 5,Blow1,80

View File

@@ -47,5 +47,5 @@ Name = CONFUSERAY
SetY = 16,110
SetOpacity = 17,100
<SE>
Play = 1,Twine,80,100
Play = 12,Confuse,80,100
Play = 1,Twine,80
Play = 12,Confuse,80

View File

@@ -78,4 +78,4 @@ Name = COTTONGUARD
SetX = 4,129
SetY = 4,237
<SE>
Play = 0,Substitute,80,100
Play = 0,Substitute,80

View File

@@ -14,4 +14,4 @@ Name = COTTONSPORE
SetX = 0,384
SetY = 0,94
<SE>
Play = 0,Sand,80,100
Play = 0,Sand,80

View File

@@ -121,4 +121,4 @@ Name = COUNTER
SetX = 5,399
SetY = 5,92
<SE>
Play = 0,MiningCollapse,80,100
Play = 0,MiningCollapse,80

View File

@@ -19,4 +19,4 @@ Name = CURSE
SetY = 3,78
SetX = 4,384
<SE>
Play = 2,Darkness6,80,100
Play = 2,Darkness6,80

View File

@@ -14,6 +14,6 @@ Name = CUT
SetX = 0,384
SetY = 0,94
<SE>
Play = 0,Slash10,80,100
Play = 3,Slash2,80,100
Play = 6,Slash11,80,100
Play = 0,Slash10,80
Play = 3,Slash2,80
Play = 6,Slash11,80

View File

@@ -30,4 +30,4 @@ Name = DEFENSECURL
SetX = 6,132
SetOpacity = 6,233
<SE>
Play = 0,Defense Curl,100,100
Play = 0,Defense Curl

View File

@@ -181,4 +181,4 @@ Name = DIZZYPUNCH
SetX = 8,447
SetY = 8,64
<SE>
Play = 0,Dizzy Punch,100,100
Play = 0,Dizzy Punch

View File

@@ -41,5 +41,5 @@ Name = DOUBLEEDGE
SetX = 10,352
SetAngle = 10,90
<SE>
Play = 0,throw,80,100
Play = 6,Damage1,80,100
Play = 0,throw,80
Play = 6,Damage1,80

View File

@@ -31,8 +31,8 @@ Name = DOUBLEKICK
SetZoomY = 2,110
SetOpacity = 2,100
<SE>
Play = 1,Blow3,80,100
Play = 3,Blow3,80,100
Play = 1,Blow3,80
Play = 3,Blow3,80
#-------------------------------
[Move,DOUBLEKICK,1]
Name = Double Kick hit 2
@@ -65,5 +65,5 @@ Name = Double Kick hit 2
SetY = 3,78
SetOpacity = 5,100
<SE>
Play = 1,Blow3,80,100
Play = 3,Blow3,80,100
Play = 1,Blow3,80
Play = 3,Blow3,80

View File

@@ -30,8 +30,8 @@ Name = DOUBLESLAP
SetX = 7,384
SetOpacity = 8,100
<SE>
Play = 3,Blow5,80,100
Play = 7,Blow5,80,100
Play = 3,Blow5,80
Play = 7,Blow5,80
#-------------------------------
[Move,DOUBLESLAP,1]
Name = DoubleSlap hit 2
@@ -63,8 +63,8 @@ Name = DoubleSlap hit 2
SetX = 7,384
SetOpacity = 7,255
<SE>
Play = 3,Blow5,80,100
Play = 7,Blow5,80,100
Play = 3,Blow5,80
Play = 7,Blow5,80
#-------------------------------
[Move,DOUBLESLAP,2]
Name = DoubleSlap hit 3
@@ -96,8 +96,8 @@ Name = DoubleSlap hit 3
SetX = 7,384
SetOpacity = 8,100
<SE>
Play = 3,Blow5,80,100
Play = 7,Blow5,80,100
Play = 3,Blow5,80
Play = 7,Blow5,80
#-------------------------------
[Move,DOUBLESLAP,3]
Name = DoubleSlap hit 4
@@ -129,8 +129,8 @@ Name = DoubleSlap hit 4
SetX = 7,384
SetOpacity = 7,255
<SE>
Play = 3,Blow5,80,100
Play = 7,Blow5,80,100
Play = 3,Blow5,80
Play = 7,Blow5,80
#-------------------------------
[Move,DOUBLESLAP,4]
Name = DoubleSlap hit 5
@@ -162,5 +162,5 @@ Name = DoubleSlap hit 5
SetX = 7,384
SetOpacity = 8,100
<SE>
Play = 3,Blow5,80,100
Play = 7,Blow5,80,100
Play = 3,Blow5,80
Play = 7,Blow5,80

View File

@@ -101,4 +101,4 @@ Name = DRAGONBREATH
SetZoomX = 3,75
SetZoomY = 3,75
<SE>
Play = 0,Fire4,80,100
Play = 0,Fire4,80

View File

@@ -18,5 +18,5 @@ Name = DRAGONCLAW
SetY = 2,102
SetAngle = 2,0
<SE>
Play = 0,Slash9,80,100
Play = 0,Thunder4,80,100
Play = 0,Slash9,80
Play = 0,Thunder4,80

View File

@@ -23,4 +23,4 @@ Name = DRAGONDANCE
SetY = 9,94
SetOpacity = 12,100
<SE>
Play = 0,Twine,80,100
Play = 0,Twine,80

View File

@@ -57,4 +57,4 @@ Name = DRAGONRAGE
SetX = 5,358
SetY = 5,110
<SE>
Play = 0,Fire6,80,100
Play = 0,Fire6,80

View File

@@ -43,4 +43,4 @@ Name = EMBER
SetY = 10,116
SetFlip = 11,false
<SE>
Play = 1,Fire2,80,100
Play = 1,Fire2,80

View File

@@ -55,4 +55,4 @@ Name = ENCORE
SetX = 17,160
SetX = 18,128
<SE>
Play = 0,Applause,80,100
Play = 0,Applause,80

View File

@@ -66,7 +66,7 @@ Name = ERUPTION
SetX = 10,371
SetY = 10,123
<SE>
Play = 0,Fire5,80,100
Play = 0,Fire2,80,100
Play = 3,Fire2,80,100
Play = 6,Fire2,80,100
Play = 0,Fire5,80
Play = 0,Fire2,80
Play = 3,Fire2,80
Play = 6,Fire2,80

View File

@@ -56,7 +56,7 @@ Name = EXPLOSION
SetOpacity = 16,200
SetOpacity = 17,150
<SE>
Play = 0,Explosion3,80,100
Play = 2,Explosion7,80,100
Play = 5,Explosion3,80,100
Play = 8,Explosion2,80,100
Play = 0,Explosion3,80
Play = 2,Explosion7,80
Play = 5,Explosion3,80
Play = 8,Explosion2,80

View File

@@ -109,4 +109,4 @@ Name = FIERYDANCE
SetX = 7,351
SetY = 7,107
<SE>
Play = 0,Wring Out,80,100
Play = 0,Wring Out,80

View File

@@ -53,4 +53,4 @@ Name = FINALGAMBIT
SetX = 20,407
SetY = 20,108
<SE>
Play = 0,MiningCollapse,100,100
Play = 0,MiningCollapse

View File

@@ -32,4 +32,4 @@ Name = FIREPLEDGE
SetY = 6,98
SetY = 7,95
<SE>
Play = 0,Mega Punch,100,100
Play = 0,Mega Punch

View File

@@ -99,4 +99,4 @@ Name = FIREPUNCH
SetY = 11,115
<SE>
Play = 0,Slam,100,115
Play = 1,Explosion,100,100
Play = 1,Explosion

View File

@@ -34,4 +34,4 @@ Name = FIRESPIN
SetZoomY = 11,50
SetOpacity = 11,100
<SE>
Play = 0,Fire5,80,100
Play = 0,Fire5,80

View File

@@ -59,4 +59,4 @@ Name = FLAIL
SetX = 23,405
SetY = 23,95
<SE>
Play = 0,Flail,100,100
Play = 0,Flail

View File

@@ -14,4 +14,4 @@ Name = FLASH
SetX = 0,384
SetY = 0,94
<SE>
Play = 0,Saint7,80,100
Play = 0,Saint7,80

View File

@@ -57,4 +57,4 @@ Name = Fly charging
SetX = 7,134
SetY = 7,166
<SE>
Play = 0,Trump Card,100,100
Play = 0,Trump Card

View File

@@ -19,6 +19,6 @@ Name = FOCUSENERGY
SetX = 0,144
SetY = 0,222
<SE>
Play = 0,Up,80,100
Play = 3,Up,80,100
Play = 6,Up,80,100
Play = 0,Up,80
Play = 3,Up,80
Play = 6,Up,80

View File

@@ -83,4 +83,4 @@ Name = FOLLOWME
SetX = 11,388
SetY = 11,111
<SE>
Play = 0,Follow Me,80,100
Play = 0,Follow Me,80

View File

@@ -31,5 +31,5 @@ Name = FRENZYPLANT
SetY = 13,98
SetOpacity = 16,100
<SE>
Play = 0,Earth4,80,100
Play = 8,Earth5,80,100
Play = 0,Earth4,80
Play = 8,Earth5,80

View File

@@ -29,8 +29,8 @@ Name = FURYATTACK
SetX = 5,264
SetY = 5,146
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[Move,FURYATTACK,1]
Name = Fury Attack hit 2
@@ -61,8 +61,8 @@ Name = Fury Attack hit 2
SetX = 3,358
SetY = 3,110
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[Move,FURYATTACK,2]
Name = Fury Attack hit 3
@@ -93,8 +93,8 @@ Name = Fury Attack hit 3
SetX = 5,264
SetY = 5,146
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[Move,FURYATTACK,3]
Name = Fury Attack hit 4
@@ -125,8 +125,8 @@ Name = Fury Attack hit 4
SetX = 3,358
SetY = 3,110
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[Move,FURYATTACK,4]
Name = Fury Attack hit 5
@@ -157,8 +157,8 @@ Name = Fury Attack hit 5
SetX = 5,264
SetY = 5,146
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[OppMove,FURYATTACK]
Name = FURYATTACK
@@ -192,8 +192,8 @@ Name = FURYATTACK
SetY = 3,242
SetAngle = 3,0
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[OppMove,FURYATTACK,1]
Name = Fury Attack hit 2 opp
@@ -227,8 +227,8 @@ Name = Fury Attack hit 2 opp
SetX = 5,220
SetY = 5,197
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[OppMove,FURYATTACK,2]
Name = Fury Attack hit 3 opp
@@ -262,8 +262,8 @@ Name = Fury Attack hit 3 opp
SetY = 3,242
SetAngle = 3,0
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[OppMove,FURYATTACK,3]
Name = Fury Attack hit 4 opp
@@ -297,8 +297,8 @@ Name = Fury Attack hit 4 opp
SetX = 5,220
SetY = 5,197
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80
#-------------------------------
[OppMove,FURYATTACK,4]
Name = Fury Attack hit 5 opp
@@ -332,5 +332,5 @@ Name = Fury Attack hit 5 opp
SetY = 3,242
SetAngle = 3,0
<SE>
Play = 3,normaldamage,80,100
Play = 5,normaldamage,80,100
Play = 3,normaldamage,80
Play = 5,normaldamage,80

View File

@@ -14,4 +14,4 @@ Name = FURYCUTTER
SetX = 0,384
SetY = 0,86
<SE>
Play = 0,Slash10,80,100
Play = 0,Slash10,80

View File

@@ -131,7 +131,7 @@ Name = FURYSWIPES
SetX = 5,483
SetY = 5,143
<SE>
Play = 0,Fury Swipes,100,100
Play = 0,Fury Swipes
#-------------------------------
[Move,FURYSWIPES,1]
Name = Fury Swipes hit 2
@@ -264,7 +264,7 @@ Name = Fury Swipes hit 2
SetX = 5,483
SetY = 5,143
<SE>
Play = 0,Fury Swipes,100,100
Play = 0,Fury Swipes
#-------------------------------
[Move,FURYSWIPES,2]
Name = Fury Swipes hit 3
@@ -397,7 +397,7 @@ Name = Fury Swipes hit 3
SetX = 5,483
SetY = 5,143
<SE>
Play = 0,Fury Swipes,100,100
Play = 0,Fury Swipes
#-------------------------------
[Move,FURYSWIPES,3]
Name = Fury Swipes hit 4
@@ -530,7 +530,7 @@ Name = Fury Swipes hit 4
SetX = 5,483
SetY = 5,143
<SE>
Play = 0,Fury Swipes,100,100
Play = 0,Fury Swipes
#-------------------------------
[Move,FURYSWIPES,4]
Name = Fury Swipes hit 5
@@ -663,4 +663,4 @@ Name = Fury Swipes hit 5
SetX = 5,483
SetY = 5,143
<SE>
Play = 0,Fury Swipes,100,100
Play = 0,Fury Swipes

View File

@@ -96,4 +96,4 @@ Name = GASTROACID
SetY = 9,83
SetX = 10,365
<SE>
Play = 0,Sweet Scent,100,100
Play = 0,Sweet Scent

View File

@@ -150,7 +150,7 @@ Name = GIGADRAIN
SetX = 5,371
SetY = 5,135
<SE>
Play = 0,Absorb2,80,100
Play = 2,Absorb2,80,100
Play = 5,Absorb2,80,100
Play = 7,Absorb2,80,100
Play = 0,Absorb2,80
Play = 2,Absorb2,80
Play = 5,Absorb2,80
Play = 7,Absorb2,80

View File

@@ -34,4 +34,4 @@ Name = GLARE
SetY = 3,90
SetX = 4,420
<SE>
Play = 0,Scary Face,80,100
Play = 0,Scary Face,80

View File

@@ -60,7 +60,7 @@ Name = GROWL
SetX = 7,230
SetY = 7,167
<SE>
PlayUserCry = 0,100,100
PlayUserCry = 0
#-------------------------------
[OppMove,GROWL]
Name = GROWL
@@ -123,4 +123,4 @@ Name = GROWL
SetX = 6,296
SetX = 7,281
<SE>
PlayUserCry = 0,100,100
PlayUserCry = 0

View File

@@ -159,4 +159,4 @@ Name = GRUDGE
SetX = 11,392
SetY = 11,134
<SE>
Play = 0,Fire1,80,100
Play = 0,Fire1,80

Some files were not shown because too many files have changed in this diff Show More