gui.rb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. ## $Id$
  2. ##
  3. ## Flexlay - A Generic 2D Game Editor
  4. ## Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
  5. ##
  6. ## This program is free software: you can redistribute it and/or modify
  7. ## it under the terms of the GNU General Public License as published by
  8. ## the Free Software Foundation, either version 3 of the License, or
  9. ## (at your option) any later version.
  10. ##
  11. ## This program is distributed in the hope that it will be useful,
  12. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ## GNU General Public License for more details.
  15. ##
  16. ## You should have received a copy of the GNU General Public License
  17. ## along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. require "layout_component.rb"
  19. $guilayout_spec = \
  20. [:vbox,
  21. [:components,
  22. [:menubar,
  23. [:name, 'menubar'],
  24. [:size, 23]],
  25. [:buttonpanel,
  26. [:name, 'buttonpanel'],
  27. [:size, 33]],
  28. [:hbox,
  29. [:components,
  30. [:editormap,
  31. [:name, 'editormap']],
  32. [:panel,
  33. [:layout, :vbox],
  34. [:size, 134],
  35. [:components,
  36. [:tab,
  37. [:padding, 3],
  38. [:components,
  39. [:listbox,
  40. [:name, 'brushbox']],
  41. [:objectselector,
  42. [:name, 'objectselector']]]],
  43. [:minimap,
  44. [:padding, 3],
  45. [:size, 134],
  46. [:name, 'minimap']]]]]]]]
  47. class GUI
  48. attr_reader :workspace, :minimap, :editor_map
  49. def initialize()
  50. @gui = GUIManager.new()
  51. components = LayoutComponent.create_from_sexpr(CL_Rect.new(0,0, $screen.width, $screen.height),
  52. SExpression.new($guilayout_spec),
  53. @gui.get_component())
  54. connect_v2_graceful($flexlay.sig_resize(), proc{|w, h|
  55. components.set_size(w, h)
  56. })
  57. @editor_map = components.get('editormap').component
  58. @workspace = @editor_map.get_workspace()
  59. @brushbox = components.get('brushbox').component
  60. @brushbox.show(false)
  61. @objectselector = components.get('objectselector').component
  62. @objectselector.add_brush(ObjectBrush.new(GameObjects::Outpost.get_sprite(),
  63. make_metadata(proc{GameObjects::Outpost.new()})))
  64. @objectselector.add_brush(ObjectBrush.new(GameObjects::SpawnPoint.get_sprite(),
  65. make_metadata(proc{GameObjects::SpawnPoint.new()})))
  66. $brushes.size.times {|i|
  67. @objectselector.add_brush(ObjectBrush.new(make_sprite($config.datadir + "/thumbnails/#{i}.png"),
  68. make_metadata(proc{GameObjects::TileObject.new(i)})))
  69. }
  70. @objectselector.show(true)
  71. connect_v2_ObjectBrush_Point(@objectselector.sig_drop(), method(:on_object_drop))
  72. connect_v1(@brushbox.sig_highlighted(), method(:brushbox_change))
  73. @workspace.set_tool(0, $tilemap_paint_tool.to_tool());
  74. @workspace.set_tool(2, $workspace_move_tool.to_tool());
  75. @button_panel = components.get('buttonpanel').component
  76. @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_new.png",
  77. proc{ gui_level_new() })
  78. @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_open.png",
  79. proc{ gui_level_load() })
  80. @button_panel.add_small_icon($flexlay_datadir + "/images/icons24/downarrow.png",
  81. proc{ gui_level_load() })
  82. @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_save.png",
  83. proc{ gui_level_save() })
  84. @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_save_as.png",
  85. proc{ gui_level_save_as() })
  86. @button_panel.add_separator()
  87. @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_copy.png", proc{})
  88. @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_paste.png", proc{})
  89. @button_panel.add_separator()
  90. @undo_icon = @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_undo.png", proc{@workspace.get_map().undo()})
  91. @redo_icon = @button_panel.add_icon($flexlay_datadir + "/images/icons24/stock_redo.png", proc{@workspace.get_map().redo()})
  92. @button_panel.add_separator()
  93. @tool_button_panel = ButtonPanel.new(320, 23, $screen.width, 33, true, @gui.get_component)
  94. @tool_button_panel.add_separator()
  95. @tool_button_panel.add_icon($flexlay_datadir + "/images/icons24/object_raise.png", proc{
  96. $objmap_select_tool.get_selection().each {|obj|
  97. @workspace.get_map().get_data().objects.raise(obj)
  98. }
  99. })
  100. @tool_button_panel.add_icon($flexlay_datadir + "/images/icons24/object_lower.png", proc{
  101. $objmap_select_tool.get_selection().each {|obj|
  102. @workspace.get_map().get_data().objects.lower(obj)
  103. }
  104. })
  105. @tool_button_panel.show(false)
  106. @toolbar = ButtonPanel.new(0, 23+33, 33, 32*4+2, false, @gui.get_component())
  107. @paint = @toolbar.add_icon($flexlay_datadir + "/images/tools/stock-tool-pencil-22.png",
  108. method(:set_tilemap_paint_tool))
  109. @select = @toolbar.add_icon($flexlay_datadir + "/images/tools/stock-tool-rect-select-22.png",
  110. method(:set_tilemap_select_tool))
  111. @zoom = @toolbar.add_icon($flexlay_datadir + "/images/tools/stock-tool-zoom-22.png",
  112. method(:set_zoom_tool))
  113. @object = @toolbar.add_icon($flexlay_datadir + "/images/tools/stock-tool-clone-22.png",
  114. method(:set_objmap_select_tool))
  115. $brushes.each {|i|
  116. (index, width, height, name) = i
  117. @brushbox.insert_item("%s - %sx%s" % [name, width, height])
  118. }
  119. @menu = components.get('menubar').component
  120. @menu.add_item("File/New...", proc{gui_level_new})
  121. @menu.add_item("File/Open...", proc{gui_level_load})
  122. @menu.add_item("File/Save...", proc{gui_level_save})
  123. @menu.add_item("File/Save As...", proc{gui_level_save_as})
  124. @menu.add_item("File/Quit", proc{@gui.quit})
  125. @menu.add_item("Zoom/1:4 (25%) ", proc{ gui_set_zoom(0.25) })
  126. @menu.add_item("Zoom/1:2 (50%) ", proc{ gui_set_zoom(0.5) })
  127. @menu.add_item("Zoom/1:1 (100%) ", proc{ gui_set_zoom(1.0) })
  128. @menu.add_item("Zoom/2:1 (200%) ", proc{ gui_set_zoom(2.0) })
  129. @menu.add_item("Zoom/4:1 (400%) ", proc{ gui_set_zoom(4.0) })
  130. @menu.add_item("Scripts/Flatten", proc{ @workspace.get_map().get_data().flatten() })
  131. @menu.add_item("Scripts/Unflatten", proc{ @workspace.get_map().get_data().unflatten() })
  132. @minimap = components.get('minimap').component
  133. @load_dialog = SimpleFileDialog.new("Load netPanzer Level", "Load", "Cancel", @gui.get_component())
  134. @load_dialog.set_filename($config.datadir + "/maps/")
  135. @save_dialog = SimpleFileDialog.new("Save netPanzer Level as...", "Save", "Cancel", @gui.get_component())
  136. @save_dialog.set_filename($config.datadir + "/maps/")
  137. connect_v2(@editor_map.sig_on_key("l"), proc{ |x, y|
  138. $objmap_select_tool.get_selection().each {|obj|
  139. @workspace.get_map().get_data().objects.raise(obj)
  140. }
  141. })
  142. connect_v2(@editor_map.sig_on_key("s"), proc{ |x, y|
  143. $objmap_select_tool.get_selection().each {|obj|
  144. @workspace.get_map().get_data().objects.lower(obj)
  145. }
  146. })
  147. connect_v2($objmap_select_tool.sig_on_right_click(), proc{|x,y|
  148. puts "Launching Menu at #{x}, #{y}"
  149. menu = Menu.new(CL_Point.new(x-16, y-16), @gui.get_component())
  150. menu.add_item("Delete Selection", proc{
  151. cmd = ObjectDeleteCommand.new(@workspace.get_map().get_metadata().objects)
  152. $objmap_select_tool.get_selection().each { |i| cmd.add_object(i) }
  153. @workspace.get_map().execute(cmd.to_command())
  154. $objmap_select_tool.clear_selection()
  155. })
  156. menu.add_item("Flatten Selection", proc{
  157. @workspace.get_map().get_data().objects.get_objects().each{|obj|
  158. obj.get_data().draw_to_tilemap(@workspace.get_map().get_data().tilemap)
  159. }
  160. cmd = ObjectDeleteCommand.new(@workspace.get_map().get_metadata().objects)
  161. @workspace.get_map().execute(cmd.to_command())
  162. $objmap_select_tool.get_selection().each { |i| cmd.add_object(i) }
  163. @workspace.get_map().execute(cmd.to_command())
  164. $objmap_select_tool.clear_selection()
  165. })
  166. menu.add_separator()
  167. menu.add_item(make_sprite($flexlay_datadir + "/images/icons16/object_raise.png"),
  168. "Raise Selection", proc{
  169. $objmap_select_tool.get_selection().each {|obj|
  170. @workspace.get_map().get_data().objects.raise(obj)
  171. }
  172. })
  173. menu.add_item(make_sprite($flexlay_datadir + "/images/icons16/object_lower.png"),
  174. "Lower Selection", proc{
  175. $objmap_select_tool.get_selection().each {|obj|
  176. @workspace.get_map().get_data().objects.lower(obj)
  177. }
  178. })
  179. menu.run()
  180. })
  181. end
  182. def brushbox_change(index)
  183. (start, width, height, name) = $brushes[index]
  184. brush = TileBrush.new(width, height)
  185. brush.set_data(Range.new(start, start + width*height).to_a)
  186. $tilemap_paint_tool.set_brush(brush)
  187. end
  188. def on_object_drop(brush, pos)
  189. obj = get_ruby_object(brush.get_data()).call()
  190. pos = @editor_map.screen2world(pos)
  191. sprite_obj = ObjMapSpriteObject.new(obj.get_sprite(), pos, make_metadata(obj))
  192. obj.data = sprite_obj
  193. cmd = ObjectAddCommand.new(@workspace.get_map().get_data().objects)
  194. cmd.add_object(sprite_obj.to_object)
  195. @workspace.get_map().execute(cmd.to_command())
  196. end
  197. def set_tilemap_paint_tool()
  198. @workspace.set_tool(0, $tilemap_paint_tool.to_tool())
  199. @paint.set_down()
  200. @select.set_up()
  201. @zoom.set_up()
  202. @object.set_up()
  203. @brushbox.show(true)
  204. @objectselector.show(false)
  205. @tool_button_panel.show(false)
  206. end
  207. def set_tilemap_select_tool()
  208. @workspace.set_tool(0, $tilemap_select_tool.to_tool())
  209. @paint.set_up()
  210. @select.set_down()
  211. @zoom.set_up()
  212. @object.set_up()
  213. @brushbox.show(false)
  214. @objectselector.show(false)
  215. @tool_button_panel.show(false)
  216. end
  217. def set_zoom_tool()
  218. @workspace.set_tool(0, $zoom_tool.to_tool())
  219. @paint.set_up()
  220. @select.set_up()
  221. @zoom.set_down()
  222. @object.set_up()
  223. @brushbox.show(false)
  224. @objectselector.show(false)
  225. @tool_button_panel.show(false)
  226. end
  227. def set_objmap_select_tool()
  228. @workspace.set_tool(0, $objmap_select_tool.to_tool())
  229. @paint.set_up()
  230. @select.set_up()
  231. @zoom.set_up()
  232. @object.set_down()
  233. @brushbox.show(false)
  234. @objectselector.show(true)
  235. @tool_button_panel.show(true)
  236. end
  237. def gui_level_save()
  238. if @workspace.get_map().get_metadata().filename
  239. @save_dialog.set_filename(@workspace.get_map().get_metadata().filename)
  240. else
  241. @save_dialog.set_filename(File::dirname(@save_dialog.get_filename()) + "/")
  242. end
  243. @save_dialog.run(method(:netpanzer_save_level))
  244. end
  245. def gui_level_load()
  246. @load_dialog.run(method(:netpanzer_load_level))
  247. end
  248. def gui_level_new()
  249. dialog = GenericDialog.new("SecretArea Property Dialog", @gui.get_component())
  250. dialog.add_string("Name: ", "New Level")
  251. dialog.add_int("Width: ", 128)
  252. dialog.add_int("Height: ", 128)
  253. dialog.set_callback(proc{|name, width, height|
  254. level = Level.new(width, height)
  255. level.activate(@workspace)
  256. level.name = name
  257. connect(level.editormap.sig_change(), method(:on_map_change))
  258. })
  259. end
  260. def gui_set_zoom(zoom)
  261. gc = @editor_map.get_gc_state()
  262. pos = gc.get_pos()
  263. gc.set_zoom(zoom)
  264. gc.set_pos(pos)
  265. end
  266. def gui_level_save_as()
  267. @save_dialog.set_filename(File::dirname(@save_dialog.get_filename()) + "/")
  268. @save_dialog.run(method(:netpanzer_save_level))
  269. end
  270. def gui_toggle_grid()
  271. tilemap = $workspace.get_map().get_metadata().data.get_tilemap()
  272. #FIXMEgrid_status = not(tilemap.get_draw_grid())
  273. #tilemap.set_draw_grid(grid_status)
  274. if tilemap.get_draw_grid() then
  275. grid_icon.set_down()
  276. else
  277. grid_icon.set_up()
  278. grid_icon = Icon(CL_Rect(CL_Point(p.inc(48), 2), CL_Size(32, 32)),
  279. make_sprite($flexlay_datadir + "/images/icons24/grid.png"), "Some tooltip", button_panel);
  280. grid_icon.set_callback(proc{gui_toggle_grid})
  281. layer_menu = Menu(CL_Point(32*11+2, 54), $gui.get_component())
  282. end
  283. end
  284. def netpanzer_load_level(filename)
  285. level = Level.new(filename)
  286. level.activate($gui.workspace)
  287. connect(level.editormap.sig_change(), method(:on_map_change))
  288. # if not(has_element($config.recent_files, filename))
  289. # $config.recent_files.push(filename)
  290. # recent_files_menu.add_item(mysprite, filename, proc{ netpanzer_load_level(filename) })
  291. # end
  292. $gui.minimap.update_minimap()
  293. end
  294. def netpanzer_save_level(filename)
  295. $gui.workspace.get_map().get_data().save(filename)
  296. end
  297. # recent_files_menu = Menu.new(CL_Point.new(32*2, 54), $gui.get_component())
  298. # for filename in $config.recent_files
  299. # recent_files_menu.add_item(mysprite, filename, proc{ netpanzer_load_level(filename) })
  300. #end
  301. def on_map_change()
  302. if (@workspace.get_map().undo_stack_size() > 0)
  303. @undo_icon.enable()
  304. else
  305. @undo_icon.disable()
  306. end
  307. if (@workspace.get_map().redo_stack_size() > 0)
  308. @redo_icon.enable()
  309. else
  310. @redo_icon.disable()
  311. end
  312. end
  313. def run()
  314. @gui.run()
  315. end
  316. end
  317. # EOF #