Refactored animation editor code into a single module

This commit is contained in:
Maruno17
2023-03-06 22:25:45 +00:00
parent ee72ad371f
commit 3a9199da1b
8 changed files with 3454 additions and 3435 deletions

View File

@@ -127,6 +127,16 @@ module Enumerable
end
end
#===============================================================================
# Collision testing
#===============================================================================
class Rect < Object
def contains?(cx, cy)
return cx >= self.x && cx < self.x + self.width &&
cy >= self.y && cy < self.y + self.height
end
end
#===============================================================================
# class File
#===============================================================================

View File

@@ -53,7 +53,7 @@ module GameData
extend ClassMethodsSymbols
include InstanceMethods
# @param other [Symbol, String, self]
# @param area [Symbol, String, self]
# @param version [Integer]
# @return [self]
def self.try_get(area, version = 0)

View File

@@ -1,3 +1,6 @@
module BattleAnimationEditor
module_function
#===============================================================================
# Controls
#===============================================================================
@@ -32,7 +35,7 @@ class Window_Menu < Window_CommandPokemon
rc = Rect.new(0, 32 * (i - toprow), self.contents.width, 32)
rc.x += self.x + self.leftEdge
rc.y += self.y + self.topEdge
return i if rc.contains(mousepos[0], mousepos[1])
return i if rc.contains?(mousepos[0], mousepos[1])
end
return -1
end
@@ -60,71 +63,9 @@ module Clipboard
end
end
#===============================================================================
# Collision testing
#===============================================================================
class Rect < Object
def contains(x, y)
return x >= self.x && x < self.x + self.width &&
y >= self.y && y < self.y + self.height
end
end
#===============================================================================
#
#===============================================================================
def pbSpriteHitTest(sprite, x, y, usealpha = true, wholecanvas = false)
return false if !sprite || sprite.disposed?
return false if !sprite.bitmap
return false if !sprite.visible
return false if sprite.bitmap.disposed?
width = sprite.src_rect.width
height = sprite.src_rect.height
if wholecanvas
xwidth = 0
xheight = 0
else
xwidth = width - 64
xheight = height - 64
width = 64 if width > 64 && !usealpha
height = 64 if height > 64 && !usealpha
end
width = sprite.bitmap.width if width > sprite.bitmap.width
height = sprite.bitmap.height if height > sprite.bitmap.height
if usealpha
spritex = sprite.x - (sprite.ox * sprite.zoom_x)
spritey = sprite.y - (sprite.oy * sprite.zoom_y)
width *= sprite.zoom_x
height *= sprite.zoom_y
else
spritex = sprite.x - sprite.ox
spritey = sprite.y - sprite.oy
spritex += xwidth / 2
spritey += xheight / 2
end
if !(x >= spritex && x <= spritex + width && y >= spritey && y <= spritey + height)
return false
end
if usealpha
# TODO: This should account for sprite.angle as well
bitmapX = sprite.src_rect.x
bitmapY = sprite.src_rect.y
bitmapX += sprite.ox
bitmapY += sprite.oy
bitmapX += (x - sprite.x) / sprite.zoom_x if sprite.zoom_x > 0
bitmapY += (y - sprite.y) / sprite.zoom_y if sprite.zoom_y > 0
bitmapX = bitmapX.round
bitmapY = bitmapY.round
if sprite.mirror
xmirror = bitmapX - sprite.src_rect.x
bitmapX = sprite.src_rect.x + 192 - xmirror
end
color = sprite.bitmap.get_pixel(bitmapX, bitmapY)
return false if color.alpha == 0
end
return true
end
def pbTrackPopupMenu(commands)
mousepos = Mouse.getMousePos
return -1 if !mousepos
@@ -262,14 +203,14 @@ class AnimationWindow < Sprite
swatchrects.push(Rect.new(arrowwidth + (i * 96) + self.x, self.y, 96, 96))
end
NUMFRAMES.times do |i|
next if !swatchrects[i].contains(mousepos[0], mousepos[1])
next if !swatchrects[i].contains?(mousepos[0], mousepos[1])
@selected = @start + i
@changed = true
refresh
return
end
# Left arrow
if left.contains(mousepos[0], mousepos[1])
if left.contains?(mousepos[0], mousepos[1])
if repeattime > 750
@start -= 3
else
@@ -279,7 +220,7 @@ class AnimationWindow < Sprite
refresh
end
# Right arrow
if right.contains(mousepos[0], mousepos[1])
if right.contains?(mousepos[0], mousepos[1])
if repeattime > 750
@start += 3
else
@@ -785,6 +726,58 @@ class AnimationCanvas < Sprite
return false
end
def pbSpriteHitTest(sprite, x, y, usealpha = true, wholecanvas = false)
return false if !sprite || sprite.disposed?
return false if !sprite.bitmap
return false if !sprite.visible
return false if sprite.bitmap.disposed?
width = sprite.src_rect.width
height = sprite.src_rect.height
if wholecanvas
xwidth = 0
xheight = 0
else
xwidth = width - 64
xheight = height - 64
width = 64 if width > 64 && !usealpha
height = 64 if height > 64 && !usealpha
end
width = sprite.bitmap.width if width > sprite.bitmap.width
height = sprite.bitmap.height if height > sprite.bitmap.height
if usealpha
spritex = sprite.x - (sprite.ox * sprite.zoom_x)
spritey = sprite.y - (sprite.oy * sprite.zoom_y)
width *= sprite.zoom_x
height *= sprite.zoom_y
else
spritex = sprite.x - sprite.ox
spritey = sprite.y - sprite.oy
spritex += xwidth / 2
spritey += xheight / 2
end
if !(x >= spritex && x <= spritex + width && y >= spritey && y <= spritey + height)
return false
end
if usealpha
# TODO: This should account for sprite.angle as well
bitmapX = sprite.src_rect.x
bitmapY = sprite.src_rect.y
bitmapX += sprite.ox
bitmapY += sprite.oy
bitmapX += (x - sprite.x) / sprite.zoom_x if sprite.zoom_x > 0
bitmapY += (y - sprite.y) / sprite.zoom_y if sprite.zoom_y > 0
bitmapX = bitmapX.round
bitmapY = bitmapY.round
if sprite.mirror
xmirror = bitmapX - sprite.src_rect.x
bitmapX = sprite.src_rect.x + 192 - xmirror
end
color = sprite.bitmap.get_pixel(bitmapX, bitmapY)
return false if color.alpha == 0
end
return true
end
def updateInput
cel = currentCel
mousepos = Mouse.getMousePos
@@ -840,7 +833,7 @@ class AnimationCanvas < Sprite
return
end
if Input.triggerex?(:P) || Input.repeatex?(:P) # Properties
pbCellProperties(self)
BattleAnimationEditor.pbCellProperties(self)
@dirty[@currentcel] = true
return
end
@@ -1016,3 +1009,4 @@ class AnimationNameWindow
def dispose; @window.dispose; end
def disposed; @window.disposed?; end
end
end

View File

@@ -1,3 +1,6 @@
module BattleAnimationEditor
module_function
#===============================================================================
#
#===============================================================================
@@ -128,12 +131,12 @@ class Button < UIControl
rect = Rect.new(self.x + 1, self.y + 1, self.width - 2, self.height - 2)
rect = toAbsoluteRect(rect)
if Input.trigger?(Input::MOUSELEFT) &&
rect.contains(mousepos[0], mousepos[1]) && !@captured
rect.contains?(mousepos[0], mousepos[1]) && !@captured
@captured = true
self.invalidate
end
if Input.release?(Input::MOUSELEFT) && @captured
self.changed = true if rect.contains(mousepos[0], mousepos[1])
self.changed = true if rect.contains?(mousepos[0], mousepos[1])
@captured = false
self.invalidate
end
@@ -217,7 +220,6 @@ class Checkbox < Button
shadowtext(bitmap, x + 36, y, size, height, self.label, @disabled)
# Draw outline
color = Color.new(120, 120, 120)
bitmap.fill_rect(x + 1, y + 1, width - 2, height - 2, color)
bitmap.fill_rect(x + 1, y + 1, width - 2, 1, color)
bitmap.fill_rect(x + 1, y + 1, 1, height - 2, color)
bitmap.fill_rect(x + 1, y + height - 2, width - 2, 1, color)
@@ -421,7 +423,7 @@ class Slider < UIControl
oldvalue = self.curvalue
repeattime = Input.time?(Input::MOUSELEFT) / 1000
# Left arrow
if left.contains(mousepos[0], mousepos[1])
if left.contains?(mousepos[0], mousepos[1])
if repeattime > 3000
self.curvalue -= 10
elsif repeattime > 1500
@@ -434,7 +436,7 @@ class Slider < UIControl
self.invalidate
end
# Right arrow
if right.contains(mousepos[0], mousepos[1])
if right.contains?(mousepos[0], mousepos[1])
if repeattime > 3000
self.curvalue += 10
elsif repeattime > 1500
@@ -673,7 +675,7 @@ class TextSlider < UIControl
oldvalue = self.curvalue
repeattime = Input.time?(Input::MOUSELEFT) / 1000
# Left arrow
if left.contains(mousepos[0], mousepos[1])
if left.contains?(mousepos[0], mousepos[1])
if repeattime > 3000
self.curvalue -= 10
elsif repeattime > 1500
@@ -685,7 +687,7 @@ class TextSlider < UIControl
self.invalidate
end
# Right arrow
if right.contains(mousepos[0], mousepos[1])
if right.contains?(mousepos[0], mousepos[1])
if repeattime > 3000
self.curvalue += 10
elsif repeattime > 1500
@@ -862,7 +864,7 @@ class ControlWindow < SpriteWindow_Base
return false if i < 0 || i >= @controls.length
rc = Rect.new(@controls[i].parentX, @controls[i].parentY,
@controls[i].width, @controls[i].height)
return rc.contains(mousepos[0], mousepos[1])
return rc.contains?(mousepos[0], mousepos[1])
end
def addControl(control)
@@ -927,3 +929,4 @@ class ControlWindow < SpriteWindow_Base
return @controls[i].curvalue
end
end
end

View File

@@ -1,3 +1,6 @@
module BattleAnimationEditor
module_function
#===============================================================================
# Paths and interpolation
#===============================================================================
@@ -430,3 +433,4 @@ def pbDefinePath(canvas)
sliderwin2.dispose
return
end
end

View File

@@ -1,3 +1,6 @@
module BattleAnimationEditor
module_function
################################################################################
# Importing and exporting
################################################################################
@@ -141,3 +144,4 @@ def pbConvertAnimsToNewFormat
end
pbMessage(_INTL("{1} animations converted to new format.", count))
end
end

View File

@@ -1,3 +1,6 @@
module BattleAnimationEditor
module_function
#===============================================================================
# Mini battle scene
#===============================================================================
@@ -533,9 +536,8 @@ def pbSelectSE(canvas, audio)
Input.update
cmdwin.update
maxsizewindow.update
if maxsizewindow.changed?(3) && animfiles.length > 0 # Play Sound
fname = (cmdwin.index == 0) ? "Cries/000" : "Anim/" + filename
pbSEPlay(RPG::AudioFile.new(fname, maxsizewindow.value(1), maxsizewindow.value(2)))
if maxsizewindow.changed?(3) && animfiles.length > 0 && filename != "" # Play Sound
pbSEPlay(RPG::AudioFile.new("Anim/" + filename, maxsizewindow.value(1), maxsizewindow.value(2)))
end
pbSEStop if maxsizewindow.changed?(4) && animfiles.length > 0 # Stop Sound
if maxsizewindow.changed?(5) # OK
@@ -945,10 +947,11 @@ def pbAnimEditorHelpWindow
cmdwin.dispose
end
#===============================================================================
#=============================================================================
# Main
#===============================================================================
#=============================================================================
def animationEditorMain(animation)
echoln animation.selected
viewport = Viewport.new(0, 0, Settings::SCREEN_WIDTH + 288, Settings::SCREEN_HEIGHT + 288)
viewport.z = 99999
# Canvas
@@ -1109,7 +1112,7 @@ def animationEditorMain(animation)
indexes = [2, 1, 3, 4] # Keeping backwards compatibility
positions.length.times do |i|
selected = "[ ]"
selected = "[x]" if animation[animation.selected].position == indexes[i]
selected = "[X]" if animation[animation.selected].position == indexes[i]
positions[i] = sprintf("%s %s", selected, positions[i])
end
pos = pbShowCommands(nil, positions, -1)
@@ -1149,6 +1152,7 @@ def animationEditorMain(animation)
viewport.dispose
RPG::Cache.clear
end
end
#===============================================================================
# Start
@@ -1162,7 +1166,7 @@ def pbAnimationEditor
end
Graphics.resize_screen(Settings::SCREEN_WIDTH + 288, Settings::SCREEN_HEIGHT + 288)
pbSetResizeFactor(1)
animationEditorMain(animation)
BattleAnimationEditor.animationEditorMain(animation)
Graphics.resize_screen(Settings::SCREEN_WIDTH, Settings::SCREEN_HEIGHT)
pbSetResizeFactor($PokemonSystem.screensize)
$game_map&.autoplay

View File

@@ -558,7 +558,7 @@ def pbExportAllAnimations
safename = anim.name.gsub(/\W/, "_")
Dir.mkdir("Animations/#{safename}") rescue nil
File.open("Animations/#{safename}/#{safename}.anm", "wb") do |f|
f.write(dumpBase64Anim(anim))
f.write(BattleAnimationEditor.dumpBase64Anim(anim))
end
if anim.graphic && anim.graphic != ""
graphicname = RTP.getImagePath("Graphics/Animations/" + anim.graphic)
@@ -626,13 +626,13 @@ def pbImportAllAnimations
pbSafeCopyFile(image, RTP.getImagePath("Graphics/Animations/" + File.basename(image)), "Graphics/Animations/" + File.basename(image))
end
Dir.glob(folder + "/*.anm") do |f|
textdata = loadBase64Anim(IO.read(f)) rescue nil
textdata = BattleAnimationEditor.loadBase64Anim(IO.read(f)) rescue nil
if textdata.is_a?(PBAnimation)
index = pbAllocateAnimation(animations, textdata.name)
missingFiles = []
textdata.name = File.basename(folder) if textdata.name == ""
textdata.id = -1 # This is not an RPG Maker XP animation
pbConvertAnimToNewFormat(textdata)
BattleAnimationEditor.pbConvertAnimToNewFormat(textdata)
if textdata.graphic && textdata.graphic != "" &&
!safeExists?(folder + "/" + textdata.graphic) &&
!FileTest.image_exist?("Graphics/Animations/" + textdata.graphic)