1117 lines
28 KiB
C
1117 lines
28 KiB
C
/*
|
|
* This file is part of the MLV Library.
|
|
*
|
|
* Copyright (C) 2010,2011,2012 Adrien Boussicault, Marc Zipstein
|
|
*
|
|
*
|
|
* This Library is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This Library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this Library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "platform.h"
|
|
|
|
#ifdef OS_WINDOWS
|
|
extern int asprintf (char **, const char *, ...);
|
|
#endif
|
|
|
|
#include "MLV_animation.h"
|
|
#include "MLV_path.h"
|
|
|
|
#include "warning_error.h"
|
|
#include "memory_management.h"
|
|
#include "tree_map.h"
|
|
|
|
#include "MLV_xml.h"
|
|
|
|
////////////////////////////////////////////////
|
|
// Animation structures
|
|
///////////////////////////////////////////////
|
|
|
|
typedef struct {
|
|
MLV_Image** images; // Layer of images
|
|
MLV_Sound** sounds; // Layer of images
|
|
unsigned int delay;
|
|
} Animation_frame;
|
|
|
|
struct _MLV_Animation {
|
|
unsigned int max_frames;
|
|
unsigned int nb_frames;
|
|
unsigned int nb_layers;
|
|
unsigned int nb_channels;
|
|
Animation_frame * frames;
|
|
};
|
|
|
|
struct _MLV_Animation_player {
|
|
int* state_sound;
|
|
int* sounds_are_being_played;
|
|
float* volume;
|
|
const MLV_Animation * animation;
|
|
enum { STOP, PLAY, PLAY_REVERT } status;
|
|
unsigned int current_frame;
|
|
unsigned int counter;
|
|
};
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
// Animation data
|
|
///////////////////////////////////////////////
|
|
|
|
MLV_Animation* MLV_create_animation(
|
|
unsigned int max_frames, unsigned int nb_layers, unsigned int nb_channels
|
|
){
|
|
MLV_Animation* result = MLV_MALLOC( 1, MLV_Animation );
|
|
result->nb_frames = 0;
|
|
result->max_frames = max_frames;
|
|
result->nb_layers = nb_layers;
|
|
result->nb_channels = nb_channels;
|
|
result->frames = MLV_MALLOC( max_frames, Animation_frame );
|
|
int i,j;
|
|
for( i=0; i<max_frames; i++ ){
|
|
if( nb_layers>0 ){
|
|
result->frames[i].images = MLV_MALLOC( nb_layers, MLV_Image* );
|
|
for( j=0; j<nb_layers; j++ ){
|
|
result->frames[i].images[j] = NULL;
|
|
}
|
|
}else{
|
|
result->frames[i].images = NULL;
|
|
}
|
|
if( nb_channels>0 ){
|
|
result->frames[i].sounds = MLV_MALLOC( nb_channels, MLV_Sound* );
|
|
for( j=0; j<nb_channels; j++ ){
|
|
result->frames[i].sounds[j] = NULL;
|
|
}
|
|
}else{
|
|
result->frames[i].sounds = NULL;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void MLV_free_animation( MLV_Animation* animation ){
|
|
int i;
|
|
for( i=0; i<animation->nb_frames; i++ ){
|
|
MLV_FREE( animation->frames[i].images, MLV_Image* );
|
|
MLV_FREE( animation->frames[i].sounds, MLV_Image* );
|
|
}
|
|
MLV_FREE( animation->frames, Animation_frame );
|
|
MLV_FREE( animation, MLV_Animation );
|
|
}
|
|
|
|
void user_is_modifying_animation(
|
|
MLV_Animation* animation, unsigned int position
|
|
){
|
|
if( position < animation->max_frames ){
|
|
if( position >= animation->nb_frames ){
|
|
animation->nb_frames = position+1;
|
|
}
|
|
}else{
|
|
char* text;
|
|
int error = asprintf(
|
|
&text,
|
|
"Tou can-t add or modify an image at the position %d, you have created an animation with only %d images.",
|
|
position, animation->max_frames
|
|
);
|
|
if( error==-1){
|
|
ERROR_FULL("Allocation memoy problem.");
|
|
}
|
|
ERROR( text );
|
|
MLV_FREE(text, char);
|
|
}
|
|
}
|
|
|
|
void MLV_change_frame_in_animation(
|
|
MLV_Image** array_of_images, MLV_Sound** array_of_sounds, unsigned int delay,
|
|
MLV_Animation* animation, unsigned int position
|
|
){
|
|
user_is_modifying_animation( animation, position );
|
|
if( array_of_images ){
|
|
int layer;
|
|
for( layer=0; layer<animation->nb_layers; layer ++){
|
|
animation->frames[
|
|
position
|
|
].images[layer] = array_of_images[layer];
|
|
}
|
|
}
|
|
if( array_of_sounds ){
|
|
int channel;
|
|
for( channel=0; channel<animation->nb_channels; channel++ ){
|
|
animation->frames[
|
|
position
|
|
].sounds[channel] = array_of_sounds[channel];
|
|
}
|
|
}
|
|
animation->frames[position].delay = delay;
|
|
}
|
|
|
|
void MLV_add_frame_in_animation(
|
|
MLV_Image** array_of_images, MLV_Sound** array_of_sounds, unsigned int delay,
|
|
MLV_Animation* animation
|
|
){
|
|
MLV_change_frame_in_animation(
|
|
array_of_images, array_of_sounds, delay, animation,
|
|
animation->nb_frames
|
|
);
|
|
}
|
|
|
|
void MLV_change_frame_image_in_animation(
|
|
MLV_Image* image, MLV_Animation* animation,
|
|
unsigned int position, unsigned int layer
|
|
){
|
|
user_is_modifying_animation( animation, position );
|
|
animation->frames[position].images[layer] = image;
|
|
}
|
|
|
|
void MLV_change_frame_sound_in_animation(
|
|
MLV_Sound* sound, MLV_Animation* animation,
|
|
unsigned int position, unsigned int channel
|
|
){
|
|
user_is_modifying_animation( animation, position );
|
|
animation->frames[position].sounds[channel] = sound;
|
|
}
|
|
|
|
void MLV_change_frame_delay_in_animation(
|
|
unsigned int delay, MLV_Animation* animation,
|
|
unsigned int position
|
|
){
|
|
user_is_modifying_animation( animation, position );
|
|
animation->frames[position].delay = delay;
|
|
}
|
|
|
|
void MLV_get_frame_from_animation(
|
|
MLV_Animation* animation, unsigned int position, unsigned int layer,
|
|
MLV_Image** image, unsigned int* delay
|
|
){
|
|
TODO
|
|
}
|
|
|
|
int MLV_get_frame_delay_from_animation(
|
|
MLV_Animation* animation, unsigned int position
|
|
){
|
|
return animation->frames[position].delay;
|
|
}
|
|
|
|
MLV_Image* MLV_get_frame_image_from_animation(
|
|
MLV_Animation* animation, unsigned int position,
|
|
unsigned int layer
|
|
){
|
|
return animation->frames[position].images[layer];
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
// Animation engine
|
|
///////////////////////////////////////////////
|
|
|
|
MLV_Animation_player* MLV_create_animation_player(
|
|
MLV_Animation* animation
|
|
){
|
|
int nb_channels = animation->nb_channels;
|
|
MLV_Animation_player* result = MLV_MALLOC( 1, MLV_Animation_player );
|
|
if( nb_channels>0 ){
|
|
result->volume = MLV_MALLOC( nb_channels, float );
|
|
result->state_sound = MLV_MALLOC( nb_channels, int );
|
|
result->sounds_are_being_played = MLV_MALLOC( nb_channels, int );
|
|
int channel;
|
|
for( channel=0; channel<nb_channels; channel++ ){
|
|
result->volume[channel]=0;
|
|
result->state_sound[channel] = 0;
|
|
result->sounds_are_being_played[channel] = 0;
|
|
}
|
|
}else{
|
|
result->volume = NULL;
|
|
result->state_sound = NULL;
|
|
result->sounds_are_being_played = NULL;
|
|
}
|
|
result->animation = animation;
|
|
MLV_rewind_animation_player( result );
|
|
return result;
|
|
}
|
|
void MLV_free_animation_player( MLV_Animation_player* animation_player ){
|
|
MLV_FREE( animation_player->volume, float );
|
|
MLV_FREE( animation_player->state_sound, int );
|
|
MLV_FREE( animation_player->sounds_are_being_played, int );
|
|
MLV_FREE( animation_player, MLV_Animation_player );
|
|
}
|
|
|
|
void MLV_play_animation_player( MLV_Animation_player* animation_player ){
|
|
animation_player->status = PLAY;
|
|
}
|
|
void MLV_play_revert_animation_player( MLV_Animation_player* animation_player ){
|
|
animation_player->status = PLAY_REVERT;
|
|
}
|
|
void MLV_stop_animation_player( MLV_Animation_player* animation_player ){
|
|
animation_player->status = STOP;
|
|
}
|
|
void MLV_rewind_animation_player( MLV_Animation_player* animation_player ){
|
|
animation_player->current_frame = 0;
|
|
animation_player->counter = 0;
|
|
MLV_stop_animation_player( animation_player );
|
|
}
|
|
void MLV_next_frame( MLV_Animation_player* animation_player ){
|
|
/* Retour à la frame 0 si nous sommes à la dernière */
|
|
if(
|
|
++animation_player->current_frame ==
|
|
animation_player->animation->nb_frames
|
|
){
|
|
animation_player->current_frame = 0;
|
|
}
|
|
animation_player->counter = 0;
|
|
}
|
|
void MLV_previous_frame(
|
|
MLV_Animation_player* animation_player
|
|
){
|
|
/* Retour à la frame 0 si nous sommes à la dernière */
|
|
if ( --animation_player->current_frame == -1 ){
|
|
animation_player->current_frame =
|
|
animation_player->animation->nb_frames-1;
|
|
}
|
|
animation_player->counter = 0;
|
|
}
|
|
|
|
void MLV_update_animation_player( MLV_Animation_player* animation_player ){
|
|
const Animation_frame * frame;
|
|
|
|
if( animation_player->status == STOP ) return;
|
|
|
|
frame = &animation_player->animation->frames[
|
|
animation_player->current_frame
|
|
];
|
|
|
|
if (frame->delay == 0) return;
|
|
|
|
// Passage à la frame suivante
|
|
if( ++animation_player->counter == frame->delay ){
|
|
switch( animation_player->status ){
|
|
case PLAY:
|
|
MLV_next_frame(animation_player);
|
|
break;
|
|
case PLAY_REVERT:
|
|
MLV_previous_frame(animation_player);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
// Remise à 0 de l'état des sons qui ont déjà été joués.
|
|
int channel;
|
|
if( animation_player->sounds_are_being_played ){
|
|
for(
|
|
channel=0; channel < animation_player->animation->nb_channels;
|
|
channel++
|
|
){
|
|
animation_player->sounds_are_being_played[channel] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void MLV_change_sound_volume_of_animation_player(
|
|
MLV_Animation_player* animation_player, unsigned int channel, float volume
|
|
){
|
|
animation_player->volume[channel]=volume;
|
|
}
|
|
|
|
|
|
void MLV_turn_off_sound_of_animation_player(
|
|
MLV_Animation_player* animation_player, unsigned int channel
|
|
){
|
|
animation_player->state_sound[channel]=0;
|
|
}
|
|
|
|
void MLV_turn_on_sound_of_animation_player(
|
|
MLV_Animation_player* animation_player, unsigned int channel
|
|
){
|
|
animation_player->state_sound[channel]=1;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
// Drawing animation
|
|
///////////////////////////////////////////////
|
|
|
|
void MLV_draw_image_from_animation_player(
|
|
MLV_Animation_player* animation_player, unsigned int layer,
|
|
int x, int y
|
|
){
|
|
MLV_draw_image(
|
|
animation_player->animation->frames[
|
|
animation_player->current_frame
|
|
].images[layer],
|
|
x,y
|
|
);
|
|
}
|
|
|
|
void MLV_draw_image_from_animation_player_on_image(
|
|
MLV_Animation_player* animation_player, unsigned int layer,
|
|
MLV_Image* image,
|
|
int x, int y
|
|
){
|
|
MLV_draw_image_on_image(
|
|
animation_player->animation->frames[
|
|
animation_player->current_frame
|
|
].images[layer],
|
|
image,
|
|
x,y
|
|
);
|
|
}
|
|
|
|
void MLV_draw_partial_image_from_animation_player_on_image(
|
|
MLV_Animation_player* animation_player, unsigned int layer,
|
|
int source_x, int source_y, int source_width, int source_height,
|
|
MLV_Image* image,
|
|
int x, int y
|
|
){
|
|
MLV_draw_partial_image_on_image(
|
|
animation_player->animation->frames[
|
|
animation_player->current_frame
|
|
].images[layer],
|
|
source_x, source_y, source_width, source_height,
|
|
image,
|
|
x, y
|
|
);
|
|
}
|
|
|
|
void MLV_draw_partial_image_from_animation_player(
|
|
MLV_Animation_player* animation_player, unsigned int layer,
|
|
int source_x, int source_y, int source_width, int source_height,
|
|
MLV_Image* image,
|
|
int x, int y
|
|
){
|
|
MLV_draw_partial_image(
|
|
animation_player->animation->frames[
|
|
animation_player->current_frame
|
|
].images[layer],
|
|
source_x, source_y, source_width, source_height,
|
|
x, y
|
|
);
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
// Playing sounds of animation
|
|
///////////////////////////////////////////////
|
|
|
|
void MLV_play_sound_from_animation_player(
|
|
MLV_Animation_player* animation_player, unsigned int channel
|
|
){
|
|
const Animation_frame* frame = &animation_player->animation->frames[
|
|
animation_player->current_frame
|
|
];
|
|
if(
|
|
animation_player->sounds_are_being_played &&
|
|
! animation_player->sounds_are_being_played[channel]
|
|
){
|
|
MLV_Sound* sound = frame->sounds[channel];
|
|
if( animation_player->state_sound[channel] && sound ){
|
|
MLV_play_sound( sound, animation_player->volume[channel] );
|
|
}
|
|
animation_player->sounds_are_being_played[channel] = 1;
|
|
}
|
|
}
|
|
|
|
void MLV_play_sounds_from_animation_player(
|
|
MLV_Animation_player* animation_player,
|
|
...
|
|
){
|
|
va_list pile;
|
|
va_start( pile, animation_player );
|
|
|
|
int layer;
|
|
layer = va_arg( pile, int );
|
|
while( layer >= 0 ) {
|
|
MLV_play_sound_from_animation_player(
|
|
animation_player, layer
|
|
);
|
|
layer = va_arg( pile, int );
|
|
}
|
|
|
|
va_end( pile );
|
|
}
|
|
|
|
void MLV_play_list_of_sounds_from_animation_player(
|
|
MLV_Animation_player* animation_player, unsigned int* layers,
|
|
unsigned int nb_layers
|
|
){
|
|
int i;
|
|
for( i=0; i< nb_layers; i++ ){
|
|
MLV_play_sound_from_animation_player(
|
|
animation_player, layers[i]
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////
|
|
// Loading animations from files
|
|
// stored in animation books.
|
|
///////////////////////////////////////////////
|
|
|
|
typedef struct _Animation_book_sound {
|
|
char* name;
|
|
MLV_Sound** channels;
|
|
} Animation_book_sound;
|
|
|
|
typedef struct _Animation_book_page {
|
|
int width;
|
|
int height;
|
|
int columns;
|
|
MLV_Image** layers;
|
|
} Animation_book_page;
|
|
|
|
struct _MLV_Animation_book {
|
|
char* xml_file;
|
|
|
|
int nb_channels;
|
|
MLV_TreeMap* channel_name_to_id;
|
|
char** channel_names;
|
|
|
|
int nb_layers;
|
|
MLV_TreeMap* layer_name_to_id;
|
|
char** layer_names;
|
|
|
|
int nb_pages;
|
|
MLV_TreeMap* page_name_to_id;
|
|
char** page_names;
|
|
Animation_book_page* pages;
|
|
|
|
int nb_sounds;
|
|
MLV_TreeMap* sound_name_to_id;
|
|
char** sound_names;
|
|
Animation_book_sound* sounds;
|
|
|
|
int nb_animations;
|
|
MLV_TreeMap* animation_name_to_id;
|
|
char** animation_names;
|
|
MLV_Animation** animations;
|
|
|
|
};
|
|
|
|
int MLV_get_number_of_animations(
|
|
MLV_Animation_book* animation_book
|
|
){
|
|
return animation_book->nb_animations;
|
|
}
|
|
|
|
void destroy_int( void* data ){
|
|
int* ptr = (int*) data;
|
|
MLV_FREE( ptr, int );
|
|
}
|
|
|
|
void insert_data_in_map( MLV_TreeMap* map, char* name, int identifiant ){
|
|
int* id = MLV_MALLOC( 1, int );
|
|
*id = identifiant;
|
|
MLV_add_data_in_tree_map(
|
|
MLV_string_to_key(name), id, destroy_int, map
|
|
);
|
|
}
|
|
|
|
MLV_Animation_book* MLV_load_animation_book(
|
|
const char* xml_file,
|
|
const char* image_directory,
|
|
const char* sound_directory
|
|
){
|
|
int i;
|
|
MLV_Animation_book* result;
|
|
|
|
if( ! MLV_path_exists( xml_file ) ){
|
|
fprintf(
|
|
stderr,
|
|
"The xml file %s doesn't exists.\n",
|
|
xml_file
|
|
);
|
|
return NULL;
|
|
}
|
|
if(
|
|
image_directory &&
|
|
( ! strcmp( image_directory, "" ) ) &&
|
|
MLV_path_exists( image_directory )
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The image directory %s doesn't exists.\n",
|
|
image_directory
|
|
);
|
|
return NULL;
|
|
}
|
|
if(
|
|
sound_directory &&
|
|
( ! strcmp( sound_directory, "" ) ) &&
|
|
MLV_path_exists( sound_directory )
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The sound directory %s doesn't exists.\n",
|
|
sound_directory
|
|
);
|
|
return NULL;
|
|
}
|
|
|
|
char* dirname = MLV_get_directory_name( xml_file );
|
|
|
|
MLV_Xml* xml = MLV_load_xml( xml_file );
|
|
|
|
if( !xml ) return NULL;
|
|
|
|
result = MLV_MALLOC( 1, MLV_Animation_book );
|
|
|
|
result->nb_animations = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/animation"
|
|
);
|
|
result->animations = MLV_MALLOC(
|
|
result->nb_animations, MLV_Animation*
|
|
);
|
|
result->animation_names = MLV_MALLOC(
|
|
result->nb_animations, char*
|
|
);
|
|
result->animation_name_to_id = MLV_create_tree_map();
|
|
for( i=0; i<result->nb_animations; i++ ){
|
|
if( MLV_get_string_value_from_xml(
|
|
xml,
|
|
&(result->animation_names[i]),
|
|
"/animation_book/animation[%d]/name", i+1
|
|
) ){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The Field /animation_book/animation[%d]/name doesn't exist.\n",
|
|
i+1
|
|
);
|
|
exit(0);
|
|
};
|
|
insert_data_in_map(
|
|
result->animation_name_to_id, result->animation_names[i], i
|
|
);
|
|
}
|
|
|
|
result->nb_layers = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/layers/layer"
|
|
);
|
|
result->layer_names = MLV_MALLOC(
|
|
result->nb_layers, char*
|
|
);
|
|
result->layer_name_to_id = MLV_create_tree_map();
|
|
for( i=0; i<result->nb_layers; i++ ){
|
|
if(
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(result->layer_names[i]), "/animation_book/layers/layer[%d]", i+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The Field /animation_book/layers/layer[%d] doesn't exist.\n",
|
|
i+1
|
|
);
|
|
exit(0);
|
|
}
|
|
insert_data_in_map(
|
|
result->layer_name_to_id, result->layer_names[i], i
|
|
);
|
|
}
|
|
|
|
result->nb_channels = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/channels/channel"
|
|
);
|
|
result->channel_names = MLV_MALLOC(
|
|
result->nb_channels, char*
|
|
);
|
|
result->channel_name_to_id = MLV_create_tree_map();
|
|
for( i=0; i<result->nb_channels; i++ ){
|
|
if(
|
|
MLV_get_string_value_from_xml(
|
|
xml,
|
|
&(result->channel_names[i]),
|
|
"/animation_book/channels/channel[%d]", i+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The Field /animation_book/channels/channel[%d] doesn't exist.\n",
|
|
i+1
|
|
);
|
|
exit(0);
|
|
};
|
|
insert_data_in_map(
|
|
result->channel_name_to_id, result->channel_names[i], i
|
|
);
|
|
}
|
|
|
|
|
|
result->nb_pages = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/page"
|
|
);
|
|
result->page_names = MLV_MALLOC(
|
|
result->nb_pages, char*
|
|
);
|
|
result->page_name_to_id = MLV_create_tree_map();
|
|
for( i=0; i<result->nb_pages; i++ ){
|
|
if(
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(result->page_names[i]),"/animation_book/page[%d]/name", i+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The Field /animation_book/page[%d]/name doesn't exist.\n",
|
|
i+1
|
|
);
|
|
exit(0);
|
|
};
|
|
insert_data_in_map(
|
|
result->page_name_to_id, result->page_names[i], i
|
|
);
|
|
}
|
|
result->pages = MLV_MALLOC(
|
|
result->nb_pages, Animation_book_page
|
|
);
|
|
|
|
result->nb_sounds = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/sound"
|
|
);
|
|
result->sound_names = MLV_MALLOC(
|
|
result->nb_sounds, char*
|
|
);
|
|
result->sound_name_to_id = MLV_create_tree_map();
|
|
for( i=0; i<result->nb_sounds; i++ ){
|
|
if(
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(result->sound_names[i]), "/animation_book/sound[%d]/name", i+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The Field /animation_book/sound[%d]/name doesn't exist.\n",
|
|
i+1
|
|
);
|
|
exit(0);
|
|
}
|
|
insert_data_in_map(
|
|
result->sound_name_to_id, result->sound_names[i], i
|
|
);
|
|
}
|
|
result->sounds = MLV_MALLOC(
|
|
result->nb_sounds, Animation_book_sound
|
|
);
|
|
|
|
int nb_layers = result->nb_layers;
|
|
int nb_channels = result->nb_channels;
|
|
int nb_pages = result->nb_pages;
|
|
int nb_sounds = result->nb_sounds;
|
|
int nb_animations = result->nb_animations;
|
|
|
|
int id_page;
|
|
for( id_page=0; id_page<nb_pages; id_page++ ){
|
|
if(
|
|
MLV_get_integer_value_from_xml(
|
|
xml, &(result->pages[id_page].width), "/animation_book/page[%d]/width", id_page+1
|
|
) ||
|
|
MLV_get_integer_value_from_xml(
|
|
xml, &(result->pages[id_page].height), "/animation_book/page[%d]/height", id_page+1
|
|
) ||
|
|
MLV_get_integer_value_from_xml(
|
|
xml, &(result->pages[id_page].columns), "/animation_book/page[%d]/columns", id_page+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. One of those fields /animation_book/page[%d]/width or /animation_book/page[%d]/height or /animation_book/page[%d]/columns are missing or are not integers.\n",
|
|
id_page+1,
|
|
id_page+1,
|
|
id_page+1
|
|
);
|
|
exit(0);
|
|
};
|
|
result->pages[id_page].layers = MLV_MALLOC( nb_layers, MLV_Image* );
|
|
for( i=0; i < nb_layers; i++ ){
|
|
result->pages[id_page].layers[i] = NULL;
|
|
}
|
|
|
|
int nb_images = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/page[%d]/image", id_page+1
|
|
);
|
|
int image;
|
|
for( image=0; image < nb_images; image++ ){
|
|
char* layer;
|
|
char* file;
|
|
if(
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(layer), "/animation_book/page[%d]/image[%d]/layer", id_page+1,
|
|
image+1
|
|
) ||
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(file), "/animation_book/page[%d]/image[%d]/file", id_page+1,
|
|
image+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. One of those Fields : /animation_book/page[%d]/image[%d]/layer or /animation_book/page[%d]/image[%d]/file are missing.\n",
|
|
id_page+1, image+1,
|
|
id_page+1, image+1
|
|
);
|
|
exit(0);
|
|
}
|
|
MLV_Key* key = MLV_string_to_key( layer );
|
|
int id_layer = *(
|
|
(int*) MLV_get_data_from_tree_map(
|
|
key, result->layer_name_to_id
|
|
)
|
|
);
|
|
MLV_free_key( key );
|
|
|
|
char* full_path;
|
|
if( MLV_path_is_absolute( file ) ){
|
|
full_path = MLV_build_path(
|
|
file, NULL
|
|
);
|
|
}else{
|
|
if( image_directory ){
|
|
full_path = MLV_build_path(
|
|
image_directory, file, NULL
|
|
);
|
|
}else{
|
|
full_path = MLV_build_path( dirname, file, NULL );
|
|
}
|
|
}
|
|
if( ! MLV_path_exists( full_path ) ){
|
|
fprintf(
|
|
stderr,
|
|
"The file %s doesn't exist.\n",
|
|
full_path
|
|
);
|
|
exit(0);
|
|
}
|
|
MLV_Image* image = MLV_load_image( full_path );
|
|
if( ! image ){
|
|
fprintf(
|
|
stderr,
|
|
"The file %s is an unknow image or is corrupted.\n",
|
|
full_path
|
|
);
|
|
exit(0);
|
|
}
|
|
result->pages[id_page].layers[ id_layer ] = image;
|
|
MLV_FREE( full_path, char );
|
|
|
|
MLV_FREE( layer, char );
|
|
MLV_FREE( file, char );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
int id_sound;
|
|
for( id_sound=0; id_sound<nb_sounds; id_sound++ ){
|
|
result->sounds[id_sound].channels = MLV_MALLOC( nb_channels, MLV_Sound* );
|
|
for( i=0; i < nb_channels; i++ ){
|
|
result->sounds[id_sound].channels[i] = NULL;
|
|
}
|
|
|
|
int nb_samples = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/sound[%d]/sample", id_sound+1
|
|
);
|
|
int sample;
|
|
for( sample=0; sample < nb_samples; sample++ ){
|
|
char* channel;
|
|
char* file;
|
|
if(
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(channel), "/animation_book/sound[%d]/sample[%d]/channel", id_sound+1,
|
|
sample+1
|
|
) ||
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(file), "/animation_book/sound[%d]/sample[%d]/file", id_sound+1,
|
|
sample+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. One of those Fields : /animation_book/sound[%d]/sample[%d]/channel or /animation_book/sound[%d]/sample[%d]/file are missing.\n",
|
|
id_sound+1, sample+1,
|
|
id_sound+1, sample+1
|
|
);
|
|
exit(0);
|
|
}
|
|
MLV_Key* key = MLV_string_to_key( channel );
|
|
int id_channel = *(
|
|
(int*) MLV_get_data_from_tree_map(
|
|
key, result->channel_name_to_id
|
|
)
|
|
);
|
|
MLV_free_key( key );
|
|
|
|
|
|
char* full_path;
|
|
if( MLV_path_is_absolute( file ) ){
|
|
full_path = MLV_build_path(
|
|
file, NULL
|
|
);
|
|
}else{
|
|
if( sound_directory ){
|
|
full_path = MLV_build_path(
|
|
sound_directory, file, NULL
|
|
);
|
|
}else{
|
|
full_path = MLV_build_path( dirname, file, NULL );
|
|
}
|
|
}
|
|
if( ! MLV_path_exists( full_path ) ){
|
|
fprintf(
|
|
stderr,
|
|
"The file %s doesn't exist.\n",
|
|
full_path
|
|
);
|
|
exit(0);
|
|
}
|
|
MLV_Sound* sound = MLV_load_sound( full_path );
|
|
if( ! sound ){
|
|
fprintf(
|
|
stderr,
|
|
"The sound file %s are unknwon or corrupted.\n",
|
|
full_path
|
|
);
|
|
exit(0);
|
|
}
|
|
result->sounds[id_sound].channels[ id_channel ] = sound;
|
|
MLV_FREE( full_path, char );
|
|
|
|
MLV_FREE( channel, char );
|
|
MLV_FREE( file, char );
|
|
}
|
|
}
|
|
|
|
|
|
int id_animation;
|
|
for( id_animation=0; id_animation<nb_animations; id_animation++ ){
|
|
char* page_name;
|
|
if(
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(page_name), "/animation_book/animation[%d]/page", id_animation+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The field : /animation_book/animation[%d]/page is missing.\n",
|
|
id_animation+1
|
|
);
|
|
exit(0);
|
|
}
|
|
MLV_Key* key = MLV_string_to_key( page_name );
|
|
int id_page = *(
|
|
(int*) MLV_get_data_from_tree_map(
|
|
key, result->page_name_to_id
|
|
)
|
|
);
|
|
MLV_free_key( key );
|
|
int width = result->pages[id_page].width;
|
|
int height = result->pages[id_page].height;
|
|
int columns = result->pages[id_page].columns;
|
|
int nb_frames = MLV_get_number_of_objects_from_xml(
|
|
xml, "/animation_book/animation[%d]/frame", id_animation+1
|
|
);
|
|
result->animations[
|
|
id_animation
|
|
] = MLV_create_animation( nb_frames, nb_layers, nb_channels );
|
|
int id_frame;
|
|
for( id_frame=0; id_frame < nb_frames; id_frame++ ){
|
|
MLV_Sound** sounds = NULL;
|
|
MLV_Image** images = NULL;
|
|
char* sound;
|
|
MLV_get_string_value_from_xml(
|
|
xml, &(sound), "/animation_book/animation[%d]/frame[%d]/sound",
|
|
id_animation+1, id_frame+1
|
|
);
|
|
if( sound ){
|
|
MLV_Key* key = MLV_string_to_key( sound );
|
|
int id_sound = *(
|
|
(int*) MLV_get_data_from_tree_map(
|
|
key, result->sound_name_to_id
|
|
)
|
|
);
|
|
MLV_free_key( key );
|
|
sounds = result->sounds[id_sound].channels;
|
|
}
|
|
int panel;
|
|
if(
|
|
MLV_get_integer_value_from_xml(
|
|
xml, &(panel), "/animation_book/animation[%d]/frame[%d]/panel",
|
|
id_animation+1, id_frame+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The field : /animation_book/animation[%d]/frame[%d]/panel is missing or is not an integer.\n",
|
|
id_animation+1, id_frame+1
|
|
);
|
|
exit(0);
|
|
}
|
|
images = MLV_MALLOC( nb_layers ,MLV_Image* );
|
|
int id_layer;
|
|
for( id_layer=0; id_layer<nb_layers; id_layer++ ){
|
|
int x = (panel%columns)*(width+1);
|
|
int y = (panel/columns)*(height+1);
|
|
if(result->pages[id_page].layers[id_layer]){
|
|
images[id_layer] = MLV_copy_partial_image(
|
|
result->pages[id_page].layers[id_layer],
|
|
x, y, width, height
|
|
);
|
|
}else{
|
|
images[id_layer] = NULL;
|
|
}
|
|
}
|
|
int time;
|
|
if(
|
|
MLV_get_integer_value_from_xml(
|
|
xml, &(time), "/animation_book/animation[%d]/frame[%d]/time",
|
|
id_animation+1, id_frame+1
|
|
)
|
|
){
|
|
fprintf(
|
|
stderr,
|
|
"The animation book xml is corrupted. The field : /animation_book/animation[%d]/frame[%d]/time is missing or is not an integer.\n",
|
|
id_animation+1, id_frame+1
|
|
);
|
|
exit(0);
|
|
};
|
|
MLV_add_frame_in_animation(
|
|
images, sounds, time, result->animations[id_animation]
|
|
);
|
|
MLV_FREE( images, MLV_Image* );
|
|
MLV_FREE( sound, char );
|
|
}
|
|
}
|
|
|
|
MLV_FREE( dirname, char );
|
|
MLV_free_xml( xml );
|
|
|
|
return result;
|
|
}
|
|
|
|
void MLV_free_animation_book(
|
|
MLV_Animation_book* animation_book
|
|
){
|
|
if( !animation_book ) return;
|
|
|
|
int i;
|
|
|
|
int id_animation;
|
|
for( id_animation=0; id_animation < animation_book->nb_animations;
|
|
id_animation++
|
|
){
|
|
MLV_Animation* animation;
|
|
animation = animation_book->animations[id_animation];
|
|
int id_frame;
|
|
for( id_frame=0; id_frame < animation->nb_frames; id_frame++ ){
|
|
int id_layer;
|
|
MLV_Image** images = animation->frames[id_frame].images;
|
|
for( id_layer=0; id_layer<animation_book->nb_layers; id_layer++ ){
|
|
if( images[id_layer] ){
|
|
MLV_free_image( images[id_layer] );
|
|
}
|
|
}
|
|
}
|
|
MLV_free_animation( animation );
|
|
}
|
|
|
|
|
|
int id_sound;
|
|
for( id_sound=0; id_sound< animation_book->nb_sounds; id_sound++ ){
|
|
int id_channel;
|
|
for(
|
|
id_channel=0; id_channel < animation_book->nb_channels;
|
|
id_channel++
|
|
){
|
|
if( animation_book->sounds[id_sound].channels[ id_channel ] ){
|
|
MLV_free_sound(
|
|
animation_book->sounds[id_sound].channels[id_channel]
|
|
);
|
|
}
|
|
}
|
|
MLV_FREE( animation_book->sounds[id_sound].channels, MLV_Image* );
|
|
}
|
|
MLV_free_tree_map( animation_book->sound_name_to_id );
|
|
for( i=0; i<animation_book->nb_sounds; i++ ){
|
|
MLV_FREE( animation_book->sound_names[i], char );
|
|
}
|
|
MLV_FREE( animation_book->sound_names, char* );
|
|
MLV_FREE( animation_book->sounds, Animation_book_sound );
|
|
|
|
int id_page;
|
|
for( id_page=0; id_page< animation_book->nb_pages; id_page++ ){
|
|
int id_layer;
|
|
for( id_layer=0; id_layer < animation_book->nb_layers; id_layer++ ){
|
|
if( animation_book->pages[id_page].layers[ id_layer ] ){
|
|
MLV_free_image(
|
|
animation_book->pages[id_page].layers[id_layer]
|
|
);
|
|
}
|
|
}
|
|
MLV_FREE( animation_book->pages[id_page].layers, MLV_Image* );
|
|
}
|
|
MLV_free_tree_map( animation_book->page_name_to_id );
|
|
for( i=0; i<animation_book->nb_pages; i++ ){
|
|
MLV_FREE( animation_book->page_names[i], char );
|
|
}
|
|
MLV_FREE( animation_book->page_names, char* );
|
|
MLV_FREE( animation_book->pages, Animation_book_page );
|
|
|
|
MLV_free_tree_map( animation_book->channel_name_to_id );
|
|
for( i=0; i<animation_book->nb_channels; i++ ){
|
|
MLV_FREE( animation_book->channel_names[i], char );
|
|
}
|
|
MLV_FREE( animation_book->channel_names, char* );
|
|
|
|
MLV_free_tree_map( animation_book->layer_name_to_id );
|
|
for( i=0; i<animation_book->nb_layers; i++ ){
|
|
MLV_FREE( animation_book->layer_names[i], char );
|
|
}
|
|
MLV_FREE( animation_book->layer_names, char* );
|
|
|
|
MLV_free_tree_map( animation_book->animation_name_to_id );
|
|
for( i=0; i<animation_book->nb_animations; i++ ){
|
|
MLV_FREE( animation_book->animation_names[i], char );
|
|
}
|
|
MLV_FREE( animation_book->animation_names, char* );
|
|
MLV_FREE( animation_book->animations, MLV_Animation* );
|
|
|
|
MLV_FREE( animation_book, MLV_Animation_book );
|
|
}
|
|
|
|
MLV_Animation* MLV_get_animation_from_id(
|
|
MLV_Animation_book* animation_book,
|
|
int id
|
|
){
|
|
return animation_book->animations[id];
|
|
}
|
|
|
|
MLV_Animation* MLV_get_animation_from_name(
|
|
MLV_Animation_book* animation_book,
|
|
const char* name
|
|
){
|
|
MLV_Key* key = MLV_string_to_key( name );
|
|
int* id_ptr =(int*) MLV_get_data_from_tree_map(
|
|
key, animation_book->animation_name_to_id
|
|
);
|
|
MLV_free_key( key );
|
|
if( !id_ptr ) return NULL;
|
|
return MLV_get_animation_from_id( animation_book, *id_ptr );
|
|
}
|
|
|
|
const char* MLV_get_name_from_id_animation(
|
|
MLV_Animation_book* animation_book, int id_animation
|
|
){
|
|
return animation_book->animation_names[ id_animation ];
|
|
}
|
|
|