Advertisement
KoBeWi

Marshal Explorer

Apr 23rd, 2017
391
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 5.11 KB | None | 0 0
  1. require 'gosu'
  2.  
  3. FONT_HEIGHT = 24
  4.  
  5. def hack_in_new_class_or_module_lol(new)
  6.   if new.end_with?("::")
  7.     eval "module #{new.chomp("::")}; end"
  8.   else
  9.     eval "class #{new}; end"
  10.   end
  11. end
  12.  
  13. class Container
  14.   attr_reader :x,:y,:child
  15.  
  16.   def initialize(x,y,kind,type,name,child)
  17.     @x,@y,@kind,@type,@name,@child=x,y,kind,type,name,child
  18.   end
  19.  
  20.   def draw(scx)
  21.     return if @x-scx>$main.width or @x+w-scx<0
  22.     h=FONT_HEIGHT
  23.     Gosu::draw_quad(@x,@y,c=(@selected ? 0xffc09000 : contains? ? 0xff208020 : 0xff404040),@x+w,@y,c,@x+w,@y+h,c,@x,@y+h,c,0)
  24.     $font.draw(text,@x+2,@y+2,1)
  25.   end
  26.  
  27.   def w
  28.     @w ||= $font.text_width(text)+4
  29.   end
  30.  
  31.   def text
  32.     @text ||=
  33.     case @kind
  34.       when :hash
  35.       @name.to_s + " => " + _child
  36.       when :array
  37.       @name.to_s + ": " + _child
  38.       when :var
  39.       @name.to_s + " = " + _child
  40.       when :root
  41.       "FILE ROOT"
  42.     else
  43.       @name
  44.     end
  45.   end
  46.  
  47.   def _child
  48.     @_child ||= (@child.class==Hash ? "{}" : @child.class==Array ? "[]" : @child.to_s)
  49.   end
  50.  
  51.   def click(x,y)
  52.     if x.between?(@x,@x+w) and y.between?(@y,@y+FONT_HEIGHT)
  53.       $main.add_level(self)
  54.     end
  55.   end
  56.  
  57.   def contains?
  58.     @contains ||= (@child.class==Hash && !@child.empty? or @child.class==Array && !@child.empty? or !@child.instance_variables.empty?)
  59.   end
  60.  
  61.   def select
  62.     @selected=true
  63.   end
  64.  
  65.   def unselect
  66.     @selected=nil
  67.   end
  68. end
  69.  
  70. class PlaceholderClass
  71.   def initialize(name)
  72.     @name=name
  73.   end
  74.  
  75.   def to_s
  76.     "/#{@name}/"
  77.   end
  78.  
  79.   def instance_variables
  80.     []
  81.   end
  82. end
  83.  
  84. class String
  85.   def to_s
  86.     return "\"#{self}\""
  87.   end
  88. end
  89.  
  90. class Symbol
  91.   def to_s
  92.     return ":#{self.id2name}"
  93.   end
  94. end
  95.  
  96. class GameWindow < Gosu::Window
  97.   def initialize
  98.     super(800, 600, false)
  99.     self.caption = "Marshal Explorer"
  100.     $font=Gosu::Font.new(self,"Courier New",FONT_HEIGHT)
  101.    
  102.     reset
  103.   end
  104.  
  105.   def update
  106.     if @drag
  107.       @scx=@drag[0]-(mouse_x-@drag[2])*(button_down?(Gosu::KbLeftShift) ? 10 : 1)
  108.       @scy=@drag[1]-(mouse_y-@drag[3])
  109.     end
  110.   end
  111.  
  112.   def draw
  113.     translate(-@scx,-@scy) do
  114.       @hierarchy.flatten.each do |c|
  115.         c.draw(@scx)
  116.       end
  117.     end
  118.    
  119.     $font.draw("Drop file into window to inspect", 16, 16, 100, 1, 1, Gosu::Color::RED) if @hierarchy.flatten.length == 1
  120.   end
  121.  
  122.   def button_down(id)
  123.     if id==Gosu::MsLeft
  124.       @hierarchy.flatten.each do |c|
  125.         c.click(mouse_x+@scx,mouse_y+@scy)
  126.       end
  127.     end
  128.    
  129.     if id==Gosu::MsRight
  130.       @drag=[@scx,@scy,mouse_x,mouse_y]
  131.     end
  132.    
  133.     if id==Gosu::KbHome
  134.       @scx=@scy=-64
  135.     end
  136.   end
  137.  
  138.   def button_up(id)
  139.     if id==Gosu::MsRight
  140.       @drag=nil
  141.     end
  142.   end
  143.  
  144.   def container?(item)
  145.     item.class==Array or item.class==Hash or item.class==HashKey && container?(item.v)
  146.   end
  147.  
  148.   def raze(base)
  149.     base_level=@hierarchy.index(@hierarchy.find{|h| h.include?(base)})
  150.     if base_level
  151.       @hierarchy.delete_if{|ar| @hierarchy.index(ar)>base_level}
  152.       @hierarchy.last.each{|h| h.unselect}
  153.     end
  154.     base.select if base
  155.    
  156.     @hierarchy << []
  157.   end
  158.  
  159.   def add_level(base)
  160.     return if base and !base.contains?
  161.     if !base
  162.       raze(base)
  163.       @hierarchy.last << Container.new(0,0,:root,$data.class,"ROOT",$data)
  164.     elsif base.child.class==Hash
  165.       raze(base)
  166.       x=base.x
  167.       base.child.each_pair do |k,v|
  168.         @hierarchy.last << Container.new(x,base.y+FONT_HEIGHT+8,:hash,v.class,k,v)
  169.         x+=@hierarchy.last.last.w+8
  170.       end
  171.     elsif base.child.class==Array
  172.       raze(base)
  173.       x=base.x
  174.       i=0
  175.       base.child.each do |v|
  176.         @hierarchy.last << Container.new(x,base.y+FONT_HEIGHT+8,:array,v.class,i,v)
  177.         x+=@hierarchy.last.last.w+8
  178.         i+=1
  179.       end
  180.     else
  181.       raze(base)
  182.       x=base.x
  183.       base.child.instance_variables.each do |k|
  184.         v=base.child.instance_variable_get(k)
  185.         @hierarchy.last << Container.new(x,base.y+FONT_HEIGHT+8,:var,v.class,k,v)
  186.         x+=@hierarchy.last.last.w+8
  187.       end
  188.     end
  189.   end
  190.  
  191.   def needs_cursor?
  192.     true
  193.   end
  194.  
  195.   def reset
  196.     @hierarchy=[]
  197.     add_level(nil)
  198.     @scx=@scy=-64
  199.   end
  200.  
  201.   def drop(file)
  202.     $data = []
  203.     $file = nil
  204.  
  205.     while true
  206.       begin
  207.         $file ||= File.new(file, "r")
  208.         $data << Marshal.load($file)
  209.       rescue ArgumentError => ae #undefined class/module
  210.         next if !ae.to_s.start_with?("undefined")
  211.         break if ae.to_s.include?("dump format error")
  212.         $file=nil
  213.         $data.clear
  214.        
  215.         new=ae.to_s.split.last
  216.        
  217.         hack_in_new_class_or_module_lol(new)
  218.       rescue TypeError => te #class needs to have method _load
  219.         next if !te.to_s.start_with?("class")
  220.        
  221.         new=te.to_s.split[1]
  222.        
  223.         $file=nil
  224.         $data.clear
  225.        
  226.         eval "class #{new}; def self._load(data); return PlaceholderClass.new('#{new}') end end"
  227.       rescue EOFError
  228.         break
  229.       end
  230.     end
  231.    
  232.     reset
  233.   end
  234. end
  235.  
  236. begin
  237.   require_relative "ClassSupply.rb"
  238. rescue LoadError
  239. end
  240.  
  241. ($main=GameWindow.new).show
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement