Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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.