#===============================================================================
# El Panoramisator 2.4
# Script créé par Zeus81
# Utilisation : $scene = Scene_Panoramisator.new
#===============================================================================
module Save_Map
AUTOTILES = []
AUTOTILES[0] = [
18, 17, 14, 13, 2, 17, 14, 13, 18, 3, 14, 13, 2, 3, 14, 13,
18, 17, 14, 7, 2, 17, 14, 7, 18, 3, 14, 7, 2, 3, 14, 7,
18, 17, 6, 13, 2, 17, 6, 13, 18, 3, 6, 13, 2, 3, 6, 13,
18, 17, 6, 7, 2, 17, 6, 7, 18, 3, 6, 7, 2, 3, 6, 7,
16, 17, 12, 13, 16, 3, 12, 13, 16, 17, 12, 7, 16, 3, 12, 7,
10, 9, 14, 13, 10, 9, 14, 7, 10, 9, 6, 13, 10, 9, 6, 7,
18, 19, 14, 15, 18, 19, 6, 15, 2, 19, 14, 15, 2, 19, 6, 15,
18, 17, 22, 21, 2, 17, 22, 21, 18, 3, 22, 21, 2, 3, 22, 21,
16, 19, 12, 15, 10, 9, 22, 21, 8, 9, 12, 13, 8, 9, 12, 7,
10, 11, 14, 15, 10, 11, 6, 15, 18, 19, 22, 23, 2, 19, 22, 23,
16, 17, 20, 21, 16, 3, 20, 21, 8, 11, 12, 15, 8, 9, 20, 21,
16, 19, 20, 23, 10, 11, 22, 23, 8, 11, 20, 23, 0, 1, 4, 5]
AUTOTILES[1] = [
2, 1, 6, 5, 0, 1, 4, 5, 2, 3, 6, 7, 0, 3, 4, 7]
AUTOTILES[2] = [
10, 9, 6, 5, 8, 9, 4, 5, 2, 1, 6, 5, 0, 1, 4, 5,
10, 11, 6, 7, 8, 11, 4, 7, 2, 3, 6, 7, 0, 3, 4, 7,
10, 9, 14, 13, 8, 9, 12, 13, 2, 1, 14, 13, 0, 1, 12, 13,
10, 11, 14, 15, 8, 11, 12, 15, 2, 3, 14, 15, 0, 3, 12, 15]
AUTOTILES[3] = [
18, 17, 14, 13, 2, 17, 14, 13, 18, 3, 14, 13, 2, 3, 14, 13,
18, 17, 14, 13, 2, 17, 14, 13, 18, 3, 14, 13, 2, 3, 14, 13,
18, 17, 14, 13, 2, 17, 14, 13, 18, 3, 14, 13, 2, 3, 14, 13,
18, 17, 14, 13, 2, 17, 14, 13, 18, 3, 14, 13, 2, 3, 14, 13,
16, 17, 12, 13, 16, 3, 12, 13, 16, 17, 12, 13, 16, 3, 12, 13,
10, 9, 14, 13, 10, 9, 14, 13, 10, 9, 14, 13, 10, 9, 14, 13,
18, 19, 14, 15, 18, 19, 14, 15, 2, 19, 14, 15, 2, 19, 14, 15,
18, 17, 14, 13, 2, 17, 14, 13, 18, 3, 14, 13, 2, 3, 14, 13,
16, 19, 12, 15, 10, 9, 14, 13, 8, 9, 12, 13, 8, 9, 12, 13,
10, 11, 14, 15, 10, 11, 14, 15, 18, 19, 14, 15, 2, 19, 14, 15,
16, 17, 12, 13, 16, 3, 12, 13, 8, 11, 12, 15, 8, 9, 12, 13,
16, 19, 12, 15, 10, 11, 14, 15, 8, 11, 12, 15, 0, 1, 12, 15]
@cache = {}
@autorect = Rect.new(0, 0, 32, 32)
@shadow = Bitmap.new(16, 32)
@shadow.fill_rect(@shadow.rect, Color.new(0, 0, 0, 128))
RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
def self.bitmap_to_buffer
RtlMoveMemory_pi.call(address = "\0"*4, @bitmap.object_id*2+16, 4)
RtlMoveMemory_pi.call(address, address.unpack("L")[0]+8, 4)
RtlMoveMemory_pi.call(address, address.unpack("L")[0]+16, 4)
RtlMoveMemory_pi.call(@buffer, address.unpack("L")[0], @buffer.size)
end
def self.new(map_id, background_color, parallax_display, shadows_display, autotiles_anime, layers_split, save_type)
map = load_data("Data/Map%03d.rvdata" % map_id)
@data, @w, @h = map.data, map.width * 32, map.height * 32
@buffer, @bitmap = "\0" * (@w * 128), Bitmap.new(@w, 32)
load_parallax(map.parallax_name) if parallax_display and parallax_display = !map.parallax_name.empty?
make_png_preparation if save_type == 1
for layer in layers_split ? (parallax_display ? -1 : 0)...3 : 0...1
z_range = layers_split ? [layer] : 0...3
animations = (layer != -1 and autotiles_anime and is_animated?(z_range)) ? 3 : 1
animations.times do |animation|
make_filename(map_id, layers_split ? layer : nil, animations != 1 ? animation : nil, save_type)
file = File.open(@filename, "wb")
file.write(make_bmp_header) if save_type == 0
@data.ysize.times do |y|
y = @data.ysize-1-y if save_type == 0
@bitmap.fill_rect(@bitmap.rect, background_color)
draw_parallax(y) if parallax_display and (z_range.include?(-1) or z_range.is_a?(Range))
draw_tiles(y, z_range, animation, shadows_display) unless z_range.include?(-1)
bitmap_to_buffer
case save_type
when 0; file.write(@buffer)
when 1; make_png_data {|s| file.putc(0); file.write(s)}
end
end
file.close
make_png if save_type == 1
end
end
@bitmap.dispose
@parallax.dispose if parallax_display
@data=@w=@h=@buffer=@bitmap=@parallax=@filename=@png_range1=@png_range2 = nil
end
def self.make_filename(map_id, layer, animation, save_type)
@filename = "Map[%03d]" % map_id
@filename << "_Layer[#{layer+1}]" if layer
@filename << "_Autotile[#{animation}]" if animation
@filename << [".bmp", ".png"][save_type]
end
def self.make_bmp_header
"BM#{[4*@w*@h+54,0,54,40,@w,@h,1,32,0,4*@w*@h,0,0,0,0].pack("L6S2L6")}"
end
def self.make_png_preparation
@png_range1 = Array.new(@w*32) {|i| i*4}
@png_range2 = Array.new(32) {|i| (31-i)*@w*4}
end
def self.make_png_data
j = @w*4
@png_range1.each {|i| @buffer[i,3] = @buffer[i,3].reverse!}
@png_range2.each {|i| yield @buffer[i, j]}
end
def self.make_png
file = File.open(@filename, "rb")
chunks = ["IHDR#{[@w,@h,8,6,0,0,0].pack("N2C5")}", "IDAT#{Zlib::Deflate.deflate(file.read, 9)}", "IEND"]
file.close
file = File.open(@filename, "wb")
file.write("\211PNG\r\n\32\n")
for chunk in chunks
file.write([chunk.size-4].pack("N"))
file.write(chunk)
file.write([Zlib.crc32(chunk)].pack("N"))
end
file.close
end
def self.is_animated?(z_range)
z_range.each {|z| @data.ysize.times {|y| @data.xsize.times {|x|
return true if (id=@data[x, y, z]).between?(2048, 2815) and !id.between?(2144, 2239)
}}}
return false
end
def self.is_table?(tile_id) tile_id and tile_id.between?(2816, 4351) and (tile_id-2816)/48%8 == 7 end
def self.is_wall?(tile_id) tile_id and tile_id > 4351 end
def self.draw_parallax(y)
rect = Rect.new(0, y*32%(@parallax.height-(@parallax.height%32 != 0 ? 32 : 0)), @parallax.width, 32)
(@w/rect.width.to_f).ceil.times {|i| @bitmap.blt(i*rect.width, 0, @parallax, rect)}
end
def self.draw_tiles(y, z_range, animation, shadows_display)
for z in z_range
@data.xsize.times do |x|
tile_id = @data[x, y, z]
if z == 0
autotable = nil if is_table?(tile_id) or is_wall?(tile_id) or !is_table?(autotable = @data[x, y-1, z])
autoshadow = (shadows_display and is_wall?(@data[x-1, y, z]) and is_wall?(@data[x-1, y-1, z]) and
(tile_id.between?(1552, 1663) or (tile_id.between?(2816, 4351) and !is_table?(tile_id))))
else autotable = autoshadow = nil
end
if tile_id != 0
if tile_id >= 2048
then @bitmap.blt(x*32, 0, load_autotile(tile_id, animation), @autorect)
else @bitmap.blt(x*32, 0, *load_tile(tile_id))
end
@bitmap.blt(x*32, 0, @shadow, @autorect) if autoshadow
end
@bitmap.blt(x*32, 0, autotable, @autorect) if autotable and (autotable = load_table(autotable))
end
end
end
def self.load_parallax(parallax_name)
bmp = Cache::parallax(parallax_name)
if bmp.height % 32 != 0
@parallax = Bitmap.new(bmp.width, bmp.height + 32)
(@parallax.height/bmp.height.to_f).ceil.times {|i| @parallax.blt(0, bmp.height*i, bmp, bmp.rect)}
bmp.dispose
else @parallax = bmp
end
end
def self.load_tile(tile_id)
unless @cache[tile_id]
@cache[tile_id] = case tile_id
when 0...256 ; [Cache.system("TileB"), Rect.new(tile_id%8*32+(tile_id<128 ? 0 : 256), tile_id/8%16*32, 32, 32)]
when 256...512 ; [Cache.system("TileC"), Rect.new(tile_id%8*32+(tile_id<384 ? 0 : 256), (tile_id-256)/8%16*32, 32, 32)]
when 512...768 ; [Cache.system("TileD"), Rect.new(tile_id%8*32+(tile_id<640 ? 0 : 256), (tile_id-512)/8%16*32, 32, 32)]
when 768...1024; [Cache.system("TileE"), Rect.new(tile_id%8*32+(tile_id<896 ? 0 : 256), (tile_id-768)/8%16*32, 32, 32)]
when 1536...1664; [Cache.system("TileA5"), Rect.new(tile_id%8*32, (tile_id-1536)/8*32, 32, 32)]
end
end
return @cache[tile_id]
end
def self.load_autotile(tile_id, animation)
if tile_id < 2816 and !tile_id.between?(2144, 2239)
then key = tile_id + animation * 10000
else key = tile_id
end
unless @cache[key]
case tile_id
when 2048...2816
if (id = (tile_id -= 2048) / 48) >= 4
x = (id % 2 == 0 ? animation*64 : 192) + id / 4 % 2 * 256
y = (id % 2 == 1 ? animation*32 : 0) + id / 2 % 2 * 96 + id / 8 * 192
type = id % 2
else x, y, type = (id < 2 ? animation*64 : 192), id % 2 * 96, 0
end
src_bmp = Cache.system("TileA1")
when 2816...4352
id, src_bmp = (tile_id -= 2816) / 48, Cache.system("TileA2")
x, y, type = id % 8 * 64, id / 8 * 96, id % 8 == 7 ? 3 : 0
when 4352...5888
id, src_bmp = (tile_id -= 4352) / 48, Cache.system("TileA3")
x, y, type = id % 8 * 64, id / 8 * 64, 2
when 5888...8192
id, src_bmp = (tile_id -= 5888) / 48, Cache.system("TileA4")
x, y, type = id % 8 * 64, id / 16 * 160 + id / 8 % 2 * 96, id / 8 % 2 * 2
end
id = tile_id % 48 * 4
@cache[key] = bmp = Bitmap.new(32, 32)
for i in 0...4
j = AUTOTILES[type][id+i] || 0
src_rect = Rect.new(x+j%4*16, y+j/4*16, 16, 16)
bmp.blt(i%2*16, i/2*16, src_bmp, src_rect)
if type == 3 and i > 1 and j != (k = AUTOTILES[0][id+i])
src_rect = Rect.new(x+k%4*16, y+k/4*16, 16, 8)
bmp.blt(i%2*16, i/2*16+8, src_bmp, src_rect)
end
end
end
return @cache[key]
end
def self.load_table(tile_id)
key = tile_id + 10000
unless @cache.include?(key)
id = (tile_id-=2816) % 48 * 4
@cache[key] = nil
for i in 2...4
if (j = AUTOTILES[0][id+i]) >= 20
@cache[key] = Bitmap.new(32, 8) unless @cache[key]
src_rect = Rect.new(448+j%4*16, tile_id/384*96+88, 16, 8)
@cache[key].blt(i%2*16, 0, Cache.system("TileA2"), src_rect)
end
end
end
return @cache[key]
end
end
class Window_MapList < Window_Selectable
def initialize
@back_sprite = Sprite.new
super(6, 36, 276, 320)
self.opacity, self.active, self.visible, self.z = 0, false, false, 120
self.contents.font = Font.new("Comic Sans MS", 20)
@back_sprite.bitmap = Bitmap.new(width-16, height-16)
@back_sprite.bitmap.fill_rect(@back_sprite.bitmap.rect, Color.new(0, 0, 128, 192))
refresh
end
def dispose
@back_sprite.bitmap.dispose
@back_sprite.dispose
super
end
def visible=(visible) @back_sprite.visible = super(visible) end
def x=(x) @back_sprite.x = x+8; super(x) end
def y=(y) @back_sprite.y = y+8; super(y) end
def z=(z) @back_sprite.z = z-10; super(z) end
def refresh
map_infos = load_data("Data/MapInfos.rvdata")
@maps_id, @item_max, @index = map_infos.keys.sort, map_infos.size, 0
font = self.contents.font
self.contents.dispose
self.contents = Bitmap.new(244, [@item_max*24, 24].max)
self.contents.font = font
@back_sprite.src_rect.height = [self.contents.height+16, @back_sprite.bitmap.height].min
for i in 0...@maps_id.size
map_id = @maps_id[i]
self.contents.fill_rect(4, i*24+2, 236, 20, Color.new(0,0,0))
self.contents.draw_text(4, i*24+2, 236, 20, " %03d - #{map_infos[map_id].name}" % map_id)
end
end
def map_id() @maps_id[@index] || 0 end
def update_help() @help_window.set_text("Touche C : Valider - Touche B : Annuler", 1) end
end
class Window_Help_Scroll < Window_Base
SPACE = " " * 8
def initialize
super(0, 360, 544, WLH + 32)
self.windowskin = nil
self.contents.font = Font.new("Comic Sans MS", 20)
@wait_count = @text_width = 0
end
def set_text(text, align = 0)
if text != @text or align != @align
@text, @align, @wait_count, self.ox, font = text, align, 100, 0, self.contents.font
if (w = self.contents.text_size(text).width) >= width - 32
text += SPACE + text
w += (@text_width = self.contents.text_size(SPACE).width + w)
else @text_width, w = 0, width - 32
end
self.contents.dispose
self.contents = Bitmap.new(w, height - 32)
self.contents.font = font
self.contents.draw_text(self.contents.rect, text, align)
end
self.ox = (self.ox >= @text_width ? 0 : self.ox+1) if @text_width > 0 and (@wait_count -= 1) < 0
end
end
class Window_Panoramisator < Window_Selectable
attr_accessor :item_max, :data
def initialize
super(0, 0, 544, 416)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = "Comic Sans MS"
@item_max, @index, @data = 9, 0, [0, Color.new(0, 0, 0, 0), true, true, false, false, 0]
refresh
end
def refresh
self.contents.clear
self.contents.fill_rect(0, 24, 512, 1, normal_color)
self.contents.fill_rect(0, 352, 512, 1, normal_color)
self.contents.font.shadow = true
self.contents.font.size = 28
self.contents.font.color = knockout_color
self.contents.draw_text(0, -8, 512, 32, "El Panoramisator", 1)
self.contents.font.size = 16
self.contents.font.color = normal_color
self.contents.draw_text(0, 336, 512, 20, "Zeus81 2008 - 2010", 2)
self.contents.draw_text(0, 348, 64, 20, "Aide")
self.contents.font.size = 20
self.contents.draw_text(8, 64, 240, 32, "Choix de la couleur de fond :")
self.contents.draw_text(256, 44, 48, 32, "Rouge", 1)
self.contents.draw_text(304, 44, 48, 32, "Vert", 1)
self.contents.draw_text(352, 44, 48, 32, "Bleu", 1)
self.contents.draw_text(400, 44, 48, 32, "Alpha", 1)
self.contents.draw_text(32, 96, 512, 32, "Afficher le panorama")
self.contents.draw_text(32, 128, 512, 32, "Afficher les ombres automatiques")
self.contents.draw_text(32, 160, 512, 32, "Animer les autotiles sur 3 frames")
self.contents.draw_text(32, 192, 512, 32, "Séparer les différentes couches sur plusieurs images")
self.contents.draw_text(32, 224, 512, 32, "Enregistrer au format BMP 32 bits")
self.contents.draw_text(32, 256, 512, 32, "Enregistrer au format PNG 32 bits")
self.contents.font.bold = true
self.contents.draw_text(0, 288, 512, 32, "EXPORTER LA MAP", 1)
self.contents.font.color.set(0,0,0)
self.contents.font.shadow = self.contents.font.bold = false
refresh_values
end
def refresh_values
if @data[0] == 0
then align, text = 1, "Veuillez sélectionner une map"
else align, text = 0, " %03d - #{load_data("Data/MapInfos.rvdata")[@data[0]].name}" % @data[0]
end
self.contents.fill_rect(10, 38, 236, 20, normal_color)
self.contents.draw_text(10, 38, 236, 20, text, align)
self.contents.fill_rect(260, 72, 40, 20, normal_color)
self.contents.fill_rect(308, 72, 40, 20, normal_color)
self.contents.fill_rect(356, 72, 40, 20, normal_color)
self.contents.fill_rect(404, 72, 40, 20, normal_color)
self.contents.draw_text(260, 72, 40, 20, @data[1].red.to_i.to_s, 1)
self.contents.draw_text(308, 72, 40, 20, @data[1].green.to_i.to_s, 1)
self.contents.draw_text(356, 72, 40, 20, @data[1].blue.to_i.to_s, 1)
self.contents.draw_text(404, 72, 40, 20, @data[1].alpha.to_i.to_s, 1)
self.contents.fill_rect(452, 48, 48, 48, @data[1])
for i in 2...8
color = (i<6 and @data[i] or i-6 == @data[6]) ? Color.new(255, 0, 0) : Color.new(128, 128, 128)
self.contents.fill_rect(12, (i+1)*32+12, 10, 10, Color.new(29, 82, 129))
self.contents.fill_rect(12+1, (i+1)*32+13, 8, 8, normal_color)
self.contents.fill_rect(12+2, (i+1)*32+14, 6, 6, color)
end
end
def update_cursor
if @item_max == 0
then self.cursor_rect.set(256+@index*48, 48, 48, 48)
else self.cursor_rect.set(@index==8 ? 128 : 0, 32+@index*32, @index.between?(2,7) ? 512 : 256, 32)
end
end
def update_help
text = case @item_max == 0 ? -1 : @index
when -1; "Entrée : Valider - Echap : Annuler - Touches directionnelles : Modifier"
when 0; "Selectionnez la map que vous désirez transformer en image(s)."
when 1; "Configurez la couleur qui remplacera les zones transparentes."
when 2; "Le panorama de la map se répètera sur toute l'image."
when 3; "Les ombres qui se mettent automatiques à droite des murs des TileA3-4."
when 4; "Pour les autotiles animés du TileA1. (Eau / Lave)"
when 5; "Une map est composée de trois couches (C1 : TileA, C2 : TileA2 en partie, C3 : TileBCDE)." <<
" Effectivement ça ne sert à rien de les séparer m'enfin sait-on jamais..."
when 6; "Enregistrement très rapide mais fichier lourd et transparence non supportée par certains logiciels."
when 7; "Enregistrement très lent mais fichier léger et transparence directement compatible." <<
" (Toutefois sauf petites maps il est préférable d'enregistrer les images en BMP puis de les" <<
" convertir en PNG via un logiciel tiers comme Gimp, c'est plus rapide)"
when 8; "Attention, cela peut prendre un certain temps selon votre configuration et la taille de la map."
end
@help_window.set_text(text, 1)
end
end
class Scene_Panoramisator < Scene_Base
def initialize() $data_system = load_data("Data/System.rvdata") unless $data_system end
def start
super
@main_window = Window_Panoramisator.new
@maplist_window = Window_MapList.new
@help_window = Window_Help_Scroll.new
@main_window.help_window = @help_window
@maplist_window.help_window = @help_window
end
def terminate
super
@main_window.dispose
@maplist_window.dispose
@help_window.dispose
end
def update
super
@main_window.update
@maplist_window.update
if @maplist_window.active
then update_maplist
elsif @main_window.item_max == 0
then update_background_color
else update_main
end
end
def update_maplist
if Input.trigger?(Input::C)
Sound.play_decision
@maplist_window.visible = @maplist_window.active = false
@main_window.active = true
@main_window.data[0] = @maplist_window.map_id
@main_window.refresh_values
elsif Input.trigger?(Input::B)
Sound.play_cancel
@maplist_window.visible = @maplist_window.active = false
@main_window.active = true
end
end
def update_main
if Input.trigger?(Input::C)
case @main_window.index
when 0
Sound.play_decision
@maplist_window.visible = @maplist_window.active = true
@main_window.active = false
when 1
Sound.play_decision
@last_background_color = @main_window.data[1].dup
@count = 1
@main_window.item_max = 0
@main_window.index = 0
when 2..7
Sound.play_decision
if @main_window.index < 6
then @main_window.data[@main_window.index] = !@main_window.data[@main_window.index]
else @main_window.data[6] = @main_window.index - 6
end
@main_window.refresh_values
when 8
if @main_window.data[0] != 0
Sound.play_save
Save_Map.new(*@main_window.data)
print(" Le traitement est terminé !\n",
"Les images se trouvent dans le dossier de votre jeu.")
else Sound.play_buzzer
end
end
elsif Input.trigger?(Input::B)
Sound.play_cancel
$scene = nil
end
end
def update_background_color
color = @main_window.data[1]
if Input.press?(Input::UP) == Input.press?(Input::DOWN)
@count = 1
elsif Input.repeat?(Input::DOWN)
Sound.play_cursor
case @main_window.index
when 0; color.red = [color.red - @count.round, 0].max
when 1; color.green = [color.green - @count.round, 0].max
when 2; color.blue = [color.blue - @count.round, 0].max
when 3; color.alpha = [color.alpha - @count.round, 0].max
end
@main_window.refresh_values
elsif Input.repeat?(Input::UP)
Sound.play_cursor
case @main_window.index
when 0; color.red += @count.round
when 1; color.green += @count.round
when 2; color.blue += @count.round
when 3; color.alpha += @count.round
end
@main_window.refresh_values
end
if Input.repeat?(Input::LEFT)
Sound.play_cursor
@main_window.index = (@main_window.index - 1) % 4
elsif Input.repeat?(Input::RIGHT)
Sound.play_cursor
@main_window.index = (@main_window.index + 1) % 4
elsif Input.trigger?(Input::C)
Sound.play_decision
@main_window.item_max = 9
@main_window.index = 1
elsif Input.trigger?(Input::B)
Sound.play_cancel
@main_window.data[1] = @last_background_color.dup
@main_window.item_max = 9
@main_window.index = 1
@main_window.refresh_values
end
@count *= 1.02
end
end