Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Allow map files to specify the filenames of their tilesets and backdrops

  • Loading branch information...
commit d94710c81441d2faa547c204649c314883428c2a 1 parent 8e650e2
@Malvineous authored
View
37 examples/gamemap.cpp
@@ -722,6 +722,43 @@ int main(int iArgC, char *cArgV[])
} else {
std::cout << "0\n"; // number of attributes
}
+
+ std::cout << (bScript ? "gfx_filename_count=" : "Number of graphics filenames: ");
+ gm::Map::FilenameVectorPtr gfxFilenames = pMap->getGraphicsFilenames();
+ if (gfxFilenames) {
+ std::cout << gfxFilenames->size() << "\n";
+ int fileNum = 0;
+ for (gm::Map::FilenameVector::const_iterator
+ i = gfxFilenames->begin(); i != gfxFilenames->end(); i++
+ ) {
+ const gm::Map::GraphicsFilename *a = &(*i);
+
+ if (bScript) {
+ std::cout << "gfx_file" << fileNum << "_name=" << a->filename << "\n";
+ std::cout << "gfx_file" << fileNum << "_type=" << a->type << "\n";
+ std::cout << "gfx_file" << fileNum << "_purpose=" << a->purpose << "\n";
+ } else {
+ std::cout << "Graphics file " << fileNum+1 << ": " << a->filename
+ << " [";
+ switch (a->purpose) {
+ case gm::Map::GraphicsFilename::Tileset:
+ std::cout << "tileset";
+ break;
+ case gm::Map::GraphicsFilename::BackgroundImage:
+ std::cout << "background image";
+ break;
+ default:
+ std::cout << "Unknown purpose <fix this>";
+ break;
+ }
+ std::cout << " of type " << a->type << "]\n";
+ }
+ fileNum++;
+ }
+ } else {
+ std::cout << "0\n"; // number of gfx filenames
+ }
+
std::cout << (bScript ? "map_type=" : "Map type: ");
gm::Map2DPtr map2d = boost::dynamic_pointer_cast<gm::Map2D>(pMap);
if (map2d) {
View
58 include/camoto/gamemaps/map.hpp
@@ -43,12 +43,26 @@ class EInvalidFormat: virtual public error {
class Map: virtual public Metadata
{
public:
- /// Attribute attached to this map
+ /// Attribute attached to this map.
+ /**
+ * Attributes are configuration options that apply to particular map files,
+ * such as a default background colour or which song to play as background
+ * music in the level.
+ *
+ * Attributes should reflect data contained in the map file itself, so for
+ * example, if the map file doesn't store some value that controls which
+ * tileset is used to draw the level, then the tileset filename shouldn't be
+ * exposed as an attribute (because if it was changed, the new value
+ * couldn't be saved back into the map file.)
+ *
+ * Attributes should reflect properties of the map that the user can and may
+ * wish to change.
+ */
struct Attribute {
enum Type {
Integer, ///< One number within a given range
Enum, ///< One choice from a list of static values
- Filename, ///< A filename of the given type
+ Filename, ///< A filename of the given file type
};
Type type; ///< What type this attribute is
std::string name; ///< Short name of this attribute
@@ -61,8 +75,20 @@ class Map: virtual public Metadata
unsigned int enumValue; ///< Enum type: current value
std::vector<std::string> enumValueNames; ///< Enum type: permitted values
- std::string filenameValue; ///< Filename type: current filename
- /// Valid filename extensions
+ /// Filename type: current filename
+ /**
+ * Filenames should be specified here as map attributes (as opposed to
+ * supplementary items) if the files are not required to load the map.
+ *
+ * Parts of the actual map (like layer data or sprite positions) should
+ * be listed as supp data because the map will be incomplete if those
+ * files are not available, but things like tileset filenames are not
+ * required to load the map (e.g. if all you want to do is find out the
+ * map dimensions) so those optional files should be listed as attributes.
+ */
+ std::string filenameValue;
+
+ /// Filename type: valid filename extensions
/**
* Any files that match this specification will be listed as valid choices
* for this attribute value. An empty string means there is no
@@ -82,6 +108,30 @@ class Map: virtual public Metadata
/// Get a list of attributes that can be set in this map.
virtual AttributePtrVectorPtr getAttributes() = 0;
+
+ /// Const-accessible version
+ virtual const AttributePtrVectorPtr getAttributes() const = 0;
+
+ /// Information about a graphics file used to render this map.
+ struct GraphicsFilename {
+ enum Purpose {
+ Tileset, ///< Normal tileset
+ BackgroundImage, ///< Image to appear behind all tiles
+ };
+ Purpose purpose;
+ std::string filename; ///< Actual filename
+ std::string type; ///< Type code (e.g. "tls-blah")
+ };
+ typedef std::vector<GraphicsFilename> FilenameVector;
+ typedef boost::shared_ptr<FilenameVector> FilenameVectorPtr;
+
+ /// Get a list of additional files needed to render the map.
+ /**
+ * This function returns a list of filenames and format types needed to
+ * render the map. Tilesets, background images, etc. These values may
+ * change as map attributes are altered.
+ */
+ virtual FilenameVectorPtr getGraphicsFilenames() const = 0;
};
/// Shared pointer to a Map.
View
27 src/fmt-map-bash.cpp
@@ -111,6 +111,29 @@ ImagePtr BashBackgroundLayer::imageFromCode(unsigned int code,
}
+Map::FilenameVectorPtr bash_getGraphicsFilenames(const Map *map)
+{
+ Map::AttributePtrVectorPtr attributes = map->getAttributes();
+ assert(attributes); // this map format always has attributes
+ assert(attributes->size() == MB_NUM_ATTRIBUTES);
+
+ Map::FilenameVectorPtr files(new Map::FilenameVector);
+ Map::GraphicsFilename gf;
+ gf.purpose = Map::GraphicsFilename::Tileset;
+ gf.type = "tls-bash-bg";
+ gf.filename = attributes->at(0)->filenameValue;
+ files->push_back(gf); // bg tiles
+
+ gf.type = "tls-bash-fg";
+ gf.filename = attributes->at(1)->filenameValue;
+ files->push_back(gf); // fg tiles
+
+ gf.filename = attributes->at(2)->filenameValue;
+ files->push_back(gf); // bon tiles
+ return files;
+}
+
+
std::string BashMapType::getMapCode() const
{
return "map-bash";
@@ -215,7 +238,6 @@ MapPtr BashMapType::open(stream::input_sptr input, SuppData& suppData) const
attr->type = Map::Attribute::Filename;
attr->name = attrNames[i];
attr->desc = attrDesc[i];
- attr->filenameValidExtension = validTypes[i];
input >> nullPadded(attr->filenameValue, 31);
if (attr->filenameValue.compare("UNNAMED") == 0) {
attr->filenameValue.clear();
@@ -229,6 +251,7 @@ MapPtr BashMapType::open(stream::input_sptr input, SuppData& suppData) const
attr->filenameValue += validTypes[i];
}
}
+ attr->filenameValidExtension = validTypes[i];
attributes->push_back(attr);
}
@@ -301,7 +324,7 @@ MapPtr BashMapType::open(stream::input_sptr input, SuppData& suppData) const
layers.push_back(fgLayer);
Map2DPtr map(new GenericMap2D(
- attributes,
+ attributes, bash_getGraphicsFilenames,
Map2D::HasViewport,
MB_VIEWPORT_WIDTH, MB_VIEWPORT_HEIGHT,
mapWidth, mapHeight,
View
2  src/fmt-map-ccaves.cpp
@@ -171,7 +171,7 @@ MapPtr CCavesMapType::open(stream::input_sptr input, SuppData& suppData) const
layers.push_back(bgLayer);
Map2DPtr map(new GenericMap2D(
- Map::AttributePtrVectorPtr(),
+ Map::AttributePtrVectorPtr(), NO_GFX_CALLBACK,
Map2D::HasViewport,
CC_VIEWPORT_WIDTH, CC_VIEWPORT_HEIGHT,
CC_MAP_WIDTH, height,
View
2  src/fmt-map-ccomic.cpp
@@ -158,7 +158,7 @@ MapPtr CComicMapType::open(stream::input_sptr input, SuppData& suppData) const
layers.push_back(bgLayer);
Map2DPtr map(new GenericMap2D(
- Map::AttributePtrVectorPtr(),
+ Map::AttributePtrVectorPtr(), NO_GFX_CALLBACK,
Map2D::HasViewport,
193, 160, // viewport size
width, height,
View
2  src/fmt-map-cosmo.cpp
@@ -227,7 +227,7 @@ MapPtr CosmoMapType::open(stream::input_sptr input, SuppData& suppData) const
layers.push_back(actorLayer);
Map2DPtr map(new GenericMap2D(
- Map::AttributePtrVectorPtr(),
+ Map::AttributePtrVectorPtr(), NO_GFX_CALLBACK,
Map2D::HasViewport,
CCA_VIEWPORT_WIDTH, CCA_VIEWPORT_HEIGHT,
mapWidth, 32768 / mapWidth,
View
2  src/fmt-map-ddave.cpp
@@ -174,7 +174,7 @@ MapPtr DDaveMapType::open(stream::input_sptr input, SuppData& suppData) const
layers.push_back(bgLayer);
Map2DPtr map(new GenericMap2D(
- Map::AttributePtrVectorPtr(),
+ Map::AttributePtrVectorPtr(), NO_GFX_CALLBACK,
Map2D::HasViewport | Map2D::HasPaths | Map2D::FixedPathCount,
20 * DD_TILE_WIDTH, 10 * DD_TILE_HEIGHT, // viewport size
DD_MAP_WIDTH, DD_MAP_HEIGHT,
View
2  src/fmt-map-harry.cpp
@@ -316,7 +316,7 @@ MapPtr HarryMapType::open(stream::input_sptr input, SuppData& suppData) const
layers.push_back(actorLayer);
Map2DPtr map(new GenericMap2D(
- attributes,
+ attributes, NO_GFX_CALLBACK,
Map2D::HasViewport,
HH_VIEWPORT_WIDTH, HH_VIEWPORT_HEIGHT,
mapWidth, mapHeight,
View
2  src/fmt-map-hocus.cpp
@@ -171,7 +171,7 @@ MapPtr HocusMapType::open(stream::input_sptr input, SuppData& suppData) const
//layers.push_back(actorLayer);
Map2DPtr map(new GenericMap2D(
- Map::AttributePtrVectorPtr(),
+ Map::AttributePtrVectorPtr(), NO_GFX_CALLBACK,
Map2D::HasViewport,
HP_VIEWPORT_WIDTH, HP_VIEWPORT_HEIGHT,
HP_MAP_WIDTH, HP_MAP_HEIGHT,
View
2  src/fmt-map-wacky.cpp
@@ -184,7 +184,7 @@ MapPtr WackyMapType::open(stream::input_sptr input, SuppData& suppData) const
paths->push_back(pathptr);
Map2DPtr map(new GenericMap2D(
- Map::AttributePtrVectorPtr(),
+ Map::AttributePtrVectorPtr(), NO_GFX_CALLBACK,
Map2D::HasPaths | Map2D::FixedPathCount,
0, 0,
WW_MAP_WIDTH, WW_MAP_HEIGHT,
View
87 src/fmt-map-wordresc.cpp
@@ -197,6 +197,31 @@ bool WordRescueAttributeLayer::tilePermittedAt(unsigned int code,
}
+Map::FilenameVectorPtr wr_getGraphicsFilenames(const Map *map)
+{
+ Map::AttributePtrVectorPtr attributes = map->getAttributes();
+ assert(attributes); // this map format always has attributes
+ assert(attributes->size() == 3);
+
+ Map::FilenameVectorPtr files(new Map::FilenameVector);
+ Map::GraphicsFilename gf;
+ gf.purpose = Map::GraphicsFilename::Tileset;
+ gf.type = "tls-wordresc";
+ gf.filename = createString("back" << (int)(attributes->at(1)->enumValue + 1)
+ << ".wr");
+ files->push_back(gf); // bg tiles
+
+ unsigned int dropNum = attributes->at(2)->enumValue;
+ if (dropNum > 0) {
+ gf.purpose = Map::GraphicsFilename::BackgroundImage;
+ gf.filename = createString("drop" << dropNum << ".wr");
+ files->push_back(gf); // fg tiles
+ }
+
+ return files;
+}
+
+
/// Write the given data to the stream, RLE encoded
int rleWrite(stream::output_sptr output, uint8_t *data, int len)
{
@@ -400,47 +425,28 @@ MapPtr WordRescueMapType::open(stream::input_sptr input, SuppData& suppData) con
attrTileset->type = Map::Attribute::Enum;
attrTileset->name = "Tileset";
attrTileset->desc = "Tileset to use for this map";
- switch (tileset) {
- case 1: attrTileset->enumValue = 0; break;
- case 2: attrTileset->enumValue = 1; break;
- case 3: attrTileset->enumValue = 2; break;
- case 5: attrTileset->enumValue = 3; break;
- case 4: attrTileset->enumValue = 4; break;
-
- case 6: attrTileset->enumValue = 5; break;
- case 7: attrTileset->enumValue = 6; break;
- case 8: attrTileset->enumValue = 7; break;
- default: attrTileset->enumValue = 0; break;
- }
+ if (tileset > 0) tileset--; // just in case it *is* ever zero
+ attrTileset->enumValue = tileset;
attrTileset->enumValueNames.push_back("Desert");
attrTileset->enumValueNames.push_back("Castle");
attrTileset->enumValueNames.push_back("Suburban");
- attrTileset->enumValueNames.push_back("Industrial");
attrTileset->enumValueNames.push_back("Spooky (episode 3 only)");
- attrTileset->enumValueNames.push_back("Custom (back5.wr)");
+ attrTileset->enumValueNames.push_back("Industrial");
attrTileset->enumValueNames.push_back("Custom (back6.wr)");
attrTileset->enumValueNames.push_back("Custom (back7.wr)");
+ attrTileset->enumValueNames.push_back("Custom (back8.wr)");
attributes->push_back(attrTileset);
Map::AttributePtr attrBackdrop(new Map::Attribute);
attrBackdrop->type = Map::Attribute::Enum;
attrBackdrop->name = "Backdrop";
attrBackdrop->desc = "Image to show behind map (overrides background colour)";
- switch (backdrop) {
- case 0: attrBackdrop->enumValue = 0; break;
- case 3: attrBackdrop->enumValue = 1; break;
- case 4: attrBackdrop->enumValue = 2; break;
- case 2: attrBackdrop->enumValue = 3; break;
-
- case 5: attrBackdrop->enumValue = 4; break;
- case 6: attrBackdrop->enumValue = 5; break;
- case 7: attrBackdrop->enumValue = 6; break;
- default: attrBackdrop->enumValue = 0; break;
- }
+ attrBackdrop->enumValue = backdrop;
attrBackdrop->enumValueNames.push_back("None (use background colour)");
+ attrBackdrop->enumValueNames.push_back("Custom (drop1.wr)");
+ attrBackdrop->enumValueNames.push_back("Cave (episodes 2-3 only)");
attrBackdrop->enumValueNames.push_back("Desert");
attrBackdrop->enumValueNames.push_back("Mountain");
- attrBackdrop->enumValueNames.push_back("Cave (episodes 2-3 only)");
attrBackdrop->enumValueNames.push_back("Custom (drop5.wr)");
attrBackdrop->enumValueNames.push_back("Custom (drop6.wr)");
attrBackdrop->enumValueNames.push_back("Custom (drop7.wr)");
@@ -581,7 +587,7 @@ MapPtr WordRescueMapType::open(stream::input_sptr input, SuppData& suppData) con
layers.push_back(itemLayer);
Map2DPtr map(new GenericMap2D(
- attributes,
+ attributes, wr_getGraphicsFilenames,
Map2D::HasViewport,
288, 152, // viewport
mapWidth, mapHeight,
@@ -621,37 +627,14 @@ void WordRescueMapType::write(MapPtr map, stream::expanding_output_sptr output,
throw stream::error("Cannot write map as there is an attribute of the "
"wrong type (tileset != enum)");
}
- uint16_t tileset;
- switch (attrTileset->enumValue) {
- case 0: tileset = 1; break;
- case 1: tileset = 2; break;
- case 2: tileset = 3; break;
- case 3: tileset = 5; break;
- case 4: tileset = 4; break;
-
- case 5: tileset = 6; break;
- case 6: tileset = 7; break;
- case 7: tileset = 8; break;
- default: tileset = 1; break;
- }
+ uint16_t tileset = attrTileset->enumValue + 1;
Map::Attribute *attrBackdrop = attributes->at(2).get();
if (attrBackdrop->type != Map::Attribute::Enum) {
throw stream::error("Cannot write map as there is an attribute of the "
"wrong type (backdrop != enum)");
}
- uint16_t backdrop;
- switch (attrBackdrop->enumValue) {
- case 0: backdrop = 0; break;
- case 1: backdrop = 3; break;
- case 2: backdrop = 4; break;
- case 3: backdrop = 2; break;
-
- case 4: backdrop = 5; break;
- case 5: backdrop = 6; break;
- case 6: backdrop = 7; break;
- default: backdrop = 0; break;
- }
+ uint16_t backdrop = attrBackdrop->enumValue;
typedef std::pair<uint16_t, uint16_t> point;
std::vector<point> itemLocations[INDEX_SIZE];
View
2  src/fmt-map-xargon.cpp
@@ -508,7 +508,7 @@ MapPtr SweeneyMapType::open(stream::input_sptr input, SuppData& suppData) const
layers.push_back(objLayer);
Map2DPtr map(new GenericMap2D(
- Map::AttributePtrVectorPtr(),
+ Map::AttributePtrVectorPtr(), NO_GFX_CALLBACK,
Map2D::HasViewport,
20 * XR_TILE_WIDTH, 10 * XR_TILE_HEIGHT, // viewport size
XR_MAP_WIDTH, XR_MAP_HEIGHT,
View
17 src/map-generic.cpp
@@ -23,8 +23,10 @@
namespace camoto {
namespace gamemaps {
-GenericMap::GenericMap(AttributePtrVectorPtr attributes)
- : attributes(attributes)
+GenericMap::GenericMap(AttributePtrVectorPtr attributes,
+ GraphicsFilenamesCallback fnGfxFiles)
+ : attributes(attributes),
+ fnGfxFiles(fnGfxFiles)
{
}
@@ -37,5 +39,16 @@ Map::AttributePtrVectorPtr GenericMap::getAttributes()
return this->attributes;
}
+const Map::AttributePtrVectorPtr GenericMap::getAttributes() const
+{
+ return this->attributes;
+}
+
+Map::FilenameVectorPtr GenericMap::getGraphicsFilenames() const
+{
+ if (this->fnGfxFiles) return this->fnGfxFiles(this);
+ return Map::FilenameVectorPtr();
+}
+
} // namespace gamemaps
} // namespace camoto
View
20 src/map-generic.hpp
@@ -21,22 +21,40 @@
#ifndef _CAMOTO_GAMEMAPS_MAP_GENERIC_HPP_
#define _CAMOTO_GAMEMAPS_MAP_GENERIC_HPP_
+#include <boost/function.hpp>
#include <camoto/gamemaps/map.hpp>
namespace camoto {
namespace gamemaps {
+/// Callback to use when the list of graphics filenames is required
+/**
+ * This is used as a convenience function, to avoid having to derive from
+ * GenericMap and implement getGraphicsFilenames().
+ */
+typedef boost::function<Map::FilenameVectorPtr(const Map *)> GraphicsFilenamesCallback;
+
+/// Value to use when there is no callback to get the list of graphics filenames
+#define NO_GFX_CALLBACK ((GraphicsFilenamesCallback)NULL)
+
/// Generic implementation of a Map.
class GenericMap: virtual public Map
{
public:
- GenericMap(AttributePtrVectorPtr attributes);
+ GenericMap(AttributePtrVectorPtr attributes,
+ GraphicsFilenamesCallback fnGfxFiles);
virtual ~GenericMap();
virtual AttributePtrVectorPtr getAttributes();
+ virtual const AttributePtrVectorPtr getAttributes() const;
+ virtual FilenameVectorPtr getGraphicsFilenames() const;
protected:
+ /// Vector holding the current attributes
AttributePtrVectorPtr attributes;
+
+ /// Callback function to get the names of the graphics files
+ GraphicsFilenamesCallback fnGfxFiles;
};
} // namespace gamemaps
View
5 src/map2d-generic.cpp
@@ -24,11 +24,12 @@
namespace camoto {
namespace gamemaps {
-GenericMap2D::GenericMap2D(AttributePtrVectorPtr attributes, int caps,
+GenericMap2D::GenericMap2D(AttributePtrVectorPtr attributes,
+ GraphicsFilenamesCallback fnGfxFiles, int caps,
unsigned int viewportWidth, unsigned int viewportHeight, unsigned int width,
unsigned int height, unsigned int tileWidth, unsigned int tileHeight,
LayerPtrVector& layers, PathPtrVectorPtr paths)
- : GenericMap(attributes),
+ : GenericMap(attributes, fnGfxFiles),
caps(caps),
viewportWidth(viewportWidth), viewportHeight(viewportHeight),
width(width), height(height),
View
7 src/map2d-generic.hpp
@@ -38,6 +38,10 @@ class GenericMap2D: virtual public Map2D, virtual public GenericMap
* @param attributes
* List of attributes that apply to this map.
*
+ * @param fnGfxFiles
+ * Callback to retrieve the list of graphics files needed to render this
+ * map.
+ *
* @param caps
* Map capabilities. One or more Caps values OR'd together.
*
@@ -88,7 +92,8 @@ class GenericMap2D: virtual public Map2D, virtual public GenericMap
* map size in pixels, then divided by the layer's different tile size to
* reveal the dimensions of the layer in a number of tiles.
*/
- GenericMap2D(AttributePtrVectorPtr attributes, int caps,
+ GenericMap2D(AttributePtrVectorPtr attributes,
+ GraphicsFilenamesCallback fnGfxFiles, int caps,
unsigned int viewportWidth, unsigned int viewportHeight,
unsigned int width, unsigned int height, unsigned int tileWidth,
unsigned int tileHeight, LayerPtrVector& layers, PathPtrVectorPtr paths);
Please sign in to comment.
Something went wrong with that request. Please try again.