OpenClonk
mapgen.c
Go to the documentation of this file.
1 /*
2  * mape - C4 Landscape.txt editor
3  *
4  * Copyright (c) 2005-2009, Armin Burgmeier
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #include <string.h>
17 
21 #include "mape/mapgen.h"
22 
23 /* Declare private API */
26 
27 
30 
33 
34 static GQuark mape_mapgen_error_quark()
35 {
36  return g_quark_from_static_string("MAPE_MAPGEN_ERROR");
37 }
38 
39 static void mape_mapgen_read_color(guint8* dest,
40  MapeMaterialMap* material_map,
41  MapeTextureMap* texture_map,
42  unsigned int matnum)
43 {
44  const gchar* texture_name;
45  const gchar* material_name;
46  const gchar* first_tex_separator;
47  const MapeMaterial* material;
48  gchar* own_texture_name;
49  guint32 color;
50 
51  if(matnum == 0)
52  {
53  /* Sky */
54  dest[matnum * 4 + 1] = 100;
55  dest[matnum * 4 + 2] = 100;
56  dest[matnum * 4 + 3] = 255;
57  }
58  else
59  {
61  texture_map,
62  matnum
63  );
64 
65  own_texture_name = NULL;
66  if(texture_name != NULL)
67  {
68  /* When the texture is animated, the texture name consists of more than
69  * one texture, separated with a '-' character. In this case, we simply
70  * use the first one for display. */
71  first_tex_separator = strchr(texture_name, '-');
72  if(first_tex_separator != NULL)
73  {
74  own_texture_name = g_strndup(
75  texture_name,
76  first_tex_separator - texture_name
77  );
78 
79  texture_name = own_texture_name;
80  }
81 
82  /* Make sure the texture exists */
83  if(!mape_texture_map_lookup_texture(texture_map, texture_name))
84  {
86  texture_map,
87  matnum
88  );
89 
91  material_map,
92  material_name
93  );
94 
95  /* It can happen that the material does not exist; this happens when
96  * a material-texture specification with texture set and invalid
97  * material occurs, such as "E-rough". In this case we display sky,
98  * since this is what happens when the texture specification is
99  * omitted (in which case no entry in the texmap is created, and
100  * matnum=0). */
101  if(!material)
102  {
103  dest[matnum * 4 + 1] = 100;
104  dest[matnum * 4 + 2] = 100;
105  dest[matnum * 4 + 3] = 255;
106  texture_name = NULL;
107  }
108  else
109  {
110  texture_name = mape_material_get_texture_overlay(material);
111  }
112  }
113  }
114 
115  if(texture_name != NULL)
116  {
118  texture_map,
119  texture_name
120  );
121 
122  dest[matnum * 4 + 1] = (color ) & 0xff;
123  dest[matnum * 4 + 2] = (color >> 8) & 0xff;
124  dest[matnum * 4 + 3] = (color >> 16) & 0xff;
125  }
126 
127  g_free(own_texture_name);
128  }
129 }
130 
131 /*
132  * Public API.
133  */
134 
143 gboolean
144 mape_mapgen_init(GError** error)
145 {
147  return TRUE;
148 }
149 
155 void
157 {
159 }
160 
168 void
170 {
171  MapeGroup* objects;
172  MapeGroup* libraries;
173  MapeGroup* map;
174  GError* error;
175 
176  error = NULL;
177  if(!error)
178  objects = mape_group_open_child(group, "Objects.ocd", &error);
179  if(!error)
180  libraries = mape_group_open_child(objects, "Libraries.ocd", &error);
181  if(!error)
182  map = mape_group_open_child(libraries, "Map.ocd", &error);
183 
184  /* TODO: Error reporting? */
185  if(error == NULL)
187 
188  if(error != NULL)
189  {
190  fprintf(stderr, "Failed to load Objects.ocd/Libraries.ocd/Map.ocd/Script.c: %s\n", error->message);
191  g_error_free(error);
192  }
193 }
194 
226 GdkPixbuf*
227 mape_mapgen_render(const gchar* filename,
228  const gchar* source,
230  const gchar* script_path,
231  MapeMaterialMap* material_map,
232  MapeTextureMap* texture_map,
233  guint width,
234  guint height,
235  GError** error)
236 {
237  C4MapgenHandle* handle;
238  const char* error_message;
239  unsigned int out_width;
240  unsigned int out_height;
241  GdkPixbuf* pixbuf;
242  guint8* out_p;
243  const unsigned char* in_p;
244  guint out_rowstride;
245  unsigned int in_rowstride;
246  guint datawidth;
247  guint8 matclrs[256 * 4];
248  unsigned int x, y;
249  unsigned int matnum;
250 
251  switch(type)
252  {
254  handle = c4_mapgen_handle_new(
255  filename,
256  source,
257  script_path,
258  _mape_material_map_get_handle(material_map),
259  _mape_texture_map_get_handle(texture_map),
260  width,
261  height
262  );
263 
264  break;
265  case MAPE_MAPGEN_MAP_C:
267  filename,
268  source,
269  _mape_material_map_get_handle(material_map),
270  _mape_texture_map_get_handle(texture_map),
271  width,
272  height
273  );
274 
275  break;
276  default:
277  handle = NULL;
278  g_assert_not_reached();
279  break;
280  }
281 
282  error_message = c4_mapgen_handle_get_error(handle);
283  if(error_message)
284  {
285  g_set_error(
286  error,
287  mape_mapgen_error_quark(),
289  "%s",
290  error_message
291  );
292 
293  c4_mapgen_handle_free(handle);
294  return NULL;
295  }
296 
297  out_width = c4_mapgen_handle_get_width(handle);
298  out_height = c4_mapgen_handle_get_height(handle);
299 
300  pixbuf = gdk_pixbuf_new(
301  GDK_COLORSPACE_RGB,
302  FALSE,
303  8,
304  out_width,
305  out_height
306  );
307 
308  if(pixbuf == NULL)
309  {
310  g_set_error(
311  error,
312  mape_mapgen_error_quark(),
314  "Insufficient memory is available"
315  );
316 
317  c4_mapgen_handle_free(handle);
318  return NULL;
319  }
320 
321  out_p = gdk_pixbuf_get_pixels(pixbuf);
322  in_p = c4_mapgen_handle_get_map(handle);
323  out_rowstride = gdk_pixbuf_get_rowstride(pixbuf);
324  in_rowstride = c4_mapgen_handle_get_rowstride(handle);
325  datawidth = gdk_pixbuf_get_width(pixbuf) * 3;
326  memset(matclrs, 0, sizeof(matclrs) );
327 
328  for(y = 0; y < out_height; ++y)
329  {
330  for(x = 0; x < out_width; ++x)
331  {
332  matnum = *in_p;
333 
334  if(matclrs[matnum * 4] == 0)
335  {
336  mape_mapgen_read_color(
337  matclrs,
338  material_map,
339  texture_map,
340  matnum
341  );
342 
343  /* Color has been loaded */
344  matclrs[matnum * 4] = 1;
345  }
346 
347  out_p[0] = matclrs[matnum * 4 + 1];
348  out_p[1] = matclrs[matnum * 4 + 2];
349  out_p[2] = matclrs[matnum * 4 + 3];
350  ++in_p;
351  out_p += 3;
352  }
353 
354  in_p += in_rowstride - out_width;
355  out_p += out_rowstride - datawidth;
356  }
357 
358  c4_mapgen_handle_free(handle);
359  return pixbuf;
360 }
361 
362 /* vim:set et sw=2 ts=2: */
typedefG_BEGIN_DECLS struct _C4GroupHandle C4GroupHandle
Definition: group-handle.h:23
MapeGroup * mape_group_open_child(MapeGroup *group, const gchar *entry, GError **error)
Definition: group.c:301
typedefG_BEGIN_DECLS struct _C4MapgenHandle C4MapgenHandle
Definition: log-handle.h:23
unsigned int c4_mapgen_handle_get_height(C4MapgenHandle *mapgen)
void c4_mapgen_handle_init_script_engine()
const char * c4_mapgen_handle_get_error(C4MapgenHandle *mapgen)
const unsigned char * c4_mapgen_handle_get_map(C4MapgenHandle *mapgen)
void c4_mapgen_handle_deinit_script_engine()
C4MapgenHandle * c4_mapgen_handle_new_script(const char *filename, const char *source, C4MaterialMapHandle *material_map, C4TextureMapHandle *texture_map, unsigned int map_width, unsigned int map_height)
unsigned int c4_mapgen_handle_get_width(C4MapgenHandle *mapgen)
void c4_mapgen_handle_free(C4MapgenHandle *mapgen)
C4MapgenHandle * c4_mapgen_handle_new(const char *filename, const char *source, const char *script_path, C4MaterialMapHandle *material_map, C4TextureMapHandle *texture_map, unsigned int map_width, unsigned int map_height)
void c4_mapgen_handle_set_map_library(C4GroupHandle *group_handle)
unsigned int c4_mapgen_handle_get_rowstride(C4MapgenHandle *mapgen)
C4TextureMapHandle * _mape_texture_map_get_handle(MapeTextureMap *map)
Definition: texture.c:591
void mape_mapgen_deinit()
Definition: mapgen.c:156
C4GroupHandle * _mape_group_get_handle(MapeGroup *group)
Definition: group.c:682
GdkPixbuf * mape_mapgen_render(const gchar *filename, const gchar *source, MapeMapgenType type, const gchar *script_path, MapeMaterialMap *material_map, MapeTextureMap *texture_map, guint width, guint height, GError **error)
Definition: mapgen.c:227
gboolean mape_mapgen_init(GError **error)
Definition: mapgen.c:144
void mape_mapgen_set_root_group(MapeGroup *group)
Definition: mapgen.c:169
C4MaterialMapHandle * _mape_material_map_get_handle(MapeMaterialMap *map)
Definition: material.c:396
enum _MapeMapgenType MapeMapgenType
@ MAPE_MAPGEN_ERROR_COMPILE
Definition: mapgen.h:38
@ MAPE_MAPGEN_ERROR_MEMORY
Definition: mapgen.h:39
@ MAPE_MAPGEN_MAP_C
Definition: mapgen.h:53
@ MAPE_MAPGEN_LANDSCAPE_TXT
Definition: mapgen.h:52
struct _C4MaterialMapHandle C4MaterialMapHandle
const gchar * mape_material_get_texture_overlay(const MapeMaterial *material)
Definition: material.c:388
MapeMaterial * mape_material_map_get_material_by_name(MapeMaterialMap *map, const gchar *name)
Definition: material.c:336
struct _MapeMaterial MapeMaterial
Definition: material.h:35
typedefG_BEGIN_DECLS struct _C4TextureMapHandle C4TextureMapHandle
const gchar * mape_texture_map_get_texture_name_from_mapping(MapeTextureMap *texture_map, guint index)
Definition: texture.c:559
const gchar * mape_texture_map_get_material_name_from_mapping(MapeTextureMap *texture_map, guint index)
Definition: texture.c:536
GdkPixbuf * mape_texture_map_lookup_texture(MapeTextureMap *texture_map, const gchar *name)
Definition: texture.c:504
guint32 mape_texture_map_get_average_texture_color(MapeTextureMap *texture_map, const gchar *name)
Definition: texture.c:580