openclonk/src/mape/material.c

418 lines
10 KiB
C

/*
* 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.
*/
/**
* SECTION:mape-material-mape
* @title: MapeMaterialMap
* @short_description: C4MaterialMap interface
* @include: mape/material.h
* @stability: Unstable
*
* #MapeMaterialMap is a simple GObject-based interface to C4MaterialMap.
* It supports loading a material map from a Material.c4g material_map file. It can
* load multiple files, with newer entries overloading previous ones in case
* of name clashes to support material overloading.
**/
#include "mape/cpp-handles/material-handle.h"
#include "mape/material.h"
/* Declare private API */
C4GroupHandle*
_mape_group_get_handle(MapeGroup* group);
C4MaterialHandle*
_mape_material_map_get_handle(MapeMaterialMap* map);
struct _MapeMaterial {
MapeMaterialMap* map;
unsigned int mat_index;
};
typedef struct _MapeMaterialMapPrivate MapeMaterialMapPrivate;
struct _MapeMaterialMapPrivate {
C4MaterialHandle* handle;
};
enum {
PROP_0,
/* read only */
PROP_N_MATERIALS
};
#define MAPE_MATERIAL_MAP_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), MAPE_TYPE_MATERIAL_MAP, MapeMaterialMapPrivate))
static GQuark mape_material_map_error_quark;
G_DEFINE_TYPE(MapeMaterialMap, mape_material_map, G_TYPE_OBJECT)
/*
* MapeMaterial
*/
static MapeMaterial*
mape_material_new(MapeMaterialMap* map,
guint mat_index)
{
MapeMaterial* material;
material = g_slice_new(MapeMaterial);
material->map = map;
material->mat_index = mat_index;
g_object_ref(map);
return material;
}
/*
* GObject overrides.
*/
static void
mape_material_map_init(MapeMaterialMap* material_map)
{
MapeMaterialMapPrivate* priv;
priv = MAPE_MATERIAL_MAP_PRIVATE(material_map);
priv->handle = c4_material_handle_new();
}
static void
mape_material_map_finalize(GObject* object)
{
MapeMaterialMap* material_map;
MapeMaterialMapPrivate* priv;
material_map = MAPE_MATERIAL_MAP(object);
priv = MAPE_MATERIAL_MAP_PRIVATE(material_map);
c4_material_handle_free(priv->handle);
G_OBJECT_CLASS(mape_material_map_parent_class)->finalize(object);
}
static void
mape_material_map_set_property(GObject* object,
guint prop_id,
const GValue* value,
GParamSpec* pspec)
{
MapeMaterialMap* material_map;
MapeMaterialMapPrivate* priv;
material_map = MAPE_MATERIAL_MAP(object);
priv = MAPE_MATERIAL_MAP_PRIVATE(material_map);
switch(prop_id)
{
/* we have only readonly properties */
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(value, prop_id, pspec);
break;
}
}
static void
mape_material_map_get_property(GObject* object,
guint prop_id,
GValue* value,
GParamSpec* pspec)
{
MapeMaterialMap* material_map;
MapeMaterialMapPrivate* priv;
material_map = MAPE_MATERIAL_MAP(object);
priv = MAPE_MATERIAL_MAP_PRIVATE(material_map);
switch(prop_id)
{
case PROP_N_MATERIALS:
g_value_set_uint(value, c4_material_handle_get_num(priv->handle));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
/*
* Gype registration.
*/
static void
mape_material_map_class_init(MapeMaterialMapClass *class)
{
GObjectClass* object_class;
object_class = G_OBJECT_CLASS(class);
mape_material_map_parent_class =
G_OBJECT_CLASS(g_type_class_peek_parent(class));
g_type_class_add_private(class, sizeof(MapeMaterialMapPrivate));
object_class->finalize = mape_material_map_finalize;
object_class->set_property = mape_material_map_set_property;
object_class->get_property = mape_material_map_get_property;
mape_material_map_error_quark =
g_quark_from_static_string("MAPE_MATERIAL_MAP_ERROR");
g_object_class_install_property(
object_class,
PROP_N_MATERIALS,
g_param_spec_uint(
"n-materials",
"Material count",
"The number of loaded materials",
0,
G_MAXUINT,
0,
G_PARAM_READABLE
)
);
}
GType
mape_material_get_type(void)
{
static GType material_type = 0;
if(material_type == 0)
{
material_type = g_boxed_type_register_static(
"MapeMaterial",
(GBoxedCopyFunc)mape_material_copy,
(GBoxedFreeFunc)mape_material_free);
}
return material_type;
}
/*
* Public API.
*/
/**
* mape_material_map_new:
*
* Creates a new #MapeMaterialMap. The map is initially empty. Use
* mape_material_map_load() to load materials from one or more Material.c4g
* group files.
*
* Return Value: A new #MapeMaterialMap. Free with g_object_unref().
**/
MapeMaterialMap*
mape_material_map_new(void)
{
return MAPE_MATERIAL_MAP(g_object_new(MAPE_TYPE_MATERIAL_MAP, NULL));
}
/**
* mape_material_map_load:
* @map: A #MapeMaterialMap.
* @from: An open #MapeGroup to load materials from.
* @error: Location to store error information, if any.
*
* Loads all the material files (*.c4m) from the group @from. If this includes
* materials with the same name as materials already contained in @map, then
* the materials in @map will be replaced by the new ones. If an error occurs
* while loading the material map the function returns %FALSE and @error is
* set.
*
* Returns: %TRUE on success, %FALSE on failure.
*/
gboolean
mape_material_map_load(MapeMaterialMap* map,
MapeGroup* from,
GError** error)
{
MapeMaterialMapPrivate* priv;
guint new_count;
g_return_val_if_fail(MAPE_IS_MATERIAL_MAP(map), FALSE);
g_return_val_if_fail(MAPE_IS_GROUP(from), FALSE);
g_return_val_if_fail(mape_group_is_open(from), FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
priv = MAPE_MATERIAL_MAP_PRIVATE(map);
new_count = c4_material_handle_load(
priv->handle, _mape_group_get_handle(from));
if(new_count > 0)
g_object_notify(G_OBJECT(map), "n-materials");
return TRUE;
}
/**
* mape_material_map_get_material_count:
* @map: A #MapeMaterialMap.
*
* Returns the number of materials contained in @map.
*
* Return Value: The number of materials in @map.
**/
guint
mape_material_map_get_material_count(MapeMaterialMap* map)
{
g_return_val_if_fail(MAPE_IS_MATERIAL_MAP(map), 0);
return c4_material_handle_get_num(MAPE_MATERIAL_MAP_PRIVATE(map)->handle);
}
/**
* mape_material_map_get_material:
* @material: A #MapeMaterialMap.
* @index: A material index.
*
* Returns the entry with the given index in the map.
*
* Returns: A new #MapeMaterial to be freed with mape_material_free() when
* no longer needed.
**/
MapeMaterial*
mape_material_map_get_material(MapeMaterialMap* map,
guint index)
{
MapeMaterialMapPrivate* priv;
g_return_val_if_fail(MAPE_IS_MATERIAL_MAP(map), NULL);
priv = MAPE_MATERIAL_MAP_PRIVATE(map);
g_return_val_if_fail(index < c4_material_handle_get_num(priv->handle), NULL);
return mape_material_new(map, index);
}
#if 0
/*
* mape_material_map_get_material_by_name:
* @map: A #MapeMaterialMap.
* @name: The name of the material to retrieve.
*
* Returns the material in the map which has the given name, if any. If there
* is no such material the function returns %NULL.
*
* Returns: A new #MapeMaterial to be freed with mape_material_free() when
* no longer needed, or %NULL.
*/
MapeMaterial*
mape_material_map_get_material_by_name(MapeMaterialMap* map,
const gchar* name)
{
MapeMaterialMapPrivate* priv;
const gchar* cur_name;
guint i;
g_return_val_if_fail(MAPE_IS_MATERIAL_MAP(map), NULL);
g_return_val_if_fail(name != NULL, NULL);
priv = MAPE_MATERIAL_MAP_PRIVATE(map);
for(i = 0; i < c4_material_handle_get_num(priv->handle); ++i)
{
cur_name = c4_material_handle_get_name(priv->handle, i);
if(g_ascii_strcasecmp(cur_name, name) == 0)
return mape_material_new(map, i);
}
return NULL;
}
#endif
/**
* mape_material_copy:
* @material: A #MapeMaterial.
*
* Creates a copy of @material.
*
* Returns: A new #MapeMaterial to be freed with mape_material_free() when
* no longer needed.
*/
MapeMaterial*
mape_material_copy(const MapeMaterial* material)
{
g_return_val_if_fail(material != NULL, NULL);
return mape_material_new(material->map, material->mat_index);
}
/**
* mape_material_free:
* @material: A #MapeMaterial.
*
* Releases all ressources taken up by @material.
*/
void
mape_material_free(MapeMaterial* material)
{
g_return_if_fail(material != NULL);
g_object_unref(material->map);
g_slice_free(MapeMaterial, material);
}
/**
* mape_material_get_name:
* @material: A #MapeMaterial.
*
* Returns the material's name.
*
* Return Value: The name of the material. The string is owned by the
* #MapeMaterial and must not be freed by the user.
*/
const gchar*
mape_material_get_name(const MapeMaterial* material)
{
MapeMaterialMapPrivate* priv;
g_return_val_if_fail(material != NULL, NULL);
priv = MAPE_MATERIAL_MAP_PRIVATE(material->map);
return c4_material_handle_get_name(priv->handle, material->mat_index);
}
/**
* mape_material_get_texture_overlay:
* @material: A #MapeMaterial.
*
* Returns the material's texture overlay as a string. This can be used to
* make a texture lookup in a corresponding #MapeTextureMap.
*
* Return Value: The texture overlay of the material. The string is owned by
* the #MapeMaterial and must not be freed by the user.
*/
const gchar*
mape_material_get_texture_overlay(const MapeMaterial* material)
{
MapeMaterialMapPrivate* priv;
g_return_val_if_fail(material != NULL, NULL);
priv = MAPE_MATERIAL_MAP_PRIVATE(material->map);
return c4_material_handle_get_texture_overlay(
priv->handle, material->mat_index);
}
/* This function is for internal use only */
C4MaterialHandle*
_mape_material_map_get_handle(MapeMaterialMap* map)
{
g_return_val_if_fail(MAPE_IS_MATERIAL_MAP(map), NULL);
return MAPE_MATERIAL_MAP_PRIVATE(map)->handle;
}
/* vim:set et sw=2 ts=2: */