paysages3d/lib_paysages/layers.c

203 lines
5.2 KiB
C

#include "layers.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define LAYERS_MAX_NAME_LENGTH 50
typedef struct
{
void* definition;
char name[LAYERS_MAX_NAME_LENGTH + 1];
} LayerInfo;
struct Layers {
LayerType type;
int count;
int max_count;
void* null_layer;
LayerInfo* layers_info;
};
Layers* layersCreate(LayerType type, int max_layer_count)
{
Layers* result = malloc(sizeof(Layers));
result->type = type;
result->count = 0;
result->max_count = max_layer_count;
result->null_layer = type.callback_create();
result->layers_info = malloc(sizeof(LayerInfo) * max_layer_count);
return result;
}
Layers* layersCreateCopy(Layers* original)
{
Layers* result = layersCreate(original->type, original->max_count);
layersCopy(original, result);
return result;
}
void layersDelete(Layers* layers)
{
int i;
for (i = 0; i < layers->count; i++)
{
layers->type.callback_delete(layers->layers_info[i].definition);
}
free(layers->null_layer);
free(layers->layers_info);
free(layers);
}
void layersCopy(Layers* source, Layers* destination)
{
int i;
assert(source->type.callback_copy == destination->type.callback_copy);
assert(source->type.callback_create == destination->type.callback_create);
assert(source->type.callback_delete == destination->type.callback_delete);
assert(source->type.callback_load == destination->type.callback_load);
assert(source->type.callback_save == destination->type.callback_save);
assert(source->type.callback_validate == destination->type.callback_validate);
assert(source->max_count == destination->max_count);
/* TODO Optimize by reusing common layers */
while (destination->count > 0)
{
layersDeleteLayer(destination, 0);
}
for (i = 0; i < source->count; i++)
{
layersAddLayer(destination, source->layers_info[i].definition);
layersSetName(destination, i, layersGetName(source, i));
}
}
void layersValidate(Layers* layers)
{
int i;
for (i = 0; i < layers->count; i++)
{
layers->type.callback_validate(layers->layers_info[i].definition);
layers->layers_info[i].name[LAYERS_MAX_NAME_LENGTH] = '\0';
}
}
void layersSave(PackStream* stream, Layers* layers)
{
int i;
packWriteInt(stream, &layers->count);
for (i = 0; i < layers->count; i++)
{
packWriteString(stream, layers->layers_info[i].name, LAYERS_MAX_NAME_LENGTH);
layers->type.callback_save(stream, layers->layers_info[i].definition);
}
}
void layersLoad(PackStream* stream, Layers* layers)
{
int i;
packReadInt(stream, &layers->count);
for (i = 0; i < layers->count; i++)
{
packReadString(stream, layers->layers_info[i].name, LAYERS_MAX_NAME_LENGTH);
layers->type.callback_load(stream, layers->layers_info[i].definition);
}
layersValidate(layers);
}
const char* layersGetName(Layers* layers, int layer)
{
if (layer >= 0 && layer < layers->count)
{
return layers->layers_info[layer].name;
}
else
{
return "";
}
}
void layersSetName(Layers* layers, int layer, const char* name)
{
if (layer >= 0 && layer < layers->count)
{
strncpy(layers->layers_info[layer].name, name, LAYERS_MAX_NAME_LENGTH);
}
}
int layersCount(Layers* layers)
{
return layers->count;
}
void* layersGetLayer(Layers* layers, int layer)
{
if (layer >= 0 && layer < layers->count)
{
return layers->layers_info[layer].definition;
}
else
{
return layers->null_layer;
}
}
int layersAddLayer(Layers* layers, void* definition)
{
if (layers->count < layers->max_count)
{
layers->layers_info[layers->count].definition = layers->type.callback_create();
if (definition)
{
layers->type.callback_copy(definition, layers->layers_info[layers->count].definition);
}
layers->count++;
layersSetName(layers, layers->count - 1, "unnamed");
return layers->count - 1;
}
else
{
return -1;
}
}
void layersDeleteLayer(Layers* layers, int layer)
{
if (layer >= 0 && layer < layers->count)
{
layers->type.callback_delete(layers->layers_info[layer].definition);
if (layers->count > 1 && layer < layers->count - 1)
{
memmove(layers->layers_info + layer, layers->layers_info + layer + 1, sizeof(LayerInfo) * (layers->count - layer - 1));
}
layers->count--;
}
}
void layersMove(Layers* layers, int layer, int new_position)
{
if (layer >= 0 && layer < layers->count && new_position != layer && new_position >= 0 && new_position < layers->count)
{
LayerInfo temp;
temp = layers->layers_info[layer];
if (new_position > layer)
{
memmove(layers->layers_info + layer, layers->layers_info + layer + 1, sizeof(LayerInfo) * (new_position - layer));
}
else
{
memmove(layers->layers_info + new_position + 1, layers->layers_info + new_position, sizeof(LayerInfo) * (layer - new_position));
}
layers->layers_info[new_position] = temp;
}
}