Logo Search packages:      
Sourcecode: vertex version File versions

editormodelcb.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <math.h>

#include <GL/gl.h>

#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>

#include "matrixmath.h"
#include "v3dmp.h"
#include "v3dmodel.h"
#include "guiutils.h"
#include "cdialog.h"

#include "editor.h"
#include "editorcb.h"
#include "editoridialog.h"
#include "editorviewcb.h"
#include "editorlist.h"
#include "editordnd.h"
#include "editorundo.h"
#include "editormodel.h"
#include "editormodelcb.h"

#include "msglist.h"
#include "messages.h"
#include "vmapixmaps.h"
#include "vmapresetmodels.h"
#include "vma.h"
#include "vmautils.h"

#ifdef MEMWATCH
# include "memwatch.h"
#endif


#include "images/icon_model_48x48.xpm"
#include "images/icon_model_other_48x48.xpm"


static void EditorModelIDialogCancelCB(void *idialog, void *data);
static gint EditorModelEditableDummyKeyCB(
        GtkWidget *widget, GdkEventKey *key, gpointer data   
);
static void EditorModelCreateDNDListSetIcon(
        ma_editor_idialog_struct *d, v3d_model_struct *model
);
static void EditorModelCreateDNDListDataRequestCB(
        GtkWidget *widget, GdkDragContext *dc,
        GtkSelectionData *selection_data, guint info, guint t,
        gpointer data
);
static void EditorModelCreateDNDListDataDeleteCB(
        GtkWidget *widget, GdkDragContext *dc, gpointer data
);
static void EditorModelCreateListSelectCB(
        GtkWidget *widget, gint row, gint column,
        GdkEventButton *event, gpointer data
);

void EditorModelCreateCB(GtkWidget *widget, gpointer data);
static void EditorModelCreateOKCB(void *idialog, void *data);
static void EditorModelCreateApplyCB(void *idialog, void *data);

void EditorModelDeleteCB(GtkWidget *widget, gpointer data);

static void EditorModelPropertiesSwitchPageCB(
        GtkNotebook *notebook, GtkNotebookPage *page, guint page_num,
        gpointer data
);
void EditorModelPropertiesCB(GtkWidget *widget, gpointer data);
static void EditorModelPropertiesOKCB(void *idialog, void *data);
static void EditorModelPropertiesApplyCB(void *idialog, void *data);


#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))

#define RADTODEG(r)     ((r) * 180 / PI)
#define DEGTORAD(d)     ((d) * PI / 180.0)


/*
 *      Checks if editor has changes, if it does not then it will
 *      mark it as having changes.
 */
#define EDITOR_DO_UPDATE_HAS_CHANGES      \
{ \
 if(!editor->has_changes) \
  editor->has_changes = TRUE; \
}


/*
 *      Generic input dialog cancel callback to unmap the input
 *      dialog.
 */
static void EditorModelIDialogCancelCB(void *idialog, void *data)
{
        ma_editor_struct *editor;
        ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)idialog;
        if(d == NULL)
            return;

        editor = (ma_editor_struct *)d->editor_ptr;
        if(editor == NULL)
            return;

        /* Reset input dialog and unmap it. */
        EditorIDialogReset(editor, d, TRUE);

        return;
}

/*
 *    For some obscure reason the GtkEditable widgets call 
 *    gtk_main_quit() when a key event is recieved while it is set
 *    not editable.
 *
 *    Here we play a trick, when the key is pressed the GtkEditable
 *    widget is set editable but when the key release is recieved
 *    the widget is set back to not editable.
 */
static gint EditorModelEditableDummyKeyCB(
        GtkWidget *widget, GdkEventKey *key, gpointer data
)
{
      gbool state;
      GtkEditable *editable;

      if(widget == NULL)
          return(FALSE);

      editable = (GtkEditable *)widget;

        state = (((*(int *)key) == GDK_KEY_PRESS) ? TRUE : FALSE);
        if(state)
            gtk_editable_set_editable(editable, TRUE);
        else
            gtk_editable_set_editable(editable, FALSE);

      return(TRUE);
}

/*
 *      Sets the DND icon based on the specified model and
 *      with respect to the given editor.
 */
static void EditorModelCreateDNDListSetIcon(
      ma_editor_idialog_struct *d, v3d_model_struct *model
)
{
      if(d == NULL)
          return;

        if(model == NULL)
        {
                
        }
        else
        {
            GdkPixmap *pixmap = NULL;
            GdkBitmap *mask = NULL;
            int icon_num = VMA_PIXMAP_MODEL_OTHER_20x20;


            if(model->type == V3D_MODEL_TYPE_STANDARD)
            icon_num = VMA_PIXMAP_MODEL_20x20;

            VMAPixmapsListGetValues(
                &vma_pixmaps_list, icon_num,
                &pixmap, &mask, NULL
            ); 

            if(pixmap != NULL)
            {
                gint w = 15, h = 15;

                gdk_window_get_size((GdkWindow *)pixmap, &w, &h);

            GUIDNDSetDragIcon(
                pixmap, mask,
                (w / 2), (h / 2)
            );
            }
        }
}

/*
 *      DND `data request' callback for input dialog's preset models
 *    clist.
 */
static void EditorModelCreateDNDListDataRequestCB(
        GtkWidget *widget, GdkDragContext *dc,
        GtkSelectionData *selection_data, guint info, guint t,
        gpointer data
)
{
        gboolean data_sent = FALSE;
      GtkWidget *w;
        GtkCList *clist = NULL;
        int new_model_num = -1;
        v3d_model_struct *new_model_ptr;
      const char *new_name_ptr = NULL;
      ma_editor_struct *editor;
      ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)data;
        if((widget == NULL) || (d == NULL) || (dc == NULL))
            return;

      editor = (ma_editor_struct *)d->editor_ptr;
      if(editor == NULL)
          return;

      /* Get widget 0 (the clist). */
        w = EditorIDialogGetWidget(d, 0);
        if((w == NULL) ? 0 : GTK_IS_CLIST(w))
            clist = GTK_CLIST(w); 
        else
            clist = NULL;

      /* Get selected row on clist. */
      if(clist != NULL)
      {
          GList *sel = clist->selection;
          new_model_num = ((sel != NULL) ? (int)sel->data : -1);
      }

      /* Get widget 1 (new name entry). */
      w = EditorIDialogGetWidget(d, 1);
        if((w == NULL) ? 0 : GTK_IS_ENTRY(w))
      {
          new_name_ptr = (const char *)gtk_entry_get_text(GTK_ENTRY(w));
      }

      /* Got available clist and selected model number? */
      if((clist != NULL) && (new_model_num >= 0))
      {
          if(new_model_num < clist->rows)
            new_model_ptr = (v3d_model_struct *)gtk_clist_get_row_data(
                clist, new_model_num
            );
          else
            new_model_ptr = NULL;

          if(new_model_ptr != NULL)
          {
                /* Send out data consisting of a command containing the
                 * following arguments:
                 * <core_ptr> <editor_num> <new_model_ptr> <new_name_ptr>
             */
            int i;
                char *buf;
                int buf_len;
                int editor_num = -1;
                vma_core_struct *core_ptr = (vma_core_struct *)editor->core_ptr;
                char num_str[80];


            /* Change new_name_ptr to "other" if this model is of
             * type V3D_MODEL_TYPE_OTHER_DATA.
             */
            if(new_model_ptr->type == V3D_MODEL_TYPE_OTHER_DATA)
                new_name_ptr = "other";

                /* Find editor number in core structure. */
                if(core_ptr != NULL)
                {
                    for(i = 0; i < core_ptr->total_editors; i++)
                    {
                        if(core_ptr->editor[i] == editor)
                        {
                            editor_num = i;
                            break;
                        }
                    }
                }

                /* Allocate buf, enough for just one model number for now
                 * since only one model can be selected.
                 */
                buf_len = 24 + 24 + 24 + 24;
                buf = (char *)malloc(buf_len * sizeof(char));
                if(buf != NULL)
                {
                    /* Format buf. */
                    (*buf) = '\0';
                    sprintf(num_str, "%.8x ", (guint)core_ptr);
                    strcat(buf, num_str);
                    sprintf(num_str, "%i ", editor_num);
                    strcat(buf, num_str);
                    sprintf(num_str, "%.8x ", (guint)new_model_ptr);
                    strcat(buf, num_str);
                    sprintf(num_str, "%.8x", (guint)new_name_ptr);
                    strcat(buf, num_str);

                    /* Send out data. */
                    gtk_selection_data_set(  
                        selection_data,
                        GDK_SELECTION_TYPE_STRING,
                        8,          /* 8 bits per character. */
                        buf, strlen(buf)
                    );
                    data_sent = TRUE;

                    /* Free buffer. */
                    free(buf);
                    buf = NULL;
                    buf_len = 0;
            }
            }
        }

        /* Failed to send out data? */
        if(!data_sent)
        {
            const char *strptr = "Error";

            gtk_selection_data_set(
                selection_data,
                GDK_SELECTION_TYPE_STRING,
                8,      /* 8 bits per character. */
                strptr, strlen(strptr)
            );
            data_sent = TRUE;
        }
}

/*
 *    DND data delete callback for the input dialog's preset models
 *    list.
 */
static void EditorModelCreateDNDListDataDeleteCB(
        GtkWidget *widget, GdkDragContext *dc, gpointer data
)
{
        /* Function no longer used. */
}

/*
 *    Input dialog preset models list select callback.
 */
static void EditorModelCreateListSelectCB(
        GtkWidget *widget, gint row, gint column,
        GdkEventButton *event, gpointer data
)
{
        static gbool reenterant = FALSE;
      GtkCList *clist;
        v3d_model_struct *model_ptr;
      ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)data;
      if(d == NULL)
            return;

        if(reenterant)
            return;
        else
            reenterant = TRUE;

      if(widget == NULL)
          clist = (GtkCList *)EditorIDialogGetWidget(d, 0);
      else
          clist = GTK_CLIST(widget);
      if(clist == NULL)
      {
          reenterant = FALSE;
          return;
      }

      /* If this is a double click, then create model. */
      if((event == NULL) ? 0 : (event->type == GDK_2BUTTON_PRESS))
      {
          EditorModelCreateOKCB(d, data);
          reenterant = FALSE;
            return;
      }

      /* Get client data on selected row as a preset model. */
      model_ptr = (v3d_model_struct *)gtk_clist_get_row_data(
          clist, row
      );

      /* Set DND icon. */
      EditorModelCreateDNDListSetIcon(
          d, model_ptr
      );

      reenterant = FALSE;
      return;
}




/*
 *    Create model dialog map callback.
 */
void EditorModelCreateCB(GtkWidget *widget, gpointer data)
{
/*        const char *msglist[] = VMA_MSGLIST_EDITOR_TOOLTIPS; */
        GtkWidget *parent;
        ma_editor_idialog_struct *d;
        ma_editor_struct *editor = (ma_editor_struct *)data;
        if(editor == NULL)
            return;

        if(!editor->initialized || editor->processing)
            return;

        if(VMAWriteProtectCheck(editor))
            return;

        d = &editor->idialog;       /* Editor's input dialog. */

        /* Reset input dialog. */
        EditorIDialogReset(editor, d, FALSE);

        /* Get input dialog's client vbox. */
        parent = EditorIDialogClientParent(d);
        if(parent != NULL) 
        {
            /* Begin creating our widgets on input dialog, order;
             *
             *  0 Model types clist
             *  1 New name entry
           */
          int i, n, icon_num;
            void *entry;
            GtkWidget *w, *parent2, *parent3;
          vma_preset_models_struct *list = &vma_preset_models;
          v3d_model_struct *model_ptr;
          GdkPixmap *pixmap;
          GdkBitmap *mask;
          gchar *heading[2];
          GtkTargetEntry dnd_type[1];

          /* Vbox for preset models clist and new name entry. */
            w = gtk_vbox_new(FALSE, 0);
            gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
            parent2 = w;

            /* Preset models clist. */
            w = gtk_scrolled_window_new(NULL, NULL);
            gtk_scrolled_window_set_policy(
                GTK_SCROLLED_WINDOW(w),
                GTK_POLICY_AUTOMATIC,
                GTK_POLICY_AUTOMATIC
            );
            gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
          parent3 = w;

            heading[0] = strdup("Model");
          heading[1] = strdup("Type");
          w = gtk_clist_new_with_titles(2, heading);
          free(heading[0]);
          free(heading[1]);
            gtk_widget_set_usize(w, 350, 250);
            gtk_clist_column_titles_passive(GTK_CLIST(w));
            gtk_clist_set_selection_mode(GTK_CLIST(w), GTK_SELECTION_BROWSE);
            gtk_clist_set_row_height(GTK_CLIST(w), VMA_LIST_ROW_SPACING);

          gtk_clist_set_column_width(
            GTK_CLIST(w), 0, 230
          );
            gtk_clist_set_column_justification(
                GTK_CLIST(w), 0, GTK_JUSTIFY_LEFT
            );
/*
          gtk_clist_set_column_width(
                GTK_CLIST(w), 1, 120
            );
 */
            gtk_clist_set_column_justification(
                GTK_CLIST(w), 1, GTK_JUSTIFY_LEFT
            );
            gtk_container_add(GTK_CONTAINER(parent3), w);
            gtk_clist_set_shadow_type(GTK_CLIST(w), GTK_SHADOW_IN);
            gtk_signal_connect(
                GTK_OBJECT(w), "select_row",
                GTK_SIGNAL_FUNC(EditorModelCreateListSelectCB),
                (gpointer)d
            );
            dnd_type[0].target = EDITOR_DND_TYPE_MODEL_CREATE_CMD;
            dnd_type[0].flags = GTK_TARGET_SAME_APP;
            dnd_type[0].info = 12345;           /* Ignored. */
          GUIDNDSetSrc(
            w,
            &dnd_type, 1,                 /* DND target types. */
            GDK_ACTION_COPY,        /* Actions. */
            GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,      /* Buttons. */
            NULL,
                EditorModelCreateDNDListDataRequestCB,
                EditorModelCreateDNDListDataDeleteCB,
                NULL,
                (gpointer)d
            );
          gtk_widget_show(w);
            /* Record as widget 0. */
            EditorIDialogRecordWidget(d, w);

          /* Add preset list of models to clist's rows as client
           * data on each row.
           */
          for(i = 0; i < list->total_models; i++)
          {
            model_ptr = list->model[i];
            if(model_ptr == NULL)
                continue;

            if(model_ptr->name != NULL)
                heading[0] = strdup(model_ptr->name);
            else
                heading[0] = strdup("(null)");
            switch(model_ptr->type)
            {
              case V3D_MODEL_TYPE_STANDARD:
                heading[1] = strdup("Standard");
                icon_num = VMA_PIXMAP_MODEL_20x20;
                break;

              case V3D_MODEL_TYPE_OTHER_DATA:
                heading[1] = strdup("Other Data");
                icon_num = VMA_PIXMAP_MODEL_OTHER_20x20;
                    break;

              default:
                heading[1] = strdup("Unknown");
                icon_num = VMA_PIXMAP_MODEL_OTHER_20x20;
                break;
            }
                VMAPixmapsListGetValues(
                    &vma_pixmaps_list, icon_num,
                    &pixmap, &mask, NULL
                );

            /* Append an item to the clist. */
            n = gtk_clist_append(
                GTK_CLIST(w), heading
            );
            gtk_clist_set_pixtext(
                GTK_CLIST(w),
                n, 0,   /* Row, column. */
                heading[0], VMA_LIST_PIXMAP_TEXT_SPACING,
                pixmap, mask
            );
            gtk_clist_set_row_data(GTK_CLIST(w), n, model_ptr);

            free(heading[0]);
            free(heading[1]);
          }

          w = gtk_table_new(2, 2, FALSE);
            gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 2);
            gtk_widget_show(w);
            parent3 = w;

          /* New model name entry. */
            w = GUIPromptBar(
                NULL, "Name:",
                NULL, &entry
            );
            gtk_table_attach(
            GTK_TABLE(parent3), w,
                0, 2, 0, 1,
                GTK_EXPAND | GTK_FILL, 0,
                2, 2
            );
            gtk_entry_set_text((GtkEntry *)entry, "New Model");
/*
            GUISetWidgetTip(
                (GtkWidget *)entry,
                MsgListMatchCaseMessage(
                    msglist,
                    VMA_MSGNAME_EDITOR_ROTATE_PRIMITIVE_ORBITAL_CENTER
                )
            );
 */
            gtk_widget_show(w);
            /* Record as widget 1. */
            EditorIDialogRecordWidget(d, (GtkWidget *)entry);


          /* Keep dialog check. */
          w = gtk_check_button_new_with_label("Keep Dialog");
          gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE);
            gtk_table_attach(
                GTK_TABLE(parent3), w,
                0, 1, 1, 2,
                0, 0,
                2, 2
            );
            gtk_widget_show(w);
            /* Record as widget 2. */
            EditorIDialogRecordWidget(d, w);
        }

        EditorIDialogMap(
            editor, d,
            "Create Model",
            "Create", NULL, "Close",
            (void *)editor,
            EditorModelCreateOKCB,
            EditorModelCreateApplyCB,
            EditorModelIDialogCancelCB
        );

      return;
}

/*
 *    Create model input dialog ok callback.
 */
static void EditorModelCreateOKCB(void *idialog, void *data)
{
      gbool keep_dialog = FALSE;
      GtkWidget *w;
        ma_editor_struct *editor;
        ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)idialog;
        if(d == NULL)
            return;

        editor = (ma_editor_struct *)d->editor_ptr;
        if(editor == NULL)
            return;

      EditorModelCreateApplyCB(idialog, data);

      /* Get keep dialog toggle. */
      w = EditorIDialogGetWidget(d, 2);
      if((w == NULL) ? 0 : GTK_IS_TOGGLE_BUTTON(w))
      {
          keep_dialog = GTK_TOGGLE_BUTTON(w)->active;
      }

        /* Reset input dialog and unmap it? */
      if(!keep_dialog)
            EditorIDialogReset(editor, d, TRUE);

        return;
}

/*
 *    Create model input dialog apply callback.
 */
static void EditorModelCreateApplyCB(void *idialog, void *data)
{
        int i;
      int new_model_num = -1;
      v3d_model_struct *new_model_ptr = NULL;
      const char *new_model_name = NULL;
        GtkWidget *w;
      GtkCList *clist;
        ma_editor_struct *editor;
        ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)idialog;
        if(d == NULL)
            return;

        editor = (ma_editor_struct *)d->editor_ptr;
        if(editor == NULL)
            return;

      if(editor->processing)
          return;

        /* Begin fetching values from widgets. */
        /* Models clist. */
      w = EditorIDialogGetWidget(d, 0);
      if((w == NULL) ? 0 : GTK_IS_CLIST(w))
          clist = GTK_CLIST(w);
      else
          clist = NULL;

        /* Get selected row on clist. */
        if(clist != NULL)
        {
            GList *sel = clist->selection;

            while(sel != NULL)
            {
                new_model_num = (int)sel->data;
                sel = sel->next;
            }

          if((new_model_num >= 0) && (new_model_num < clist->rows))
            new_model_ptr = gtk_clist_get_row_data(clist, new_model_num);
        }

        /* New model name entry. */
      w = EditorIDialogGetWidget(d, 1);
      if((w == NULL) ? 0 : GTK_IS_ENTRY(w))
      {
          new_model_name = (const char *)gtk_entry_get_text(GTK_ENTRY(w));
          if(new_model_name == NULL)
            new_model_name = "(null)";
      }


        EditorSetBusy(editor);

      /* Got new model to create? */
      if(new_model_ptr != NULL)
      {
          gchar *text[1];
          v3d_model_struct *model_ptr;
          gint sel_model_num = EditorSelectedModelIndex(editor);
          GtkCList *models_clist = (GtkCList *)editor->models_list;


          /* Change new_model_name to "other" if this model is of
           * type V3D_MODEL_TYPE_OTHER_DATA.
           */
          if(new_model_ptr->type == V3D_MODEL_TYPE_OTHER_DATA)
            new_model_name = "other";  

          if(models_clist != NULL)
          {
            if((sel_model_num >= 0) && (sel_model_num < editor->total_models))
            {
                /* Unselect editor's current selected model, this will
                 * cause data to be synced when the unselect callback
                 * is called.
                 */
                gtk_clist_unselect_row(models_clist, sel_model_num, 0);

                /* Insert new model at position sel_model_num. */

                /* Allocate more pointers. */
                editor->total_models++;
                editor->model = (v3d_model_struct **)realloc(
                  editor->model,
                  editor->total_models * sizeof(v3d_model_struct *)
                );
                if(editor->model == NULL)
                {
                  editor->total_models = 0;
                  editor->selected_model_item = -1;
                }
                else
                {
                  /* Shift pointers. */
                  for(i = editor->total_models - 1;
                            i > sel_model_num;
                      i--
                  )
                      editor->model[i] = editor->model[i - 1];

                  /* Copy new reference model. */
                  editor->model[sel_model_num] = model_ptr =
                      V3DModelDup(new_model_ptr);
                  /* Do not realize primitives on newly created
                   * model, they shouldn't have any primitives that
                   * need realizing.
                   */

                  /* Newly created model valid? */
                  if(model_ptr != NULL)
                  {
                      /* Update name for new model? */
                      if(new_model_name != NULL)
                      {
                        free(model_ptr->name);
                        model_ptr->name = strdup(new_model_name);
                      }

                  }

                  /* Insert new item into gui list. */
                  if(new_model_name != NULL)
                      text[0] = strdup(new_model_name);
                  else
                      text[0] = strdup("(null)");
                  gtk_clist_insert(
                      models_clist,
                      sel_model_num,
                      text
                  );
                  free(text[0]);

                  /* Update new item on models list. */
                  EditorListModelsSet(
                      GTK_WIDGET(models_clist), sel_model_num,
                      editor->model[sel_model_num], FALSE
                  );

                  /* Select newly created model. */
                  gtk_clist_select_row(models_clist, sel_model_num, 0);

                  EDITOR_DO_UPDATE_HAS_CHANGES
                }
            }
            else
            {
                /* Append new model. */

                    /* Allocate more pointers. */
                    sel_model_num = editor->total_models;
                editor->total_models = sel_model_num + 1;
                    editor->model = (v3d_model_struct **)realloc(
                        editor->model,
                        editor->total_models * sizeof(v3d_model_struct *)
                    );
                    if(editor->model == NULL)
                    {
                        editor->total_models = 0;
                        editor->selected_model_item = -1;
                    }
                else
                {
                        /* Copy new reference model. */
                        editor->model[sel_model_num] = model_ptr =
                      V3DModelDup(new_model_ptr);
                        /* Do not realize primitives on newly created
                         * model, they shouldn't have any primitives that
                         * need realizing.
                         */

                        /* Newly created model valid? */
                        if(model_ptr != NULL)
                        {
                            /* Update name for new model? */
                            if(new_model_name != NULL)
                            {
                                free(model_ptr->name);
                                model_ptr->name = strdup(new_model_name);
                            }
                         
                        }

                        /* Append new item into gui list. */
                        if(new_model_name != NULL)
                            text[0] = strdup(new_model_name);
                        else
                            text[0] = strdup("(null)");
                        gtk_clist_append(
                            models_clist,
                            text
                        );
                        free(text[0]);

                        /* Update new item on models list. */
                        EditorListModelsSet(
                            GTK_WIDGET(models_clist), sel_model_num,
                            editor->model[sel_model_num], FALSE
                        );

                        /* Select newly created model. */
                        gtk_clist_select_row(models_clist, sel_model_num, 0);

                        EDITOR_DO_UPDATE_HAS_CHANGES
                }
            }
          }
      }
      else
      {
          /* Error, cannot get new model reference to create. */
            CDialogSetTransientFor(editor->toplevel);
            CDialogGetResponse(
"Create Model Failed!",
"Unable to create a model from NULL reference model.",
"The reference data does not exist for this model, please\n\
verify that the preset model is defined properly or try\n\
a different model.",
                CDIALOG_ICON_ERROR,
                CDIALOG_BTNFLAG_OK | CDIALOG_BTNFLAG_HELP,
                CDIALOG_BTNFLAG_OK
            );
            CDialogSetTransientFor(NULL);

      }


        /* Update menus and redraw views. */
        EditorUpdateMenus(editor);
        EditorUpdateAllViewMenus(editor);
        EditorRedrawAllViews(editor); 

        EditorSetReady(editor);

      return;
}

/*
 *      Delete selected model callback.
 */
void EditorModelDeleteCB(GtkWidget *widget, gpointer data)
{
      gint model_num;
        GtkCList *clist;
        v3d_model_struct *model_ptr;
        ma_editor_struct *editor = (ma_editor_struct *)data;
        if(editor == NULL)
            return;

        if(!editor->initialized || editor->processing)
            return;

        if(VMAWriteProtectCheck(editor))
            return;

        clist = (GtkCList *)editor->models_list;
  
        /* Check if a model is selected. */
        model_num = EditorSelectedModelIndex(editor);
        model_ptr = V3DModelListGetPtr(
            editor->model, editor->total_models, model_num
        );
        if(model_ptr != NULL)
        {
            int status, buf_len;
            char *buf, *model_name = model_ptr->name;

            buf_len = ((model_name == NULL) ?
                0 : strlen(model_name)
            ) + 256;
            buf = (char *)malloc((buf_len + 1) * sizeof(char));
            if(buf != NULL)
                sprintf(buf,
"Are you sure you want to delete the selected model named\n`%s'?",
                    model_name
                );
        
            CDialogSetTransientFor(editor->toplevel);
            status = CDialogGetResponse(
"Delete Selected Model?", 
                buf,
"You are being asked if you want to delete the selected\n\
model from the models list. This operation cannot be undone,\n\
so if you are unsure say `no'.",
                CDIALOG_ICON_WARNING,
                CDIALOG_BTNFLAG_YES | CDIALOG_BTNFLAG_NO |
                CDIALOG_BTNFLAG_HELP,
                CDIALOG_BTNFLAG_NO
            );
            CDialogSetTransientFor(NULL);

            free(buf);

            switch(status)
            {
              case CDIALOG_RESPONSE_YES:
              case CDIALOG_RESPONSE_YES_TO_ALL:
              case CDIALOG_RESPONSE_OK:
                EditorModelDelete(editor, model_num);
                EDITOR_DO_UPDATE_HAS_CHANGES
                /* Select next model which is now the row model_num. */
                if(clist != NULL)
            {
                if(model_num >= editor->total_models)
                  gtk_clist_select_row(clist,
                      MAX(editor->total_models - 1, 0),
                      0
                  );
                else
                  gtk_clist_select_row(clist, model_num, 0);
            }
                break;
            }
        }

        EditorUpdateMenus(editor);
        EditorUpdateAllViewMenus(editor);
        EditorRedrawAllViews(editor);

        return;
}


/*
 *    Model properties note book switch page callback.
 */
static void EditorModelPropertiesSwitchPageCB(
        GtkNotebook *notebook, GtkNotebookPage *page, guint page_num,
        gpointer data
)
{
        static gbool reenterant = FALSE;
      int type;
      GtkWidget *w;
      ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)data;
        if((notebook == NULL) || (d == NULL))
            return;  
  
        if(reenterant)
            return;
        else
            reenterant = TRUE;

      /* Get widget 1, the model type. */
      type = (int)EditorIDialogGetWidget(d, 1);

      /* Get widget 0, the main notebook. */
        w = EditorIDialogGetWidget(d, 0);
      if((w != NULL) && (w == GTK_WIDGET(notebook)))
      {


      }

        reenterant = FALSE;
        return;
}

/*
 *    Model properties callback.
 */
void EditorModelPropertiesCB(GtkWidget *widget, gpointer data)
{
/*    const char *msglist[] = VMA_MSGLIST_EDITOR_TOOLTIPS; */
        GtkWidget *parent;
        ma_editor_idialog_struct *d;
        ma_editor_struct *editor = (ma_editor_struct *)data;
        if(editor == NULL)
            return;

        if(!editor->initialized || editor->processing)
            return;

        d = &editor->idialog;           /* Editor's input dialog. */

        /* Reset input dialog. */
        EditorIDialogReset(editor, d, FALSE);

        /* Get input dialog's client vbox. */
        parent = EditorIDialogClientParent(d);
        if(parent != NULL)
        {
          /* Begin creating our widgets on input dialog, order;
           *
           *      0     Main note book
           *      1     Model type (unsigned int)
           *      2     General: model icon fixed
           *      3     General: model name entry
           *
           * Other widgets depend on type of model.
           */
          gint model_num;
          v3d_model_struct *model_ptr = NULL;
          u_int8_t **icon_data;
            GtkWidget *w, *parent2, *parent3, *parent4, *parent5;

          /* Get selected model on editor. */
          model_num = EditorSelectedModelIndex(editor);
          if((model_num >= 0) && (model_num < editor->total_models))
            model_ptr = editor->model[model_num];
          if(model_ptr == NULL)
            model_num = -1;

          /* Set size of parent. */
          gtk_widget_set_usize(parent, 400, 350);

          /* Main notebook. */
          w = gtk_notebook_new();
          gtk_notebook_set_tab_pos(GTK_NOTEBOOK(w), GTK_POS_TOP);
          gtk_box_pack_start(GTK_BOX(parent), w, TRUE, TRUE, 0);
          gtk_notebook_set_scrollable(GTK_NOTEBOOK(w), TRUE);
            gtk_notebook_set_show_tabs(GTK_NOTEBOOK(w), TRUE);
            gtk_notebook_set_show_border(GTK_NOTEBOOK(w), TRUE);
/*          gtk_notebook_set_page(GTK_NOTEBOOK(w), 0); */
            gtk_signal_connect(
                GTK_OBJECT(w), "switch_page",
                GTK_SIGNAL_FUNC(EditorModelPropertiesSwitchPageCB),
                (gpointer)d
            );
            gtk_widget_show(w);
          /* Record as widget 0. */
            EditorIDialogRecordWidget(d, w);
            parent2 = w;


          /* Record model type as widget 1. */
          if(model_ptr == NULL)
            EditorIDialogRecordWidget(d, (GtkWidget *)0);
          else
            EditorIDialogRecordWidget(d, (GtkWidget *)model_ptr->type);


          /* Create the `general page' regardless of model type or
           * even if there is no model selected.
           */
          w = gtk_vbox_new(FALSE, 5);
          gtk_notebook_append_page(
            GTK_NOTEBOOK(parent2), w,
            gtk_label_new("General")
          );
          gtk_container_border_width(GTK_CONTAINER(w), 5);
          gtk_widget_show(w);
          parent3 = w;

          /* Hbox to hold icon and name entry. */
          w = gtk_hbox_new(FALSE, 2);
          gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
          gtk_widget_show(w);
            parent4 = w;

          /* General: Icon. */
          if(model_ptr == NULL)
          {
            icon_data = NULL;
          }
          else
          {
            switch(model_ptr->type)
            {
              case V3D_MODEL_TYPE_STANDARD:
                icon_data = (u_int8_t **)icon_model_48x48_xpm;
                break;

              default:
                icon_data = (u_int8_t **)icon_model_other_48x48_xpm;
                break;
            }
          }
          w = (GtkWidget *)GUICreateMenuItemIcon(icon_data);
          if(w != NULL)
          {
            gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
            gtk_widget_set_usize(w, 48, 48);
            gtk_widget_show(w);
          }
          /* Record as widget 2. */
          EditorIDialogRecordWidget(d, w);

          /* General: Name entry. */
          w = gtk_entry_new();
          if((model_ptr == NULL) ? 0 : (model_ptr->name != NULL))
          {
            gtk_entry_set_text(GTK_ENTRY(w), model_ptr->name);

            /* Name cannot be changed for models of type
             * V3D_MODEL_TYPE_OTHER_DATA since they really do not
             * have names.
             */
            if(model_ptr->type == V3D_MODEL_TYPE_OTHER_DATA)
            {
                gtk_signal_connect_after(
                  GTK_OBJECT(w), "key_press_event",
                  GTK_SIGNAL_FUNC(EditorModelEditableDummyKeyCB),
                  (gpointer)d
                );
                gtk_signal_connect_after(
                  GTK_OBJECT(w), "key_release_event",
                  GTK_SIGNAL_FUNC(EditorModelEditableDummyKeyCB),
                  (gpointer)d
                );
                gtk_entry_set_editable(GTK_ENTRY(w), FALSE);
            }
          }
          gtk_box_pack_start(GTK_BOX(parent4), w, TRUE, TRUE, 0);
          /* Record as widget 3. */
            EditorIDialogRecordWidget(d, w);
            gtk_widget_show(w);

          /* General: Is model of type V3D_MODEL_TYPE_STANDARD. */
          if((model_ptr == NULL) ? 0 :
            (model_ptr->type == V3D_MODEL_TYPE_STANDARD)
          )
          {
            vma_model_stats_struct stat_buf;
            char text[256];

            /* Settings frame. */
            w = gtk_frame_new("Settings");
            gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
            gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_ETCHED_IN);
            gtk_widget_show(w);
            parent4 = w;
            w = gtk_vbox_new(FALSE, 2);
            gtk_container_add(GTK_CONTAINER(parent4), w);
            gtk_container_border_width(GTK_CONTAINER(w), 5);
            gtk_widget_show(w);
                parent4 = w;

            /* Show model in world views. */
            w = gtk_check_button_new_with_label("Show Model In World Views");
            if(model_ptr->flags & V3D_MODEL_FLAG_HIDE)
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), FALSE);
            else
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), TRUE);
            gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
                /* Record as widget 4. */
                EditorIDialogRecordWidget(d, w);
            gtk_widget_show(w);

                /* Statistics frame. */
                w = gtk_frame_new("Statistics");
                gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
                gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_ETCHED_IN);
                gtk_widget_show(w);
                parent4 = w;
                w = gtk_vbox_new(FALSE, 2);
                gtk_container_add(GTK_CONTAINER(parent4), w);
                gtk_container_border_width(GTK_CONTAINER(w), 5);
                gtk_widget_show(w);
                parent4 = w;

            VMAModelGetStats(model_ptr, &stat_buf);

                /* Size. */
                parent5 = w = gtk_hbox_new(FALSE, 0);
                gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
                gtk_widget_show(w);
                sprintf(text, "Size: %ld bytes", stat_buf.size);
                w = gtk_label_new(text);
                gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
                gtk_widget_show(w);

            /* Total primitives. */
            parent5 = w = gtk_hbox_new(FALSE, 0);
            gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
            sprintf(text, "Primitives: %i (%ld bytes)",
                stat_buf.primitives, stat_buf.size_primitives
            );
            w = gtk_label_new(text);
            gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
            gtk_widget_show(w);
          }
          /* General: Is model of type V3D_MODEL_TYPE_OTHER_DATA. */
          else if((model_ptr == NULL) ? 0 :
                    (model_ptr->type == V3D_MODEL_TYPE_OTHER_DATA)
            )
            {
            vma_model_stats_struct stat_buf;
            char text[256];

                /* Statistics frame. */
                w = gtk_frame_new("Statistics");
                gtk_box_pack_start(GTK_BOX(parent3), w, FALSE, FALSE, 0);
                gtk_frame_set_shadow_type(GTK_FRAME(w), GTK_SHADOW_ETCHED_IN);
                gtk_widget_show(w);
                parent4 = w;
                w = gtk_vbox_new(FALSE, 2);
                gtk_container_add(GTK_CONTAINER(parent4), w);
                gtk_container_border_width(GTK_CONTAINER(w), 5);
                gtk_widget_show(w);
                parent4 = w;

            VMAModelGetStats(model_ptr, &stat_buf);

                /* Size. */
                parent5 = w = gtk_hbox_new(FALSE, 0);
                gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
                gtk_widget_show(w);
                sprintf(text, "Size: %ld bytes", stat_buf.size);
                w = gtk_label_new(text);
                gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
                gtk_widget_show(w);

                /* Total lines. */
                parent5 = w = gtk_hbox_new(FALSE, 0);
                gtk_box_pack_start(GTK_BOX(parent4), w, FALSE, FALSE, 0);
                gtk_widget_show(w);
                sprintf(text, "Lines: %i (%ld bytes)", stat_buf.lines,
                stat_buf.size_lines
            );
                w = gtk_label_new(text);
                gtk_box_pack_start(GTK_BOX(parent5), w, FALSE, FALSE, 0);
                gtk_widget_show(w);

          }

          /* Create widgets on each notebook page depending on the
           * model type.
           */







        }

      EditorIDialogMap(
            editor, d,
            "Model Properties",
            "Set", "Apply", "Cancel",
            (void *)editor,
            EditorModelPropertiesOKCB,
            EditorModelPropertiesApplyCB,
            EditorModelIDialogCancelCB
        );

      return;
}

/*
 *    Model properties ok callback.
 */
static void EditorModelPropertiesOKCB(void *idialog, void *data)
{
        ma_editor_struct *editor;
        ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)idialog;
        if(d == NULL)
            return;

        editor = (ma_editor_struct *)d->editor_ptr;
        if(editor == NULL)
            return;

        EditorModelPropertiesApplyCB(idialog, data);

      EditorIDialogReset(editor, d, TRUE);

      return;
}

/*
 *    Model properties ok callback.
 */
static void EditorModelPropertiesApplyCB(void *idialog, void *data)
{
        GtkWidget *w;
      gint type, model_num;
      v3d_model_struct *model_ptr = NULL;
        ma_editor_struct *editor;
        ma_editor_idialog_struct *d = (ma_editor_idialog_struct *)idialog;
        if(d == NULL)
            return;

        editor = (ma_editor_struct *)d->editor_ptr;
        if(editor == NULL)
            return;

        if(!editor->initialized || editor->processing)
            return;

        if(VMAWriteProtectCheck(editor))
            return;

        /* Get widget 1, the model type. */
        type = (int)EditorIDialogGetWidget(d, 1);

      /* Get selected model on editor. */
      model_num = EditorSelectedModelIndex(editor);
        if((model_num >= 0) && (model_num < editor->total_models))
            model_ptr = editor->model[model_num];
        if(model_ptr == NULL)
            model_num = -1;

      /* Type must match. */
      if(model_ptr != NULL)
      {
          if(type != model_ptr->type)
          {
                CDialogSetTransientFor(editor->toplevel);
                CDialogGetResponse(
"Model Type Mismatch",
"Selected model type does not match model type\n\
of values to be applied. Try reselecting the model\n\
and edit the properties again.",
"You have tried to apply values for a model type that\n\
does not match the model type currently selected on\n\
the editor (possibly that you have selected a different\n\
model). Try reselecting the model and edit the\n\
properties again.",
                    CDIALOG_ICON_WARNING,
                    CDIALOG_BTNFLAG_OK | CDIALOG_BTNFLAG_HELP,
                    CDIALOG_BTNFLAG_OK
                );
                CDialogSetTransientFor(NULL);
            return;
          }
      }
      else
      {
          /* No model selected, give up. */
          return;
      }


      /* Begin applying values to model. */
      EditorSetBusy(editor);

      /* Selected model valid? */
      if(model_ptr != NULL)
      {
          /* Handle by model type (which matches the values on the
           * input dialog's widgets. We need to fetch and apply values
           * based on type because the type determines which widget
           * index numbers correspond to which piece of data on the
           * input dialog.
           */
          switch(model_ptr->type)
          {
            case V3D_MODEL_TYPE_STANDARD:
            /* Get widget 3, the model name entry. */
            w = EditorIDialogGetWidget(d, 3);
            if((w == NULL) ? 0 : GTK_IS_ENTRY(w))
            {
                const char *cstrptr = (const char *)gtk_entry_get_text(
                  GTK_ENTRY(w)
                );
                if(cstrptr != NULL)
                {
                  free(model_ptr->name);
                  model_ptr->name = strdup(cstrptr);
                }
            }

            /* Get widget 4, show model check. */
                w = EditorIDialogGetWidget(d, 4);
                if((w == NULL) ? 0 : GTK_IS_TOGGLE_BUTTON(w))
                {
                if(GTK_TOGGLE_BUTTON(w)->active)
                  model_ptr->flags &= ~V3D_MODEL_FLAG_HIDE;
                else
                  model_ptr->flags |= V3D_MODEL_FLAG_HIDE;
            }

            break;

            case V3D_MODEL_TYPE_OTHER_DATA:
                /* Get widget 3, the model name entry. */
                w = EditorIDialogGetWidget(d, 3);
                if((w == NULL) ? 0 : GTK_IS_ENTRY(w))
                {
                    const char *cstrptr = (const char *)gtk_entry_get_text(
                        GTK_ENTRY(w)
                    );
                    if(cstrptr != NULL)
                    {
                        free(model_ptr->name);
                        model_ptr->name = strdup(cstrptr);
                    }
                }

            break;

            default:
                CDialogSetTransientFor(editor->toplevel);
                CDialogGetResponse(
"Unsupported Model Type",
"Cannot apply values for this unsupported model type.",
"The model type you are trying to apply values for is\n\
not supported by this program.",
                    CDIALOG_ICON_WARNING,
                    CDIALOG_BTNFLAG_OK | CDIALOG_BTNFLAG_HELP,
                    CDIALOG_BTNFLAG_OK
                );
                CDialogSetTransientFor(NULL);
            break;
          }

          /* Update listing of model on editor's models list. */
          EditorListModelsSet(
            editor->models_list, model_num,
            model_ptr, TRUE
          );
          EDITOR_DO_UPDATE_HAS_CHANGES
      }

        /* Update menus and redraw views. */
        EditorUpdateMenus(editor);
        EditorUpdateAllViewMenus(editor);
        EditorRedrawAllViews(editor);

        EditorSetReady(editor);

      return;
}

Generated by  Doxygen 1.6.0   Back to index