21 |
#include "world.hh" |
#include "world.hh" |
22 |
#include "lua.hh" |
#include "lua.hh" |
23 |
#include "video.hh" |
#include "video.hh" |
24 |
|
#include "gui.hh" |
25 |
|
#include "objects.hh" |
26 |
#include "px/sdl.hh" |
#include "px/sdl.hh" |
27 |
|
//#include "px/windows.hh" |
28 |
#include <iostream> |
#include <iostream> |
29 |
|
|
30 |
#include "display.hh" |
#include "display.hh" |
37 |
|
|
38 |
using display::ScreenArea; |
using display::ScreenArea; |
39 |
using display::DisplayEngine; |
using display::DisplayEngine; |
40 |
|
using display::Model; |
41 |
|
using world::ObjectTraits; |
42 |
|
|
43 |
namespace |
namespace |
44 |
{ |
{ |
45 |
class Action { |
class EditorDisplay : public display::CommonDisplay { |
46 |
public: |
public: |
47 |
void perform() { on_perform(); } |
EditorDisplay(const ScreenArea &a); |
48 |
void undo() { on_undo(); } |
~EditorDisplay() {} |
49 |
|
|
50 |
|
void tick(double dtime) {} |
51 |
|
|
52 |
|
Model *make_model (const std::string &name); |
53 |
private: |
private: |
|
virtual void on_perform() = 0; |
|
|
virtual void on_undo() = 0; |
|
|
}; |
|
54 |
|
|
|
class Creator { |
|
|
public: |
|
|
virtual ~Creator() {} |
|
|
virtual void emit_code(ostream &os) = 0; |
|
55 |
}; |
}; |
56 |
|
|
57 |
class StoneCreator : public Creator { |
class IconBar : public gui::Container { |
58 |
public: |
public: |
59 |
private: |
IconBar (const ScreenArea &a, int rows, int cols) |
60 |
void emit_code(ostream &os) { |
: m_area (a), m_rows (rows), m_cols(cols), |
61 |
os << "set_stone(\"" << kind |
m_bgcolor (150,150,150) |
62 |
<< "\"," << pos.x << ","<<pos.y<<")\n"; |
{} |
|
} |
|
|
string kind; |
|
|
GridPos pos; |
|
|
}; |
|
|
} |
|
63 |
|
|
64 |
|
~IconBar() {} |
65 |
|
|
66 |
/* |
ScreenArea get_area() const { return m_area; } |
|
* This is the class that is responsible for displaying the level |
|
|
* currently being edited. |
|
|
*/ |
|
|
|
|
|
namespace |
|
|
{ |
|
|
class Image; |
|
67 |
|
|
68 |
class ImagePack { |
// Widget interface. |
69 |
public: |
void draw (px::GC &gc, const px::Rect &area) { |
70 |
static ImagePack *make_pack (int size); |
set_color (gc, m_bgcolor); |
71 |
|
box (gc, area); |
72 |
|
} |
73 |
|
|
74 |
union { |
private: |
75 |
struct { |
// Variables. |
76 |
int layerbits : 5; // Which layers are present? |
ScreenArea m_area; |
77 |
|
int m_rows, m_cols; |
78 |
} pack_info; |
px::RGB m_bgcolor; |
79 |
ImagePack *next_avail; |
|
|
}; |
|
|
Image *images[0]; |
|
80 |
}; |
}; |
81 |
|
|
|
} |
|
82 |
|
|
83 |
|
enum EditMode { |
84 |
//---------------------------------------------------------------------- |
MODE_FLOOR, |
85 |
// Level representation inside the level editor |
MODE_ITEMS, |
86 |
//---------------------------------------------------------------------- |
MODE_STONES, |
87 |
namespace |
MODE_ACTORS |
88 |
{ |
}; |
89 |
|
|
90 |
class Level { |
class Level { |
91 |
public: |
public: |
92 |
Level (); |
Level (); |
111 |
virtual void write_level (Level *l) = 0; |
virtual void write_level (Level *l) = 0; |
112 |
}; |
}; |
113 |
|
|
|
} |
|
114 |
|
|
|
Level::Level () |
|
|
{ |
|
|
} |
|
115 |
|
|
116 |
|
class Action { |
|
//---------------------------------------------------------------------- |
|
|
// Icon bar |
|
|
//---------------------------------------------------------------------- |
|
|
namespace |
|
|
{ |
|
|
class IconBar { |
|
117 |
public: |
public: |
118 |
IconBar (const ScreenArea &a) : m_area (a) {} |
void perform() { on_perform(); } |
119 |
~IconBar() {} |
void undo() { on_undo(); } |
120 |
|
private: |
121 |
|
virtual void on_perform() = 0; |
122 |
|
virtual void on_undo() = 0; |
123 |
|
}; |
124 |
|
|
125 |
ScreenArea get_area() const { return m_area; } |
class Tool { |
126 |
|
public: |
127 |
|
virtual ~Tool() {} |
128 |
|
|
129 |
|
}; |
130 |
|
|
131 |
|
class ItemTool : public Tool { |
132 |
|
public: |
133 |
|
}; |
134 |
|
|
135 |
|
class FloorTool : public Tool { |
136 |
|
public: |
137 |
|
}; |
138 |
|
|
139 |
|
class StoneTool : public Tool { |
140 |
|
public: |
141 |
|
}; |
142 |
|
|
143 |
|
class ActorTool : public Tool { |
144 |
|
public: |
145 |
|
}; |
146 |
|
|
147 |
|
class SignalTool : public Tool { |
148 |
|
public: |
149 |
|
}; |
150 |
|
|
151 |
|
|
152 |
|
class Editor : sdl::EventHandler { |
153 |
|
public: |
154 |
|
Editor(); |
155 |
|
~Editor(); |
156 |
|
|
157 |
|
void run(); |
158 |
|
|
159 |
|
void set_cursor (const string &name); |
160 |
|
|
161 |
private: |
private: |
162 |
|
// Private methods. |
163 |
|
void set_floor (int x, int y, const string &name); |
164 |
|
void set_item (int x, int y, const string &name); |
165 |
|
void set_stone (int x, int y, const string &name); |
166 |
|
|
167 |
|
void set_mode (EditMode m); |
168 |
|
|
169 |
|
void new_world (int w, int h); |
170 |
|
|
171 |
|
void scroll (double xoff, double yoff); |
172 |
|
void scroll_abs (double x, double y); |
173 |
|
|
174 |
|
// EventHandler interface. |
175 |
|
bool on_mousemotion (SDL_Event &e); |
176 |
|
bool on_mousebutton (SDL_Event &e); |
177 |
|
bool on_keydown (SDL_Event &e); |
178 |
|
|
179 |
// Variables. |
// Variables. |
180 |
ScreenArea m_area; |
ScreenArea m_editarea; |
181 |
|
ScreenArea m_iconarea; |
182 |
|
EditorDisplay m_display; |
183 |
|
IconBar m_iconbar; |
184 |
|
bool m_quit_editor; |
185 |
|
display::SpriteHandle m_cursor; |
186 |
|
|
187 |
|
EditMode m_editmode; |
188 |
|
|
189 |
|
// AvailableObjects m_avail_objects; |
190 |
}; |
}; |
|
} |
|
191 |
|
|
192 |
|
} |
193 |
|
|
194 |
|
|
195 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
196 |
// Display engine for the editor |
// Level representation inside the level editor |
197 |
//---------------------------------------------------------------------- |
//---------------------------------------------------------------------- |
198 |
namespace |
|
199 |
|
Level::Level () |
200 |
{ |
{ |
201 |
class EditorDisplay : public display::CommonDisplay { |
} |
|
public: |
|
|
EditorDisplay(const ScreenArea &a); |
|
|
~EditorDisplay() {} |
|
202 |
|
|
203 |
void tick(double dtime) {} |
|
204 |
private: |
//---------------------------------------------------------------------- |
205 |
|
// Icon bar |
206 |
|
//---------------------------------------------------------------------- |
207 |
|
|
|
}; |
|
208 |
|
|
209 |
} |
|
210 |
|
//---------------------------------------------------------------------- |
211 |
|
// Display engine for the editor |
212 |
|
//---------------------------------------------------------------------- |
213 |
|
|
214 |
EditorDisplay::EditorDisplay(const ScreenArea &a) |
EditorDisplay::EditorDisplay(const ScreenArea &a) |
215 |
: CommonDisplay(a) |
: CommonDisplay(a) |
226 |
OBJFLAG_SignalRecipient = 0x2, |
OBJFLAG_SignalRecipient = 0x2, |
227 |
}; |
}; |
228 |
|
|
|
enum ObjectType { |
|
|
OBJTYPE_Floor, |
|
|
OBJTYPE_Item, |
|
|
OBJTYPE_Stone, |
|
|
OBJTYPE_Actor |
|
|
}; |
|
|
|
|
|
enum Signals { |
|
|
SIGNAL_None = 0, |
|
|
SIGNAL_Trigger = 0x01, |
|
|
SIGNAL_Open = 0x02, |
|
|
SIGNAL_Close = 0x04, |
|
|
SIGNAL_OpenClose = 0x08, |
|
|
SIGNAL_On = 0x10, |
|
|
SIGNAL_Off = 0x20, |
|
|
SIGNAL_OnOff = 0x40, |
|
|
}; |
|
|
|
|
229 |
char *signal_names[] = { |
char *signal_names[] = { |
230 |
"trigger", |
"trigger", |
231 |
"open", |
"open", |
236 |
"on / off" |
"on / off" |
237 |
}; |
}; |
238 |
|
|
239 |
struct ObjectTraits { |
|
|
ObjectTraits (const std::string &name_, |
|
|
const std::string &short_text_, |
|
|
const std::string &long_text_, |
|
|
ObjectType type_) |
|
|
: name(name_), |
|
|
short_text(short_text_), |
|
|
long_text(long_text_), |
|
|
type(type_), |
|
|
send_signals(SIGNAL_None), |
|
|
receive_signals (SIGNAL_None) |
|
|
{} |
|
|
|
|
|
string name; |
|
|
string short_text; |
|
|
string long_text; |
|
|
ObjectType type; |
|
|
Signals send_signals; |
|
|
Signals receive_signals; |
|
|
float required_enigma_version; |
|
|
}; |
|
|
|
|
240 |
class AvailableObjects { |
class AvailableObjects { |
241 |
public: |
public: |
242 |
vector<string> m_avail_floors; |
AvailableObjects(); |
243 |
vector<string> m_avail_items; |
vector<ObjectTraits> floors; |
244 |
vector<string> m_avail_stones; |
vector<ObjectTraits> items; |
245 |
|
vector<ObjectTraits> stones; |
246 |
private: |
private: |
247 |
|
|
248 |
}; |
}; |
|
} |
|
249 |
|
|
250 |
|
|
251 |
|
} |
252 |
|
AvailableObjects::AvailableObjects() |
253 |
|
{ |
254 |
|
floors.push_back (ObjectTraits ("fl-metal", world::OBJTYPE_Floor)); |
255 |
|
} |
256 |
|
|
257 |
|
|
258 |
//====================================================================== |
//====================================================================== |
259 |
// THE EDITOR |
// THE EDITOR |
260 |
//====================================================================== |
//====================================================================== |
|
namespace |
|
|
{ |
|
|
class Editor : sdl::EventHandler { |
|
|
public: |
|
|
Editor(); |
|
|
~Editor(); |
|
|
|
|
|
void run(); |
|
|
private: |
|
|
// Private methods. |
|
|
void set_floor (int x, int y, const std::string &name); |
|
|
|
|
|
void new_world (int w, int h); |
|
|
|
|
|
void scroll (double xoff, double yoff); |
|
|
void scroll_abs (double x, double y); |
|
|
|
|
|
// EventHandler interface. |
|
|
bool on_mousemotion (SDL_Event &e); |
|
|
bool on_mousebutton (SDL_Event &e); |
|
|
bool on_keydown (SDL_Event &e); |
|
|
|
|
|
// Variables. |
|
|
ScreenArea m_editarea; |
|
|
ScreenArea m_iconarea; |
|
|
EditorDisplay display; |
|
|
IconBar m_iconbar; |
|
|
bool m_quit_editor; |
|
|
display::SpriteHandle m_cursor; |
|
|
|
|
|
AvailableObjects m_avail_objects; |
|
|
}; |
|
|
} |
|
261 |
|
|
262 |
Editor::Editor() |
Editor::Editor() |
263 |
: m_editarea (0,0,640,13*32), |
: m_editarea (0,0,640,13*32), |
264 |
m_iconarea (0,13*32,640,64), |
m_iconarea (0,13*32,640,64), |
265 |
display (m_editarea), |
m_display (m_editarea), |
266 |
m_iconbar (m_iconarea), |
m_iconbar (m_iconarea, 2, 640/32), |
267 |
m_quit_editor (false), |
m_quit_editor (false), |
268 |
m_cursor(display.add_effect(V2(), display::MakeModel("it-hammer"))) |
m_cursor(), |
269 |
|
m_editmode (MODE_FLOOR) |
270 |
{ |
{ |
|
m_cursor.replace_model (display::MakeModel ("ac-blackball")); |
|
271 |
} |
} |
272 |
|
|
273 |
Editor::~Editor() |
Editor::~Editor() |
283 |
|
|
284 |
while (!m_quit_editor) { |
while (!m_quit_editor) { |
285 |
video::HideMouse(); |
video::HideMouse(); |
286 |
display.redraw(); |
m_display.redraw(); |
287 |
video::ShowMouse(); |
video::ShowMouse(); |
288 |
video::GetScreen()->flush_updates(); |
video::GetScreen()->flush_updates(); |
289 |
|
|
296 |
} |
} |
297 |
|
|
298 |
void |
void |
299 |
|
Editor::set_mode (EditMode m) |
300 |
|
{ |
301 |
|
m_editmode = m; |
302 |
|
} |
303 |
|
|
304 |
|
void |
305 |
Editor::set_floor (int x, int y, const std::string &name) |
Editor::set_floor (int x, int y, const std::string &name) |
306 |
{ |
{ |
307 |
display.set_floor (x, y, display::MakeModel (name)); |
m_display.set_floor (x, y, display::MakeModel (name)); |
308 |
cout << "setting floor at " << x << "," << y << ": " <<name<<endl; |
} |
309 |
|
|
310 |
|
void |
311 |
|
Editor::set_item (int x, int y, const string &name) |
312 |
|
{ |
313 |
|
m_display.set_item (x, y, display::MakeModel (name)); |
314 |
|
} |
315 |
|
|
316 |
|
void |
317 |
|
Editor::set_stone (int x, int y, const string &name) |
318 |
|
{ |
319 |
|
m_display.set_stone (x, y, display::MakeModel (name)); |
320 |
} |
} |
321 |
|
|
322 |
|
|
323 |
void |
void |
324 |
Editor::new_world (int w, int h) |
Editor::new_world (int w, int h) |
325 |
{ |
{ |
326 |
display.new_world (w, h); |
m_display.new_world (w, h); |
327 |
for (int x=0; x<w; ++x) |
for (int x=0; x<w; ++x) |
328 |
for (int y=0; y<h; ++y) |
for (int y=0; y<h; ++y) |
329 |
set_floor (x, y, "fl-normal"); |
set_floor (x, y, "fl-normal"); |
330 |
|
m_cursor = m_display.add_effect(V2(), display::MakeModel("it-hammer")); |
331 |
|
} |
332 |
|
|
333 |
|
void |
334 |
|
Editor::set_cursor (const string &name) |
335 |
|
{ |
336 |
|
m_cursor.replace_model (display::MakeModel (name)); |
337 |
} |
} |
338 |
|
|
339 |
|
|
340 |
void |
void |
341 |
Editor::scroll (double xoff, double yoff) |
Editor::scroll (double xoff, double yoff) |
342 |
{ |
{ |
343 |
DisplayEngine *engine = display.get_engine(); |
DisplayEngine *engine = m_display.get_engine(); |
344 |
V2 newoffset = engine->get_offset() + V2(xoff, yoff); |
V2 newoffset = engine->get_offset() + V2(xoff, yoff); |
345 |
video::HideMouse(); |
video::HideMouse(); |
346 |
engine->move_offset (newoffset); |
engine->move_offset (newoffset); |
350 |
void |
void |
351 |
Editor::scroll_abs (double x, double y) |
Editor::scroll_abs (double x, double y) |
352 |
{ |
{ |
353 |
DisplayEngine *engine = display.get_engine(); |
DisplayEngine *engine = m_display.get_engine(); |
354 |
video::HideMouse(); |
video::HideMouse(); |
355 |
engine->move_offset(V2 (x, y)); |
engine->move_offset(V2 (x, y)); |
356 |
video::ShowMouse(); |
video::ShowMouse(); |
359 |
bool |
bool |
360 |
Editor::on_mousemotion(SDL_Event &e) |
Editor::on_mousemotion(SDL_Event &e) |
361 |
{ |
{ |
362 |
// DisplayEngine *engine = display.get_engine(); |
DisplayEngine *engine = m_display.get_engine(); |
363 |
// V2 worldpos = engine->to_world (V2(e.motion.x, e.motion.y)); |
V2 worldpos = engine->to_world (V2(e.motion.x, e.motion.y)); |
364 |
// cout << "cursor pos: " << worldpos << endl; |
worldpos[0] = int(worldpos[0]); |
365 |
// m_cursor.move (worldpos); |
worldpos[1] = int(worldpos[1]); |
366 |
|
m_cursor.move (worldpos); |
367 |
return true; |
return true; |
368 |
} |
} |
369 |
|
|
372 |
{ |
{ |
373 |
if (e.button.type == SDL_MOUSEBUTTONDOWN) |
if (e.button.type == SDL_MOUSEBUTTONDOWN) |
374 |
{ |
{ |
375 |
DisplayEngine *engine = display.get_engine(); |
DisplayEngine *engine = m_display.get_engine(); |
376 |
V2 worldpos = engine->to_world (V2(e.motion.x, e.motion.y)); |
V2 worldpos = engine->to_world (V2(e.motion.x, e.motion.y)); |
377 |
set_floor (int(worldpos[0]), int(worldpos[1]), "fl-hay"); |
int x = int(worldpos[0]); |
378 |
|
int y = int(worldpos[1]); |
379 |
|
|
380 |
|
switch (m_editmode) { |
381 |
|
case MODE_FLOOR: |
382 |
|
set_floor (x, y, "fl-hay"); |
383 |
|
break; |
384 |
|
case MODE_ITEMS: |
385 |
|
set_item (x, y, "it-umbrella"); |
386 |
|
break; |
387 |
|
case MODE_STONES: |
388 |
|
set_stone (x, y, "st-brownie"); |
389 |
|
break; |
390 |
|
case MODE_ACTORS: |
391 |
|
break; |
392 |
|
} |
393 |
return true; |
return true; |
394 |
} |
} |
395 |
return false; |
return false; |
434 |
if (e.key.keysym.mod & KMOD_SHIFT) |
if (e.key.keysym.mod & KMOD_SHIFT) |
435 |
; |
; |
436 |
else |
else |
437 |
; |
set_mode(MODE_ACTORS); |
438 |
break; |
break; |
439 |
case SDLK_f: |
case SDLK_f: |
440 |
if (e.key.keysym.mod & KMOD_SHIFT) |
if (e.key.keysym.mod & KMOD_SHIFT) |
441 |
; |
; |
442 |
else |
else |
443 |
; |
set_mode(MODE_FLOOR); |
444 |
break; |
break; |
445 |
case SDLK_i: |
case SDLK_i: |
446 |
if (e.key.keysym.mod & KMOD_SHIFT) |
if (e.key.keysym.mod & KMOD_SHIFT) |
447 |
; |
; |
448 |
else |
else |
449 |
; |
set_mode(MODE_ITEMS); |
450 |
break; |
break; |
451 |
case SDLK_s: |
case SDLK_s: |
452 |
if (e.key.keysym.mod & KMOD_SHIFT) |
if (e.key.keysym.mod & KMOD_SHIFT) |
453 |
; |
; |
454 |
else |
else |
455 |
; |
set_mode (MODE_STONES); |
456 |
break; |
break; |
457 |
|
|
458 |
default: |
default: |