Logo Search packages:      
Sourcecode: vertex version File versions

clrselcb.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>

#include <GL/gl.h>
#include <GL/glu.h>

#include <gtk/gtk.h>
#include <gtkgl/gtkglarea.h>

#include "guiutils.h"
#include "cdialog.h"
#include "csd.h"

#include "v3dmp.h"

#include "editor.h"
#include "editorlist.h"
#include "editorviewcb.h"

#include "clrsel.h"
#include "clrselcb.h"

#include "vmacfg.h"
#include "vmacfglist.h"
#include "vma.h"
#include "vmautils.h"

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


void ClrSelQuadricErrorCB(GLenum error_code);
void ClrSelDestroyCB(GtkObject *object, gpointer data);
gint ClrSelCloseCB(
        GtkWidget *widget, GdkEvent *event, gpointer data
);
gint ClrSelViewEventCB(GtkWidget *widget, gpointer event, gpointer data);
void ClrSelSelectColorCB(GtkWidget *widget, gpointer data);
void ClrSelScaleCB(GtkWidget *widget, gpointer data);
void ClrSelEntryCB(GtkWidget *widget, gpointer data);
void ClrSelUpdatePreviewCheckCB(GtkWidget *widget, gpointer data);
void ClrSelPrevQObjCB(GtkWidget *widget, gpointer data);
void ClrSelNextQObjCB(GtkWidget *widget, gpointer data);
void ClrSelSetCB(GtkWidget *widget, gpointer data);
void ClrSelApplyCB(GtkWidget *widget, gpointer data);
void ClrSelCloseBtnCB(GtkWidget *widget, gpointer 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)))

#ifndef GDK_BUTTON1
# define GDK_BUTTON1    1
#endif

#define DEGTORAD(d)     ((d) * (PI) / 180.0)


/*
 *    GL quadric object error code callback.
 */
void ClrSelQuadricErrorCB(GLenum error_code)
{
      const GLubyte *cstrptr = gluErrorString(error_code);
      if(cstrptr == NULL)
          fprintf(stderr, "gluQuadric error: Unknown.\n");
      else
          fprintf(stderr, "gluQuadric error: %s.\n", cstrptr);

      return;
}


/*
 *    Destroy callback.
 */
void ClrSelDestroyCB(GtkObject *object, gpointer data)
{
      return;
}

/*
 *    Close window callback.
 */
gint ClrSelCloseCB(
        GtkWidget *widget, GdkEvent *event, gpointer data
)
{
      ClrSelCloseBtnCB(widget, data);
      return(TRUE);
}


/*
 *    Select color button callback.
 */
void ClrSelSelectColorCB(GtkWidget *widget, gpointer data)
{
      static gbool reenterant = FALSE;
      gbool status;
      GtkWidget *w;
      GtkAdjustment *adj;
      csd_color_struct start_color, *color_rtn;
      vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
      if(cs == NULL)
            return;

      if(!cs->initialized)
          return;

      if(reenterant)
          return;
      else
          reenterant = TRUE;

      /* Get starting color. */
      w = cs->red_scale;
      if(w != NULL)
      {
          adj = gtk_range_get_adjustment(GTK_RANGE(w));
          if(adj != NULL)
            start_color.r = (gdouble)adj->value;
      }

        w = cs->green_scale;
        if(w != NULL)
        {
            adj = gtk_range_get_adjustment(GTK_RANGE(w));
            if(adj != NULL)
                start_color.g = (gdouble)adj->value;
        }

        w = cs->blue_scale;
        if(w != NULL)
        {
            adj = gtk_range_get_adjustment(GTK_RANGE(w));
            if(adj != NULL)
                start_color.b = (gdouble)adj->value;
        }

        w = cs->alpha_scale;
        if(w != NULL)
        {
            adj = gtk_range_get_adjustment(GTK_RANGE(w));
            if(adj != NULL)
                start_color.a = (gdouble)adj->value;
        }

      /* Get user response to select new color. */
      CSDSetTransientFor(cs->toplevel);
      status = CSDGetResponse(
            "Select Color",
            "Select", "Cancel",
            &start_color, &color_rtn,
            NULL, NULL
        );
      CSDSetTransientFor(NULL);

      /* User cancled? */
      if(!status)
      {
          reenterant = FALSE;
          return;
      }

      /* Got color return? */
      if(color_rtn == NULL)
      {
          reenterant = FALSE;
          return;
      }

      /* Set new color. */
        w = cs->red_scale;
        if(w != NULL)
        {
            adj = gtk_range_get_adjustment(GTK_RANGE(w));
            if(adj != NULL)
          {
                adj->value = (gfloat)color_rtn->r;
            gtk_adjustment_value_changed(adj);
          }
        }
        w = cs->green_scale;
        if(w != NULL)
        {
            adj = gtk_range_get_adjustment(GTK_RANGE(w));
            if(adj != NULL)
            {   
                adj->value = (gfloat)color_rtn->g;
                gtk_adjustment_value_changed(adj);
            }
        }
        w = cs->blue_scale;
        if(w != NULL)
        {
            adj = gtk_range_get_adjustment(GTK_RANGE(w));
            if(adj != NULL)
            {   
                adj->value = (gfloat)color_rtn->b;
                gtk_adjustment_value_changed(adj);
            }
        }
        w = cs->alpha_scale;
        if(w != NULL)
        {
            adj = gtk_range_get_adjustment(GTK_RANGE(w));
            if(adj != NULL)
            {
                adj->value = (gfloat)color_rtn->a; 
                gtk_adjustment_value_changed(adj);
            }
        }

      reenterant = FALSE;
      return;
}

/*
 *    View glarea widget event callback.
 */
gint ClrSelViewEventCB(GtkWidget *widget, gpointer event, gpointer data)
{
      static gbool button1_state = FALSE;
      static gbool last_x, last_y;
      gint etype;
      double val_d;
      gbool status = FALSE;
      GdkModifierType mask;
      gint x, y;
      GtkWidget *w;
      GdkEventButton *button;
        GdkEventMotion *motion;
        GdkEventConfigure *configure;
        vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
        if(cs == NULL)
            return(status);

        /* Get pointer view glarea widget. */
        w = cs->view;
        if(w != widget)
            return(status);

        /* Handle by event type. */
        etype = (*(gint *)event);
        switch(etype)
        {
          case GDK_EXPOSE:
            ClrSelDrawView(cs);
            status = TRUE;
            break;

          case GDK_CONFIGURE:
            configure = (GdkEventConfigure *)event; 
            if(!cs->realized)
                cs->realized = TRUE;

            cs->view_width = configure->width;
          cs->view_height = configure->height;

            if(!ClrSelViewEnableContext(cs))
                glViewport(
                    0, 0,
                    configure->width, configure->height
                );

          status = TRUE;
          break;

          case GDK_BUTTON_PRESS:
            button = (GdkEventButton *)event;
            switch(button->button)
            {
              case GDK_BUTTON1:
                button1_state = TRUE;
            last_x = button->x;
            last_y = button->y;
                break;
          }
            /* Grab pointer so it confines to view. */   
            if(!GTK_WIDGET_NO_WINDOW(w))
                gdk_pointer_grab(
                    w->window,
                    TRUE,
                    GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
                    w->window,
                    GDK_NONE,
                    GDK_CURRENT_TIME
                );
          status = TRUE;
          break;

          case GDK_BUTTON_RELEASE:   
            button = (GdkEventButton *)event;
            switch(button->button)
            {
              case GDK_BUTTON1:
            button1_state = FALSE;
            /* Record last light orbital position. */
            val_d = cs->light_origin;
                VMACFGItemListMatchSetValue(
                    option, VMA_CFG_PARM_CLRSEL_LIGHT_ORBIT_POSITION,
                    (void *)&val_d, FALSE
                );
                break;
          }
            /* Ungrab pointer. */
            gdk_pointer_ungrab(GDK_CURRENT_TIME);
            status = TRUE;
          break;

          case GDK_MOTION_NOTIFY:
            motion = (GdkEventMotion *)event;
            if(motion->is_hint)
            {
                if(button1_state)
                    gdk_window_get_pointer(
                        motion->window, &x, &y, &mask
                    );
            }
          else
          {
                x = motion->x;
                y = motion->y;
                mask = motion->state;
          }
          if(button1_state)
          {
            /* Rotate light origin by 2 degrees per 1 pixel. */
            gint dx = x - last_x;

            cs->light_origin -= DEGTORAD(dx * 2);
            while(cs->light_origin >= (2.0 * PI))
                cs->light_origin -= (2.0 * PI);
            while(cs->light_origin < (0.0 * PI))
                    cs->light_origin += (2.0 * PI);

            ClrSelDrawView(cs);
          }

          /* Record last position. */
          last_x = x;
          last_y = y;
            status = TRUE;
            break;
      }

      return(status);
}

/*
 *    Scale callback, called whenever a scale's adjustment changes in
 *    value. Note that the input widget is actually the scale's
 *    GtkAdjustment.
 */
void ClrSelScaleCB(GtkWidget *widget, gpointer data)
{
      static gbool reenterant = FALSE;
      gbool update_preview;
      double val_d;
      GtkWidget *w, *scale, *entry;
      vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
      GtkAdjustment *adj = (GtkAdjustment *)widget;
      if((adj == NULL) || (cs == NULL))
          return;

      if(!cs->initialized)
          return;

      if(reenterant)
          return;
      else
          reenterant = TRUE;

      w = cs->update_view_check;
      update_preview = ((w == NULL) ?
          TRUE : GTK_TOGGLE_BUTTON(w)->active
      );

      /* Check which scale the adj belongs to and update that
       * scale's associated entry.
       */

#define DO_SET_ENTRY    \
{ \
 if(entry != NULL) \
 { \
  const gchar *cstrptr = gtk_entry_get_text(GTK_ENTRY(entry)); \
  if(cstrptr != NULL) \
  { \
   gfloat cur_value = atof(cstrptr); \
 \
   /* Compare up to 2 digits of coeff. */ \
   if((gint)(cur_value * 100) != (gint)(adj->value * 100)) \
   { \
    gchar num_str[80]; \
    sprintf(num_str, "%.2f", adj->value); \
    gtk_entry_set_text(GTK_ENTRY(entry), num_str); \
   } \
  } \
 } \
}
        scale = cs->light_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
            val_d = adj->value;
                VMACFGItemListMatchSetValue(
                    option, VMA_CFG_PARM_CLRSEL_LIGHT_BRIGHTNESS,
                    (void *)&val_d, FALSE
                );

                entry = cs->light_entry;
                DO_SET_ENTRY
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }

      scale = cs->red_scale;
      if(scale != NULL)
      {
          if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
          {
            entry = cs->red_entry;
            DO_SET_ENTRY
                ClrSelDrawColorDA(cs);
            if(update_preview)
                ClrSelDrawView(cs);
          }
      }
        scale = cs->green_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
            entry = cs->green_entry;
            DO_SET_ENTRY
                ClrSelDrawColorDA(cs);
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }
        scale = cs->blue_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
            entry = cs->blue_entry;
            DO_SET_ENTRY
                ClrSelDrawColorDA(cs);
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }
        scale = cs->alpha_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
            entry = cs->alpha_entry;
            DO_SET_ENTRY
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }

        scale = cs->ambient_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
                entry = cs->ambient_entry;
                DO_SET_ENTRY
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }
        scale = cs->diffuse_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
                entry = cs->diffuse_entry;
                DO_SET_ENTRY
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }
        scale = cs->specular_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
                entry = cs->specular_entry;
                DO_SET_ENTRY
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }
        scale = cs->shininess_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
                entry = cs->shininess_entry;
                DO_SET_ENTRY
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }
        scale = cs->emission_scale;
        if(scale != NULL)
        {
            if(adj == gtk_range_get_adjustment(GTK_RANGE(scale)))
            {
                entry = cs->emission_entry;
                DO_SET_ENTRY
            if(update_preview)
                ClrSelDrawView(cs);
            }
        }

#undef DO_SET_ENTRY

      reenterant = FALSE;
      return;
}

/*
 *    Entry callback, called whenever text in a entry is modified.
 */
void ClrSelEntryCB(GtkWidget *widget, gpointer data)
{
        static gbool reenterant = FALSE;
      const gchar *cstrptr;
        GtkWidget *w, *scale;
      GtkAdjustment *adj;
        vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
        if((widget == NULL) || (cs == NULL))
            return;

        if(!cs->initialized)
            return;

        if(reenterant)
            return;
        else 
            reenterant = TRUE;

      /* Check which entry it is, when we match an entry we will
       * update its associated scale's adjustments.
       */
#define DO_CHECK_AND_UPDATE   \
{ \
 if((w == widget) && (scale != NULL)) \
 { \
  adj = gtk_range_get_adjustment(GTK_RANGE(scale)); \
  if(adj != NULL) \
  { \
   cstrptr = (const gchar *)gtk_entry_get_text(GTK_ENTRY(w)); \
   if(cstrptr != NULL) \
   { \
    adj->value = (gfloat)CLIP(atof(cstrptr), adj->lower, adj->upper); \
    gtk_adjustment_value_changed(adj); \
   } \
  } \
 } \
}
        w = cs->light_entry;
        scale = cs->light_scale;
        DO_CHECK_AND_UPDATE


      w = cs->red_entry;
      scale = cs->red_scale;
      DO_CHECK_AND_UPDATE

        w = cs->green_entry;
        scale = cs->green_scale;
        DO_CHECK_AND_UPDATE

        w = cs->blue_entry;
        scale = cs->blue_scale;
        DO_CHECK_AND_UPDATE

        w = cs->alpha_entry;
        scale = cs->alpha_scale;
        DO_CHECK_AND_UPDATE


        w = cs->ambient_entry;
        scale = cs->ambient_scale;
        DO_CHECK_AND_UPDATE

        w = cs->diffuse_entry;
        scale = cs->diffuse_scale;
        DO_CHECK_AND_UPDATE

        w = cs->specular_entry;
        scale = cs->specular_scale;
        DO_CHECK_AND_UPDATE

        w = cs->shininess_entry;
        scale = cs->shininess_scale;
        DO_CHECK_AND_UPDATE

        w = cs->emission_entry;
        scale = cs->emission_scale;
        DO_CHECK_AND_UPDATE

#undef DO_CHECK_AND_UPDATE

      reenterant = FALSE;
      return;
}

/*
 *    Update preview check callback.
 */
void ClrSelUpdatePreviewCheckCB(GtkWidget *widget, gpointer data)
{
      if(widget != NULL)
      {
          u_int8_t val_u8 = GTK_TOGGLE_BUTTON(widget)->active;

          VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_CLRSEL_UPDATE_PREVIEW,
            (void *)&val_u8, FALSE
          );
      }

      return;
}


/*
 *    Previous quadrics object type button callback.
 */
void ClrSelPrevQObjCB(GtkWidget *widget, gpointer data)
{
      u_int32_t val_u32;
        vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
        if(cs == NULL)
            return;

        if(!cs->initialized)
            return;

      cs->qobj_type--;
      if(cs->qobj_type < 0)
          cs->qobj_type = 3;

      val_u32 = cs->qobj_type;
      VMACFGItemListMatchSetValue(
          option, VMA_CFG_PARM_CLRSEL_PREVIEW_QOBJ_TYPE,
          (void *)&val_u32, FALSE
      );

      ClrSelUpdateMenus(cs);
      ClrSelDrawView(cs);

      return;
}

/*
 *    Next quadrics object type button callback.
 */
void ClrSelNextQObjCB(GtkWidget *widget, gpointer data)
{
        u_int32_t val_u32;
        vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
        if(cs == NULL)
            return;

        if(!cs->initialized)
            return;

        cs->qobj_type++;
        if(cs->qobj_type > 3)
            cs->qobj_type = 0;

        val_u32 = cs->qobj_type;
        VMACFGItemListMatchSetValue(
            option, VMA_CFG_PARM_CLRSEL_PREVIEW_QOBJ_TYPE,
            (void *)&val_u32, FALSE
        );            

        ClrSelUpdateMenus(cs);
        ClrSelDrawView(cs);

      return;
}


/*
 *    Set button callback.
 */
void ClrSelSetCB(GtkWidget *widget, gpointer data)
{
        vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
        if(cs == NULL)
            return;

      if(!cs->initialized)
            return;

      ClrSelApplyCB(widget, data);

        ClrSelUnmap(cs);

      return;
}

/*
 *    Apply button callback.
 */
void ClrSelApplyCB(GtkWidget *widget, gpointer data)
{
      GtkWidget *w;
      GtkAdjustment *adj;
      int i, model_num, pn;
      v3d_model_struct *model_ptr;
      void *p;
      mp_color_struct *mp_color;
      ma_editor_struct *editor;
        vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
        if(cs == NULL)
            return;

        if(!cs->initialized)
            return;

      /* Get pointer to editor. */
      editor = (ma_editor_struct *)cs->editor_ptr;
      if(editor == NULL)
          return;

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

      if(VMAWriteProtectCheck(editor))
          return;

#define DO_NO_PRIM_SELECTED   \
{ \
 CDialogSetTransientFor(editor->toplevel); \
 CDialogGetResponse( \
"Cannot Apply Color!", \
"No color primitive selected to apply these color values to.\n", \
"You need to select a primitive of type color to apply these\n\
color values to.", \
  CDIALOG_ICON_ERROR, \
  CDIALOG_BTNFLAG_OK | CDIALOG_BTNFLAG_HELP, \
  CDIALOG_BTNFLAG_OK \
 ); \
 CDialogSetTransientFor(NULL); \
}

      /* Get selected model on editor. */
      model_num = EditorSelectedModelIndex(editor);
      model_ptr = V3DModelListGetPtr(
          editor->model, editor->total_models, model_num
      );
      if(model_ptr == NULL)
      {
          DO_NO_PRIM_SELECTED
          return;
      }

      /* Itterate through each selected primitive on editor. */
      for(i = 0; i < editor->total_selected_primitives; i++)
      {
          pn = editor->selected_primitive[i];
          p = V3DMPListGetPtr(
            model_ptr->primitive, model_ptr->total_primitives, pn
          );
          if(p == NULL)
            continue;

          /* Primitive must be of type V3DMP_TYPE_COLOR. */
          if((*(int *)p) != V3DMP_TYPE_COLOR)
          {
            CDialogSetTransientFor(editor->toplevel);
            CDialogGetResponse(
"Invalid Primitive Type!",
"Cannot apply color values to a primitive that is\n\
not a color primitive.",
"One or more selected primitives is not of type color,\n\
therefore color values cannot be applied to them.",
                CDIALOG_ICON_ERROR,
                CDIALOG_BTNFLAG_OK | CDIALOG_BTNFLAG_HELP,
                CDIALOG_BTNFLAG_OK
            );
            CDialogSetTransientFor(NULL);
            continue;
          }
          else
          {
            mp_color = (mp_color_struct *)p;
          }

          /* Begin setting new values on the color primitive. */

          w = cs->red_scale;
          if(w != NULL)
          {
              adj = gtk_range_get_adjustment(GTK_RANGE(w));
              mp_color->r = (double)CLIP(adj->value, 0.0, 1.0);
          }
            w = cs->green_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->g = (double)CLIP(adj->value, 0.0, 1.0);
            }
            w = cs->blue_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->b = (double)CLIP(adj->value, 0.0, 1.0);
            }
            w = cs->alpha_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->a = (double)CLIP(adj->value, 0.0, 1.0);
            }
            w = cs->ambient_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->ambient = (double)CLIP(adj->value, 0.0, 1.0);
            }
            w = cs->diffuse_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->diffuse = (double)CLIP(adj->value, 0.0, 1.0);
            }
            w = cs->specular_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->specular = (double)CLIP(adj->value, 0.0, 1.0);
            }
            w = cs->shininess_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->shininess = (double)CLIP(adj->value, 0.0, 1.0);
            }
            w = cs->emission_scale;
            if(w != NULL)
            {
                adj = gtk_range_get_adjustment(GTK_RANGE(w));
                mp_color->emission = (double)CLIP(adj->value, 0.0, 1.0);
            }

          /* Update has changes marker on editor. */
          if(!editor->has_changes)
            editor->has_changes = TRUE;

          /* Update editor's values list. */
          if(editor->total_selected_primitives == 1)
          {
            EditorListDeleteValuesG(editor);
            EditorListAddValuesRG(editor, p);
          }

          /* Update row on editor's primitives list. */
          EditorListPrimitivesSetColor(
            editor->primitives_list, pn, p, TRUE
          );
      }

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

#undef DO_NO_PRIM_SELECTED

        return;
}

/*
 *    Close button callback.
 */
void ClrSelCloseBtnCB(GtkWidget *widget, gpointer data)
{
        vma_clrsel_struct *cs = (vma_clrsel_struct *)data;
        if(cs == NULL)
            return;

        if(!cs->initialized)
            return;

      ClrSelUnmap(cs);

        return;
}

Generated by  Doxygen 1.6.0   Back to index