home *** CD-ROM | disk | FTP | other *** search
/ hobbes.nmsu.edu 2008 / 2008-06-02_hobbes.nmsu.edu.zip / new / scummc-0.2.0-os2.zip / ScummC / src / costview.c < prev    next >
Encoding:
C/C++ Source or Header  |  2008-05-15  |  23.0 KB  |  912 lines

  1. /* ScummC
  2.  * Copyright (C) 2004-2006  Alban Bedel
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17.  *
  18.  */
  19.  
  20. /**
  21.  * @file costview.c
  22.  * @brief Gtk based costume viewer
  23.  */
  24.  
  25. #include "config.h"
  26.  
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <inttypes.h>
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #include <fcntl.h>
  33. #include <string.h>
  34.  
  35.  
  36. #include "scc_fd.h"
  37. #include "scc_util.h"
  38. #include "scc_cost.h"
  39. #include "scc_img.h"
  40. #include "scc.h"
  41. #include "scc_param.h"
  42.  
  43. #include "costview_help.h"
  44.  
  45. #include <gtk/gtk.h>
  46.  
  47.  
  48. typedef struct cost_view_anim_def {
  49.   int width,height;
  50.   int step_width;
  51.   int start,end;
  52.  
  53.   int drag;
  54.  
  55.   uint16_t* pc;
  56.   scc_cost_anim_def_t* def;
  57. } cost_view_anim_def_t;
  58.  
  59. static int motion_anim_def_cb(GtkWidget *area,GdkEventMotion *ev,
  60.                   cost_view_anim_def_t* d) {
  61.   int r = 0;
  62.   if(!d->drag) return 0;
  63.  
  64.   //printf("Motion: %d %d => [%d %d]\n",ev->x,ev->y,d->start,d->end);
  65.  
  66.   if(d->drag == 1) { // start side
  67.     if(ev->x < d->start-(3*d->step_width/4) &&
  68.        d->start-d->step_width >= 0)
  69.       d->start -= d->step_width, r = 1;
  70.     else if(ev->x > d->start+(3*d->step_width/4) &&
  71.         d->start+d->step_width < d->end)
  72.       d->start += d->step_width, r = 1;
  73.   } else {
  74.     if(ev->x < d->end-(3*d->step_width/4) &&
  75.        d->end-d->step_width > d->start)
  76.       d->end -= d->step_width, r = 1;
  77.     else if(ev->x > d->end + (3*d->step_width/4) &&
  78.         d->end+d->step_width < d->width)
  79.       d->end += d->step_width, r = 1;
  80.   }
  81.  
  82.   if(r) {
  83.     d->def->start = (d->start-2)/d->step_width;
  84.     d->def->end = (d->end-d->step_width-2)/d->step_width;
  85.  
  86.     if(*d->pc < d->def->start) *d->pc = d->def->start;
  87.     if(*d->pc > d->def->end) *d->pc = d->def->end;
  88.  
  89.     gtk_widget_queue_draw(area);
  90.   }
  91.   return 0;
  92. }
  93.  
  94. static int btn_press_anim_def_cb(GtkWidget *area,GdkEventButton *ev,
  95.                  cost_view_anim_def_t* d) {
  96.   printf("Press %d\n",ev->button);
  97.   if(ev->button != 1) return 0;
  98.  
  99.   if(ev->y < 2 || ev->y >= d->height-2 ||
  100.      ev->x < d->start-2 || ev->x > d->end+2) return 0;
  101.  
  102.   if(ev->x <= d->start+8)
  103.     d->drag = 1;
  104.   else if(ev->x >= d->end-8)
  105.     d->drag = 2;
  106.  
  107.   return 0;
  108. }
  109.  
  110. static int btn_release_anim_def_cb(GtkWidget *area,GdkEventButton *ev,
  111.                  cost_view_anim_def_t* d) {
  112.   if(ev->button != 1) return 0;
  113.  
  114.   d->drag = 0;
  115.  
  116.   return 0;
  117. }
  118.  
  119. static void expose_anim_def_cb(GtkWidget *area,GdkEvent* ev,
  120.                    cost_view_anim_def_t* d) {
  121.   int i;
  122.   GdkRectangle rec;
  123.  
  124.   if(d->start >= d->width) return;
  125.  
  126.   if(d->end >= d->width) d->end = d->width-1;
  127.  
  128.   rec.x = 0;
  129.   rec.y = 0;
  130.   rec.width = d->width;
  131.   rec.height = d->height;
  132.  
  133.   for(i = 2+d->step_width/2 ; i < d->width ; i += d->step_width)
  134.     gdk_draw_line(area->window,
  135.            area->style->fg_gc[GTK_WIDGET_STATE(area)],
  136.            i,0,i,d->height);
  137.  
  138.   gtk_paint_box(area->style,
  139.         area->window,
  140.         GTK_WIDGET_STATE(area),
  141.         GTK_SHADOW_OUT,
  142.         &rec,
  143.         area,
  144.         NULL,
  145.         d->start,2,
  146.         d->end-d->start,d->height-4);
  147.   gtk_paint_resize_grip(area->style,
  148.             area->window,
  149.             GTK_WIDGET_STATE(area),
  150.             &rec,
  151.             area,
  152.             NULL,
  153.             GDK_WINDOW_EDGE_WEST,
  154.             d->start+2,4,
  155.             2,d->height-10);
  156.   gtk_paint_resize_grip(area->style,
  157.             area->window,
  158.             GTK_WIDGET_STATE(area),
  159.             &rec,
  160.             area,
  161.             NULL,
  162.             GDK_WINDOW_EDGE_EAST,
  163.             d->end-4,4,
  164.             2,d->height-10);
  165.  
  166.   if(d->pc) {
  167.     uint16_t pc = *d->pc;
  168.  
  169.     if(pc >= d->def->start && pc <= d->def->end)
  170.       gtk_paint_vline(area->style,
  171.               area->window,
  172.               GTK_STATE_SELECTED,
  173.               &rec,
  174.               area,
  175.               NULL,
  176.               4,d->height-6,pc*d->step_width+(d->step_width/2));
  177.   }
  178. }
  179.  
  180. void destroy_anim_def_cb(GtkWidget* area,cost_view_anim_def_t* d) {
  181.   if(d) free(d);
  182. }
  183.  
  184. GtkWidget* cost_view_anim_def_new(scc_cost_anim_def_t* def,uint16_t* pc,
  185.                   int width,int height,int steps) {
  186.   GtkWidget* area;
  187.   cost_view_anim_def_t* d = calloc(1,sizeof(cost_view_anim_def_t));
  188.  
  189.   d->pc = pc;
  190.   d->def = def;
  191.  
  192.   d->width = width;
  193.   d->height = height;
  194.  
  195.   area = gtk_drawing_area_new();
  196.   gtk_widget_set_size_request(area,width,height);
  197.   g_signal_connect(G_OBJECT(area),"expose-event",
  198.            G_CALLBACK(expose_anim_def_cb),d);
  199.   g_signal_connect(G_OBJECT(area),"motion-notify-event",
  200.            G_CALLBACK(motion_anim_def_cb),d);
  201.   g_signal_connect(G_OBJECT(area),"button-press-event",
  202.            G_CALLBACK(btn_press_anim_def_cb),d);
  203.   g_signal_connect(G_OBJECT(area),"button-release-event",
  204.            G_CALLBACK(btn_release_anim_def_cb),d);
  205.   g_signal_connect(G_OBJECT(area),"destroy",
  206.              G_CALLBACK(destroy_anim_def_cb),d);
  207.   gtk_widget_add_events(area,GDK_POINTER_MOTION_MASK|
  208.             GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
  209.   d->step_width = steps;
  210.  
  211.   d->start = 2+d->def->start*d->step_width;
  212.   d->end = 2+(d->def->end+1)*d->step_width;
  213.  
  214.   return area;
  215. }
  216.  
  217.  
  218. typedef struct cost_view_anim_def_tbl {
  219.   scc_cost_dec_t* dec;
  220.   cost_view_anim_def_t* limbs[16];
  221.   int step_size;
  222.   GtkWidget *cmd_win;
  223.   GtkWidget *def_win;
  224.   GtkWidget* loop_win;
  225.   GtkAdjustment* hadj;
  226. } cost_view_anim_def_tbl_t;
  227.  
  228. GtkWidget* cost_view_anim_def_tbl_header(scc_cost_dec_t* dec,int step_size) {
  229.   GtkWidget *box,*lbl;
  230.   int i;
  231.   char buf[20];
  232.  
  233.   box = gtk_hbox_new(0,0);
  234.   for(i = 0 ; i < dec->cost->cmds_size ; i++) {
  235.     sprintf(buf,"%u",dec->cost->cmds[i]);
  236.     lbl = gtk_label_new(buf);
  237.     gtk_widget_set_size_request(lbl,step_size,20);
  238.     gtk_label_set_justify(GTK_LABEL(lbl),GTK_JUSTIFY_CENTER);
  239.     gtk_box_pack_start(GTK_BOX(box),lbl,0,0,0);
  240.   }
  241.  
  242.   return box;
  243. }
  244.  
  245. static void toogle_anim_loop_cb(GtkToggleButton* btn,uint8_t* flags) {
  246.   int mode = gtk_toggle_button_get_active(btn);
  247.  
  248.   if(mode)
  249.     *flags |= 1;
  250.   else
  251.     *flags &= ~1;
  252. }
  253.  
  254. void cost_view_anim_def_load_anim(GtkWidget* tbl) {
  255.   cost_view_anim_def_tbl_t* p = g_object_get_data(G_OBJECT(tbl),"priv");
  256.   GtkWidget *box,*w;
  257.   GtkObject *hadj;
  258.   int i;
  259.   char buf[20];
  260.  
  261.   if(GTK_BIN(p->cmd_win)->child)
  262.     gtk_object_destroy(GTK_OBJECT(GTK_BIN(p->cmd_win)->child));
  263.  
  264.   if(GTK_BIN(p->def_win)->child)
  265.     gtk_object_destroy(GTK_OBJECT(GTK_BIN(p->def_win)->child));
  266.  
  267.   if(GTK_BIN(p->loop_win)->child)
  268.     gtk_object_destroy(GTK_OBJECT(GTK_BIN(p->loop_win)->child));
  269.  
  270.   gtk_container_add(GTK_CONTAINER(p->cmd_win),
  271.             cost_view_anim_def_tbl_header(p->dec,p->step_size));
  272.   gtk_widget_show_all(p->cmd_win);
  273.  
  274.   box = gtk_vbox_new(0,0);
  275.   for(i = 0 ; i < 16 ; i++) {
  276.     if(p->dec->anim->limb[i].start == 0xFFFF) continue;
  277.     gtk_box_pack_start(GTK_BOX(box),
  278.                cost_view_anim_def_new(&p->dec->anim->limb[i],
  279.                           &p->dec->pc[i],
  280.                           (p->step_size+1)*
  281.                           p->dec->cost->cmds_size,
  282.                           20,p->step_size),
  283.                0,0,0);
  284.   }
  285.   gtk_container_add(GTK_CONTAINER(p->def_win),box);
  286.   gtk_widget_show_all(p->def_win);
  287.  
  288.   box = gtk_vbox_new(0,0);
  289.   for(i = 0 ; i < 16 ; i++) {
  290.     if(p->dec->anim->limb[i].start == 0xFFFF) continue;
  291.     w = gtk_check_button_new();
  292.     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
  293.                  p->dec->anim->limb[i].flags);
  294.     g_signal_connect(G_OBJECT(w),"toggled",
  295.              G_CALLBACK(toogle_anim_loop_cb),
  296.              &p->dec->anim->limb[i].flags);
  297.     gtk_widget_set_size_request(w,10,20);
  298.     gtk_box_pack_start(GTK_BOX(box),w,0,0,0);
  299.   }
  300.   gtk_container_add(GTK_CONTAINER(p->loop_win),box);
  301.   gtk_widget_show_all(p->loop_win);
  302. }
  303.  
  304. GtkWidget* cost_view_anim_def_tbl_new(scc_cost_dec_t* dec,int step_size) {
  305.   cost_view_anim_def_tbl_t* p = calloc(1,sizeof(cost_view_anim_def_tbl_t));
  306.   GtkWidget *vbox,*hbox,*scr1,*scr2,*def_box,*w;
  307.   GtkObject *hadj,*vadj;
  308.   int i;
  309.  
  310.  
  311.   p->dec = dec;
  312.   p->step_size = step_size;
  313.  
  314.   hbox = gtk_hbox_new(0,0);
  315.   g_object_set_data(G_OBJECT(hbox),"priv",p);
  316.  
  317.   vbox = gtk_vbox_new(0,0);
  318.  
  319.   hadj = gtk_adjustment_new(0,0,step_size*100,
  320.                 step_size/4,step_size,step_size);
  321.   scr1 = gtk_scrolled_window_new(GTK_ADJUSTMENT(hadj),NULL);
  322.   //scr1 = gtk_scrolled_window_new(NULL,NULL);
  323.  
  324.   p->cmd_win = gtk_viewport_new(NULL,NULL);
  325.   gtk_container_add(GTK_CONTAINER(scr1),p->cmd_win);
  326.   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr1),
  327.                  GTK_POLICY_NEVER,
  328.                  GTK_POLICY_NEVER);
  329.  
  330.   gtk_box_pack_start(GTK_BOX(vbox),scr1,0,0,0);                 
  331.  
  332.  
  333.   scr2 = gtk_scrolled_window_new(GTK_ADJUSTMENT(hadj),NULL);
  334.   //scr2 = gtk_scrolled_window_new(NULL,NULL);
  335.   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr2),
  336.                  GTK_POLICY_AUTOMATIC,
  337.                  GTK_POLICY_NEVER);
  338.   p->def_win = gtk_viewport_new(NULL,NULL);
  339.   gtk_container_add(GTK_CONTAINER(scr2),p->def_win);
  340.  
  341.   gtk_box_pack_start(GTK_BOX(vbox),scr2,1,1,0);
  342.  
  343.   gtk_box_pack_start(GTK_BOX(hbox),vbox,1,1,0);
  344.  
  345.   
  346.   vbox = gtk_vbox_new(0,0);
  347.   w = gtk_label_new("Loop");
  348.   gtk_widget_set_size_request(w,20,24);
  349.   gtk_box_pack_start(GTK_BOX(vbox),w,0,0,0);
  350.  
  351.  
  352.   scr1 = gtk_scrolled_window_new(NULL,
  353.                    gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scr2)));
  354.   //scr1 = gtk_scrolled_window_new(NULL,NULL);
  355.   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scr1),
  356.                  GTK_POLICY_NEVER,
  357.                  GTK_POLICY_AUTOMATIC);
  358.   p->loop_win = gtk_viewport_new(NULL,NULL);
  359.   gtk_container_add(GTK_CONTAINER(scr1),p->loop_win);
  360.   gtk_box_pack_start(GTK_BOX(vbox),scr1,1,1,0);
  361.  
  362.   w = gtk_drawing_area_new();
  363.   gtk_widget_set_size_request(w,20,19);
  364.   gtk_box_pack_start(GTK_BOX(vbox),w,0,0,0);
  365.  
  366.   gtk_box_pack_start(GTK_BOX(hbox),vbox,0,0,0);
  367.  
  368.   gtk_widget_set_size_request(hbox,600,100);
  369.  
  370.   return hbox;
  371.                     
  372. }
  373.  
  374.  
  375.  
  376. typedef struct scc_cost_view {
  377.   scc_pal_t *pal; // the palette
  378.   scc_cost_dec_t dec; // decoder
  379.   //  scc_cost_t* cost; // loaded costume
  380.   //  scc_cost_anim_t* anim; // loaded anim
  381.  
  382.  
  383.   GtkWidget* win;
  384.  
  385.   GtkWidget* anim_combo;
  386.   GtkListStore* anim_store;
  387.   
  388.   GtkWidget* limb_combo;
  389.   GtkListStore* limb_store;
  390.  
  391.   GtkWidget* pic_list;
  392.   GtkListStore* pic_store;
  393.  
  394.   GtkWidget* anim_img;
  395.   GtkWidget* limb_img;
  396.  
  397.   GtkWidget* anim_def_tbl;
  398.  
  399.  
  400.   uint8_t* buf;
  401.   int buf_w,buf_h;
  402.  
  403.   GdkGC* img_gc;
  404.   GdkRgbCmap *img_cmap;
  405.  
  406.   char play;
  407. } scc_cost_view_t;
  408.  
  409. static void scc_cost_view_load_anim(scc_cost_view_t* cv,uint16_t aid) {
  410.   GtkAdjustment* adj;
  411.   int old_aid = (cv->dec.anim) ? cv->dec.anim->id : -1;
  412.  
  413.   if(!scc_cost_dec_load_anim(&cv->dec,aid)) {
  414.     printf("Anim %d not found\n",aid);
  415.     return;
  416.   }
  417.  
  418.   cost_view_anim_def_load_anim(cv->anim_def_tbl);
  419.  
  420.   if(old_aid < 0 || old_aid != cv->dec.anim->id) {
  421.     adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(cv->anim_img->parent->parent));
  422.     gtk_adjustment_set_value(adj,(adj->upper-adj->page_size-adj->lower)/2+
  423.                  adj->lower);
  424.     adj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(cv->anim_img->parent->parent));
  425.     gtk_adjustment_set_value(adj,(adj->upper-adj->page_size-adj->lower)/2+
  426.                  adj->lower);
  427.   
  428.   }
  429.  
  430.   if(cv->buf)
  431.     memset(cv->buf,0,cv->buf_w*cv->buf_h);
  432.   gtk_widget_queue_draw(cv->anim_img);
  433.  
  434. }
  435.  
  436. static void anim_selected_cb(GtkWidget *entry,scc_cost_view_t* cv) {
  437.   scc_cost_anim_t *anim;
  438.   int id;
  439.  
  440.   id = atoi(gtk_editable_get_chars(GTK_EDITABLE(entry),0,-1));
  441.   if(id < 0) {
  442.     printf("Invalid anim number\n");
  443.     return;
  444.   }
  445.  
  446.   scc_cost_view_load_anim(cv,id);
  447.   
  448. }
  449.  
  450. int play_timeout_cb(scc_cost_view_t* cv) {
  451.   if(cv->play <= 0) {
  452.     cv->play = -1;
  453.     return FALSE;
  454.   }
  455.   
  456.   scc_cost_dec_step(&cv->dec);  
  457.   gtk_widget_queue_draw(cv->anim_img);
  458.   gtk_widget_queue_draw(cv->anim_def_tbl);
  459.  
  460.   return TRUE;
  461. }
  462.  
  463. static void anim_play_cb(GtkWidget *tbtn,scc_cost_view_t* cv) {
  464.   if(!cv->dec.anim) return;
  465.  
  466.   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tbtn))) {
  467.     if(cv->play > 0) return;
  468.     cv->play = 1;
  469.     g_timeout_add(200,(GSourceFunc)play_timeout_cb,cv);
  470.     
  471.   } else
  472.     cv->play = 0;
  473. }
  474.  
  475.  
  476.  
  477. static void scc_cost_view_load_pic(scc_cost_view_t* cv,scc_cost_pic_t *pic) {
  478.  
  479.   GtkTreeIter iter;
  480.  
  481.   gtk_list_store_clear(cv->pic_store);
  482.  
  483.   while(pic) {
  484.     gtk_list_store_append(cv->pic_store,&iter);
  485.     gtk_list_store_set(cv->pic_store,&iter,
  486.                0,pic->id,
  487.                1,pic->width,
  488.                2,pic->height,
  489.                3,pic->rel_x,
  490.                4,pic->rel_y,
  491.                -1);
  492.     pic = pic->next;
  493.   }
  494.   
  495. }
  496.  
  497. static void limb_selected_cb(GtkWidget *entry,scc_cost_view_t* cv) {
  498.   int id;
  499.  
  500.   id = atoi(gtk_editable_get_chars(GTK_EDITABLE(entry),0,-1));
  501.   if(id < 0 || id > 15) {
  502.     printf("Invalid limb number\n");
  503.     return;
  504.   }
  505.  
  506.  
  507.   scc_cost_view_load_pic(cv,cv->dec.cost->limb_pic[id]);
  508.   
  509. }
  510.  
  511. static void limb_pic_selected_cb(GtkWidget* pic_list,GtkTreePath* path,
  512.                  GtkTreeViewColumn* col,
  513.                  scc_cost_view_t* cv) {
  514.   gtk_widget_queue_draw(cv->limb_img);
  515. }
  516.  
  517. GtkWidget* create_limb_select(scc_cost_view_t* cv) {
  518.   GtkWidget* vbox;
  519.   GtkWidget* hbox;
  520.   GtkWidget* w, *scroll, *list;
  521.   GtkCellRenderer* render = gtk_cell_renderer_text_new();
  522.  
  523.   vbox = gtk_vbox_new(0,2);
  524.   
  525.   hbox = gtk_hbox_new(0,2);
  526.  
  527.   w = gtk_label_new("Limb");
  528.   gtk_box_pack_start(GTK_BOX(hbox),w,0,0,5);
  529.  
  530.   cv->limb_store = gtk_list_store_new(2,G_TYPE_INT,G_TYPE_STRING);
  531.  
  532.   cv->limb_combo = gtk_combo_box_entry_new_with_model(GTK_TREE_MODEL(cv->limb_store),1);
  533.   g_signal_connect(G_OBJECT(GTK_BIN(cv->limb_combo)->child),"activate",
  534.            G_CALLBACK(limb_selected_cb),cv);
  535.   gtk_box_pack_start(GTK_BOX(hbox),cv->limb_combo,0,0,5);
  536.   gtk_box_pack_start(GTK_BOX(vbox),hbox,0,0,5);
  537.   
  538.   
  539.   // The list
  540.   scroll = gtk_scrolled_window_new(NULL,NULL);
  541.   gtk_container_set_border_width(GTK_CONTAINER(scroll),5);
  542.   cv->pic_store = gtk_list_store_new(7,G_TYPE_INT,
  543.                       G_TYPE_INT,G_TYPE_INT,
  544.                       G_TYPE_INT,G_TYPE_INT,
  545.                       G_TYPE_INT,G_TYPE_INT);
  546.  
  547.   cv->pic_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(cv->pic_store));
  548.  
  549.   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cv->pic_list),
  550.                           -1,"Idx",render,
  551.                           "text",0,NULL);
  552.   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cv->pic_list),
  553.                           -1,"Width",render,
  554.                           "text",1,NULL);
  555.   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cv->pic_list),
  556.                           -1,"Height",render,
  557.                           "text",2,NULL);
  558.  
  559.   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cv->pic_list),
  560.                           -1,"X",render,
  561.                           "text",3,NULL);  
  562.   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cv->pic_list),
  563.                           -1,"Y",render,
  564.                           "text",4,NULL);
  565.   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cv->pic_list),
  566.                           -1,"Move X",render,
  567.                           "text",5,NULL);
  568.   gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(cv->pic_list),
  569.                           -1,"Move Y",render,
  570.                           "text",6,NULL);
  571.  
  572.   g_signal_connect(G_OBJECT(cv->pic_list),"row-activated",
  573.            G_CALLBACK(limb_pic_selected_cb),cv);
  574.  
  575.   gtk_container_add(GTK_CONTAINER(scroll),cv->pic_list);
  576.   gtk_box_pack_start(GTK_BOX(vbox),scroll,1,1,5);
  577.  
  578.     // The last row of buttons
  579.   hbox = gtk_hbox_new(0,2);
  580.  
  581.   w = gtk_button_new_with_label("Edit");
  582.   gtk_box_pack_end(GTK_BOX(hbox),w,0,0,5);
  583.  
  584.   w = gtk_button_new_with_label("Remove");
  585.   gtk_box_pack_end(GTK_BOX(hbox),w,0,0,5);
  586.  
  587.   w = gtk_button_new_with_label("Add");
  588.   gtk_box_pack_end(GTK_BOX(hbox),w,0,0,5);
  589.   
  590.   gtk_box_pack_start(GTK_BOX(vbox),hbox,0,0,5);
  591.   
  592.  
  593.   w = gtk_frame_new("Pictures");
  594.   gtk_container_add(GTK_CONTAINER(w),vbox);
  595.  
  596.   return w;
  597. }
  598.  
  599. static void expose_img_cb(GtkWidget *img,GdkEvent* ev,scc_cost_view_t* cv) {
  600.   int x1,x2,y1,y2;
  601.   int x,y;
  602.  
  603.   //if(!scc_cost_dec_bbox(&cv->dec,&x1,&y1,&x2,&y2)) return;
  604.   //w = x2-x1;
  605.   //h = y2-y1;
  606.   
  607.   if(!cv->buf || cv->buf_h/10 != img->allocation.height/10  || 
  608.      cv->buf_w/10 < img->allocation.width/10) {
  609.     cv->buf_h = (img->allocation.height/10)*10;
  610.     cv->buf_w = (img->allocation.width/10)*10;
  611.     cv->buf = realloc(cv->buf,cv->buf_h*cv->buf_w);
  612.     
  613.   }
  614.  
  615.   if(!cv->img_gc) cv->img_gc = gdk_gc_new(img->window);
  616.  
  617.   memset(cv->buf,0,cv->buf_h*cv->buf_w);
  618.   scc_cost_dec_frame(&cv->dec,cv->buf,cv->buf_w/2,cv->buf_h/2,
  619.              cv->buf_w,cv->buf_h,cv->buf_w,NULL,0,255,255);
  620.  
  621.   //printf("Draw Image !!!\n");
  622.  
  623.   
  624.  
  625.   gdk_draw_indexed_image(img->window,cv->img_gc,
  626.              (img->allocation.width%10)/2,
  627.              (img->allocation.height%10)/2,
  628.              cv->buf_w,cv->buf_h,GDK_RGB_DITHER_NONE,
  629.              cv->buf,cv->buf_w,cv->img_cmap);
  630.   
  631. }
  632.  
  633. static void expose_limb_img_cb(GtkWidget *img,GdkEvent* ev,scc_cost_view_t* cv) {
  634.   GtkTreeIter iter;
  635.   GtkTreeSelection* psel = gtk_tree_view_get_selection(GTK_TREE_VIEW(cv->pic_list));
  636.   int id,pid;
  637.   scc_cost_pic_t* pic;
  638.  
  639.   if(!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(cv->limb_combo),&iter))
  640.     return;
  641.   gtk_tree_model_get(GTK_TREE_MODEL(cv->limb_store),&iter,0,&id,-1);
  642.  
  643.   if(!gtk_tree_selection_get_selected(psel,(GtkTreeModel**)&cv->pic_store,&iter))
  644.     return;
  645.  
  646.   
  647.   gtk_tree_model_get(GTK_TREE_MODEL(cv->pic_store),&iter,0,&pid,-1);
  648.   
  649.   pic = scc_cost_get_limb_pic(cv->dec.cost,id,pid,4);
  650.  
  651.   if(!pic) {
  652.     printf("Failed to find the right picture!!!\n");
  653.     return;
  654.   } else {
  655.     uint8_t buf[pic->width*pic->height];
  656.     scc_cost_decode_pic(cv->dec.cost,pic,buf,pic->width,NULL,0,
  657.             0,pic->width,0,pic->height,-1,255,255,0);
  658.  
  659.     gdk_draw_indexed_image(img->window,cv->img_gc,
  660.                (img->allocation.width%10)/2,
  661.                (img->allocation.height%10)/2,
  662.                pic->width,pic->height,GDK_RGB_DITHER_NONE,
  663.                buf,pic->width,cv->img_cmap);
  664.   }
  665.  
  666. }
  667.  
  668. GtkWidget* create_anim_view(scc_cost_view_t* cv) {
  669.   GtkWidget *pan,*vbox,*hbox;
  670.   GtkWidget* w;
  671.  
  672.   pan = gtk_vpaned_new();
  673.  
  674.   vbox = gtk_vbox_new(0,2);
  675.   hbox = gtk_hbox_new(0,2);
  676.  
  677.   w = gtk_label_new("Anim:");
  678.   gtk_box_pack_start(GTK_BOX(hbox),w,0,0,5);
  679.   cv->anim_store = gtk_list_store_new(2,G_TYPE_INT,G_TYPE_STRING);
  680.   cv->anim_combo = gtk_combo_box_entry_new_with_model(GTK_TREE_MODEL(cv->anim_store),1);
  681.   gtk_box_pack_start(GTK_BOX(hbox),cv->anim_combo,0,0,5);
  682.   g_signal_connect(G_OBJECT(GTK_BIN(cv->anim_combo)->child),"activate",
  683.            G_CALLBACK(anim_selected_cb),cv);
  684.  
  685.   w = gtk_toggle_button_new_with_label("Play");
  686.   gtk_box_pack_end(GTK_BOX(hbox),w,0,0,5);
  687.   g_signal_connect(G_OBJECT(w),"toggled",
  688.            G_CALLBACK(anim_play_cb),cv);
  689.  
  690.   
  691.   gtk_box_pack_start(GTK_BOX(vbox),hbox,0,0,5);
  692.  
  693.   cv->anim_def_tbl = cost_view_anim_def_tbl_new(&cv->dec,50);
  694.  
  695.   gtk_box_pack_start(GTK_BOX(vbox),cv->anim_def_tbl,1,1,5);
  696.  
  697.   gtk_paned_add1(GTK_PANED(pan),vbox);
  698.  
  699.   w = gtk_scrolled_window_new(NULL,NULL);
  700.  
  701.   cv->anim_img = gtk_drawing_area_new();
  702.   gtk_widget_set_size_request(cv->anim_img,600,500);
  703.   g_signal_connect(G_OBJECT(cv->anim_img),"expose-event",
  704.            G_CALLBACK(expose_img_cb),cv);
  705.  
  706.   gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(w),cv->anim_img);
  707.  
  708.   gtk_paned_add2(GTK_PANED(pan),w);
  709.  
  710.   return pan;
  711. }
  712.  
  713. static int quit_cb(GtkWidget *widget,GdkEvent *event,gpointer user_data) {
  714.   gtk_main_quit();
  715.   return 0;
  716. }
  717.  
  718.  
  719. scc_cost_view_t* create_win(void) {
  720.   scc_cost_view_t* cv = calloc(1,sizeof(scc_cost_view_t));
  721.   GtkWidget* hpan,*vpan;
  722.   GtkWidget *w;
  723.   GdkPixmap* pmap;
  724.  
  725.   cv->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  726.   g_signal_connect(G_OBJECT(cv->win),"destroy-event",
  727.              G_CALLBACK(quit_cb),NULL);
  728.   g_signal_connect(G_OBJECT(cv->win),"delete-event",
  729.              G_CALLBACK(quit_cb),NULL);
  730.   gtk_container_set_border_width(GTK_CONTAINER(cv->win),5);
  731.  
  732.   hpan = gtk_hpaned_new();
  733.   vpan = gtk_vpaned_new();
  734.  
  735.  
  736.  
  737.   w = create_limb_select(cv);
  738.   gtk_paned_add1(GTK_PANED(vpan),w);
  739.   
  740.   w = gtk_scrolled_window_new(NULL,NULL);
  741.   cv->limb_img = gtk_drawing_area_new();
  742.   gtk_widget_set_size_request(cv->limb_img,200,200);
  743.   g_signal_connect(G_OBJECT(cv->limb_img),"expose-event",
  744.              G_CALLBACK(expose_limb_img_cb),cv);
  745.   gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(w),cv->limb_img);
  746.   gtk_paned_add2(GTK_PANED(vpan),w);
  747.  
  748.  
  749.   gtk_paned_add1(GTK_PANED(hpan),vpan);
  750.  
  751.   w = create_anim_view(cv);
  752.   gtk_paned_add2(GTK_PANED(hpan),w);
  753.  
  754.   gtk_container_add(GTK_CONTAINER(cv->win),hpan);
  755.  
  756.   gtk_widget_set_size_request(cv->win,600,400);
  757.   gtk_widget_show_all(cv->win);
  758.   
  759.   return cv;
  760. }
  761.  
  762. void scc_cost_view_load_pal(scc_cost_view_t* cv,scc_pal_t* pal) {
  763.   int i;
  764.  
  765.   if(cv->img_cmap) gdk_rgb_cmap_free(cv->img_cmap);
  766.  
  767.   cv->img_cmap = malloc(sizeof(GdkRgbCmap));
  768.  
  769.   cv->img_cmap->n_colors = 256;
  770.  
  771.   for(i = 0; i < 256 ; i++)
  772.     cv->img_cmap->colors[i] = ((pal->r[i])<<16) | ((pal->g[i])<<8) | pal->b[i];
  773.  
  774. }
  775.  
  776. int scc_cost_view_load(scc_cost_view_t* cv,scc_pal_t* pal,scc_cost_t* cost) {
  777.   scc_cost_anim_t* a;
  778.   GtkTreeIter iter;
  779.   char tmp[20];
  780.   int l;
  781.  
  782.   scc_cost_dec_init(&cv->dec);
  783.  
  784.   scc_cost_view_load_pal(cv,pal);
  785.  
  786.   for(a = cost->anims ; a ; a = a->next) {
  787.     gtk_list_store_append(cv->anim_store,&iter);
  788.     sprintf(tmp,"%u",a->id);
  789.     gtk_list_store_set(cv->anim_store,&iter,0,a->id,1,tmp,-1);
  790.   }
  791.  
  792.   for(l = 0 ; l < 16 ; l++) {
  793.     if(!cost->limb_pic[l]) continue;
  794.     gtk_list_store_append(cv->limb_store,&iter);
  795.     sprintf(tmp,"%u",l);
  796.     gtk_list_store_set(cv->limb_store,&iter,0,l,1,tmp,-1);
  797.   }
  798.  
  799.   cv->pal = pal;
  800.   cv->dec.cost = cost;
  801.  
  802.   return 0;
  803. }
  804.  
  805. static scc_pal_t* open_pals_file(char* path) {
  806.   scc_fd_t* fd = new_scc_fd(path,O_RDONLY,0);
  807.   uint32_t type,len;
  808.   scc_pal_t* pal;
  809.  
  810.   if(!fd) {
  811.     printf("Failed to open %s.\n",path);
  812.     return NULL;
  813.   }
  814.  
  815.   type = scc_fd_r32(fd);
  816.   len = scc_fd_r32be(fd);
  817.  
  818.   if(type != MKID('P','A','L','S')) {
  819.     printf("%s is not a pals file.\n",path);
  820.     scc_fd_close(fd);
  821.     return NULL;
  822.   }
  823.  
  824.   pal = scc_parse_pals(fd,len-8);
  825.   
  826.   scc_fd_close(fd);
  827.   return pal;
  828. }
  829.  
  830. static scc_cost_t* open_cost_file(char * path) {
  831.   scc_fd_t* fd = new_scc_fd(path,O_RDONLY,0);
  832.   uint32_t type,len;
  833.   scc_cost_t* cost;
  834.  
  835.   if(!fd) {
  836.     printf("Failed to open %s.\n",path);
  837.     return NULL;
  838.   }
  839.  
  840.   type = scc_fd_r32(fd);
  841.   len = scc_fd_r32be(fd);
  842.  
  843.   if(type != MKID('C','O','S','T')) {
  844.     printf("%s is not a costume file.\n",path);
  845.     scc_fd_close(fd);
  846.     return NULL;
  847.   }
  848.  
  849.   cost = scc_parse_cost(fd,len-8);
  850.   
  851.   scc_fd_close(fd);
  852.   return cost;
  853. }
  854.  
  855. static char* pals_path = NULL;
  856. static char* bmp_path = NULL;
  857.  
  858. static scc_param_t costview_params[] = {
  859.   { "pals", SCC_PARAM_STR, 0, 0, &pals_path },
  860.   { "bmp", SCC_PARAM_STR, 0, 0, &bmp_path },
  861.   { "help", SCC_PARAM_HELP, 0, 0, &costview_help },
  862.   { NULL, 0, 0, 0, NULL }
  863. };
  864.  
  865. int main(int argc,char** argv) {
  866.   scc_cl_arg_t* files;
  867.   scc_cost_dec_t dec;
  868.   scc_cost_view_t* cv;
  869.   scc_cost_t* cost;
  870.   scc_pal_t* pal;
  871.  
  872.   // make gtk pump his args
  873. //  gtk_init(&argc,&argv);
  874.  
  875.   files = scc_param_parse_argv(costview_params,argc-1,&argv[1]);
  876.   if(!files) scc_print_help(&costview_help,1);
  877.  
  878.   gtk_init_check(&argc,&argv);
  879.   cv = create_win();
  880.  
  881.   if(bmp_path) {
  882.     int i;
  883.     scc_img_t* img = scc_img_open(bmp_path);
  884.     if(!img) {
  885.       scc_log(LOG_ERR,"Failed to open %s.\n",bmp_path);
  886.       return -1;
  887.     }
  888.     pal = calloc(1,sizeof(scc_pal_t));
  889.     for(i = 0 ; i < img->ncol && i < 256 ; i++) {
  890.       pal->r[i] = img->pal[3*i];
  891.       pal->g[i] = img->pal[3*i+1];
  892.       pal->b[i] = img->pal[3*i+2];
  893.     }
  894.     scc_img_free(img);
  895.   } else {
  896.     if(!pals_path) {
  897.       scc_log(LOG_WARN,"No palette given on the command line, using default.pals.\n");
  898.       pals_path = "default.pals";
  899.     }
  900.     pal = open_pals_file(pals_path);
  901.     if(!pal) return -1;
  902.   }
  903.   
  904.   cost = open_cost_file(files->val);
  905.   if(!cost) return -1;
  906.    
  907.   scc_cost_view_load(cv,pal,cost);
  908.  
  909.   gtk_main();
  910.   return 0;
  911. }
  912.