diff --git a/share/grafx2/skins/skin_Aurora.png b/share/grafx2/skins/skin_Aurora.png index 7b9177b9..e86663f3 100644 Binary files a/share/grafx2/skins/skin_Aurora.png and b/share/grafx2/skins/skin_Aurora.png differ diff --git a/share/grafx2/skins/skin_DPaint.png b/share/grafx2/skins/skin_DPaint.png index 52fd2076..eae8e114 100644 Binary files a/share/grafx2/skins/skin_DPaint.png and b/share/grafx2/skins/skin_DPaint.png differ diff --git a/share/grafx2/skins/skin_classic.png b/share/grafx2/skins/skin_classic.png index 2216df0c..2241f990 100644 Binary files a/share/grafx2/skins/skin_classic.png and b/share/grafx2/skins/skin_classic.png differ diff --git a/share/grafx2/skins/skin_modern.png b/share/grafx2/skins/skin_modern.png index 39be261d..b062284d 100644 Binary files a/share/grafx2/skins/skin_modern.png and b/share/grafx2/skins/skin_modern.png differ diff --git a/share/grafx2/skins/skin_scenish.png b/share/grafx2/skins/skin_scenish.png index 2fcfb587..eb7a574a 100644 Binary files a/share/grafx2/skins/skin_scenish.png and b/share/grafx2/skins/skin_scenish.png differ diff --git a/src/buttons.c b/src/buttons.c index ea9c9702..2ac97018 100644 --- a/src/buttons.c +++ b/src/buttons.c @@ -1620,15 +1620,15 @@ void Copy_image_only(void) if (i == Spare_current_layer) { // Copy the current layer - memcpy(Spare_backups->Pages->Image[i],Main_backups->Pages->Image[Main_current_layer],Main_image_width*Main_image_height); + memcpy(Spare_backups->Pages->Image[i].Pixels,Main_backups->Pages->Image[Main_current_layer].Pixels,Main_image_width*Main_image_height); } else { // Resize the original layer Copy_part_of_image_to_another( - Spare_backups->Pages->Next->Image[i],0,0,Min(old_width,Spare_image_width), + Spare_backups->Pages->Next->Image[i].Pixels,0,0,Min(old_width,Spare_image_width), Min(old_height,Spare_image_height),old_width, - Spare_backups->Pages->Image[i],0,0,Spare_image_width); + Spare_backups->Pages->Image[i].Pixels,0,0,Spare_image_width); } } diff --git a/src/const.h b/src/const.h index 2dcb9f6a..58e11b99 100644 --- a/src/const.h +++ b/src/const.h @@ -71,7 +71,11 @@ /// Character to display in menus for an ellipsis. #define ELLIPSIS_CHARACTER '…' #define NB_LAYERS 1 ///< Initial number of layers for a new image +#ifdef NOLAYERS +#define MAX_NB_LAYERS 999 ///< Maximum number of layers that can be used in grafx2. Note that 32 is upper limit because of a few bit fields. +#else #define MAX_NB_LAYERS 16 ///< Maximum number of layers that can be used in grafx2. Note that 32 is upper limit because of a few bit fields. +#endif #define BRUSH_CONTAINER_PREVIEW_WIDTH 16 ///< Size for preview of a brush in Brush container #define BRUSH_CONTAINER_PREVIEW_HEIGHT 16 ///< Size for preview of a brush in Brush container #define BRUSH_CONTAINER_COLUMNS 4 ///< Number of columns in the Brush container @@ -289,6 +293,12 @@ enum BUTTON_NUMBERS BUTTON_LAYER_REMOVE, BUTTON_LAYER_UP, BUTTON_LAYER_DOWN, + BUTTON_ANIM_TIME, + BUTTON_ANIM_FIRST_FRAME, + BUTTON_ANIM_PREV_FRAME, + BUTTON_ANIM_NEXT_FRAME, + BUTTON_ANIM_LAST_FRAME, + BUTTON_ANIM_PLAY, BUTTON_LAYER_SELECT, // Main menu diff --git a/src/engine.c b/src/engine.c index 85a40981..80984aa6 100644 --- a/src/engine.c +++ b/src/engine.c @@ -79,6 +79,12 @@ char * Menu_tooltip[NB_BUTTONS]= "Drop layer ", "Raise layer ", "Lower layer ", + "Set frame time ", + "Go to first frame ", + "Go to previous frame ", + "Go to next frame ", + "Go to last frame ", + "Preview animation ", "Layer select / toggle ", "Paintbrush choice ", "Adjust / Transform menu ", diff --git a/src/factory.c b/src/factory.c index 947ea03b..42b9fdd4 100644 --- a/src/factory.c +++ b/src/factory.c @@ -299,9 +299,9 @@ int L_SetPictureSize(lua_State* L) for (i=0; iPages->Nb_layers; i++) { Copy_part_of_image_to_another( - Main_backups->Pages->Next->Image[i],0,0,Min(Main_backups->Pages->Next->Width,Main_image_width), + Main_backups->Pages->Next->Image[i].Pixels,0,0,Min(Main_backups->Pages->Next->Width,Main_image_width), Min(Main_backups->Pages->Next->Height,Main_image_height),Main_backups->Pages->Next->Width, - Main_backups->Pages->Image[i],0,0,Main_image_width); + Main_backups->Pages->Image[i].Pixels,0,0,Main_image_width); } Redraw_layered_image(); @@ -326,9 +326,9 @@ int L_SetSparePictureSize(lua_State* L) for (i=0; iPages->Nb_layers; i++) { Copy_part_of_image_to_another( - Spare_backups->Pages->Next->Image[i],0,0,Min(Spare_backups->Pages->Next->Width,Spare_image_width), + Spare_backups->Pages->Next->Image[i].Pixels,0,0,Min(Spare_backups->Pages->Next->Width,Spare_image_width), Min(Spare_backups->Pages->Next->Height,Spare_image_height),Spare_backups->Pages->Next->Width, - Spare_backups->Pages->Image[i],0,0,Spare_image_width); + Spare_backups->Pages->Image[i].Pixels,0,0,Spare_image_width); } Redraw_spare_image(); @@ -637,7 +637,7 @@ int L_GetSpareLayerPixel(lua_State* L) lua_pushinteger(L, Spare_backups->Pages->Transparent_color); return 1; } - lua_pushinteger(L, *(Spare_backups->Pages->Image[Spare_current_layer] + y*Spare_image_width + x)); + lua_pushinteger(L, *(Spare_backups->Pages->Image[Spare_current_layer].Pixels + y*Spare_image_width + x)); return 1; } diff --git a/src/fileformats.c b/src/fileformats.c index 62bd2735..476b8499 100644 --- a/src/fileformats.c +++ b/src/fileformats.c @@ -1706,18 +1706,26 @@ typedef struct typedef struct { - // byte Block_identifier : 0x21 - // byte Function : 0xF9 - // byte Block_size // 4 + byte Block_identifier; // 0x21 + byte Function; // 0xF9 + byte Block_size; // 4 byte Packed_fields; // 11100000 : Reserved // 00011100 : Disposal method // 00000010 : User input flag // 00000001 : Transparent flag word Delay_time; // Time for this frame to stay displayed byte Transparent_color; // Which color index acts as transparent - //word Bloc_terminator; // 0x00 + word Block_terminator; // 0x00 } T_GIF_GCE; // Graphic Control Extension +enum DISPOSAL_METHOD +{ + DISPOSAL_METHOD_UNDEFINED = 0, + DISPOSAL_METHOD_DO_NOT_DISPOSE = 1, + DISPOSAL_METHOD_RESTORE_BGCOLOR = 2, + DISPOSAL_METHOD_RESTORE_PREVIOUS = 3, +}; + // -- Tester si un fichier est au format GIF -------------------------------- void Test_GIF(T_IO_Context * context) @@ -1801,8 +1809,9 @@ word GIF_get_next_code(void) // -- Affiche un nouveau pixel -- -void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, byte color) +void GIF_new_pixel(T_IO_Context * context, T_GIF_IDB *idb, int is_transparent, byte color) { + if (!is_transparent || color!=context->Transparent_color) Set_pixel(context, idb->Pos_X+GIF_pos_X, idb->Pos_Y+GIF_pos_Y,color); GIF_pos_X++; @@ -1872,7 +1881,11 @@ void Load_GIF(T_IO_Context * context) word value_eof; // Valeur <=> End d'image long file_size; int number_LID; // Nombre d'images trouvées dans le fichier - short current_layer = 0; + int current_layer = 0; + int last_delay = 0; + byte is_transparent = 0; + byte disposal_method = DISPOSAL_METHOD_RESTORE_BGCOLOR; + byte previous_disposal_method = DISPOSAL_METHOD_RESTORE_BGCOLOR; /////////////////////////////////////////////////// FIN DES DECLARATIONS // @@ -1972,19 +1985,23 @@ void Load_GIF(T_IO_Context * context) && Read_word_le(GIF_file,&(GCE.Delay_time)) && Read_byte(GIF_file,&(GCE.Transparent_color))) { + previous_disposal_method = disposal_method; + disposal_method = (GCE.Packed_fields >> 2) & 7; + last_delay = GCE.Delay_time; + context->Transparent_color= GCE.Transparent_color; if (GCE.Packed_fields & 1) { if (number_LID == 0) context->Background_transparent = 1; - context->Transparent_color= GCE.Transparent_color; } else { if (number_LID == 0) context->Background_transparent = 0; - context->Transparent_color = 0; // Reset transparent color } - + is_transparent = + (previous_disposal_method==DISPOSAL_METHOD_DO_NOT_DISPOSE + ||previous_disposal_method==DISPOSAL_METHOD_UNDEFINED); } else File_error=2; @@ -2117,7 +2134,35 @@ void Load_GIF(T_IO_Context * context) // Attempt to add a layer to current image current_layer++; Set_loading_layer(context, current_layer); +#ifdef NOLAYERS + if (context->Type == CONTEXT_MAIN_IMAGE) + { + if (is_transparent) + // Copy the content of previous layer, in case of loading a GIF + // that uses transparency compression + memcpy( + Main_backups->Pages->Image[Main_current_layer].Pixels, + Main_backups->Pages->Image[Main_current_layer-1].Pixels, + Main_backups->Pages->Width*Main_backups->Pages->Height); + else + memset( + Main_backups->Pages->Image[Main_current_layer].Pixels, + LSDB.Backcol, + Main_backups->Pages->Width*Main_backups->Pages->Height); + } +#endif } + else + { + if (context->Type == CONTEXT_MAIN_IMAGE) + memset( + Main_backups->Pages->Image[Main_current_layer].Pixels, + LSDB.Backcol, + Main_backups->Pages->Width*Main_backups->Pages->Height); + } + + // Duration was set in the previously loaded GCE + Set_frame_duration(context, last_delay*10); number_LID++; // lecture de 10 derniers octets @@ -2202,7 +2247,7 @@ void Load_GIF(T_IO_Context * context) special_case=alphabet_stack[alphabet_stack_pos++]=GIF_current_code; do - GIF_new_pixel(context, &IDB, alphabet_stack[--alphabet_stack_pos]); + GIF_new_pixel(context, &IDB, is_transparent, alphabet_stack[--alphabet_stack_pos]); while (alphabet_stack_pos!=0); alphabet_prefix[alphabet_free ]=old_code; @@ -2222,7 +2267,7 @@ void Load_GIF(T_IO_Context * context) alphabet_free =(1<Nb_layers>1) + Write_bytes(GIF_file,"\x21\xFF\x0BNETSCAPE2.0\x03\x01\x00\x00\x00",19); +#endif // Ecriture du commentaire if (context->Comment[0]) @@ -2471,24 +2520,36 @@ void Save_GIF(T_IO_Context * context) current_layer++) { // Write a Graphic Control Extension - byte GCE_block[] = "\x21\xF9\x04\x04\x05\x00\x00\x00"; - // 'Default' values: - // Disposal method "Do not dispose" - // Duration 5/100s (minimum viable value for current web browsers) - - if (current_layer > 0 || context->Background_transparent) - GCE_block[3] |= 1; // Transparent color flag - GCE_block[6] = context->Transparent_color; + T_GIF_GCE GCE; Set_saving_layer(context, current_layer); + GCE.Block_identifier = 0x21; + GCE.Function = 0xF9; + GCE.Block_size=4; +#ifdef NOLAYERS + GCE.Packed_fields=(2<<2)|(context->Background_transparent); + GCE.Delay_time=Get_frame_duration(context)/10; +#else + if (current_layer==0) + GCE.Packed_fields=(1<<2)|(context->Background_transparent); + else + GCE.Packed_fields=(1<<2)|(1); + GCE.Delay_time=5; // Duration 5/100s (minimum viable value for current web browsers) if (current_layer == context->Nb_layers -1) - { - // "Infinite" delay for last frame - GCE_block[4] = 255; - GCE_block[5] = 255; - } - if (Write_bytes(GIF_file,GCE_block,8)) + GCE.Delay_time=0xFFFF; // Infinity (10 minutes) +#endif + GCE.Transparent_color=context->Transparent_color; + GCE.Block_terminator=0x00; + + if (Write_byte(GIF_file,GCE.Block_identifier) + && Write_byte(GIF_file,GCE.Function) + && Write_byte(GIF_file,GCE.Block_size) + && Write_byte(GIF_file,GCE.Packed_fields) + && Write_word_le(GIF_file,GCE.Delay_time) + && Write_byte(GIF_file,GCE.Transparent_color) + && Write_byte(GIF_file,GCE.Block_terminator) + ) { // On va écrire un block indicateur d'IDB et l'IDB du fichier diff --git a/src/global.h b/src/global.h index 133972af..8aa18abd 100644 --- a/src/global.h +++ b/src/global.h @@ -336,7 +336,7 @@ GFX2_GLOBAL short Main_magnifier_offset_X; /// Y position (in image space) of the pixel to display in the top left corner of the magnified view. GFX2_GLOBAL short Main_magnifier_offset_Y; /// Index of layer currently being edited -GFX2_GLOBAL byte Main_current_layer; +GFX2_GLOBAL int Main_current_layer; /// Bitfield that records which layers are visible. 2^0 for 0, 2^1 for 1, 2^2 for 2, etc. GFX2_GLOBAL dword Main_layers_visible; /// Index to use next time, when creating incremental backups, to make unique filename. @@ -402,7 +402,7 @@ GFX2_GLOBAL short Spare_magnifier_offset_X; /// Y position (in image space) of the pixel to display in the top left corner of the magnified view. GFX2_GLOBAL short Spare_magnifier_offset_Y; /// Index of layer currently being edited -GFX2_GLOBAL byte Spare_current_layer; +GFX2_GLOBAL int Spare_current_layer; /// Bitfield that records which layers are visible. 2^0 for 0, 2^1 for 1, 2^2 for 2, etc. GFX2_GLOBAL dword Spare_layers_visible; /// Index to use next time, when creating incremental backups, to make unique filename. @@ -495,7 +495,11 @@ GFX2_GLOBAL T_Menu_Bar Menu_bars[MENUBAR_COUNT] #ifdef GLOBAL_VARIABLES = {{MENU_WIDTH, 9, 1, 45, {NULL,NULL,NULL}, 20, BUTTON_HIDE }, // Status +#ifdef NOLAYERS + {MENU_WIDTH, 14, 1, 35, {NULL,NULL,NULL}, 236, BUTTON_LAYER_SELECT }, // Animation +#else {MENU_WIDTH, 10, 1, 35, {NULL,NULL,NULL}, 144, BUTTON_LAYER_SELECT }, // Layers +#endif {MENU_WIDTH, 35, 1, 0, {NULL,NULL,NULL}, 254, BUTTON_CHOOSE_COL }} // Main #endif ; diff --git a/src/graph.c b/src/graph.c index b95429a2..bf7b90a9 100644 --- a/src/graph.c +++ b/src/graph.c @@ -632,9 +632,9 @@ void Resize_image(word chosen_width,word chosen_height) for (i=0; iPages->Nb_layers; i++) { Copy_part_of_image_to_another( - Main_backups->Pages->Next->Image[i],0,0,Min(old_width,Main_image_width), + Main_backups->Pages->Next->Image[i].Pixels,0,0,Min(old_width,Main_image_width), Min(old_height,Main_image_height),old_width, - Main_backups->Pages->Image[i],0,0,Main_image_width); + Main_backups->Pages->Image[i].Pixels,0,0,Main_image_width); } Redraw_layered_image(); } @@ -655,7 +655,7 @@ void Remap_spare(void) short y_pos; // Variable de balayage de la brosse byte used[256]; // Tableau de booléens "La couleur est utilisée" int color; - byte layer; + int layer; // On commence par initialiser le tableau de booléens à faux for (color=0;color<=255;color++) @@ -665,7 +665,7 @@ void Remap_spare(void) for (layer=0; layerPages->Nb_layers; layer++) for (y_pos=0;y_posPages->Image[layer]+(y_pos*Spare_image_width+x_pos))]=1; + used[*(Spare_backups->Pages->Image[layer].Pixels+(y_pos*Spare_image_width+x_pos))]=1; // On va maintenant se servir de la table "used" comme table de // conversion: pour chaque indice, la table donne une couleur de @@ -682,7 +682,7 @@ void Remap_spare(void) // qui craint un peu, on peut faire l'échange dans la brosse de toutes les // teintes. for (layer=0; layerPages->Nb_layers; layer++) - Remap_general_lowlevel(used,Spare_backups->Pages->Image[layer],Spare_backups->Pages->Image[layer],Spare_image_width,Spare_image_height,Spare_image_width); + Remap_general_lowlevel(used,Spare_backups->Pages->Image[layer].Pixels,Spare_backups->Pages->Image[layer].Pixels,Spare_image_width,Spare_image_height,Spare_image_width); // Change transparent color index Spare_backups->Pages->Transparent_color=used[Spare_backups->Pages->Transparent_color]; @@ -979,7 +979,7 @@ void Fill(short * top_reached , short * bottom_reached, byte Read_pixel_from_backup_layer(word x,word y) { - return *((y)*Main_image_width+(x)+Main_backups->Pages->Next->Image[Main_current_layer]); + return *((y)*Main_image_width+(x)+Main_backups->Pages->Next->Image[Main_current_layer].Pixels); } void Fill_general(byte fill_color) @@ -1035,34 +1035,34 @@ void Fill_general(byte fill_color) // Il va maintenant falloir qu'on "turn" ce gros caca "into" un truc qui // ressemble un peu plus à ce à quoi l'utilisateur peut s'attendre. if (top_reached>Limit_top) - Copy_part_of_image_to_another(Main_backups->Pages->Next->Image[Main_current_layer], // source + Copy_part_of_image_to_another(Main_backups->Pages->Next->Image[Main_current_layer].Pixels, // source Limit_left,Limit_top, // Pos X et Y dans source (Limit_right-Limit_left)+1, // width copie top_reached-Limit_top,// height copie Main_image_width, // width de la source - Main_backups->Pages->Image[Main_current_layer], // Destination + Main_backups->Pages->Image[Main_current_layer].Pixels, // Destination Limit_left,Limit_top, // Pos X et Y destination Main_image_width); // width destination if (bottom_reachedPages->Next->Image[Main_current_layer], + Copy_part_of_image_to_another(Main_backups->Pages->Next->Image[Main_current_layer].Pixels, Limit_left,bottom_reached+1, (Limit_right-Limit_left)+1, Limit_bottom-bottom_reached, - Main_image_width,Main_backups->Pages->Image[Main_current_layer], + Main_image_width,Main_backups->Pages->Image[Main_current_layer].Pixels, Limit_left,bottom_reached+1,Main_image_width); if (left_reached>Limit_left) - Copy_part_of_image_to_another(Main_backups->Pages->Next->Image[Main_current_layer], + Copy_part_of_image_to_another(Main_backups->Pages->Next->Image[Main_current_layer].Pixels, Limit_left,top_reached, left_reached-Limit_left, (bottom_reached-top_reached)+1, - Main_image_width,Main_backups->Pages->Image[Main_current_layer], + Main_image_width,Main_backups->Pages->Image[Main_current_layer].Pixels, Limit_left,top_reached,Main_image_width); if (right_reachedPages->Next->Image[Main_current_layer], + Copy_part_of_image_to_another(Main_backups->Pages->Next->Image[Main_current_layer].Pixels, right_reached+1,top_reached, Limit_right-right_reached, (bottom_reached-top_reached)+1, - Main_image_width,Main_backups->Pages->Image[Main_current_layer], + Main_image_width,Main_backups->Pages->Image[Main_current_layer].Pixels, right_reached+1,top_reached,Main_image_width); for (y_pos=top_reached;y_pos<=bottom_reached;y_pos++) @@ -2924,7 +2924,7 @@ byte Effect_layer_copy(word x,word y,byte color) { if (colorPages->Nb_layers) { - return *((y)*Main_image_width+(x)+Main_backups->Pages->Image[color]); + return *((y)*Main_image_width+(x)+Main_backups->Pages->Image[color].Pixels); } return Read_pixel_from_feedback_screen(x,y); } @@ -2974,16 +2974,16 @@ byte Read_pixel_from_current_screen (word x,word y) byte color; if (Main_current_layer==4) - return *(Main_backups->Pages->Image[Main_current_layer] + x+y*Main_image_width); + return *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width); color = *(Main_screen+y*Main_image_width+x); if (color != Main_backups->Pages->Transparent_color) // transparent color return color; depth = *(Main_visible_image_depth_buffer.Image+x+y*Main_image_width); - return *(Main_backups->Pages->Image[depth] + x+y*Main_image_width); + return *(Main_backups->Pages->Image[depth].Pixels + x+y*Main_image_width); #else - return *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer]); + return *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer].Pixels); #endif } @@ -2993,30 +2993,29 @@ void Pixel_in_current_screen (word x,word y,byte color,int with_preview) if (!Constraint_mode) { byte depth = *(Main_visible_image_depth_buffer.Image+x+y*Main_image_width); - *(Main_backups->Pages->Image[Main_current_layer] + x+y*Main_image_width)=color; + *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width)=color; if ( depth <= Main_current_layer) { if (color == Main_backups->Pages->Transparent_color) // transparent color // fetch pixel color from the topmost visible layer - color=*(Main_backups->Pages->Image[depth] + x+y*Main_image_width); + color=*(Main_backups->Pages->Image[depth].Pixels + x+y*Main_image_width); *(x+y*Main_image_width+Main_screen)=color; if (with_preview) Pixel_preview(x,y,color); } - } else if ( Main_current_layer == 4) { if (color<4) { // Paste in layer - *(Main_backups->Pages->Image[Main_current_layer] + x+y*Main_image_width)=color; + *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width)=color; // Paste in depth buffer *(Main_visible_image_depth_buffer.Image+x+y*Main_image_width)=color; // Fetch pixel color from the target raster layer - color=*(Main_backups->Pages->Image[color] + x+y*Main_image_width); + color=*(Main_backups->Pages->Image[color].Pixels + x+y*Main_image_width); // Draw that color on the visible image buffer *(x+y*Main_image_width+Main_screen)=color; @@ -3029,9 +3028,9 @@ void Pixel_in_current_screen (word x,word y,byte color,int with_preview) byte depth; // Paste in layer - *(Main_backups->Pages->Image[Main_current_layer] + x+y*Main_image_width)=color; + *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width)=color; // Search depth - depth = *(Main_backups->Pages->Image[4] + x+y*Main_image_width); + depth = *(Main_backups->Pages->Image[4].Pixels + x+y*Main_image_width); if ( depth == Main_current_layer) { @@ -3046,13 +3045,13 @@ void Pixel_in_current_screen (word x,word y,byte color,int with_preview) { byte depth; - *(Main_backups->Pages->Image[Main_current_layer] + x+y*Main_image_width)=color; + *(Main_backups->Pages->Image[Main_current_layer].Pixels + x+y*Main_image_width)=color; depth = *(Main_visible_image_depth_buffer.Image+x+y*Main_image_width); if ( depth <= Main_current_layer) { if (color == Main_backups->Pages->Transparent_color) // transparent color // fetch pixel color from the topmost visible layer - color=*(Main_backups->Pages->Image[depth] + x+y*Main_image_width); + color=*(Main_backups->Pages->Image[depth].Pixels + x+y*Main_image_width); *(x+y*Main_image_width+Main_screen)=color; @@ -3061,7 +3060,7 @@ void Pixel_in_current_screen (word x,word y,byte color,int with_preview) } } #else - *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer])=color; + *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer].Pixels)=color; if (with_preview) Pixel_preview(x,y,color); #endif @@ -3069,15 +3068,15 @@ void Pixel_in_current_screen (word x,word y,byte color,int with_preview) void Pixel_in_spare(word x,word y, byte color) { - *((y)*Spare_image_width+(x)+Spare_backups->Pages->Image[Spare_current_layer])=color; + *((y)*Spare_image_width+(x)+Spare_backups->Pages->Image[Spare_current_layer].Pixels)=color; } void Pixel_in_current_layer(word x,word y, byte color) { - *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer])=color; + *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer].Pixels)=color; } byte Read_pixel_from_current_layer(word x,word y) { - return *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer]); + return *((y)*Main_image_width+(x)+Main_backups->Pages->Image[Main_current_layer].Pixels); } diff --git a/src/helpfile.h b/src/helpfile.h index ed722a8b..a5fe74d3 100644 --- a/src/helpfile.h +++ b/src/helpfile.h @@ -306,15 +306,18 @@ static const T_Help_table helptable_help[] = HELP_LINK (" Next : %s", SPECIAL_NEXT_USER_BACKCOLOR) HELP_LINK (" Previous: %s", SPECIAL_PREVIOUS_USER_BACKCOLOR) HELP_TEXT ("") - HELP_TEXT ("LAYERS") + HELP_TEXT ("LAYERS / ANIMATION FRAMES") HELP_TEXT ("") HELP_LINK (" Menu : %s", 0x100+BUTTON_LAYER_MENU) HELP_LINK (" Add new : %s", 0x100+BUTTON_LAYER_ADD) HELP_LINK (" Delete : %s", 0x100+BUTTON_LAYER_REMOVE) +#ifndef NOLAYERS HELP_LINK (" Merge : %s", 0x100+BUTTON_LAYER_MERGE) +#endif HELP_LINK (" Move up : %s", 0x100+BUTTON_LAYER_UP) HELP_LINK (" Move down : %s", 0x100+BUTTON_LAYER_DOWN) //HELP_LINK (" Set transp: %s", 0x100+BUTTON_LAYER_COLOR) +#ifndef NOLAYERS HELP_TEXT (" Select :") HELP_LINK (" 1 : %s", SPECIAL_LAYER1_SELECT) HELP_LINK (" 2 : %s", SPECIAL_LAYER2_SELECT) @@ -333,6 +336,13 @@ static const T_Help_table helptable_help[] = HELP_LINK (" 6 : %s", SPECIAL_LAYER6_TOGGLE) HELP_LINK (" 7 : %s", SPECIAL_LAYER7_TOGGLE) HELP_LINK (" 8 : %s", SPECIAL_LAYER8_TOGGLE) +#else + HELP_LINK (" Go to first: %s", 0x100+BUTTON_ANIM_FIRST_FRAME) + HELP_LINK (" Go to previous: %s", 0x100+BUTTON_ANIM_PREV_FRAME) + HELP_LINK (" Go to next: %s", 0x100+BUTTON_ANIM_NEXT_FRAME) + HELP_LINK (" Go to last: %s", 0x100+BUTTON_ANIM_LAST_FRAME) + HELP_LINK (" Set duration: %s", 0x100+BUTTON_ANIM_TIME) +#endif HELP_TEXT ("") HELP_LINK (" Format check : %s", SPECIAL_FORMAT_CHECKER) HELP_LINK (" Format check menu: %s", SPECIAL_FORMAT_CHECKER_MENU) @@ -2924,6 +2934,14 @@ T_Help_section Help_section[] = HELP_TABLE_DECLARATION(helptable_layerdel) HELP_TABLE_DECLARATION(helptable_layerup) HELP_TABLE_DECLARATION(helptable_layerdown) + // TODO: implement specific help sections for anim buttons + HELP_TABLE_DECLARATION(helptable_layerselect) + HELP_TABLE_DECLARATION(helptable_layerselect) + HELP_TABLE_DECLARATION(helptable_layerselect) + HELP_TABLE_DECLARATION(helptable_layerselect) + HELP_TABLE_DECLARATION(helptable_layerselect) + HELP_TABLE_DECLARATION(helptable_layerselect) + // HELP_TABLE_DECLARATION(helptable_layerselect) HELP_TABLE_DECLARATION(helptable_paintbrush) HELP_TABLE_DECLARATION(helptable_adjust) diff --git a/src/hotkeys.c b/src/hotkeys.c index 3467b6b2..02fbdb58 100644 --- a/src/hotkeys.c +++ b/src/hotkeys.c @@ -1657,6 +1657,54 @@ T_Key_config ConfigKey[NB_SHORTCUTS] = { true, 0, 0}, + {200, + "Set frame time", + "Opens a window where you", + "can set the current animation", + "frame duration.", + true, + 0, // No shortcut + 0}, + {201, + "Go to first frame", + "Edits the first frame of", + "an animation", + "", + true, + 0, // No shortcut + 0}, + {202, + "Go to last frame", + "Edits the last frame of", + "an animation", + "", + true, + 0, // No shortcut + 0}, + {203, + "Go to previous frame", + "Edits the previous frame of", + "an animation", + "", + true, + 0, // No shortcut + 0}, + {204, + "Go to next frame", + "Edits the next frame of", + "an animation", + "", + true, + 0, // No shortcut + 0}, + {205, + "Preview animation", + "Runs the current animation.", + "", + "", + true, + 0, // No shortcut + 0}, }; word Ordering[NB_SHORTCUTS]= @@ -1861,4 +1909,10 @@ word Ordering[NB_SHORTCUTS]= SPECIAL_CYCLE_MODE, SPECIAL_FORMAT_CHECKER, SPECIAL_FORMAT_CHECKER_MENU, + 0x100+BUTTON_ANIM_TIME, + 0x100+BUTTON_ANIM_FIRST_FRAME, + 0x100+BUTTON_ANIM_LAST_FRAME, + 0x100+BUTTON_ANIM_PREV_FRAME, + 0x100+BUTTON_ANIM_NEXT_FRAME, + 0x100+BUTTON_ANIM_PLAY, }; diff --git a/src/init.c b/src/init.c index 8be7e423..c42b3aea 100644 --- a/src/init.c +++ b/src/init.c @@ -374,9 +374,16 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) // Layerbar if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "layer bar")) return 1; - if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Layerbar_block[0], Menu_bars[MENUBAR_LAYERS].Skin_width, Menu_bars[MENUBAR_LAYERS].Height,"layer bar",0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Layerbar_block[0], 144, 10,"layer bar",0)) return 1; - cursor_y+= Menu_bars[MENUBAR_LAYERS].Height; + cursor_y+= 10; + + // Animbar + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "anim bar")) + return 1; + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Animbar_block[0], 236, 14,"anim bar",0)) + return 1; + cursor_y+= 14; // Status bar if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "status bar")) @@ -395,9 +402,16 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) // Layerbar (selected) if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected layer bar")) return 1; - if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Layerbar_block[1], Menu_bars[MENUBAR_LAYERS].Skin_width, Menu_bars[MENUBAR_LAYERS].Height,"selected layer bar",0)) + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Layerbar_block[1], 144, 10,"selected layer bar",0)) return 1; - cursor_y+= Menu_bars[MENUBAR_LAYERS].Height; + cursor_y+= 10; + + // Animbar (selected) + if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected anim bar")) + return 1; + if (Read_GUI_block(gfx, gui, cursor_x, cursor_y, gfx->Animbar_block[1], 236, 14,"selected anim bar",0)) + return 1; + cursor_y+= 14; // Status bar (selected) if (GUI_seek_down(gui, &cursor_x, &cursor_y, neutral_color, "selected status bar")) @@ -635,7 +649,9 @@ byte Parse_skin(SDL_Surface * gui, T_Gui_skin *gfx) memcpy(gfx->Menu_block[2], gfx->Menu_block[0], Menu_bars[MENUBAR_TOOLS].Skin_width*Menu_bars[MENUBAR_TOOLS].Height); memcpy(gfx->Layerbar_block[2], gfx->Layerbar_block[0], - Menu_bars[MENUBAR_LAYERS].Skin_width*Menu_bars[MENUBAR_LAYERS].Height); + sizeof(gfx->Layerbar_block[0])); + memcpy(gfx->Animbar_block[2], gfx->Animbar_block[0], + sizeof(gfx->Animbar_block[0])); memcpy(gfx->Statusbar_block[2], gfx->Statusbar_block[0], Menu_bars[MENUBAR_STATUS].Skin_width*Menu_bars[MENUBAR_STATUS].Height); @@ -1146,6 +1162,7 @@ void Init_buttons(void) FAMILY_INSTANT); // Layer bar +#ifndef NOLAYERS Init_button(BUTTON_LAYER_MENU, 0,0, 57,9, @@ -1210,6 +1227,89 @@ void Init_buttons(void) 0,0, Do_nothing, FAMILY_INSTANT); +#else + // Anim bar + Init_button(BUTTON_LAYER_MENU, + 0,0, + 44,13, + BUTTON_SHAPE_RECTANGLE, + Button_Layer_menu, Button_Layer_menu, + 0,0, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_ANIM_TIME, + 45,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Anim_time, Button_Anim_time, + 0,0, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_ANIM_FIRST_FRAME, + 116,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Anim_first_frame, Button_Anim_first_frame, + 0,0, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_ANIM_PREV_FRAME, + 130,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Anim_prev_frame, Button_Anim_continuous_prev, + 0,1, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_ANIM_NEXT_FRAME, + 144,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Anim_next_frame, Button_Anim_continuous_next, + 0,1, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_ANIM_LAST_FRAME, + 158,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Anim_last_frame, Button_Anim_last_frame, + 0,0, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_LAYER_ADD, + 177,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Layer_add, Button_Layer_add, + 0,0, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_LAYER_REMOVE, + 191,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Layer_remove, Button_Layer_remove, + 0,0, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_LAYER_DOWN, + 205,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Layer_down, Button_Layer_down, + 0,0, + Do_nothing, + FAMILY_INSTANT); + Init_button(BUTTON_LAYER_UP, + 219,0, + 13,13, + BUTTON_SHAPE_RECTANGLE, + Button_Layer_up, Button_Layer_up, + 0,0, + Do_nothing, + FAMILY_INSTANT); +#endif // Status bar Init_button(BUTTON_HIDE, 0,0, @@ -2695,7 +2795,11 @@ void Set_current_skin(const char *skinfile, T_Gui_skin *gfx) for (i=0; i<3; i++) { Menu_bars[MENUBAR_TOOLS ].Skin[i] = (byte*)&(gfx->Menu_block[i]); +#ifndef NOLAYERS Menu_bars[MENUBAR_LAYERS].Skin[i] = (byte*)&(gfx->Layerbar_block[i]); +#else + Menu_bars[MENUBAR_LAYERS].Skin[i] = (byte*)&(gfx->Animbar_block[i]); +#endif Menu_bars[MENUBAR_STATUS].Skin[i] = (byte*)&(gfx->Statusbar_block[i]); } } diff --git a/src/layers.c b/src/layers.c index 6b8abfb9..31009ab0 100644 --- a/src/layers.c +++ b/src/layers.c @@ -29,8 +29,9 @@ #include "input.h" #include "help.h" #include "misc.h" +#include "readline.h" -void Layer_activate(byte layer, short side) +void Layer_activate(int layer, short side) { word old_layers; @@ -103,8 +104,18 @@ void Button_Layer_add(void) Backup_layers(0); if (!Add_layer(Main_backups,Main_current_layer+1)) { + #ifdef NOLAYERS + // Make a copy of current image, so the display is unchanged + memcpy( + Main_backups->Pages->Image[Main_current_layer].Pixels, + Main_backups->Pages->Image[Main_current_layer-1].Pixels, + Main_backups->Pages->Width*Main_backups->Pages->Height); + #else Update_depth_buffer(); + // I just noticed this might be unneeded, since the new layer + // is transparent, it shouldn't have any visible effect. Display_all_screen(); + #endif Display_layerbar(); End_of_modification(); } @@ -154,7 +165,7 @@ void Button_Layer_select(void) void Button_Layer_toggle(void) { - short layer; + int layer; // Determine which button is clicked according to mouse position layer = (Mouse_X/Menu_factor_X - Menu_bars[MENUBAR_LAYERS].Skin_width) / Layer_button_width; @@ -318,7 +329,7 @@ void Button_Layer_up(void) if (Main_current_layer < (Main_backups->Pages->Nb_layers-1)) { - byte * tmp; + T_Image tmp; dword layer_flags; // Backup with unchanged layers @@ -357,7 +368,7 @@ void Button_Layer_down(void) if (Main_current_layer > 0) { - byte * tmp; + T_Image tmp; dword layer_flags; // Backup with unchanged layers @@ -389,3 +400,250 @@ void Button_Layer_down(void) Unselect_button(BUTTON_LAYER_DOWN); Display_cursor(); } + +int Interpret_delay(int delay) +{ + // Firefox behavior + if (delay>30) + return delay; + if (delay==0) + return 100; + return 30; +} +void Button_Anim_time(void) +{ + short clicked_button; + int mode=0; + int frame; + char buffer[5+1]; + T_Special_button * input_duration_button; + int duration=Main_backups->Pages->Image[Main_current_layer].Duration; + + Open_window(166,110,"Animation speed"); + + Print_in_window(80,20,"ms",MC_Black,MC_Light); + input_duration_button = Window_set_input_button(33,18,5); // 1 + + Num2str(duration,buffer,5); + Print_in_window_limited(input_duration_button->Pos_X+2,input_duration_button->Pos_Y+2,buffer,input_duration_button->Width/8,MC_Black,MC_Light); + + Print_in_window(24,37,"Set this frame",MC_Black,MC_Light); + Window_set_normal_button(7, 34, 13,13,"X" , 0,1,KEY_NONE); // 2 + + Print_in_window(24,55,"Set all frames",MC_Black,MC_Light); + Window_set_normal_button(7, 52, 13,13,"" , 0,1,KEY_NONE); // 3 + + Print_in_window(24,73,"Add to all frames",MC_Black,MC_Light); + Window_set_normal_button(7, 70, 13,13,"" , 0,1,KEY_NONE); // 4 + + Window_set_normal_button( 7, 92, 51,14,"OK" , 0,1,SDLK_RETURN); // 5 + Window_set_normal_button(63, 92, 51,14,"Cancel", 0,1,KEY_ESC); // 6 + + Update_window_area(0,0,Window_width, Window_height); + + do + { + + clicked_button=Window_clicked_button(); + if (Is_shortcut(Key,0x100+BUTTON_HELP)) + Window_help(BUTTON_ANIM_TIME, NULL); + switch(clicked_button) + { + case 1: // duration + Num2str(duration,buffer,5); + Hide_cursor(); + if (Readline(input_duration_button->Pos_X+2, + input_duration_button->Pos_Y+2, + buffer, + 5, + INPUT_TYPE_DECIMAL)) + { + duration=atoi(buffer); + } + Print_in_window_limited(input_duration_button->Pos_X+2,input_duration_button->Pos_Y+2,buffer,input_duration_button->Width/8,MC_Black,MC_Light); + Display_cursor(); + break; + case 2: // Radio: set 1 + case 3: // Radio: set all + case 4: // Radio: add + mode=clicked_button-2; + Hide_cursor(); + Print_in_window(10,37,mode==0?"X":" ",MC_Black,MC_Light); + Print_in_window(10,55,mode==1?"X":" ",MC_Black,MC_Light); + Print_in_window(10,73,mode==2?"X":" ",MC_Black,MC_Light); + Display_cursor(); + break; + } + } + while (clicked_button<5); + + // On exit + Hide_cursor(); + Close_window(); + if (clicked_button==5) + { + // Accept changes + Backup_layers(0); + switch(mode) + { + case 0: + if (duration<1) + duration=1; + Main_backups->Pages->Image[Main_current_layer].Duration = duration; + break; + case 1: + if (duration<1) + duration=1; + for (frame=0; framePages->Nb_layers; frame++) + { + Main_backups->Pages->Image[frame].Duration = duration; + } + break; + case 2: + for (frame=0; framePages->Nb_layers; frame++) + { + int cur_duration = Main_backups->Pages->Image[frame].Duration+duration; + if (cur_duration<1) + cur_duration=1; + else if (cur_duration>32767) + cur_duration=32767; + Main_backups->Pages->Image[frame].Duration = cur_duration; + } + break; + break; + } + End_of_modification(); + } + + Unselect_button(BUTTON_ANIM_TIME); + Display_cursor(); +} + +void Button_Anim_first_frame(void) +{ + if (Main_current_layer>0) + Layer_activate(0,LEFT_SIDE); + + Hide_cursor(); + Unselect_button(BUTTON_ANIM_FIRST_FRAME); + Display_cursor(); +} + +void Button_Anim_prev_frame(void) +{ + if (Main_backups->Pages->Nb_layers>1) + { + if (Main_current_layer==0) + Layer_activate(Main_backups->Pages->Nb_layers-1,LEFT_SIDE); + else + Layer_activate(Main_current_layer-1,LEFT_SIDE); + } + Hide_cursor(); + Unselect_button(BUTTON_ANIM_PREV_FRAME); + Display_cursor(); +} + +void Button_Anim_next_frame(void) +{ + if (Main_backups->Pages->Nb_layers>1) + { + if (Main_current_layer==Main_backups->Pages->Nb_layers-1) + Layer_activate(0,LEFT_SIDE); + else + Layer_activate(Main_current_layer+1,LEFT_SIDE); + } + + Hide_cursor(); + Unselect_button(BUTTON_ANIM_NEXT_FRAME); + Display_cursor(); +} + +void Button_Anim_last_frame(void) +{ + if (Main_current_layer < (Main_backups->Pages->Nb_layers-1)) + Layer_activate((Main_backups->Pages->Nb_layers-1),LEFT_SIDE); + + Hide_cursor(); + Unselect_button(BUTTON_ANIM_LAST_FRAME); + Display_cursor(); +} + +void Button_Anim_play(void) +{ + Hide_cursor(); + + // + + Unselect_button(BUTTON_ANIM_PLAY); + Display_cursor(); +} + +void Button_Anim_continuous_next(void) +{ + Uint32 time_start; + int time_in_current_frame=0; + + time_start = SDL_GetTicks(); + + do + { + int target_frame; + Uint32 time_now; + + Get_input(20); + + time_now=SDL_GetTicks(); + time_in_current_frame += time_now-time_start; + time_start=time_now; + target_frame = Main_current_layer; + while (time_in_current_frame > Main_backups->Pages->Image[target_frame].Duration) + { + time_in_current_frame -= Interpret_delay(Main_backups->Pages->Image[target_frame].Duration); + target_frame = (target_frame+1) % Main_backups->Pages->Nb_layers; + } + if (target_frame != Main_current_layer) + { + Layer_activate(target_frame,LEFT_SIDE); + } + + } while (Mouse_K); + + Hide_cursor(); + Unselect_button(BUTTON_ANIM_NEXT_FRAME); + Display_cursor(); +} + +void Button_Anim_continuous_prev(void) +{ + Uint32 time_start; + int time_in_current_frame=0; + + time_start = SDL_GetTicks(); + + do + { + int target_frame; + Uint32 time_now; + + Get_input(20); + + time_now=SDL_GetTicks(); + time_in_current_frame += time_now-time_start; + time_start=time_now; + target_frame = Main_current_layer; + while (time_in_current_frame > Main_backups->Pages->Image[target_frame].Duration) + { + time_in_current_frame -= Interpret_delay(Main_backups->Pages->Image[target_frame].Duration); + target_frame = (target_frame+Main_backups->Pages->Nb_layers-1) % Main_backups->Pages->Nb_layers; + } + if (target_frame != Main_current_layer) + { + Layer_activate(target_frame,LEFT_SIDE); + } + + } while (Mouse_K); + + Hide_cursor(); + Unselect_button(BUTTON_ANIM_NEXT_FRAME); + Display_cursor(); +} diff --git a/src/layers.h b/src/layers.h index 9bf83f49..2c2fe3bf 100644 --- a/src/layers.h +++ b/src/layers.h @@ -30,6 +30,12 @@ void Button_Layer_up(void); void Button_Layer_down(void); void Button_Layer_select(void); void Button_Layer_toggle(void); -void Layer_activate(byte layer, short side); - - +void Layer_activate(int layer, short side); +void Button_Anim_time(void); +void Button_Anim_first_frame(void); +void Button_Anim_prev_frame(void); +void Button_Anim_next_frame(void); +void Button_Anim_last_frame(void); +void Button_Anim_play(void); +void Button_Anim_continuous_prev(void); +void Button_Anim_continuous_next(void); diff --git a/src/loadsave.c b/src/loadsave.c index a61c2ce4..fbd2eca5 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -321,6 +321,29 @@ void Set_palette_fake_24b(T_Palette palette) } } +void Set_frame_duration(T_IO_Context *context, int duration) +{ + switch(context->Type) + { + case CONTEXT_MAIN_IMAGE: + Main_backups->Pages->Image[context->Current_layer].Duration = duration; + break; + default: + break; + } +} + +int Get_frame_duration(T_IO_Context *context) +{ + switch(context->Type) + { + case CONTEXT_MAIN_IMAGE: + return Main_backups->Pages->Image[context->Current_layer].Duration; + default: + return 0; + } +} + /// /// Generic allocation and similar stuff, done at beginning of image load, /// as soon as size is known. @@ -644,7 +667,7 @@ void Load_image(T_IO_Context *context) Cursor_shape=CURSOR_SHAPE_HOURGLASS; Display_cursor(); Flush_update(); - if (Convert_24b_bitmap_to_256(Main_backups->Pages->Image[0],context->Buffer_image_24b,context->Width,context->Height,context->Palette)) + if (Convert_24b_bitmap_to_256(Main_backups->Pages->Image[0].Pixels,context->Buffer_image_24b,context->Width,context->Height,context->Palette)) File_error=2; else { @@ -1213,7 +1236,7 @@ void Init_context_layered_image(T_IO_Context * context, char *file_name, char *f context->Ratio=PIXEL_TALL; else context->Ratio=PIXEL_SIMPLE; - context->Target_address=Main_backups->Pages->Image[0]; + context->Target_address=Main_backups->Pages->Image[0].Pixels; context->Pitch=Main_image_width; // Color cyling ranges: @@ -1280,18 +1303,18 @@ void Init_context_surface(T_IO_Context * context, char *file_name, char *file_di } /// Function to call when need to switch layers. -void Set_saving_layer(T_IO_Context *context, byte layer) +void Set_saving_layer(T_IO_Context *context, int layer) { context->Current_layer = layer; if (context->Type == CONTEXT_MAIN_IMAGE) { - context->Target_address=Main_backups->Pages->Image[layer]; + context->Target_address=Main_backups->Pages->Image[layer].Pixels; } } /// Function to call when need to switch layers. -void Set_loading_layer(T_IO_Context *context, byte layer) +void Set_loading_layer(T_IO_Context *context, int layer) { context->Current_layer = layer; @@ -1311,7 +1334,7 @@ void Set_loading_layer(T_IO_Context *context, byte layer) Main_layers_visible = (2<Target_address=Main_backups->Pages->Image[layer]; + context->Target_address=Main_backups->Pages->Image[layer].Pixels; } } diff --git a/src/loadsave.h b/src/loadsave.h index ca05b6ef..9ce5ce12 100644 --- a/src/loadsave.h +++ b/src/loadsave.h @@ -62,7 +62,7 @@ typedef struct T_Palette Palette; short Width; short Height; - byte Nb_layers; + int Nb_layers; char Comment[COMMENT_SIZE+1]; byte Background_transparent; byte Transparent_color; @@ -83,7 +83,7 @@ typedef struct T_Color_cycle Cycle_range[16]; /// Internal: during load, marks which layer is being loaded. - short Current_layer; + int Current_layer; /// Internal: Used to mark truecolor images on loading. Only used by preview. //byte Is_truecolor; @@ -215,10 +215,13 @@ void Set_pixel(T_IO_Context *context, short x, short y, byte c); /// Set the color of a 24bit pixel (on load) void Set_pixel_24b(T_IO_Context *context, short x, short y, byte r, byte g, byte b); /// Function to call when need to switch layers. -void Set_loading_layer(T_IO_Context *context, byte layer); +void Set_loading_layer(T_IO_Context *context, int layer); /// Function to call when need to switch layers. -void Set_saving_layer(T_IO_Context *context, byte layer); - +void Set_saving_layer(T_IO_Context *context, int layer); +/// Function to call when loading an image's duration +void Set_frame_duration(T_IO_Context *context, int duration); +/// Function to call to get an image's duration for saving +int Get_frame_duration(T_IO_Context *context); // ================================================================= // What follows here are the definitions of functions and data diff --git a/src/misc.c b/src/misc.c index 28a8ea0f..c3354623 100644 --- a/src/misc.c +++ b/src/misc.c @@ -61,7 +61,7 @@ word Count_used_colors(dword* usage) // For each layer for (layer = 0; layer < Main_backups->Pages->Nb_layers; layer++) { - current_pixel = Main_backups->Pages->Image[layer]; + current_pixel = Main_backups->Pages->Image[layer].Pixels; // For each pixel in picture for (i = 0; i < nb_pixels; i++) { @@ -188,7 +188,7 @@ void Clear_current_image_with_stencil(byte color, byte * stencil) int nb_pixels=0; //ECX //al=color //edi=Screen_pixels - byte* pixel=Main_backups->Pages->Image[Main_current_layer]; + byte* pixel=Main_backups->Pages->Image[Main_current_layer].Pixels; int i; nb_pixels=Main_image_height*Main_image_width; @@ -205,7 +205,7 @@ void Clear_current_image(byte color) // Effacer l'image courante avec une certaine couleur { memset( - Main_backups->Pages->Image[Main_current_layer], + Main_backups->Pages->Image[Main_current_layer].Pixels, color , Main_image_width * Main_image_height ); @@ -306,7 +306,7 @@ byte Read_pixel_from_spare_screen(word x,word y) #ifndef NOLAYERS return *(Spare_visible_image.Image + y*Spare_image_width + x); #else - return *(Spare_backups->Pages->Image[Spare_current_layer] + y*Spare_image_width + x); + return *(Spare_backups->Pages->Image[Spare_current_layer].Pixels + y*Spare_image_width + x); #endif } @@ -362,7 +362,7 @@ void Remap_general_lowlevel(byte * conversion_table,byte * in_buffer, byte *out_ void Copy_image_to_brush(short start_x,short start_y,short Brush_width,short Brush_height,word image_width) { - byte* src=start_y*image_width+start_x+Main_backups->Pages->Image[Main_current_layer]; //Adr départ image (ESI) + byte* src=start_y*image_width+start_x+Main_backups->Pages->Image[Main_current_layer].Pixels; //Adr départ image (ESI) byte* dest=Brush_original_pixels; //Adr dest brosse (EDI) int dx; @@ -407,7 +407,7 @@ void Replace_colors_within_limits(byte * replace_table) // Pour chaque pixel sur la ligne : for (x = Limit_left;x <= Limit_right;x ++) { - pixel = Main_backups->Pages->Image[Main_current_layer]+y*Main_image_width+x; + pixel = Main_backups->Pages->Image[Main_current_layer].Pixels+y*Main_image_width+x; *pixel = replace_table[*pixel]; } } diff --git a/src/oldies.c b/src/oldies.c index 9be48122..6134205f 100644 --- a/src/oldies.c +++ b/src/oldies.c @@ -33,7 +33,7 @@ void Pixel_in_layer(word x,word y, byte layer, byte color) { - *((y)*Main_image_width+(x)+Main_backups->Pages->Image[layer])=color; + *((y)*Main_image_width+(x)+Main_backups->Pages->Image[layer].Pixels)=color; } byte C64_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *background) @@ -73,7 +73,7 @@ byte C64_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *background) { for (x=0;x<4;x++) { - byte c=*((row)*Main_image_width+(col*4+x)+Main_backups->Pages->Image[2]); + byte c=*((row)*Main_image_width+(col*4+x)+Main_backups->Pages->Image[2].Pixels); used_colors[row][col] |= 1<Pages->Image[0]); + byte c=*((row)*Main_image_width+0+Main_backups->Pages->Image[0].Pixels); if (c<16) { line_color[row]=c; @@ -97,7 +97,7 @@ byte C64_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *background) { for (col=0;col<40;col++) { - byte c=*((row)*Main_image_width+(col*4)+Main_backups->Pages->Image[1]); + byte c=*((row)*Main_image_width+(col*4)+Main_backups->Pages->Image[1].Pixels); if (c<16) { block_color[row/8][col]=c; @@ -309,7 +309,7 @@ byte C64_FLI(byte *bitmap, byte *screen_ram, byte *color_ram, byte *background) for(x=0; x<4; x++) { byte bits; - byte c=*((row*8+y)*Main_image_width+(col*4+x)+Main_backups->Pages->Image[2]); + byte c=*((row*8+y)*Main_image_width+(col*4+x)+Main_backups->Pages->Image[2].Pixels); if (c==line_color[row*8+y]) // BG color diff --git a/src/operatio.c b/src/operatio.c index cbddd2d4..c83549be 100644 --- a/src/operatio.c +++ b/src/operatio.c @@ -2841,7 +2841,7 @@ void Scroll_12_5(void) else { // One layer at once - Scroll_picture(Main_backups->Pages->Next->Image[Main_current_layer], Main_backups->Pages->Image[Main_current_layer], x_offset, y_offset); + Scroll_picture(Main_backups->Pages->Next->Image[Main_current_layer].Pixels, Main_backups->Pages->Image[Main_current_layer].Pixels, x_offset, y_offset); Redraw_current_layer(); } @@ -2898,7 +2898,7 @@ void Scroll_0_5(void) // Do the actual scroll operation on all layers. for (i=0; iPages->Nb_layers; i++) //if ((1<Pages->Next->Image[i], Main_backups->Pages->Image[i], x_offset, y_offset); + Scroll_picture(Main_backups->Pages->Next->Image[i].Pixels, Main_backups->Pages->Image[i].Pixels, x_offset, y_offset); // Update the depth buffer too ... // It would be faster to scroll it, but we don't have method // for in-place scrolling. diff --git a/src/pages.c b/src/pages.c index b7901bb8..d3a263eb 100644 --- a/src/pages.c +++ b/src/pages.c @@ -57,16 +57,19 @@ long Stats_pages_number=0; long long Stats_pages_memory=0; /// Allocate and initialize a new page. -T_Page * New_page(byte nb_layers) +T_Page * New_page(int nb_layers) { T_Page * page; - page = (T_Page *)malloc(sizeof(T_Page)+nb_layers*sizeof(byte *)); + page = (T_Page *)malloc(sizeof(T_Page)+nb_layers*sizeof(T_Image)); if (page!=NULL) { int i; for (i=0; iImage[i]=NULL; + { + page->Image[i].Pixels=NULL; + page->Image[i].Duration=1; + } page->Width=0; page->Height=0; memset(page->Palette,0,sizeof(T_Palette)); @@ -110,13 +113,13 @@ byte * New_layer(long pixel_size) } /// Free a layer -void Free_layer(T_Page * page, byte layer) +void Free_layer(T_Page * page, int layer) { short * ptr; - if (page->Image[layer]==NULL) + if (page->Image[layer].Pixels==NULL) return; - ptr = (short *)(page->Image[layer]); + ptr = (short *)(page->Image[layer].Pixels); if (-- (*(ptr-1))) // Users-- return; else { @@ -189,7 +192,7 @@ void Download_infos_page_main(T_Page * page) } //Update_buffers( page->Width, page->Height); - //memcpy(Main_screen, page->Image[Main_current_layer], page->Width*page->Height); + //memcpy(Main_screen, page->Image[Main_current_layer].Pixels, page->Width*page->Height); } @@ -206,13 +209,13 @@ void Redraw_layered_image(void) int i; for (i=0; i< Main_image_width*Main_image_height; i++) { - layer = *(Main_backups->Pages->Image[4]+i); - Main_visible_image.Image[i]=*(Main_backups->Pages->Image[layer]+i); + layer = *(Main_backups->Pages->Image[4].Pixels+i); + Main_visible_image.Image[i]=*(Main_backups->Pages->Image[layer].Pixels+i); } // Copy it to the depth buffer memcpy(Main_visible_image_depth_buffer.Image, - Main_backups->Pages->Image[4], + Main_backups->Pages->Image[4].Pixels, Main_image_width*Main_image_height); // Next @@ -226,7 +229,7 @@ void Redraw_layered_image(void) { // Copy it in Main_visible_image memcpy(Main_visible_image.Image, - Main_backups->Pages->Image[layer], + Main_backups->Pages->Image[layer].Pixels, Main_image_width*Main_image_height); // Initialize the depth buffer @@ -248,7 +251,7 @@ void Redraw_layered_image(void) int i; for (i=0; iPages->Image[layer]+i); + byte color = *(Main_backups->Pages->Image[layer].Pixels+i); if (color != Main_backups->Pages->Transparent_color) // transparent color { *(Main_visible_image.Image+i) = color; @@ -299,7 +302,7 @@ void Update_depth_buffer(void) int i; for (i=0; iPages->Image[layer]+i); + byte color = *(Main_backups->Pages->Image[layer].Pixels+i); if (color != Main_backups->Pages->Transparent_color) // transparent color { *(Main_visible_image_depth_buffer.Image+i) = layer; @@ -323,7 +326,7 @@ void Redraw_spare_image(void) { // Copy it in Spare_visible_image memcpy(Spare_visible_image.Image, - Spare_backups->Pages->Image[layer], + Spare_backups->Pages->Image[layer].Pixels, Spare_image_width*Spare_image_height); // No depth buffer in the spare @@ -344,7 +347,7 @@ void Redraw_spare_image(void) int i; for (i=0; iPages->Image[layer]+i); + byte color = *(Spare_backups->Pages->Image[layer].Pixels+i); if (color != Spare_backups->Pages->Transparent_color) // transparent color { *(Spare_visible_image.Image+i) = color; @@ -366,14 +369,14 @@ void Redraw_current_layer(void) byte depth = *(Main_visible_image_depth_buffer.Image+i); if (depth<=Main_current_layer) { - byte color = *(Main_backups->Pages->Image[Main_current_layer]+i); + byte color = *(Main_backups->Pages->Image[Main_current_layer].Pixels+i); if (color != Main_backups->Pages->Transparent_color) // transparent color { *(Main_visible_image.Image+i) = color; } else { - *(Main_visible_image.Image+i) = *(Main_backups->Pages->Image[depth]+i); + *(Main_visible_image.Image+i) = *(Main_backups->Pages->Image[depth].Pixels+i); } } } @@ -385,7 +388,7 @@ void Upload_infos_page_main(T_Page * page) { if (page!=NULL) { - //page->Image[Main_current_layer]=Main_screen; + //page->Image[Main_current_layer].Pixels=Main_screen; page->Width=Main_image_width; page->Height=Main_image_height; memcpy(page->Palette,Main_palette,sizeof(T_Palette)); @@ -409,7 +412,7 @@ void Upload_infos_page_spare(T_Page * page) { if (page!=NULL) { - //page->Image[Spare_current_layer]=Spare_screen; + //page->Image[Spare_current_layer].Pixels=Spare_screen; page->Width=Spare_image_width; page->Height=Spare_image_height; memcpy(page->Palette,Spare_palette,sizeof(T_Palette)); @@ -423,9 +426,9 @@ void Update_FX_feedback(byte with_feedback) { if (with_feedback) - FX_feedback_screen=Main_backups->Pages->Image[Main_current_layer]; + FX_feedback_screen=Main_backups->Pages->Image[Main_current_layer].Pixels; else - FX_feedback_screen=Main_backups->Pages->Next->Image[Main_current_layer]; + FX_feedback_screen=Main_backups->Pages->Next->Image[Main_current_layer].Pixels; } void Clear_page(T_Page * page) @@ -435,7 +438,8 @@ void Clear_page(T_Page * page) for (i=0; iNb_layers; i++) { Free_layer(page, i); - page->Image[i]=NULL; + page->Image[i].Pixels=NULL; + page->Image[i].Duration=1; } // Free_gradient() : This data is reference-counted @@ -621,9 +625,10 @@ int Create_new_page(T_Page * new_page, T_List_of_pages * list, dword layer_mask) for (i=0; iNb_layers; i++) { if ((1<Image[i]=New_layer(new_page->Height*new_page->Width); + new_page->Image[i].Pixels=New_layer(new_page->Height*new_page->Width); else - new_page->Image[i]=Dup_layer(list->Pages->Image[i]); + new_page->Image[i].Pixels=Dup_layer(list->Pages->Image[i].Pixels); + new_page->Image[i].Duration=list->Pages->Image[i].Duration; } } @@ -669,8 +674,8 @@ void Update_screen_targets(void) Main_screen=Main_visible_image.Image; Screen_backup=Main_visible_image_backup.Image; #else - Main_screen=Main_backups->Pages->Image[Main_current_layer]; - Screen_backup=Main_backups->Pages->Next->Image[Main_current_layer]; + Main_screen=Main_backups->Pages->Image[Main_current_layer].Pixels; + Screen_backup=Main_backups->Pages->Next->Image[Main_current_layer].Pixels; #endif } @@ -762,10 +767,10 @@ int Init_all_backup_lists(int width,int height) for (i=0; iPages->Nb_layers; i++) { - Main_backups->Pages->Image[i]=New_layer(width*height); - if (! Main_backups->Pages->Image[i]) + Main_backups->Pages->Image[i].Pixels=New_layer(width*height); + if (! Main_backups->Pages->Image[i].Pixels) return 0; - memset(Main_backups->Pages->Image[i], 0, width*height); + memset(Main_backups->Pages->Image[i].Pixels, 0, width*height); } #ifndef NOLAYERS Main_visible_image.Width = 0; @@ -811,10 +816,10 @@ int Init_all_backup_lists(int width,int height) // Spare for (i=0; iPages->Image[i]=New_layer(width*height); - if (! Spare_backups->Pages->Image[i]) + Spare_backups->Pages->Image[i].Pixels=New_layer(width*height); + if (! Spare_backups->Pages->Image[i].Pixels) return 0; - memset(Spare_backups->Pages->Image[i], 0, width*height); + memset(Spare_backups->Pages->Image[i].Pixels, 0, width*height); } //memset(Spare_screen,0,Spare_image_width*Spare_image_height); @@ -833,7 +838,7 @@ void Set_number_of_backups(int nb_backups) // (nb_backups = Nombre de backups, sans compter les pages courantes) } -int Backup_new_image(byte layers,int width,int height) +int Backup_new_image(int layers,int width,int height) { // Retourne 1 si une nouvelle page est disponible et 0 sinon T_Page * new_page; @@ -900,7 +905,7 @@ int Backup_with_new_dimensions(int width,int height) // Fill with transparent color for (i=0; iPages->Nb_layers;i++) { - memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height); + memset(Main_backups->Pages->Image[i].Pixels, Main_backups->Pages->Transparent_color, width*height); } Update_buffers(width, height); @@ -959,10 +964,10 @@ int Backup_in_place(int width,int height) { // Replace layers Free_layer(Main_backups->Pages,i); - Main_backups->Pages->Image[i]=new_layer[i]; + Main_backups->Pages->Image[i].Pixels=new_layer[i]; // Fill with transparency - memset(Main_backups->Pages->Image[i], Main_backups->Pages->Transparent_color, width*height); + memset(Main_backups->Pages->Image[i].Pixels, Main_backups->Pages->Transparent_color, width*height); } Main_backups->Pages->Width=width; @@ -1009,7 +1014,7 @@ int Backup_and_resize_the_spare(int width,int height) T_Page * new_page; int return_code=0; - byte nb_layers; + int nb_layers; nb_layers=Spare_backups->Pages->Nb_layers; // On crée un descripteur pour la nouvelle page de brouillon @@ -1032,7 +1037,7 @@ int Backup_and_resize_the_spare(int width,int height) for (i=0; iPages->Image[i], Spare_backups->Pages->Transparent_color, width*height); + memset(Spare_backups->Pages->Image[i].Pixels, Spare_backups->Pages->Transparent_color, width*height); } // Update_buffers(width, height); // Not for spare @@ -1088,8 +1093,8 @@ void Backup_layers(dword layer_mask) for (i=0; iPages->Nb_layers;i++) { if ((1<Pages->Image[i], - Main_backups->Pages->Next->Image[i], + memcpy(Main_backups->Pages->Image[i].Pixels, + Main_backups->Pages->Next->Image[i].Pixels, Main_image_width*Main_image_height); } // Light up the 'has unsaved changes' indicator @@ -1122,8 +1127,8 @@ void Backup_the_spare(dword layer_mask) for (i=0; iPages->Nb_layers;i++) { if ((1<Pages->Image[i], - Spare_backups->Pages->Next->Image[i], + memcpy(Spare_backups->Pages->Image[i].Pixels, + Spare_backups->Pages->Next->Image[i].Pixels, Spare_image_width*Spare_image_height); } // Light up the 'has unsaved changes' indicator @@ -1277,7 +1282,7 @@ void End_of_modification(void) } /// Add a new layer to latest page of a list. Returns 0 on success. -byte Add_layer(T_List_of_pages *list, byte layer) +byte Add_layer(T_List_of_pages *list, int layer) { T_Page * source_page; T_Page * new_page; @@ -1301,7 +1306,7 @@ byte Add_layer(T_List_of_pages *list, byte layer) return 1; } // Re-allocate the page itself, with room for one more pointer - new_page = realloc(source_page, sizeof(T_Page)+(list->Pages->Nb_layers+1)*sizeof(byte *)); + new_page = realloc(source_page, sizeof(T_Page)+(list->Pages->Nb_layers+1)*sizeof(T_Image)); if (!new_page) { Error(0); @@ -1322,7 +1327,8 @@ byte Add_layer(T_List_of_pages *list, byte layer) { new_page->Image[i]=new_page->Image[i-1]; } - new_page->Image[layer]=new_image; + new_page->Image[layer].Pixels=new_image; + new_page->Image[layer].Duration=1; // Fill with transparency, initially memset(new_image, Main_backups->Pages->Transparent_color, list->Pages->Height*list->Pages->Width); // transparent color @@ -1359,7 +1365,7 @@ byte Add_layer(T_List_of_pages *list, byte layer) } /// Delete a layer from the latest page of a list. Returns 0 on success. -byte Delete_layer(T_List_of_pages *list, byte layer) +byte Delete_layer(T_List_of_pages *list, int layer) { T_Page * page; int i; @@ -1432,9 +1438,9 @@ byte Merge_layer() int i; for (i=0; iPages->Image[Main_current_layer]+i); + byte color = *(Main_backups->Pages->Image[Main_current_layer].Pixels+i); if (color != Main_backups->Pages->Transparent_color) // transparent color - *(Main_backups->Pages->Image[Main_current_layer-1]+i) = color; + *(Main_backups->Pages->Image[Main_current_layer-1].Pixels+i) = color; } return Delete_layer(Main_backups,Main_current_layer); } diff --git a/src/pages.h b/src/pages.h index 31a514c5..5efacf03 100644 --- a/src/pages.h +++ b/src/pages.h @@ -58,14 +58,14 @@ extern T_Bitmap Spare_visible_image; void Download_infos_page_main(T_Page * page); void Upload_infos_page_main(T_Page * page); /// Add a new layer to latest page of a list. Returns 0 on success. -byte Add_layer(T_List_of_pages *list, byte layer); +byte Add_layer(T_List_of_pages *list, int layer); /// Delete a layer from the latest page of a list. Returns 0 on success. -byte Delete_layer(T_List_of_pages *list, byte layer); +byte Delete_layer(T_List_of_pages *list, int layer); /// Merges the current layer onto the one below it. byte Merge_layer(); // private -T_Page * New_page(byte nb_layers); +T_Page * New_page(int nb_layers); void Download_infos_page_spare(T_Page * page); void Upload_infos_page_spare(T_Page * page); void Clear_page(T_Page * page); @@ -95,7 +95,7 @@ void Free_page_of_a_list(T_List_of_pages * list); int Init_all_backup_lists(int width,int height); void Set_number_of_backups(int nb_backups); -int Backup_new_image(byte layers,int width,int height); +int Backup_new_image(int layers,int width,int height); int Backup_with_new_dimensions(int width,int height); /// /// Resizes a backup step in-place (doesn't add a Undo/Redo step). diff --git a/src/palette.c b/src/palette.c index d3f3aca2..2a802f27 100644 --- a/src/palette.c +++ b/src/palette.c @@ -315,7 +315,7 @@ void Remap_image_highlevel(byte * conversion_table) // Remap all layers for (layer=0; layerPages->Nb_layers; layer++) - Remap_general_lowlevel(conversion_table,Main_backups->Pages->Image[layer],Main_backups->Pages->Image[layer],Main_image_width,Main_image_height,Main_image_width); + Remap_general_lowlevel(conversion_table,Main_backups->Pages->Image[layer].Pixels,Main_backups->Pages->Image[layer].Pixels,Main_image_width,Main_image_height,Main_image_width); // Remap transparent color Main_backups->Pages->Transparent_color = diff --git a/src/struct.h b/src/struct.h index ce507262..25b2c2ea 100644 --- a/src/struct.h +++ b/src/struct.h @@ -379,6 +379,12 @@ typedef struct // Ces structures sont manipulées à travers des fonctions de gestion du // backup dans "graph.c". +typedef struct T_Image +{ + byte * Pixels; + int Duration; +} T_Image; + /// This is the data for one step of Undo/Redo, for one image. /// This structure is resized dynamically to hold pointers to all of the layers in the picture. /// The pointed layers are just byte* holding the raw pixel data. But at Image[0]-1 you will find a short that is used as a reference counter for each layer. @@ -399,12 +405,12 @@ typedef struct T_Page T_Gradient_array *Gradients; ///< Pointer to the gradients used by the image. byte Background_transparent; ///< Boolean, true if Layer 0 should have transparent pixels byte Transparent_color; ///< Index of transparent color. 0 to 255. - byte Nb_layers; ///< Number of layers + int Nb_layers; ///< Number of layers #if __GNUC__ < 3 // gcc2 doesn't suport [], but supports [0] which does the same thing. - byte * Image[0]; ///< Pixel data for the (first layer of) image. + T_Image Image[0]; ///< Pixel data for the (first layer of) image. #else - byte * Image[]; ///< Pixel data for the (first layer of) image. + T_Image Image[]; ///< Pixel data for the (first layer of) image. #endif // No field after Image[] ! Dynamic layer allocation for Image[1], [2] etc. } T_Page; @@ -461,6 +467,7 @@ typedef struct /// Bitmap data for the menu, a single rectangle. byte Menu_block[3][35][MENU_WIDTH]; byte Layerbar_block[3][10][144]; + byte Animbar_block[3][14][236]; byte Statusbar_block[3][9][20]; /// Bitmap data for the icons that are displayed over the menu. byte Menu_sprite[2][NB_MENU_SPRITES][MENU_SPRITE_HEIGHT][MENU_SPRITE_WIDTH]; diff --git a/src/transform.c b/src/transform.c index f603fa4a..a468af30 100644 --- a/src/transform.c +++ b/src/transform.c @@ -385,40 +385,40 @@ void Button_Transform_menu(void) case 2 : // Flip X for (i=0; iPages->Nb_layers; i++) { - memcpy(Main_backups->Pages->Image[i],Main_backups->Pages->Next->Image[i],Main_image_width*Main_image_height); - Flip_X_lowlevel(Main_backups->Pages->Image[i], Main_image_width, Main_image_height); + memcpy(Main_backups->Pages->Image[i].Pixels,Main_backups->Pages->Next->Image[i].Pixels,Main_image_width*Main_image_height); + Flip_X_lowlevel(Main_backups->Pages->Image[i].Pixels, Main_image_width, Main_image_height); } break; case 3 : // Flip Y for (i=0; iPages->Nb_layers; i++) { - memcpy(Main_backups->Pages->Image[i],Main_backups->Pages->Next->Image[i],Main_image_width*Main_image_height); - Flip_Y_lowlevel(Main_backups->Pages->Image[i], Main_image_width, Main_image_height); + memcpy(Main_backups->Pages->Image[i].Pixels,Main_backups->Pages->Next->Image[i].Pixels,Main_image_width*Main_image_height); + Flip_Y_lowlevel(Main_backups->Pages->Image[i].Pixels, Main_image_width, Main_image_height); } break; case 4 : // -90° Rotation for (i=0; iPages->Nb_layers; i++) { - Rotate_270_deg_lowlevel(Main_backups->Pages->Next->Image[i], Main_backups->Pages->Image[i], old_width, old_height); + Rotate_270_deg_lowlevel(Main_backups->Pages->Next->Image[i].Pixels, Main_backups->Pages->Image[i].Pixels, old_width, old_height); } break; case 5 : // +90° Rotation for (i=0; iPages->Nb_layers; i++) { - Rotate_90_deg_lowlevel(Main_backups->Pages->Next->Image[i], Main_backups->Pages->Image[i], old_width, old_height); + Rotate_90_deg_lowlevel(Main_backups->Pages->Next->Image[i].Pixels, Main_backups->Pages->Image[i].Pixels, old_width, old_height); } break; case 6 : // 180° Rotation for (i=0; iPages->Nb_layers; i++) { - memcpy(Main_backups->Pages->Image[i],Main_backups->Pages->Next->Image[i],Main_image_width*Main_image_height); - Rotate_180_deg_lowlevel(Main_backups->Pages->Image[i], Main_image_width, Main_image_height); + memcpy(Main_backups->Pages->Image[i].Pixels,Main_backups->Pages->Next->Image[i].Pixels,Main_image_width*Main_image_height); + Rotate_180_deg_lowlevel(Main_backups->Pages->Image[i].Pixels, Main_image_width, Main_image_height); } break; case 7 : // Resize for (i=0; iPages->Nb_layers; i++) { - Rescale(Main_backups->Pages->Next->Image[i], old_width, old_height, Main_backups->Pages->Image[i], Main_image_width, Main_image_height, 0, 0); + Rescale(Main_backups->Pages->Next->Image[i].Pixels, old_width, old_height, Main_backups->Pages->Image[i].Pixels, Main_image_width, Main_image_height, 0, 0); } break; } @@ -426,9 +426,9 @@ void Button_Transform_menu(void) for (i=0; iPages->Next->Image[i],0,0,Min(old_width,Main_image_width), + Main_backups->Pages->Next->Image[i].Pixels,0,0,Min(old_width,Main_image_width), Min(old_height,Main_image_height),old_width, - Main_backups->Pages->Image[i],0,0,Main_image_width); + Main_backups->Pages->Image[i].Pixels,0,0,Main_image_width); } */ Redraw_layered_image(); diff --git a/src/windows.c b/src/windows.c index a89fa54f..966e3237 100644 --- a/src/windows.c +++ b/src/windows.c @@ -464,6 +464,7 @@ void Draw_bar_remainder(word current_menu, word x_off) /// Display / update the layer menubar void Display_layerbar(void) { +#ifndef NOLAYERS word x_off=0; word button_width = LAYER_SPRITE_WIDTH; word button_number = Main_backups->Pages->Nb_layers; @@ -547,6 +548,21 @@ void Display_layerbar(void) Menu_Y+Menu_bars[MENUBAR_LAYERS].Top*Menu_factor_Y, horiz_space*Menu_factor_X, Menu_bars[MENUBAR_LAYERS].Height*Menu_factor_Y); +#else + char str[8]; + // Rest of horizontal line + Draw_bar_remainder(MENUBAR_LAYERS, Menu_bars[MENUBAR_LAYERS].Skin_width); + // Frame# background rectangle + // Block((Menu_bars[MENUBAR_LAYERS].Skin_width)*Menu_factor_X,(0+Menu_bars[MENUBAR_LAYERS].Top)*Menu_factor_Y+Menu_Y,8*8*Menu_factor_X,8*Menu_factor_Y,MC_Light); + // Frame #/# + snprintf(str, 5, "#%3d", Main_current_layer+1); + Print_general((82)*Menu_factor_X,(Menu_bars[MENUBAR_LAYERS].Top+3)*Menu_factor_Y+Menu_Y,str,MC_Black,MC_Light); + Update_rect( + (82)*Menu_factor_X, + (Menu_bars[MENUBAR_LAYERS].Top+3)*Menu_factor_Y+Menu_Y, + 4*8*Menu_factor_X, + 8*Menu_factor_Y); +#endif } @@ -3172,10 +3188,14 @@ void Remap_menu_sprites() Remap_pixel(&Gfx->Statusbar_block[k][j][i]); // Layer bar for (k=0; k<3; k++) - for (j=0; jLayerbar_block[k][j][i]); - + // Anim bar + for (k=0; k<3; k++) + for (j=0; j<14; j++) + for (i=0; i<236; i++) + Remap_pixel(&Gfx->Animbar_block[k][j][i]); // Help fonts for (k=0; k<256; k++) for (j=0; j<8; j++)