From 4b4da8646b40d7816f304208b53a842946f5b055 Mon Sep 17 00:00:00 2001 From: Armin Burgmeier Date: Mon, 7 Jan 2013 00:16:43 +0100 Subject: [PATCH] Handle-ify the mapgen call --- CMakeLists.txt | 4 +- src/mape/cpp-handles/mapgen-handle.cpp | 121 +++++++++++++++ src/mape/cpp-handles/mapgen-handle.h | 41 +++++ src/mape/editview.c | 7 +- src/mape/mapgen.c | 199 ++++++++++++++++++++++++ src/mape/mapgen.cpp | 202 ------------------------- src/mape/mapgen.h | 45 +++--- 7 files changed, 395 insertions(+), 224 deletions(-) create mode 100644 src/mape/cpp-handles/mapgen-handle.cpp create mode 100644 src/mape/cpp-handles/mapgen-handle.h create mode 100644 src/mape/mapgen.c delete mode 100644 src/mape/mapgen.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dd574df4..0a2c0db7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -561,6 +561,8 @@ set(OC_CLONK_SOURCES set(MAPE_SOURCES src/mape/cpp-handles/group-handle.h src/mape/cpp-handles/group-handle.cpp + src/mape/cpp-handles/mapgen-handle.h + src/mape/cpp-handles/mapgen-handle.cpp src/mape/cpp-handles/material-handle.h src/mape/cpp-handles/material-handle.cpp src/mape/cpp-handles/texture-handle.h @@ -581,7 +583,7 @@ set(MAPE_SOURCES src/mape/iconview.c src/mape/iconview.h src/mape/mape.c - src/mape/mapgen.cpp + src/mape/mapgen.c src/mape/mapgen.h src/mape/material.c src/mape/material.h diff --git a/src/mape/cpp-handles/mapgen-handle.cpp b/src/mape/cpp-handles/mapgen-handle.cpp new file mode 100644 index 000000000..e1b66344b --- /dev/null +++ b/src/mape/cpp-handles/mapgen-handle.cpp @@ -0,0 +1,121 @@ +/* + * mape - C4 Landscape.txt editor + * + * Copyright (c) 2005-2009 Armin Burgmeier + * + * Portions might be copyrighted by other authors who have contributed + * to OpenClonk. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * See isc_license.txt for full license and disclaimer. + * + * "Clonk" is a registered trademark of Matthes Bender. + * See clonk_trademark_license.txt for full license. + */ + +#include "C4Include.h" +//#include +//#include +//#include +//#include +//#include +#include + +#include "mape/cpp-handles/material-handle.h" +#include "mape/cpp-handles/texture-handle.h" +#include "mape/cpp-handles/mapgen-handle.h" + +#define HANDLE_TO_MATERIAL_MAP(handle) (reinterpret_cast(handle)) +#define HANDLE_TO_TEXTURE_MAP(handle) (reinterpret_cast(handle)) + +extern "C" { + +struct _C4MapgenHandle { + unsigned int width; + unsigned int height; + StdCopyStrBuf error_message; + BYTE* data; +}; + +C4MapgenHandle* c4_mapgen_handle_new(const char* filename, const char* source, C4MaterialMapHandle* material_map, C4TextureMapHandle* texture_map, unsigned int map_width, unsigned int map_height) +{ + try + { + C4SLandscape landscape; + landscape.Default(); + + landscape.MapWdt = map_width; + landscape.MapHgt = map_height; + landscape.MapPlayerExtend = 0; + + C4MapCreatorS2 mapgen( + &landscape, + HANDLE_TO_TEXTURE_MAP(texture_map), + HANDLE_TO_MATERIAL_MAP(material_map), + 1 + ); + + C4MCParser parser(&mapgen); + parser.ParseMemFile(source, filename); + + int32_t out_width, out_height; + BYTE* array = mapgen.RenderBuf(NULL, out_width, out_height); + if(array == NULL) throw C4MCParserErr(&parser, "No map definition in source file"); + + C4MapgenHandle* handle = new C4MapgenHandle; + handle->width = out_width; + handle->height = out_height; + handle->error_message = NULL; + handle->data = array; + return handle; + } + catch(const C4MCParserErr& err) + { + C4MapgenHandle* handle = new C4MapgenHandle; + handle->width = 0; + handle->height = 0; + handle->error_message.Copy(err.Msg); + handle->data = NULL; + return handle; + } +} + +void c4_mapgen_handle_free(C4MapgenHandle* mapgen) +{ + delete[] mapgen->data; + delete mapgen; +} + +const unsigned char* c4_mapgen_handle_get_map(C4MapgenHandle* mapgen) +{ + return reinterpret_cast(mapgen->data); +} + +unsigned int c4_mapgen_handle_get_width(C4MapgenHandle* mapgen) +{ + assert(mapgen->data != NULL); + return mapgen->width; +} + +unsigned int c4_mapgen_handle_get_height(C4MapgenHandle* mapgen) +{ + assert(mapgen->data != NULL); + return mapgen->height; +} + +unsigned int c4_mapgen_handle_get_rowstride(C4MapgenHandle* mapgen) +{ + assert(mapgen->data != NULL); + return DWordAligned(mapgen->width); +} + +const char* c4_mapgen_handle_get_error(C4MapgenHandle* mapgen) +{ + if(mapgen->data != NULL) + return NULL; + return mapgen->error_message.getData(); +} + +} // extern "C" diff --git a/src/mape/cpp-handles/mapgen-handle.h b/src/mape/cpp-handles/mapgen-handle.h new file mode 100644 index 000000000..63eddb6e8 --- /dev/null +++ b/src/mape/cpp-handles/mapgen-handle.h @@ -0,0 +1,41 @@ +/* + * mape - C4 Landscape.txt editor + * + * Copyright (c) 2005-2009 Armin Burgmeier + * + * Portions might be copyrighted by other authors who have contributed + * to OpenClonk. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * See isc_license.txt for full license and disclaimer. + * + * "Clonk" is a registered trademark of Matthes Bender. + * See clonk_trademark_license.txt for full license. + */ + +#ifndef INC_MAPE_C4_MAPGEN_HANDLE_H +#define INC_MAPE_C4_MAPGEN_HANDLE_H + +#include + +#include "mape/cpp-handles/material-handle.h" +#include "mape/cpp-handles/texture-handle.h" + +G_BEGIN_DECLS + +typedef struct _C4MapgenHandle C4MapgenHandle; + +C4MapgenHandle* c4_mapgen_handle_new(const char* filename, const char* source, C4MaterialMapHandle* material_map, C4TextureMapHandle* texture_map, unsigned int map_width, unsigned int map_height); +void c4_mapgen_handle_free(C4MapgenHandle* mapgen); + +const unsigned char* c4_mapgen_handle_get_map(C4MapgenHandle* mapgen); +unsigned int c4_mapgen_handle_get_width(C4MapgenHandle* mapgen); +unsigned int c4_mapgen_handle_get_height(C4MapgenHandle* mapgen); +unsigned int c4_mapgen_handle_get_rowstride(C4MapgenHandle* mapgen); +const char* c4_mapgen_handle_get_error(C4MapgenHandle* mapgen); + +G_END_DECLS + +#endif /* INC_MAPE_C4_MAPGEN_HANDLE_H */ diff --git a/src/mape/editview.c b/src/mape/editview.c index dc43d0254..307f0ae99 100644 --- a/src/mape/editview.c +++ b/src/mape/editview.c @@ -87,13 +87,14 @@ static GdkPixbuf* mape_edit_view_render_map(const gchar* source, return NULL; } - pixbuf = mape_mapgen_generate( + pixbuf = mape_mapgen_render( + "Landscape.txt", /* TODO: Use actual filename */ source, mat_map, tex_map, - error, map_width, - map_height + map_height, + error ); return pixbuf; diff --git a/src/mape/mapgen.c b/src/mape/mapgen.c new file mode 100644 index 000000000..3934a94fb --- /dev/null +++ b/src/mape/mapgen.c @@ -0,0 +1,199 @@ +/* + * mape - C4 Landscape.txt editor + * + * Copyright (c) 2005-2009 Armin Burgmeier + * + * Portions might be copyrighted by other authors who have contributed + * to OpenClonk. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * See isc_license.txt for full license and disclaimer. + * + * "Clonk" is a registered trademark of Matthes Bender. + * See clonk_trademark_license.txt for full license. + */ + +#include + +#include "mape/cpp-handles/mapgen-handle.h" +#include "mape/cpp-handles/material-handle.h" +#include "mape/cpp-handles/texture-handle.h" +#include "mape/mapgen.h" + +/* Declare private API */ +C4MaterialMapHandle* +_mape_material_map_get_handle(MapeMaterialMap* map); + +C4TextureMapHandle* +_mape_texture_map_get_handle(MapeTextureMap* map); + +static GQuark mape_mapgen_error_quark() +{ + return g_quark_from_static_string("MAPE_MAPGEN_ERROR"); +} + +static void mape_mapgen_read_color(guint8* dest, + MapeMaterialMap* material_map, + unsigned int matnum) +{ + const MapeMaterial* mat; + + if(matnum == 0) + { + dest[matnum * 4 + 1] = 100; + dest[matnum * 4 + 2] = 100; + dest[matnum * 4 + 3] = 255; + } + else + { + /* TODO: matnum is actually texmap entry, so find matnum from + * it. Actually we don't need to know the material + * actually, just get color from texture + render... */ + mat = mape_material_map_get_material(material_map, matnum - 1); + + dest[matnum * 4 + 1] = 0xff; + dest[matnum * 4 + 2] = 0xff; + dest[matnum * 4 + 3] = 0xff; + } +} + +/* + * Public API. + */ + +/** + * mape_mapgen_render: + * + * @filename: The filename of the file that is being parsed. This is only used + * for display purposes. + * @source: The map generator source code for the map to generate. + * @material_map: The material map containing the materials to be used during + * map generation. + * @texture_map: The texture map containing the textures to be used during map + * generation. + * @width: The width of the map to generate. + * @height: The height of the map to generate. + * @error: Location to store error information, if any, or %NULL. + * + * Renders the map described by @source with the C4MapCreatorS2 into a pixbuf. + * The pixel color depends on the texture at the corresponding position and is + * determined by the average color of that texture. + * + * In case an error occurs, for example when the map generator source code is + * not valid, @error is set and the function returns %NULL. + * + * Return Value: A #GdkPixbuf with the generated map, or %NULL. Free with + * g_object_unref(). + **/ +GdkPixbuf* +mape_mapgen_render(const gchar* filename, + const gchar* source, + MapeMaterialMap* material_map, + MapeTextureMap* texture_map, + guint width, + guint height, + GError** error) +{ + C4MapgenHandle* handle; + const char* error_message; + unsigned int out_width; + unsigned int out_height; + GdkPixbuf* pixbuf; + guint8* out_p; + const unsigned char* in_p; + guint out_rowstride; + unsigned int in_rowstride; + guint datawidth; + guint8 matclrs[128 * 4]; + unsigned int x, y; + + handle = c4_mapgen_handle_new( + filename, + source, + _mape_material_map_get_handle(material_map), + _mape_texture_map_get_handle(texture_map), + width, + height + ); + + error_message = c4_mapgen_handle_get_error(handle); + if(error_message) + { + g_set_error( + error, + mape_mapgen_error_quark(), + MAPE_MAPGEN_ERROR_COMPILE, + "%s", + error_message + ); + + c4_mapgen_handle_free(handle); + return NULL; + } + + out_width = c4_mapgen_handle_get_width(handle); + out_height = c4_mapgen_handle_get_height(handle); + + pixbuf = gdk_pixbuf_new( + GDK_COLORSPACE_RGB, + FALSE, + 8, + out_width, + out_height + ); + + if(pixbuf == NULL) + { + g_set_error( + error, + mape_mapgen_error_quark(), + MAPE_MAPGEN_ERROR_MEMORY, + "Insufficient memory is available" + ); + + c4_mapgen_handle_free(handle); + return NULL; + } + + out_p = gdk_pixbuf_get_pixels(pixbuf); + in_p = c4_mapgen_handle_get_map(handle); + out_rowstride = gdk_pixbuf_get_rowstride(pixbuf); + in_rowstride = c4_mapgen_handle_get_rowstride(handle); + datawidth = gdk_pixbuf_get_width(pixbuf) * 3; + memset(matclrs, 0, sizeof(matclrs) ); + + for(x = 0; x < out_width; ++x) + { + for(y = 0; y < out_height; ++y) + { + unsigned int matnum = *in_p & 0x7f; + if(matclrs[matnum * 4] == 0) + { + mape_mapgen_read_color( + matclrs, + material_map, + matnum + ); + + /* Color has been loaded */ + matclrs[matnum * 4] = 1; + } + + out_p[0] = matclrs[matnum * 4 + 1]; + out_p[1] = matclrs[matnum * 4 + 2]; + out_p[2] = matclrs[matnum * 4 + 3]; + ++in_p; + out_p += 3; + } + + in_p += in_rowstride - out_width; + out_p += out_rowstride - datawidth; + } + + c4_mapgen_handle_free(handle); + return pixbuf; +} + +/* vim:set et sw=2 ts=2: */ diff --git a/src/mape/mapgen.cpp b/src/mape/mapgen.cpp deleted file mode 100644 index f0bc435a9..000000000 --- a/src/mape/mapgen.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * mape - C4 Landscape.txt editor - * - * Copyright (c) 2005-2009 Armin Burgmeier - * - * Portions might be copyrighted by other authors who have contributed - * to OpenClonk. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * See isc_license.txt for full license and disclaimer. - * - * "Clonk" is a registered trademark of Matthes Bender. - * See clonk_trademark_license.txt for full license. - */ - -#define MAPE_COMPILING_CPP - -#include -#include -#include -#include -#include -#include - -#include - -#include "mape/cpp-handles/material-handle.h" -#include "mape/cpp-handles/texture-handle.h" -#include "mape/mapgen.h" - -extern "C" C4MaterialMapHandle* _mape_material_map_get_handle(MapeMaterialMap*); -extern "C" C4TextureMapHandle* _mape_texture_map_get_handle(MapeTextureMap*); - -#define CPPTEXMAP(map) (reinterpret_cast(_mape_texture_map_get_handle(map))) -#define CPPMATMAP(map) (reinterpret_cast(_mape_material_map_get_handle(map))) - -extern "C" -{ - -static void mape_mapgen_read_color(guint8* dest, - MapeMaterialMap* material_map, - unsigned int matnum) -{ - const MapeMaterial* mat; - GdkColor color; - - if(matnum == 0) - { - dest[matnum * 4 + 1] = 100; - dest[matnum * 4 + 2] = 100; - dest[matnum * 4 + 3] = 255; - } - else - { - /* TODO: matnum is actually texmap entry, so find matnum from - * it. Actually we don't need to know the material - * actually, just get color from texture + render... */ - mat = mape_material_map_get_material(material_map, matnum - 1); - - /* TODO: Read color from texture, needs TexMap lookup */ - color.red = 0xffff; - color.green = 0xffff; - color.blue = 0xffff; - - dest[matnum * 4 + 1] = color.red * 0xff / 0xffff; - dest[matnum * 4 + 2] = color.green * 0xff / 0xffff; - dest[matnum * 4 + 3] = color.blue * 0xff / 0xffff; - } -} - -GdkPixbuf* mape_mapgen_generate(const gchar* source, - MapeMaterialMap* material_map, - MapeTextureMap* texture_map, - GError** error, - unsigned int map_width, - unsigned int map_height) -{ - int32_t width, height; - int32_t x, y; - guint8* pix; - BYTE* arry; - BYTE* index; - int aligned_width; - unsigned int rowstride; - unsigned int datawidth; - GdkPixbuf* pixbuf; - - aligned_width = DWordAligned(map_width); - - arry = NULL; - try - { - C4SLandscape landscape; - landscape.Default(); - - landscape.MapWdt = map_width; - landscape.MapHgt = map_height; - landscape.MapPlayerExtend = 0; - - C4MapCreatorS2 mapgen( - &landscape, - CPPTEXMAP(texture_map), - CPPMATMAP(material_map), - 1 - ); - - C4MCParser parser(&mapgen); - - // TODO: Pass correct filename - parser.ParseMemFile(source, "Landscape.txt"); - - arry = mapgen.RenderBuf(NULL, width, height); - if(arry == NULL) - { - g_set_error( - error, - g_quark_from_static_string("MAPE_MAPGEN_ERROR"), - MAPE_MAPGEN_ERROR_MISSING_MAP, - "No map definition in source file" - ); - - return NULL; - } - - pixbuf = gdk_pixbuf_new( - GDK_COLORSPACE_RGB, - FALSE, - 8, - map_width, - map_height - ); - - if(pixbuf == NULL) - { - g_set_error( - error, - g_quark_from_static_string("MAPE_MAPGEN_ERROR"), - MAPE_MAPGEN_ERROR_MEMORY, - "Insufficient memory is available" - ); - - delete[] arry; - return NULL; - } - - pix = gdk_pixbuf_get_pixels(pixbuf); - rowstride = gdk_pixbuf_get_rowstride(pixbuf); - datawidth = gdk_pixbuf_get_width(pixbuf) * 3; - index = arry; - - guint8 matclrs[128 * 4]; - memset(matclrs, 0, sizeof(matclrs) ); - - for(x = 0; x < map_height; ++ x) - { - for(y = 0; y < map_width; ++ y) - { - BYTE matnum = *index & 0x7f; - if(matclrs[matnum * 4] == 0) - { - mape_mapgen_read_color( - matclrs, - material_map, - matnum - ); - - /* Color has been loaded */ - matclrs[matnum * 4] = 1; - } - - pix[0] = matclrs[matnum * 4 + 1]; - pix[1] = matclrs[matnum * 4 + 2]; - pix[2] = matclrs[matnum * 4 + 3]; - ++ index; - pix += 3; - } - - index += aligned_width - map_width; - pix += rowstride - datawidth; - } - - delete[] arry; - return pixbuf; - } - catch(const C4MCParserErr& err) - { - g_set_error( - error, - g_quark_from_static_string("MAPE_MAPGEN_ERROR"), - MAPE_MAPGEN_ERROR_COMPILE, - "%s", - err.Msg - ); - - delete[] arry; - return NULL; - } -} - -} // extern "C" diff --git a/src/mape/mapgen.h b/src/mape/mapgen.h index fdc61ee15..23811b3e5 100644 --- a/src/mape/mapgen.h +++ b/src/mape/mapgen.h @@ -18,31 +18,40 @@ #ifndef INC_MAPE_MAPGEN_H #define INC_MAPE_MAPGEN_H +#include #include + #include "mape/material.h" #include "mape/texture.h" -#ifdef MAPE_COMPILING_CPP -extern "C" { -#endif +G_BEGIN_DECLS -typedef enum MapeMapgenError_ { - MAPE_MAPGEN_ERROR_MEMORY, - MAPE_MAPGEN_ERROR_COMPILE, - MAPE_MAPGEN_ERROR_MISSING_MAP, - - MAPE_MAPGEN_ERROR_FAILED +/** + * MapeMapgenError: + * @MAPE_MAPGEN_ERROR_COMPILE: An error occured while compiling the + * Landscape.txt source code. + * @MAPE_GROUP_ERROR_MEMORY: Insufficient memory was available to render the + * map. + * + * These errors are from the MAPE_MAPGEN_ERROR error domain. They can occur + * when rendering a map from a Landscape.txt file. + */ +typedef enum _MapeMapgenError { + MAPE_MAPGEN_ERROR_COMPILE, + MAPE_MAPGEN_ERROR_MEMORY } MapeMapgenError; -GdkPixbuf* mape_mapgen_generate(const gchar* source, - MapeMaterialMap* material_map, - MapeTextureMap* texture_map, - GError** error, - unsigned int map_with, - unsigned int map_height); +GdkPixbuf* +mape_mapgen_render(const gchar* filename, + const gchar* source, + MapeMaterialMap* material_map, + MapeTextureMap* texture_map, + guint width, + guint height, + GError** error); -#ifdef MAPE_COMPILING_CPP -} /* extern "C" */ -#endif +G_END_DECLS #endif /* INC_MAPE_MAPGEN_H */ + +/* vim:set et sw=2 ts=2: */