Cinema 4D - my C++ plugins - add text

From NoskeWiki
Jump to navigation Jump to search
Add text plugin dialog

About

NOTE: This page is a daughter page of: Cinema 4D


This page contains code for a C++ plugin I've written for Cinema 4D. To understand how it compiles see Cinema 4D - my C++ plugins.

addtext.cpp - for quickly adding new 3D text

//------------------
//-- FILE:    addtext.cpp
//-- AUTHORS: Andrew Noske
//--
//-- This Cinema 4D menu plugin allows you to easily add text to the scene.
//-- The text is extruded, so that it is visible when rendered, and has several
//-- options for font and text positioning - including the option to add it
//-- directly in front of a camera.
//-- 
//-- For more information see: http://www.andrewnoske.com/wiki/index.php?title=Cinema_4D


//########################################
//-- Includes and Globals Variables:

#include "c4d.h"

#define ID_ADDTEXTDIALOGTEST 1023850
                                      // My unique registered plugin ID for "Add Text".

enum                                // Uniquely identify all your dialog elements here.
{
  DLG_EDIT_TEXT    = 1000,
  DLG_SPN_SIZE     = 1001,
  DLG_SPN_EXTRUDEZ,
  DLG_CHK_EXTRUDE,
  DLG_CHK_FACECAM,
  DLG_CHK_SELECT,
  DLG_BTN_ADD,
  DLG_CBO_ALIGN,
  DLG_RAD_PLACE,
  DLG_LBL1,
  DLG_LBL2,
  DLG_LBL3,
  DLG_LBL4,
  DLG_LBL5,
  DLG_LBL6,
  DLG_LBL7,
  DLG_GRP1,
  DLG_GRP2,
  DLG_GRP3
};


 
//########################################
//-- AddTextDialog class: (the main dialog for this plugin)

class AddTextDialog : public GeDialog
{
 public:
  AddTextDialog(void)            {}
  virtual ~AddTextDialog(void)   {}
   
  //----------
  //-- Set up your dialog elements here:
  
  virtual Bool CreateLayout(void)
  {
    this->SetTitle( "Add Text" );
    GroupBorderSpace( 5, 5, 5, 5 );
    GroupSpace(10,10);
    
    AddStaticText        (DLG_LBL1,BFH_LEFT,0,0,"text:", BORDER_NONE);
    AddMultiLineEditText (DLG_EDIT_TEXT,BFH_SCALEFIT|BFV_SCALEFIT,300,0);
    
    GroupBegin(DLG_GRP1,BFH_LEFT,2,0,"font",BFV_GRIDGROUP_EQUALROWS);
      GroupSpace(5,5);
      
      AddStaticText        (DLG_LBL2, BFH_LEFT,0,0,"size:", BORDER_NONE);
      AddEditNumberArrows  (DLG_SPN_SIZE,BFH_LEFT,50,0);
      
      AddStaticText       (DLG_LBL3,BFH_LEFT,0,0,"align:", BORDER_NONE);
      AddComboBox         (DLG_CBO_ALIGN, BFH_LEFT, 0, 0 );         // Combo box.
      AddChild            (DLG_CBO_ALIGN, PRIM_TEXT_ALIGN_LEFT,   "left" );
      AddChild            (DLG_CBO_ALIGN, PRIM_TEXT_ALIGN_MIDDLE, "middle" );
      AddChild            (DLG_CBO_ALIGN, PRIM_TEXT_ALIGN_RIGHT,  "right" );
      
      AddCheckbox         (DLG_CHK_EXTRUDE,  BFH_LEFT,0,0,    "extrude:");
      AddEditNumberArrows (DLG_SPN_EXTRUDEZ, BFH_LEFT,50,0);
      
    GroupEnd();
    
    GroupBegin( DLG_GRP2,BFH_LEFT,1,0,"place:",BFV_GRIDGROUP_EQUALROWS );
      GroupBorder(BORDER_WITH_TITLE|BORDER_THIN_IN);  
      GroupBorderSpace( 5, 5, 5, 5 );
      
      AddRadioGroup(DLG_RAD_PLACE, BFH_SCALEFIT, 1 );                   // Radio group.
      AddChild( DLG_RAD_PLACE, 0, "default (global coordinates)" );
      AddChild( DLG_RAD_PLACE, 1, "as child of selected object" );
      AddChild( DLG_RAD_PLACE, 2, "in front of \"Camera\"" );
      
    GroupEnd();
    
    AddCheckbox         (DLG_CHK_FACECAM, BFH_SCALEFIT,0,0, "always face active camera");
    AddCheckbox         (DLG_CHK_SELECT,  BFH_SCALEFIT,0,0, "select text (after adding)");
    AddButton           (DLG_BTN_ADD,     BFH_LEFT,0,0, "Add Text");
    
    return TRUE;
  }
    
  //----------
  //-- Assign dialog elements their initial values here:
  
  virtual Bool InitValues(void)
  {
    this->SetString      (DLG_EDIT_TEXT,    "Hello World");
    this->SetReal        (DLG_SPN_SIZE,     (Real)100, 1,  1000, 1 );
    this->SetReal        (DLG_SPN_EXTRUDEZ, (Real)10,   0, 1000, 1  );
    this->SetLong        (DLG_CBO_ALIGN,    PRIM_TEXT_ALIGN_MIDDLE);
    this->SetBool        (DLG_CHK_EXTRUDE,  true);
    this->SetLong        (DLG_RAD_PLACE,    0);
    this->SetBool        (DLG_CHK_FACECAM,  false);
    this->SetBool        (DLG_CHK_SELECT,   true);
    return TRUE;
  }
    
  //----------
  //-- Deal with any modification or "clicking" events here:

  virtual Bool Command(LONG id,const BaseContainer &msg)
  {
    switch (id)
    {
      case (DLG_BTN_ADD):
      {
        BaseDocument *doc = GetActiveDocument();
        
        //## GET USER ENTERED DATA:
            
        String text;      this->GetString (DLG_EDIT_TEXT,    text);
        Real   size;      this->GetReal   (DLG_SPN_SIZE,     size);
        Real   align;     this->GetReal   (DLG_CBO_ALIGN,    align);
        Bool   extrude;   this->GetBool   (DLG_CHK_EXTRUDE,  extrude);
        Real   extrudeZ;  this->GetReal   (DLG_SPN_EXTRUDEZ, extrudeZ);
        Real   place;     this->GetReal   (DLG_RAD_PLACE,    place);
        Bool   faceCam;   this->GetBool   (DLG_CHK_FACECAM,  faceCam);
        Bool   select;    this->GetBool   (DLG_CHK_SELECT,   select);
        
        if( !extrude )
          extrudeZ = 0;
        
        //## DETERMINE WHICH OBJECT WILL BE THE PARENT (WHEN ADDING OUR OBJECT)
        
        BaseObject *objParent = NULL;              // Will be the parent of our extruded text.
                
        if(place == 1)          // "as a child of current object"
        {
          objParent = doc->GetActiveObject();
          if(!objParent)
          {
            MessageDialog( "You have not selected a valid object" );
            return false;
          }
        }
        else if(place == 2)     // "in front of 'Camera'"
        {
          objParent = doc->SearchObject("Camera");
          if(!objParent)
          {
            MessageDialog( "Could not find an object called 'Camera'" );
            return false;
          }
          
          //## FIND OR ADD NULL OBJECT CALLED "FG":
          
          BaseObject *objFG = NULL;
          for( BaseObject *obj = objParent->GetDown(); (obj); obj = obj->GetNext() )
            if( obj->GetName() == "FG" )
              objFG = obj;
          
          if( !objFG )
          {
            MessageDialog( "Text will be added to a container called 'FG' \n"
                           "under 'Camera'. \n"
                           "\n"
                           "NOTE: \n"
                           " > It is advised you set the camera's near clipping \n"
                           "    to '0.999' to avoid objects penetrating the text. \n"
                           " > You may need to change the scale or position of \n"
                           "   'FG' if you change the camera's field of view." );
            
            objFG = BaseObject::Alloc( Onull );
            objFG->SetParameter( DescID(ID_BASEOBJECT_REL_POSITION, VECTOR_Z), GeData( (float)1.0f ), DESCFLAGS_SET_0 );
            objFG->SetParameter( ID_BASEOBJECT_REL_SCALE, GeData( Vector(0.001f,0.001f,0.001f) ), DESCFLAGS_SET_0 );
            objFG->SetName("FG");
            doc->InsertObject( objFG, objParent, NULL );
            doc->AddUndo( UNDOTYPE_NEW, objFG );
          }
          
          if(select)
          {
            objParent->ChangeNBit( NBIT_OM1_FOLD, NBITCONTROL_SET );
            objFG->ChangeNBit( NBIT_OM1_FOLD, NBITCONTROL_SET );
          }
          
          objParent = objFG;
        }
        
        
        doc->StartUndo();
        
        //## CREATE AND ADD NEW EXTRUDE NURBS OBJECT:
        
        BaseObject *objExtr = BaseObject::Alloc( Oextrude );
        objExtr->SetParameter( EXTRUDEOBJECT_MOVE, GeData( Vector(0.0f,0.0f,(float)extrudeZ) ), DESCFLAGS_SET_0);
        objExtr->SetName( text );
        doc->InsertObject( objExtr, objParent, NULL );
        doc->AddUndo( UNDOTYPE_NEW, objExtr );
        
        if( faceCam )
        {
          BaseTag *tag = BaseTag::Alloc( Tlookatcamera );
          tag->SetParameter(LOOKATCAMERA_PITCH, GeData(0), DESCFLAGS_SET_0);
          objExtr->InsertTag(tag, NULL);
          doc->AddUndo( UNDOTYPE_NEW, tag );
        }
        
        
        //## CREATE NEW TEXT SPLINE OBJECT AND ADD UNDER EXTRUDE:
            
        BaseObject *objText = BaseObject::Alloc( Osplinetext );
        objText->SetParameter(PRIM_TEXT_TEXT,   GeData(text), DESCFLAGS_SET_0);
        objText->SetParameter(PRIM_TEXT_HEIGHT, GeData(size), DESCFLAGS_SET_0);
        objText->SetParameter(PRIM_TEXT_ALIGN,  GeData(align), DESCFLAGS_SET_0);
        if( faceCam )
          objText->SetParameter( DescID(ID_BASEOBJECT_REL_ROTATION, VECTOR_X), GeData( (float)0.01745329f*180.0f ), DESCFLAGS_SET_0 );
        objText->SetName( text );
        doc->InsertObject( objText, objExtr, NULL );
        
        if( select )
        {
          doc->SetActiveObject( objText );
          objExtr->ChangeNBit( NBIT_OM1_FOLD, NBITCONTROL_SET );
          EventAdd();
        }
        
        doc->AddUndo( UNDOTYPE_NEW, objText );
        
        //## PRINT OUT VALUES AND REFRESH:
        
        StatusSetText("Text added");
        GePrint("Text size:" + RealToString(size) );
            
        doc->EndUndo();
        DrawViews( DRAWFLAGS_NO_THREAD );
      }
      break;
    }
    return TRUE;
  }
};

//########################################

class AddTextDialogTest : public CommandData
{
 private:
  AddTextDialog dlg;

 public:
  virtual Bool Execute(BaseDocument *doc)
  {
    return dlg.Open(DLG_TYPE_ASYNC, ID_ADDTEXTDIALOGTEST,-1,-1);        // Opens the dialog window.
  }
};

//########################################

Bool RegisterAddTextDialog(void)
{
  return RegisterCommandPlugin(ID_ADDTEXTDIALOGTEST, "Add Text",
                               0,NULL,String("Add Text"),gNew AddTextDialogTest );
}


See Also

Code license
For all of the code on my site... if there are specific instruction or licence comments please leave them in. If you copy my code with minimum modifications to another webpage, or into any code other people will see I would love an acknowledgment to my site.... otherwise, the license for this code is more-or-less WTFPL (do what you want)! If only copying <20 lines, then don't bother. That said - if you'd like to add a web-link to my site www.andrewnoske.com or (better yet) the specific page with code, that's a really sweet gestures! Links to the page may be useful to yourself or your users and helps increase traffic to my site. Hope my code is useful! :)