查看: 3041|回复: 0

[原创发布] 兼容新三作的地图编辑器【雾】

[复制链接]
梦石
0
星屑
163
在线时间
249 小时
注册时间
2014-7-18
回帖
26
发表于 2017-5-1 00:04:14 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 M.Winderic. 于 2017-5-1 10:07 编辑

编辑器只将数据导出csv,
导入功能、RM地图的兼容性或者用在非RM作品,
请自己写RPG::Map之类的东西,
VA的全自动画笔还请自行实现(取半格等)


说人话就是:

使用本工具时,以下事情做得到:
  • 使用键盘进行基本的地图绘制
  • 使用多个图层、多个图块
  • 将绘制的地图以“纯文本”形式导出

使用本工具时,以下事情请自己找程序猿实现:
  • RMVA的全自动画笔功能
  • 图块位置微调
  • 使用鼠标进行基本的地图绘制
  • 导入“纯文本”形式或者RMXP/VX/VA格式的地图

使用本工具时,以下事情做不到:
  • 无法直接将绘制的地图保存成图片
  • 不支持中文







兼容 RM 新三作的地图编辑器【大雾】
用法与 vi/vim 类似

snapshot.png

懒人包下载:
ebrgss_tilesets_editor.zip (3.62 MB, 下载次数: 132)

源码:
[fold=toolkit.rb]
[pre lang="ruby"]#!/usr/bin/env ruby
#coding:utf-8

#======================================================================#
#             [LibRGSSS] Ruby Game Slight Scripting System             #
#----------------------------------------------------------------------#
# This project is licensed under the                                   #
# Creative Commons Attribution-ShareAlike 4.0 International License.   #
#======================================================================#

module RGSSS

  module CLanguage
    { :cchar=>'C', :clong=>'L', :clonglong=>'Q', :cint=>'I', :cptr=>'J' }.each{|k, v|
      CLanguage.const_set k.to_s.capitalize, [0].pack(v).freeze
      CLanguage.const_set "P#{ k }", ( l = proc { CLanguage.const_get(k.to_s.capitalize).dup } )
      define_method(k, &l)
    }
    define_method(:cmem){|size| Array.new(size, 0).pack('C*') }
  end

  module LazyWin32API
    extend Module.new {
      KEYS = { 'b' => 'I', 'v' => 'V' }
      define_method(:apis)       { @apis || @apis = Hash.new{|h, k| h[k] = {} } }
      define_method(:set)        {|d, f, i, o| apis[d][f] = Win32API.new(d, f, i, o) }
      define_method(:gsub_api)   {|*a| a.map{|w| KEYS.each{|k, v| w.gsub! k, v}; w } }
      define_method(:phrase_args){|a|
        return 'V' if a.empty?
        return a.map {|obj|
          case obj
          when ::Integer; 'i';
          when ::String;  'p';
          end
        }.join
      }
      def method_missing(meth, *a, &blk)
        begin
          dll, func, i, o = meth.to_s.split('_')
          i, o = gsub_api(i || phrase_args(a), o || 'i')
          c = apis[dll][func] || set(dll, func, i, o)
          r = c.call(*a)
          return r
        rescue
          super
        end
      end
    }
    hloadtime = Time.new
    # A Special thanks to ZiSu@66RPG thread-id: 157287
    HwndSelf = LazyWin32API.user33_GetHWND
    # A Special thanks to Artoria@66RPG thread-id: 344608, post-id: 2397031
    if HwndSelf == 0
      msg, r, pm, ac = "\0"*24, 0,
        Win32API.new('user32', 'PeekMessage','pLLLL','L'),
        Win32API.new('user32', 'GetAncestor', 'LL', 'L')
      HwndTop = while true do
        break r if pm.call(msg, 0, 0, 0, 0) != 0 and
              ((r = ac.call(msg.unpack('L').first, 3))!=0)
        if Time.new - hloadtime > 1
          hloadtime = Time.new
          Graphics.update
        end
      end
    end
    HWnd = HwndSelf != 0 ? HwndSelf : HwndTop
  end

ConsoleTest = <<__ConsoleTest__
  module LazyConsole
    # You may want a better console from the link below: (Artoria@66RPG thread-id: 343335)
    # https://github.com/Artoria/RMSFX/blob/master/gameconsole.rb
    LazyWin32API.kernel32_AllocConsole
    @stdin  = File.open("CONIN$", "r")
    @stdout = File.open("CONOUT$", "w")
    @stderr = File.open("CONOUT$", "w")
    LazyWin32API.user32_SwitchToThisWindow LazyWin32API::HWnd, 1
    define_method(:print)   {|*a| a.each{|w| @stdout.write w; @stdout.flush } }
    module_function :print
    module ::Kernel
      define_method(:p)     {|*a| RGSSS::LazyConsole.print a.map{|w| w.inspect + "\n" }.join }
      define_method(:print) {|*a| RGSSS::LazyConsole.print *a }
      define_method(:printf){|*a| RGSSS::LazyConsole.print sprintf *a }
    end
    END {
      [@stdin, @stdout].each{|w| w.close }
      LazyWin32API.kernel32_FreeConsole
    }
  end
__ConsoleTest__

  module Inspector0x
    Pointer = '0x%07x'.freeze
    class Inspector0xPtr < String; def inspect; self; end; end
    def printf0x(str, lsb=false)
      r = []
      s = str.unpack('C*').each_with_index.map{|c|
        r.push 32 <= c && c <= 126 ? [32, c].pack('C*') : [32, 32].pack('C*')
        next "%02x" % c
      }
      a = proc{|t, b| (0..3).map{|i| "#{ t[4*b+i] }" }.join }
      l = proc{|t, b| (0..3).map{|i|  a[ t,4*b+i]    }.join ' ' }
      print (0...((r.size+31)/32)).map{|j|
        l[r, 2*j] + '  ' + l[r, 2*j+1] + "\n" +
        l[s, 2*j] + '  ' + l[s, 2*j+1] + "\n"
      }.join
    end
    def sprintf0x(obj)
      obj = (obj.unpack('J')[0]||0) if obj.is_a? String
      Inspector0xPtr.new(sprintf(Pointer, obj))
    end
    def inspector0x(klass, obj_id, inner_dom)
      z = inner_dom.map{|k, v| " #{ k }=#{ v.inspect }"}.join(',')
      "#<#{ klass }:#{ sprintf0x obj_id }#{ z }>"
    end
  end

  class ::Bitmap
    include Inspector0x
    define_method(:inspect){
      inspector0x self.class, object_id, { :width => self.width, :height => self.height }
    }
  end

  module LazyUI

    extend CLanguage

    extend Module.new {

      attr_reader :ty, :by
      include CLanguage

      define_method(:client_rect){
        rect = clong * 4
        LazyWin32API.user32_GetClientRect(LazyWin32API::HWnd, rect)
        return *(rect.unpack('llll'))
      }

      define_method(:window_width) { client_rect[2] }
      define_method(:window_height){ client_rect[3] }

      def arrange(objs)
        @ty = 0; @by = LazyUI.window_height
        objs.each {|w|
          w.init_y = w.y = @ty
          unless w.type.include? :float
            unless w.type.include? :bottom
              @ty += w.bitmap.height
            end
            if w.type.include? :bottom
              @by -= w.bitmap.height
              w.init_y = w.y = @by
            end
          end
        }
      end

      def need_resize?
        @ow = @ow || 0;     @oh = @oh || 0
         @w = window_width;  @h = window_height
        r = (@ow != @w) || (@oh != @h)
        if r; @ow = @w; @oh = @h; end
        return r
      end

      def screen(*objs, &update_block)
        i = true
        arrange objs
        while i
          if need_resize?
            arrange objs
            objs.each{|w| w.auto_resize(@w, @h) }
          end
          ::Input.update
          objs.each{|w| w.respond }
          i = update_block[*objs]
          ::Graphics.update
        end
      end

      def mouse_pos
        api_mouse = cmem(4*2)
        LazyWin32API.user32_GetCursorPos   api_mouse
        LazyWin32API.user32_ScreenToClient LazyWin32API::HWnd, api_mouse
        return api_mouse.unpack('ii')
      end

      def key_state(code)
        LazyWin32API.user32_GetKeyState(code) & 0xFF
      end

      def fetch_letter
        (0x30..0x5A).each{|k| return [k].pack('C') if key? k }
        return false
      end

      def key?(code)
        z = key_state(code)
        if z < 128;              Key_PLock[code] = 0; Key_PLoop[code] = 0; return false; end
        if Key_PLoop[code] > 36;                                           return  true; end
        if Key_PLock[code] >  0; Key_PLoop[code] += 1;                     return false; end
        return Key_PLock[code] = Key_Lock
      end

      def update
        Key_PLock.each{|k, v| Key_PLock[k] -= 1 unless v <= 0 }
      end

    }

    class UniversalUI < ::Sprite
      attr_accessor :init_y, :type
      def initialize(type, *a, &b)
        @type, @respond_block = type, b
        super(*a)
      end
      define_method(:respond){|*a|self.instance_eval(*a, &@respond_block) if @respond_block }
      define_method(:auto_resize){|w, h|}
    end

    class Window < UniversalUI
      States = [:hover, :down]
      attr_accessor :text, :w, :h
      def cfg(type)
        c  = DefaultWindowBorder
        c  =    InfoWindowBorder    if type.include? :info
        c  =  StatusWindowBorder    if type.include? :status
        ff = DefaultFontFamily
        ff =    MonoFontFamily      if type.include? :mono# or type.include? :info
        fs = DefaultFontSizeRegular
        fs = DefaultFontSizeSmall   if type.include? :status
        fs = DefaultFontSizeTitle   if type.include? :title
        fs = DefaultFontSizeInfo    if type.include? :info
        fc = DefaultFontColor
        fc =    DarkFontColor       if type.include? :dark
        fc =  ActiveFontColor       if type.include? :hover or type.include? :down
        bg = DefaultBackGroundColor
        bg =    DarkBackGroundColor if type.include? :dark
        bg =   HoverBackGroundColor if type.include? :hover
        bg =    DownBackGroundColor if type.include? :down
        return c, ff, fs, fc, bg
      end
      def initialize(*argv, &respond_block)
        @text, @type, @w, @h, *args = argv
        c, ff, fs, fc, bg = cfg @type
        @auto_resize = true unless @w and @h
        @w = @w || LazyUI.window_width
        @h = @h || (     c + fs ) if @type.include? :info
        @h = @h || ( 2 * c + fs )
        super(@type, *args, &respond_block)
        self.bitmap = Bitmap.new @w, @h
        self.z = DefaultWindowZIndex
        self.refresh
      end
      def mouse_in_self?
        a, b = LazyUI.mouse_pos
        return( a >= self.x          and b >= self.y          and
                a <  self.x + self.w and b <  self.y + self.h )
      end
      define_method(:do_normal){ States.each{|w| @type.delete w } }
      define_method(:do_down)  { do_normal; @type.push :down  }
      define_method(:do_hover) { do_normal; @type.push :hover }
      def refresh
        c, ff, fs, fc, bg = cfg @type
        self.bitmap.clear
        self.bitmap.font.name  = ff
        self.bitmap.font.size  = fs
        self.bitmap.font.color = fc
        r = self.bitmap.text_size(@text)
        self.bitmap.fill_rect 0, 0, @w, @h, bg
        x, y = c, c
        y = c + ( @h - 2 * c - r.height ) / 2
        self.bitmap.draw_text x, y, r.width, r.height, @text
      end
      define_method(:auto_resize){|w, h|
        if @auto_resize
          @w = w
          self.bitmap.dispose
          self.bitmap = Bitmap.new @w, @h
          self.refresh
        end
      }
    end

    class Picture < UniversalUI
      def initialize(bmp, *args, &respond_block)
        @type = type
        super(*args, &respond_block)
        case bmp
        when ::Bitmap
          self.bitmap = bmp
        when ::String
          self.bitmap = ::Bitmap.new bmp
        when nil
          self.bitmap = ::Bitmap.new 8, 8
        end
      end
    end

    class FixHeight < UniversalUI
      attr_reader :init
      def initialize(*a, &b)
        @init = false
        super(*a, &b)
      end
      def respond
        auto_resize LazyUI.window_width, 0 unless @init
        super
      end
    end

    class VerticalBar < FixHeight
      def initialize(x, w, color, *a, &b)
        @w, @color = w, color
        super([:float], *a, &b)
        self.x = x
      end
      def auto_resize(w_, h_)
        h = LazyUI.by - LazyUI.ty
        w = @w
        self.bitmap = Bitmap.new(w, h)
        self.bitmap.fill_rect(0, 0, w, h, @color)
        @init = true
      end
    end

    class CanvasBack < FixHeight
      W = Color.new 255, 255, 255
      B = Color.new 204, 204, 204
      Z = 8
      def initialize
        super([:float])
        self.z = -1
      end
      def auto_resize(w, h_)
        h = LazyUI.by - LazyUI.ty
        self.bitmap = Bitmap.new(w, h)
        c = false
        (0..(w + 7)/8).each{|x|
          d = c = !c
          (0..(h + 7)/8).each{|y|
            self.bitmap.fill_rect(x * 8, y * 8, 8, 8, (d = !d) ? W : B)
          }
        }
        @init = true
      end
    end

    class CanvasCover < FixHeight
      B = Color.new 192, 192, 192, 192
      def initialize(&b)
        self.instance_eval(&b)
        super([:float])
      end
      def auto_resize(w, h_)
        h = LazyUI.by - LazyUI.ty
        self.bitmap = Bitmap.new(w, h)
        self.bitmap.fill_rect 0, 0, w, h, B
        @init = true
      end
      def respond
        auto_resize LazyUI.window_width, 0 unless @init
        super
      end
    end

  end

  module LazyUI

    Key_Lock                  = 24
    Key_PLock                 = Hash.new { |h, k| h[k] = 0 }
    Key_PLoop                 = Hash.new { |h, k| h[k] = 0 }

    DefaultBackGroundColor    = Color.new(128, 128, 128, 128)
    DefaultBackGroundColorZ   = Color.new(128, 128, 128, 255)
       DarkBackGroundColor    = Color.new( 32,  32,  32, 128)
       DarkBackGroundColorZ   = Color.new( 32,  32,  32, 255)
      HoverBackGroundColor    = Color.new(255, 255, 255, 200)
       DownBackGroundColor    = Color.new(255, 255, 255, 128)

    DefaultWindowZIndex       = 64


    unless window_width < 1280 && window_height < 720

       StatusWindowBorder     = 8
      DefaultWindowBorder     = 4
         InfoWindowBorder     = 2

      DefaultFontSizeInfo     = 16
      DefaultFontSizeSmall    = 16
      DefaultFontSizeRegular  = 24
      DefaultFontSizeTitle    = 36

    else

       StatusWindowBorder     = 0
      DefaultWindowBorder     = 0
         InfoWindowBorder     = 0

      DefaultFontSizeInfo     =  8
      DefaultFontSizeSmall    = 12
      DefaultFontSizeRegular  = 16
      DefaultFontSizeTitle    = 24

    end
    ChineseFontFamily         = [
                                  'Source Han Sans SC Light',
                                  'DengXian Light',
                                  'SimSun'
                                ]
    DefaultFontFamily         = [
                                  'Calibri Light',
                                  'Arial',
                                  'Helvetica'
                                ]
       MonoFontFamily         = [
                                  'Source Code Pro',
                                  'Lucida Console',
                                  'Consolas',
                                  'Courier New'
                                ]

    DefaultFontColor          = Color.new(255, 255, 255, 255)
       DarkFontColor          = Color.new(192, 192, 192, 255)
     ActiveFontColor          = Color.new(  0,   0,   0, 255)

    EMPTYBMP = Bitmap.new 8, 8

    def self.mkc(*i, &b)
      mkb = Bitmap.new 32, 32
      mkb.fill_rect 0, 0, 32, 32, Color.new(*i)
      mkb.fill_rect 2, 2, 28, 28, Color.new(0, 0, 0, 0)
      b.call(mkb) if b
      return mkb
    end

    MkC = proc{|b|
      b.fill_rect  4,  0, 24,  2, Color.new(0, 0, 0, 0)
      b.fill_rect  0,  4,  2, 24, Color.new(0, 0, 0, 0)
      b.fill_rect 30,  4,  2, 24, Color.new(0, 0, 0, 0)
      b.fill_rect  4, 30, 24,  2, Color.new(0, 0, 0, 0)
    }

    mKcW = (0..32).map{|i|mkc     8*i,     8*i,     8*i, 8*i}
    mKCW = (0..32).map{|i|mkc     8*i,     8*i,     8*i, 8*i, &MkC}
    mKcB = (0..32).map{|i|mkc 255-8*i, 255-8*i, 255-8*i, 8*i}
    mKCB = (0..32).map{|i|mkc 255-8*i, 255-8*i, 255-8*i, 8*i, &MkC}
    mkcr = (0..32).map{|i|mkc     8*i,       0,       0, 8*i}
    mKcr = (0..32).map{|i|mkc     8*i,       0,       0, 8*i, &MkC}
    mkcg = (0..32).map{|i|mkc       0,     8*i,       0, 8*i}
    mKcg = (0..32).map{|i|mkc       0,     8*i,       0, 8*i, &MkC}
    mkcb = (0..32).map{|i|mkc       0,       0,     8*i, 8*i}
    mKcb = (0..32).map{|i|mkc       0,       0,     8*i, 8*i, &MkC}
    mkcc = (0..32).map{|i|mkc       0,     8*i,     8*i, 8*i}
    mKcc = (0..32).map{|i|mkc       0,     8*i,     8*i, 8*i, &MkC}
    mkcm = (0..32).map{|i|mkc     8*i,       0,     8*i, 8*i}
    mKcm = (0..32).map{|i|mkc     8*i,       0,     8*i, 8*i, &MkC}
    mkcy = (0..32).map{|i|mkc     8*i,     8*i,       0, 8*i}
    mKcy = (0..32).map{|i|mkc     8*i,     8*i,       0, 8*i, &MkC}
    mkcW = (0..95).map{|i|mKcW[i/3]}
    mkcB = (0..95).map{|i|mKcB[i/3]}
    mkCW = (0..95).map{|i|mKCW[i/3]}
    mkCB = (0..95).map{|i|mKCB[i/3]}

    BlinkCB     = mkCW + mkCW.reverse + mkCB + mkCB.reverse
    BlinkWB     = mkcW + mkcW.reverse + mkcB + mkcB.reverse
    BlinkAll    = mkcr + mkcr.reverse + mkcg + mkcg.reverse + mkcb + mkcb.reverse +
                  mkcm + mkcm.reverse + mkcy + mkcy.reverse + mkcc + mkcc.reverse
    BlinkCA     = mKcr + mKcr.reverse + mKcg + mKcg.reverse + mKcb + mKcb.reverse +
                  mKcm + mKcm.reverse + mKcy + mKcy.reverse + mKcc + mKcc.reverse

  end

  module Kboard
    #==========================================================================
    Mouse_L       = 0x01        # left mouse button
    Mouse_R       = 0x02        # right mouse button
    Mouse_M       = 0x04        # middle mouse button
    Mouse_4       = 0x05        # 4th mouse button
    Mouse_5       = 0x06        # 5th mouse button
    #--------------------------------------------------------------------------
    Key_BACK      = 0x08        # BACKSPACE key
    Key_TAB       = 0x09        # TAB key
    Key_RETURN    = 0x0D        # ENTER key
    Key_SHIFT     = 0x10        # SHIFT key
    Key_CTLR      = 0x11        # CTLR key
    Key_ALT       = 0x12        # ALT key
    Key_PAUSE     = 0x13        # PAUSE key
    Key_CAPITAL   = 0x14        # CAPS LOCK key
    Key_ESCAPE    = 0x1B        # ESC key
    Key_SPACE     = 0x20        # SPACEBAR
    Key_PRIOR     = 0x21        # PAGE UP key
    Key_NEXT      = 0x22        # PAGE DOWN key
    Key_END       = 0x23        # END key
    Key_HOME      = 0x24        # HOME key
    Key_LEFT      = 0x25        # LEFT ARROW key
    Key_UP        = 0x26        # UP ARROW key
    Key_RIGHT     = 0x27        # RIGHT ARROW key
    Key_DOWN      = 0x28        # DOWN ARROW key
    Key_SELECT    = 0x29        # SELECT key
    Key_PRINT     = 0x2A        # PRINT key
    Key_BB        = 0x2B        # SELECT key
    Key_SNAPSHOT  = 0x2C        # PRINT SCREEN key
    Key_INSERT    = 0x2D        # INS key
    Key_DELETE    = 0x2E        # DEL key
    #--------------------------------------------------------------------------
    Key_0         = 0x30        # 0 key
    Key_1         = 0x31        # 1 key
    Key_2         = 0x32        # 2 key
    Key_3         = 0x33        # 3 key
    Key_4         = 0x34        # 4 key
    Key_5         = 0x35        # 5 key
    Key_6         = 0x36        # 6 key
    Key_7         = 0x37        # 7 key
    Key_8         = 0x38        # 8 key
    Key_9         = 0x39        # 9 key
    #--------------------------------------------------------------------------
    Key_A         = 0x41        # A key
    Key_B         = 0x42        # B key
    Key_C         = 0x43        # C key
    Key_D         = 0x44        # D key
    Key_E         = 0x45        # E key
    Key_F         = 0x46        # F key
    Key_G         = 0x47        # G key
    Key_H         = 0x48        # H key
    Key_I         = 0x49        # I key
    Key_J         = 0x4A        # J key
    Key_K         = 0x4B        # K key
    Key_L         = 0x4C        # L key
    Key_M         = 0x4D        # M key
    Key_N         = 0x4E        # N key
    Key_O         = 0x4F        # O key
    Key_P         = 0x50        # P key
    Key_Q         = 0x51        # Q key
    Key_R         = 0x52        # R key
    Key_S         = 0x53        # S key
    Key_T         = 0x54        # T key
    Key_U         = 0x55        # U key
    Key_V         = 0x56        # V key
    Key_W         = 0x57        # W key
    Key_X         = 0x58        # X key
    Key_Y         = 0x59        # Y key
    Key_Z         = 0x5A        # Z key
    #--------------------------------------------------------------------------
    Key_LWIN      = 0x5B        # Left Windows key (Microsoft Natural keyboard)
    Key_RWIN      = 0x5C        # Right Windows key (Natural keyboard)
    Key_APPS      = 0x5D        # Applications key (Natural keyboard)
    #--------------------------------------------------------------------------
    Key_NUMPAD0   = 0x60        # Numeric keypad 0 key
    Key_NUMPAD1   = 0x61        # Numeric keypad 1 key
    Key_NUMPAD2   = 0x62        # Numeric keypad 2 key
    Key_NUMPAD3   = 0x63        # Numeric keypad 3 key
    Key_NUMPAD4   = 0x64        # Numeric keypad 4 key
    Key_NUMPAD5   = 0x65        # Numeric keypad 5 key
    Key_NUMPAD6   = 0x66        # Numeric keypad 6 key
    Key_NUMPAD7   = 0x67        # Numeric keypad 7 key
    Key_NUMPAD8   = 0x68        # Numeric keypad 8 key
    Key_NUMPAD9   = 0x69        # Numeric keypad 9 key
    Key_MULTIPLY  = 0x6A        # Multiply key (*)
    Key_ADD       = 0x6B        # Add key (+)
    Key_SEPARATOR = 0x6C        # Separator key
    Key_SUBTRACT  = 0x6D        # Subtract key (-)
    Key_DECIMAL   = 0x6E        # Decimal key
    Key_DIVIDE    = 0x6F        # Divide key (/)
    #--------------------------------------------------------------------------
    Key_F1        = 0x70        # F1 key
    Key_F2        = 0x71        # F2 key
    Key_F3        = 0x72        # F3 key
    Key_F4        = 0x73        # F4 key
    Key_F5        = 0x74        # F5 key
    Key_F6        = 0x75        # F6 key
    Key_F7        = 0x76        # F7 key
    Key_F8        = 0x77        # F8 key
    Key_F9        = 0x78        # F9 key
    Key_F10       = 0x79        # F10 key
    Key_F11       = 0x7A        # F11 key
    Key_F12       = 0x7B        # F12 key
    #--------------------------------------------------------------------------
    Key_NUMLOCK   = 0x90        # NUM LOCK key
    Key_SCROLL    = 0x91        # SCROLL LOCK key
    #--------------------------------------------------------------------------
    Key_LSHIFT    = 0xA0        # Left SHIFT key
    Key_RSHIFT    = 0xA1        # Right SHIFT key
    Key_LCONTROL  = 0xA2        # Left CONTROL key
    Key_RCONTROL  = 0xA3        # Right CONTROL key
    Key_L_ALT     = 0xA4        # Left ALT key
    Key_R_ALT     = 0xA5        # Right ALT key
    #--------------------------------------------------------------------------
    Key_SEP       = 0xBC        # , key
    Key_DASH      = 0xBD        # - key
    Key_DOTT      = 0xBE        # . Key
  end
end

#======================================================================#
#                               CC-BY-SA                               #
#======================================================================#
[/pre]
[/fold]
[fold=map_editor.rb]
[pre lang="ruby"]#!/usr/bin/env ruby
#coding:utf-8

#======================================================================#
#             [LibRGSSS] Ruby Game Slight Scripting System             #
#----------------------------------------------------------------------#
# This project is licensed under the                                   #
# Creative Commons Attribution-ShareAlike 4.0 International License.   #
#======================================================================#

module RGSSSEditor

  def kload(pth, lib='rgsss_editor', base='./lib')
    eval File.read "#{ base }/#{ lib }/#{ pth }"
  end
  module_function :kload

  kload 'ebrgss_compatible_toolkit/toolkit.rb', 'rgsss/extension'

  include RGSSS

  MAX_LAYER = LazyUI::DefaultWindowZIndex

  SAVE_FILE = './output/map.csv'

  Title = '[Project-LibRGSSS] RGSS Compatible Tilesets Editor'
  HMsg1 = [
    %q{`PN' to navigate Tileset ( Previous / Next )},
    %q{`EB' to move Tileset ( End / Back )},
    %q{`UD' to navigate Layer ( Up / Down )},
    %q{`HJKL' or <Arrow> keys to move Cursor ( left / down / up / right )},
  ]
  HMsg2 = [
    %q{`T' or <Tab> key to switch between Tileset and Canvas},
    %q{`I' or <Space> key to paint on Canvas or toggle Blocks on Tileset},
    %q{`X' or <Delete> key to clean Blocks on Canvas},
    %q{`R' or <Backspace> key to clean selection on Tileset},
  ]
  HMsg3 = [
    %q{<Escape> key to type command},
    %q{Command `:HELP' to show help message},
    %q{Command `:R' to load},
    %q{Command `:W' to save},
    %q{Command `:W' to exit},
  ]
  %q{<Enter> key to edit Block ( Unsupported yet, finish it yourself please)}

  if LazyUI::window_width < 1280 || LazyUI::window_height < 720
    print "HELP MESSAGE: \n\n" + ( HMsg1 + HMsg2 + HMsg3 ).join(". \n") + ".\n\n" + '-' * 80 +
      "\n\nTo avoid this message, keep your window NOT LESS THAN 1280x720 please.\n"
  end

  BMPs = {}

  loadtime = Time.new
  (
    Dir['./Graphics/Tilesets/*' ] +
    []#Dir['./Graphics/Autotiles/*']
  ).each_with_index { |e, idx|
    if Time.new - loadtime > 1
      loadtime = Time.new
      Graphics.update
    end
    loadbmp = Bitmap.new e
    BMPs[e] = [loadbmp, loadbmp.width / 32, loadbmp.height / 32]
  }

  CursorPassive = LazyUI::BlinkWB
  CursorActive  = LazyUI::BlinkAll

  MaxCanvasX = proc{ [ (LazyUI::window_width - $app[:mapx]) / 32 , 8].max }
  MaxCanvasY = proc{ [ (LazyUI.by - LazyUI.ty) / 32     , 8].max }

  canvasMapAll = proc{|b|
    (0..MaxCanvasX[]).each{|mx|(0..MaxCanvasY[]).each{|my|
      dx = $app[:cx] +             (mx - $app[:dx])
      dy = $app[:cy] + $app[:ty] + (my - $app[:dy])
      b.call mx, my, dx, dy
    }}
  }

  $app = {
    :tid    => 0,
    :cid    => 0,
    :list   => BMPs.to_a.sort,
    :bmps   => BMPs.to_a.sort.collect{|k, (w, *_)| w },
    :posx   => 0,
    :posy   => 0,
    :mapx   => 0,
    :mapy   => 0,
    :cx     => 0,
    :cy     => 0,
    :dx     => 0,
    :dy     => 0,
    :ty     => 0,
    :active => 0,
    :layer  => 0,
    :cover  => false,
    :dst    => Hash.new{|h0,k0|h0[k0]=Hash.new{|h1,k1|nil}},
    :select => Hash.new{|h0,k0|h0[k0]=Hash.new{|h1,k1|nil}},
    :canvas => Hash.new{|h0,k0|h0[k0]=Hash.new{|h1,k1|h1[k1]=Hash.new{|h2,k2|nil}}}
  }

  class ECOMap < LazyUI::UniversalUI
    class MapPoint < Sprite
      attr_accessor :data
      def initialize(dx, dy, map, *a)
        @dx, @dy, @map = dx, dy, map
        super(*a)
        self.bitmap = ::Bitmap.new 32, 32
        reposition
      end
      def reposition
        self.x = @dx * 32 + @map.x
        self.y = @dy * 32 + @map.y
      end
    end
    def initialize(map, src, x, *a, &b)
      @map, @src = map, src
      super(*a, &b)
      self.bitmap = ::Bitmap.new 8, 8
      self.x = x
      self.z = MAX_LAYER
      @init = false
    end
    def refresh
      if Chkapp[$app] != @lstapp
        auto_resize RGSSSEditor::LazyUI.window_width, 0
        @lstapp = Chkapp[$app]
      end
      auto_resize RGSSSEditor::LazyUI.window_width, 0 unless @init
      @map.each{|kz, vz| vz.each{|kx, vx| vx.each{|ky, point|
        point.reposition
        point.z = kz
        point.z = MAX_LAYER + 1 if $app[:layer] == kz
      }}}
    end
    def draw(dx, dy, si, sx, sy, dz)
      c = @map[$app[:layer]][dx][dy] ||
        ( @map[$app[:layer]][dx][dy] ||= MapPoint.new(dx, dy, self) )
      c.bitmap.clear
      c.bitmap.blt 0, 0, @src[si], Rect.new(sx * 32, sy * 32, 32, 32)
      c.data = [dz, dx, dy, $app[:list][$app[:tid]][0], sx, sy]
    end
    def clean(dx, dy, si, sx, sy, sz)
      c = @map[$app[:layer]][dx][dy] ||
        ( @map[$app[:layer]][dx][dy] ||= MapPoint.new(dx, dy, self) )
      c.bitmap.clear
      c.data = nil
    end
    def auto_resize(w, h_)
      h = RGSSSEditor::LazyUI.by - RGSSSEditor::LazyUI.ty
      self.bitmap = Bitmap.new w - self.x, h
      self.bitmap.fill_rect 0, 0, w - self.x, h, Color.new(0, 0, 0, 192)
      @init = true
    end
  end

  class SelMap < LazyUI::UniversalUI
    class SelPoint < Sprite
      def initialize(dx, dy, map, *a)
        @dx, @dy, @map = dx, dy, map
        super(*a)
        self.bitmap = ::Bitmap.new 32, 32
        self.visible = false
        reposition
      end
      def reposition
        self.x = @dx * 32 + @map.x
        self.y = @dy * 32 + @map.y
        self.z = MAX_LAYER + 2
      end
    end
    def initialize(map, *a, &b)
      super([:float], *a, &b)
      @map = map
      self.bitmap = ::Bitmap.new 8, 8
    end
    def toggle(x, y)
      @map[x][y] = @map[x][y] || SelPoint.new(x, y, self)
      @map[x][y].visible = !@map[x][y].visible
    end
  end

  b  = proc {|i, a, x| (i + x) % a }
  ab = proc {|i, a, x| b[i, a.size, x] }

  Chkapp = proc{|a|next a[:layer], a[:cx], a[:cy] + a[:ty], a[:dx], a[:dy], a[:list][a[:tid]][0]}
  spapp  = proc{|app| sprintf '{%02d} (%02d,%02d) -> [%02d,%02d] ~ %s', *Chkapp[app] }

  man = proc{|str|
    str.gsub('/\A','').gsub('\Z/', '').gsub('|', ' | ').gsub('\A','').gsub('\Z','')
  }

  AppLoad = proc{|f|
  }
  AppSave = proc{|f|
    result = []
    $app[:canvas].each{|kz, vz| vz.each{|kx, vx| vx.each{|ky, point|
      result.push point.data.map{|e| e.inspect }.join(', ') if point and point.data
    }}}
    string = result.join("\n") + "\n"
    File.open(f, "w"){|file| file.write string }
  }

  CMDSTR = %q{# HELP MESSAGE:
case cmd
when /\AH\Z|\AHELP\Z/
  print man[CMDSTR]
  result = 'CMD HELP'
when /\AR\Z|\AREAD\Z/
  AppLoad[SAVE_FILE]
  result = sprintf 'Successfully READ from %s', SAVE_FILE
when /\AW\Z|\AWRITE\Z/
  AppSave[SAVE_FILE]
  result = sprintf 'Successfully WROTE to %s',  SAVE_FILE
when /\AQ\Z|\AQUIT\Z|\AEXIT\Z|\AEXITWITHOUTSAVING\Z/
  $exit = true
  result = 'CMD EXIT without saving'
when /\AX\Z|\AZZ\Z|\AWQ\Z|\AFINISH\Z|\ASAVEANDEXIT\Z/
  appSave[SAVE_FILE]
  $exit = true
  result = 'CMD SAVE and exit'
when ''
  result = false
else
  result = 'Command Error'
end
}

  cmdproc = proc {|update_block|

    cmd = ''
    timer = Time.new
    cmdio = true
    ioptr = true
    result = nil
    while true
      cmd = ''  if LazyUI.key? Kboard::Key_ESCAPE
      cmd.chop! if LazyUI.key? Kboard::Key_BACK
      break     if LazyUI.key? Kboard::Key_RETURN
      if l = LazyUI.fetch_letter
        cmd += l
      end
      iot = Time.new
      if iot - timer >= 1
        timer = iot
        ioptr = !ioptr
      end
      update_block.call cmd, ioptr if update_block
      LazyUI.update
      Graphics.update
    end

    eval CMDSTR

    next result

  }

  $exit = false

  Graphics.frame_rate = 60

  LazyUI.screen(
    LazyUI::Window.new(Title, [:title]),
    LazyUI::Window.new('', [:dark, :mono, :status]){
      cmdexit = nil
      if LazyUI.key? Kboard::Key_ESCAPE
        $app[:cover].z = 64
        cmdexit = cmdproc[proc{|cmd, ioptr| @text = ":#{ cmd }#{ ioptr ? '_' : '' }"; refresh }]
      end
      $app[:cover].z = -2
      $app[:tid] = ab[$app[:tid], $app[:list], -1] if LazyUI.key? Kboard::Key_P
      $app[:tid] = ab[$app[:tid], $app[:list],  1] if LazyUI.key? Kboard::Key_N
      @text = spapp[$app]
      @text = cmdexit if cmdexit
      if Chkapp[$app] != @lstapp or cmdexit != nil
        refresh
        @lstapp = Chkapp[$app]
      end
    },
    LazyUI::VerticalBar.new(0, 32, LazyUI::DarkBackGroundColorZ),
    LazyUI::Picture.new(nil, [:float]){
      self.bitmap = $app[:list][$app[:tid]][1][0]
      $app[:tilex] = self.bitmap.width + 32
      sp = 32 * ( $app[:list][$app[:tid]][1][2] - 1 )
      self.oy = [ self.oy + 32, sp].min if LazyUI.key? Kboard::Key_E
      self.oy = [ self.oy - 32,  0].max if LazyUI.key? Kboard::Key_B
      $app[:ty] = self.oy / 32
      $app[:posx] = self.x = 32; $app[:posy] = self.y
    },
    LazyUI::Picture.new(CursorPassive[$app[:cid]], [:float]){
      self.bitmap = ($app[:active] == 0) ? CursorActive[$app[:cid]] : CursorPassive[$app[:cid]]
      self.x = $app[:posx] + 32 * $app[:cx]
      self.y = $app[:posy] + 32 * $app[:cy]
      self.z = MAX_LAYER + 2
      t = $app[:list][$app[:tid]][1]
      x0 = [LazyUI::window_width / 32, t[1]            ].min
      y0 = [MaxCanvasY[],              t[2] - $app[:ty]].min
      $app[:cy] = [[0, $app[:cy]].max, t[2] - $app[:ty] - 1].min
      next unless $app[:active] == 0
      $app[:cx] = b[$app[:cx], x0, -1] if LazyUI.key?(Kboard::Key_H) or
                                          LazyUI.key?(Kboard::Key_LEFT)
      $app[:cy] = b[$app[:cy], y0,  1] if LazyUI.key?(Kboard::Key_J) or
                                          LazyUI.key?(Kboard::Key_DOWN)
      $app[:cy] = b[$app[:cy], y0, -1] if LazyUI.key?(Kboard::Key_K) or
                                          LazyUI.key?(Kboard::Key_UP)
      $app[:cx] = b[$app[:cx], x0,  1] if LazyUI.key?(Kboard::Key_L) or
                                          LazyUI.key?(Kboard::Key_RIGHT)
    },
    SelMap.new($app[:select]){
      self.x = $app[:posx]; self.y = $app[:posy] - 32 * $app[:ty]
      if $app[:active] == 0 and LazyUI.key? Kboard::Key_SPACE
        toggle $app[:cx], $app[:cy] + $app[:ty]
      end
      @map.each{|kx, vx| vx.each{|ky, point|
        z = ($app[:active] == 0) ? LazyUI::BlinkCA : LazyUI::BlinkCB
        point.bitmap = z[$app[:cid]]
        point.reposition
      }}
    },
    LazyUI::VerticalBar.new(0, 32, LazyUI::DarkBackGroundColorZ){ self.x = $app[:tilex] },
    ECOMap.new($app[:canvas], $app[:bmps], 256 + 32 * 2, [:float]){
      if $app[:active] == 1 and LazyUI.key?(Kboard::Key_I) or LazyUI.key?(Kboard::Key_SPACE)
        sf = false
        canvasMapAll[proc{|mx, my, dx, dy|
          s = $app[:select][dx][dy]
          if s and s.visible
            draw mx, my, $app[:tid], dx, dy, $app[:layer]
            sf = true
          end
        }]
        unless sf
          draw $app[:dx], $app[:dy], $app[:tid], $app[:cx], $app[:cy] + $app[:ty], $app[:layer]
        end
      end
      if $app[:active] == 1 and LazyUI.key?(Kboard::Key_X) or LazyUI.key?(Kboard::Key_DELETE)
        sf = false
        canvasMapAll[proc{|mx, my, dx, dy|
          s = $app[:select][dx][dy]
          if s and s.visible
            clean mx, my, $app[:tid], dx, dy, $app[:layer]
            sf = true
          end
        }]
        unless sf
          clean $app[:dx], $app[:dy], $app[:tid], $app[:cx], $app[:cy] + $app[:ty], $app[:layer]
        end
      end
      $app[:layer] = [$app[:layer] + 1, MAX_LAYER].min if LazyUI.key?(Kboard::Key_U)
      $app[:layer] = [$app[:layer] - 1,         0].max if LazyUI.key?(Kboard::Key_D)
      $app[:mapx] = self.x = 32 + $app[:tilex]; $app[:mapy] = self.y
      refresh
    },
    LazyUI::Picture.new(CursorPassive[$app[:cid]], [:float]){
      self.bitmap = ($app[:active] == 1) ? CursorActive[$app[:cid]] : CursorPassive[$app[:cid]]
      self.x = $app[:mapx] + 32 * $app[:dx]
      self.y = $app[:mapy] + 32 * $app[:dy]
      self.z = MAX_LAYER + 2
      next unless $app[:active] == 1
      $app[:dx] = b[$app[:dx], MaxCanvasX[], -1] if LazyUI.key?(Kboard::Key_H) or
                                                    LazyUI.key?(Kboard::Key_LEFT)
      $app[:dy] = b[$app[:dy], MaxCanvasY[],  1] if LazyUI.key?(Kboard::Key_J) or
                                                    LazyUI.key?(Kboard::Key_DOWN)
      $app[:dy] = b[$app[:dy], MaxCanvasY[], -1] if LazyUI.key?(Kboard::Key_K) or
                                                    LazyUI.key?(Kboard::Key_UP)
      $app[:dx] = b[$app[:dx], MaxCanvasX[],  1] if LazyUI.key?(Kboard::Key_L) or
                                                    LazyUI.key?(Kboard::Key_RIGHT)
    },
    SelMap.new($app[:dst]){
      self.x = $app[:mapx]; self.y = $app[:mapy]
      canvasMapAll[proc{|mx, my, dx, dy|
        @map[mx][my] = @map[mx][my] || SelMap::SelPoint.new(mx, my, self)
        @map[mx][my].visible = $app[:select][dx][dy] ? $app[:select][dx][dy].visible : false
      }]
      @map.each{|kx, vx| vx.each{|ky, point|
        z = ($app[:active] == 1) ? LazyUI::BlinkCA : LazyUI::BlinkCB
        point.bitmap = z[$app[:cid]]
        point.reposition
      }}
    },
    LazyUI::Window.new(HMsg1.join(', ') + '. ', [:dark, :info, :bottom, :hint]),
    LazyUI::Window.new(HMsg2.join(', ') + '. ', [:dark, :info, :bottom, :hint]),
    LazyUI::Window.new(HMsg3.join(', ') + '. ', [:dark, :info, :bottom, :hint]),
    LazyUI::CanvasBack.new,
    LazyUI::CanvasCover.new{$app[:cover] = self}
  ){
    $app[:cid]    = ab[$app[:cid],   CursorPassive, 1]
    $app[:active] =  b[$app[:active],            2, 1] if false or
      LazyUI.key?(Kboard::Key_T) or LazyUI.key?(Kboard::Key_TAB)
    $app[:select].each{|kx, vx|vx.each{|ky, vy| vy.visible = false if vy}} if false or
      LazyUI.key?(Kboard::Key_R) or LazyUI.key?(Kboard::Key_BACK)
    LazyUI.update
    next !$exit
  }

end

#======================================================================#
#                               CC-BY-SA                               #
#======================================================================#
[/pre]
[/fold]




评分

参与人数 2星屑 +566 收起 理由
莫言别离 + 66 塞糖
唯道集虚 + 500 塞糖

查看全部评分

Role Play Games had saved me, but I can never save them.
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部