Skip to content

Commit 9a08420

Browse files
committed
Read and write paired .tilemap+.attrmap files; and fix GBC attribute bit meanings
1 parent f50c607 commit 9a08420

File tree

11 files changed

+285
-70
lines changed

11 files changed

+285
-70
lines changed

TODO.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
## Features
44

5+
* **"Grosser Block":** Select MxN tiles at once for placement, from the tileset or tilemap
6+
* **Auto-Load:** Guess the associated tileset for a tilemap
57
* **.tileset files:** Read and export lists of images with start+offset+length values
6-
* **.attrmap files:** Open paired tilemap and attrmap files, supporting all attribute bytes
7-
* **"Grosser Block":** Select MxN tiles at once for placement
8-
* **Auto-Load:** Guess associated tileset for a tilemap
98
* Native-looking build on Mac OS X (involves publishing an app bundle release, and using the system menu bar)
109
* Scale the UI for high-DPI displays
1110
* Generate tilemap images from the command line

res/open-disabled.xpm

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* XPM */
2+
static const char *OPEN_DISABLED_XPM[] = {
3+
"16 16 9 1",
4+
" c None",
5+
"# c #8F8F8F",
6+
"+ c #A4A4A4",
7+
". c #DDDDDD",
8+
"@ c #ACACAC",
9+
"- c #F4F4F4",
10+
"$ c #878787",
11+
"= c #939393",
12+
", c #B9B9B9",
13+
" ++########## ",
14+
" #.++.......# ",
15+
" #...++@@@@@# ",
16+
" #....+----@@ ",
17+
" #....+----@-@ ",
18+
" #....+----@@@@ ",
19+
" #....+-------@ ",
20+
" #....+-----=-@ ",
21+
" #....+-----$=@ ",
22+
" #....+-$$$$$,$ ",
23+
" #....+-$,,,,,,$",
24+
" #....+-$$$$$,$ ",
25+
" #....+-----$=@ ",
26+
" ++...+-----=-@ ",
27+
" ++.+@@@@@@@@ ",
28+
" ++ "
29+
};

src/icons.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "new.xpm"
99
#include "open.xpm"
10+
#include "open-disabled.xpm"
1011
#include "save.xpm"
1112
#include "save-disabled.xpm"
1213
#include "print.xpm"
@@ -39,6 +40,7 @@
3940

4041
static Fl_Pixmap NEW_ICON(NEW_XPM);
4142
static Fl_Pixmap OPEN_ICON(OPEN_XPM);
43+
static Fl_Pixmap OPEN_DISABLED_ICON(OPEN_DISABLED_XPM);
4244
static Fl_Pixmap SAVE_ICON(SAVE_XPM);
4345
static Fl_Pixmap SAVE_DISABLED_ICON(SAVE_DISABLED_XPM);
4446
static Fl_Pixmap PRINT_ICON(PRINT_XPM);

src/main-window.cpp

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
#endif
3939

4040
Main_Window::Main_Window(int x, int y, int w, int h, const char *) : Fl_Double_Window(x, y, w, h, PROGRAM_NAME),
41-
_tile_buttons(), _tilemap_file(), _tileset_files(), _recent_tilemaps(), _recent_tilesets(), _tilemap(), _tilesets(),
42-
_wx(x), _wy(y), _ww(w), _wh(h) {
41+
_tile_buttons(), _tilemap_file(), _attrmap_file(), _tileset_files(), _recent_tilemaps(), _recent_tilesets(),
42+
_tilemap(), _tilesets(), _wx(x), _wy(y), _ww(w), _wh(h) {
4343

4444
Tile_State::tilesets(&_tilesets);
4545

@@ -337,7 +337,7 @@ Main_Window::Main_Window(int x, int y, int w, int h, const char *) : Fl_Double_W
337337
OS_MENU_ITEM("&Width...", FL_COMMAND + 'd', (Fl_Callback *)tilemap_width_cb, this, 0),
338338
OS_MENU_ITEM("Re&size...", FL_COMMAND + 'e', (Fl_Callback *)resize_cb, this, 0),
339339
OS_MENU_ITEM("Re&format...", FL_COMMAND + 'f', (Fl_Callback *)reformat_cb, this, FL_MENU_DIVIDER),
340-
OS_MENU_ITEM("&Image to Tiles...", FL_COMMAND + 'i', (Fl_Callback *)image_to_tiles_cb, this, 0),
340+
OS_MENU_ITEM("&Image to Tiles...", FL_COMMAND + 'x', (Fl_Callback *)image_to_tiles_cb, this, 0),
341341
{},
342342
OS_SUBMENU("&Help"),
343343
OS_MENU_ITEM("&Help", FL_F + 1, (Fl_Callback *)help_cb, this, FL_MENU_DIVIDER),
@@ -457,7 +457,7 @@ Main_Window::Main_Window(int x, int y, int w, int h, const char *) : Fl_Double_W
457457
_reformat_tb->image(REFORMAT_ICON);
458458
_reformat_tb->deimage(REFORMAT_DISABLED_ICON);
459459

460-
_image_to_tiles_tb->tooltip("Image to Tiles... (Ctrl+I)");
460+
_image_to_tiles_tb->tooltip("Image to Tiles... (Ctrl+X)");
461461
_image_to_tiles_tb->callback((Fl_Callback *)image_to_tiles_cb, this);
462462
_image_to_tiles_tb->image(INPUT_ICON);
463463

@@ -733,13 +733,23 @@ void Main_Window::update_tilemap_metadata() {
733733
}
734734
else {
735735
const char *basename = fl_filename_name(_tilemap_file.c_str());
736-
_tilemap_name->label(basename);
736+
if (_attrmap_file.size()) {
737+
char buffer[FL_PATH_MAX] = {};
738+
strcpy(buffer, basename);
739+
strcat(buffer, " / ");
740+
basename = fl_filename_name(_attrmap_file.c_str());
741+
strcat(buffer, basename);
742+
_tilemap_name->copy_label(buffer);
743+
}
744+
else {
745+
_tilemap_name->label(basename);
746+
}
737747
}
738748
const char *name = format_name(Config::format());
739749
_tilemap_format->label(name);
740750
}
741751
else {
742-
_tilemap_name->label("No file selected");
752+
_tilemap_name->label(NO_FILE_SELECTED_LABEL);
743753
_tilemap_format->label("");
744754
}
745755
}
@@ -762,7 +772,7 @@ void Main_Window::update_tileset_metadata() {
762772
}
763773
}
764774
else {
765-
_tileset_name->label("No files selected");
775+
_tileset_name->label(NO_FILES_SELECTED_LABEL);
766776
}
767777
}
768778

@@ -880,7 +890,8 @@ void Main_Window::update_active_controls() {
880890
}
881891
int tdw = 12 + Fl::scrollbar_size(), tdh = 12 + OS_TAB_HEIGHT;
882892
_left_tabs->size_range(tw + tdw, min_th + tdh, tw + tdw, max_th + tdh);
883-
_left_tabs->resize(_left_tabs->x(), _left_tabs->y(), _left_tabs->w(), _tilemap_scroll->h());
893+
int tdx = _left_tabs->x() - _tilemap_scroll->x();
894+
_left_tabs->resize(_left_tabs->x(), _left_tabs->y(), _left_tabs->w(), _tilemap_scroll->h() + tdx);
884895

885896
if (format_has_palettes(Config::format())) {
886897
_palettes_tab->activate();
@@ -1058,7 +1069,6 @@ void Main_Window::swap_tiles(Tile_Tessera *tt) {
10581069
void Main_Window::open_tilemap(const char *filename, size_t width, size_t height) {
10591070
if (filename) {
10601071
_tilemap_options_dialog->use_tilemap(filename);
1061-
_tilemap_options_dialog->format(guess_format(filename));
10621072
_tilemap_options_dialog->show(this);
10631073
if (_tilemap_options_dialog->canceled()) { return; }
10641074
}
@@ -1069,16 +1079,21 @@ void Main_Window::open_tilemap(const char *filename, size_t width, size_t height
10691079
const char *basename;
10701080

10711081
if (filename) {
1082+
const char *attrmap_filename = _tilemap_options_dialog->attrmap_filename();
1083+
10721084
_tilemap_file = filename;
1085+
_attrmap_file = attrmap_filename ? attrmap_filename : "";
10731086
basename = fl_filename_name(filename);
1087+
const char *attrmap_basename = fl_filename_name(attrmap_filename);
10741088

10751089
Config::format(_tilemap_options_dialog->format());
10761090

1077-
Tilemap::Result r = _tilemap.read_tiles(filename);
1091+
Tilemap::Result r = _tilemap.read_tiles(filename, attrmap_filename);
10781092
if (r) {
10791093
_tilemap.clear();
10801094
std::string msg = "Error reading ";
1081-
msg = msg + basename + "!\n\n" + Tilemap::error_message(r);
1095+
msg = msg + (r >= Tilemap::ATTRMAP_BAD_FILE ? attrmap_basename : basename);
1096+
msg = msg + "!\n\n" + Tilemap::error_message(r);
10821097
_error_dialog->message(msg);
10831098
_error_dialog->show(this);
10841099
return;
@@ -1093,6 +1108,7 @@ void Main_Window::open_tilemap(const char *filename, size_t width, size_t height
10931108
}
10941109
else {
10951110
_tilemap_file = "";
1111+
_attrmap_file = "";
10961112
basename = NEW_TILEMAP_NAME;
10971113

10981114
Config::format(_new_tilemap_dialog->format());
@@ -1146,10 +1162,11 @@ void Main_Window::open_recent_tilemap(int n) {
11461162

11471163
bool Main_Window::save_tilemap(bool force) {
11481164
const char *filename = _tilemap_file.c_str();
1165+
const char *attrmap_filename = _attrmap_file.c_str();
11491166
const char *basename = fl_filename_name(filename);
11501167

11511168
if (_tilemap.modified() || force) {
1152-
if (!_tilemap.write_tiles(filename)) {
1169+
if (!_tilemap.write_tiles(filename, attrmap_filename)) {
11531170
std::string msg = "Could not write to ";
11541171
msg = msg + basename + "!";
11551172
_error_dialog->message(msg);
@@ -1337,7 +1354,10 @@ void Main_Window::image_to_tiles() {
13371354

13381355
const char *tilemap_filename = _image_to_tiles_dialog->tilemap_filename();
13391356
const char *tilemap_basename = fl_filename_name(tilemap_filename);
1340-
if (!Tilemap::write_tiles(tilemap_filename, tilemap, fmt)) {
1357+
char attrmap_filename[FL_PATH_MAX] = {};
1358+
strcpy(attrmap_filename, tilemap_filename);
1359+
fl_filename_setext(attrmap_filename, sizeof(attrmap_filename), ATTRMAP_EXT);
1360+
if (!Tilemap::write_tiles(tilemap_filename, attrmap_filename, tilemap, fmt)) {
13411361
for (Tile_Tessera *tt : tilemap) {
13421362
delete tt;
13431363
}
@@ -1510,6 +1530,7 @@ void Main_Window::close_cb(Fl_Widget *, Main_Window *mw) {
15101530
mw->_tiles_scroll->scroll_to(0, 0);
15111531
mw->init_sizes();
15121532
mw->_tilemap_file.clear();
1533+
mw->_attrmap_file.clear();
15131534
mw->update_tilemap_metadata();
15141535
mw->update_status(NULL);
15151536
mw->update_active_controls();
@@ -1841,7 +1862,6 @@ void Main_Window::resize_cb(Fl_Menu_ *, Main_Window *mw) {
18411862

18421863
void Main_Window::reformat_cb(Fl_Menu_ *, Main_Window *mw) {
18431864
if (!mw->_tilemap.size()) { return; }
1844-
mw->_reformat_dialog->use_tilemap(mw->_tilemap_file.c_str());
18451865
mw->_reformat_dialog->format(Config::format());
18461866
mw->_reformat_dialog->show(mw);
18471867
if (mw->_reformat_dialog->canceled()) { return; }

src/main-window.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class Main_Window : public Fl_Double_Window {
7373
Image_To_Tiles_Dialog *_image_to_tiles_dialog;
7474
Help_Window *_help_window;
7575
// Data
76-
std::string _tilemap_file;
76+
std::string _tilemap_file, _attrmap_file;
7777
std::vector<std::string> _tileset_files;
7878
std::string _recent_tilemaps[NUM_RECENT], _recent_tilesets[NUM_RECENT];
7979
Tilemap _tilemap;

0 commit comments

Comments
 (0)