VrayProxy Creator (Coffee-Plugin)

Aus CINEMA 4D Wiki

Wechseln zu: Navigation, Suche

In diesem Artikel wird das Coffee-Plugin "VrayProxy Creator" vorgestellt, und samt Quellcode dokumentiert.

Wenn man in VrayForC4D 1.1 VrayProxies erstellen möchte, ist das manchmal schon ganz schön viel Arbeit; besonders wenn das Original-Modell aus mehreren Unterobjekten besteht. Dieses Plugin erleichtert die Arbeit enorm und reduziert den Aufwand quasi auf einen Mausklick.


Inhaltsverzeichnis


Dateien

Quellcode

Hier ist nun der Quellcode des Plugins. Die Datei sollte als "CreateVrayProxy.cof" gespeichert werden.



///////////////////////////////////
//
// VrayProxy Creator
// -----------------
//
// OpenSource
// 2009 by www.c4d-jack.de
//
///////////////////////////////////


////////////////
// Std Strings
const var PLUGIN_NAME             = "VrayProxy Creator";
const var PLUGIN_VERSION          = "1.02";
const var PLUGIN_COPYRIGHT        = "2009 by www.c4d-jack.de, OpenSource without warranty";
const var PLUGIN_HELP             = "Creates a VrayProxy from the selected object";
const var PLUGIN_ICON             = "CreateVrayProxy.tif";
const var TXT_MAINTAIN_HIERARCHY  = "Maintain hierarchy structure?";
const var TXT_SUFFIX_PROXY        = "_Proxy";

///////////////
// Plugin IDs
const var PLUGIN_ID           = 1024004;    // Registered on www.PluginCafé.com
const var VRAY_EXPORTERTAG_ID = 1023051;    // Retrieved from BaseTag::GetType()
const var VRAY_PROXYOBJECT_ID = 1021309;    // Retrieved from BaseObject::GetType()
const var VRAY_PROXYOBJECT_LINK_ID = 1500;    // ID of Proxy Tag link field


//////////////////////
// Class declaration

class VrayProxyCreator : MenuPlugin
{
  public:
    VrayProxyCreator();

    GetID();
    GetName();
    GetHelp();
  
    GetIcon();
    GetState();

    Execute(doc);
}


//////////////
// Functions
Create_a_proxy(op, doc, parent, previous)
// Creates a VrayProxy of an object (just a single one!)
{
  // 1. Create MeshExporter Tag
  var ExpTag = AllocTag(VRAY_EXPORTERTAG_ID);     // Create Vray MeshExporter Tag
  doc->AddUndo(UNDO_TAG_NEW, ExpTag);             // Add Undo
  op->InsertTag(ExpTag);                          // Attach tag to original object
  
  // 2. Create VrayProxy object
  var PrxObj = AllocObject(VRAY_PROXYOBJECT_ID);  // Create VrayProxy object
  PrxObj#VRAY_PROXYOBJECT_LINK_ID = ExpTag;       // Link tag into object
  PrxObj->SetName(op->GetName());                 // Set name
  doc->AddUndo(UNDO_OBJECT_NEW, PrxObj);          // Add Undo
  doc->InsertObject(PrxObj, parent, previous);    // Insert proxy object into document
  PrxObj->SetMg(op->GetMg());                     // Apply original object's global maxtrix
  PrxObj->Message(MSG_UPDATE);                    // Update Proxy object
  
  // 3. Copy all Texture Tags from Original object to VrayProxy
  var TexTag = op->GetFirstTag();
  var LastTag = NULL;
  
  // Iterate tags
  while (TexTag) {
    // If a Texture Tag is found
    if (TexTag->GetType() == Ttexture) {
      // Create new tag
      var NewTexTag = AllocTag(Ttexture);
      
      // Get all settings and links from found Texture tag
      NewTexTag#TEXTURETAG_MATERIAL = TexTag#TEXTURETAG_MATERIAL;
      NewTexTag#TEXTURETAG_RESTRICTION = TexTag#TEXTURETAG_RESTRICTION;
      NewTexTag->SetContainer(TexTag->GetContainer());
      
      // Attach new tag to VrayProxy object
      doc->AddUndo(UNDO_TAG_NEW, NewTexTag);    // Add Undo
      PrxObj->InsertTag(NewTexTag, LastTag);    // Attach tag to Proxy object
      PrxObj->Message(MSG_UPDATE);              // Update Proxy object
      LastTag = NewTexTag;                      // Remember created tag (to maintain original tag order)
    }
    
    // Continue iteration with next Tag
    TexTag = TexTag->GetNext();
  }
 
  return PrxObj;    // Return created proxy object
}

IterateHierarchy(startobj, parent, doc, FlatHierarchy, FirstLevel)
// Iterates the hierarchy, starting with first child of "op"
// and creates VrayProxy objects for each object
{
  var op = startobj;
  var previous = NULL;
  
  while (op) {
    previous = Create_a_proxy(op, doc, parent, previous);     // Create Proxy object
    
    if (FlatHierarchy)
      IterateHierarchy(op->GetDown(), parent, doc, FlatHierarchy, FALSE);    // Iterate op's child hierarchy
    else
      IterateHierarchy(op->GetDown(), previous, doc, FlatHierarchy, FALSE);  // Iterate op's child hierarchy
  
    // Continue iteration
    if (!FirstLevel) op = op->GetNext();  // FirstLevel Check to prevent iterating the whole scene!
    else return;
  }
}


//////////////////
// Class members

VrayProxyCreator::Execute(doc)
{
  // Called when the menu item is chosen
  var op = doc->GetActiveObject();
  
  println("Starting " + PLUGIN_NAME + "...");
  
  if (op) {
    // Start Undo session
    doc->StartUndo();
    
    // Here we go...
    if (TextDialog(TXT_MAINTAIN_HIERARCHY, DLG_YESNO) == DLG_R_YES) {
      // Create proxy objects and reproduce original hierarchy structure
      StopAllThreads();      
      IterateHierarchy(op, NULL, doc, FALSE, TRUE);
    }
    else {
      // Create proxy objects in a flat hierarchy structure
      StopAllThreads();
      var ParentObj = AllocObject(Onull);
      ParentObj->SetName(op->GetName() + TXT_SUFFIX_PROXY);
      doc->AddUndo(UNDO_OBJECT_NEW, ParentObj);
      doc->InsertObject(ParentObj, NULL, NULL);
      ParentObj->SetMg(op->GetMg());
      ParentObj->Message(MSG_UPDATE);
      
      IterateHierarchy(op, ParentObj, doc, TRUE, TRUE);
    }
    
    // Hide original object
    doc->AddUndo(UNDO_OBJECT, op);
    op#ID_BASEOBJECT_VISIBILITY_EDITOR = 1;
    op#ID_BASEOBJECT_VISIBILITY_RENDER = 1;
    
    // Finalize Undo session
    doc->EndUndo();
    
    // Hack to draw proxies in editor (no idea why this is necessary)
    doc->DoUndo();
    doc->DoRedo();
    
    // Update scene
    EventAdd(EVENT_FORCEREDRAW);
  }
  
  println("...finished");
}

VrayProxyCreator::VrayProxyCreator() 
{
  // Constructor
  super(); 
}

VrayProxyCreator::GetID() 
{ 
  // Get plugin ID
  return PLUGIN_ID;
}


VrayProxyCreator::GetName()
{
  // Get plugin name
  return PLUGIN_NAME;
}

VrayProxyCreator::GetHelp()
{ 
  // Get help string
  return PLUGIN_HELP;
}

VrayProxyCreator::GetIcon()
{ 
  // Get icon for menu item
  var fn = GeGetRootFilename(); 
  fn->RemoveLast();             
  fn->AddLast(PLUGIN_ICON);  
  var bm = new(BaseBitmap, 1, 1);
  bm->Load(fn); 
  return bm;
}

VrayProxyCreator::GetState()
{ 
  // Enable or disable menu item
  var doc = GetActiveDocument();
  if (doc->GetActiveObject())
    return CMD_ENABLED;
  else
    return 0;
}


/////////
// Main

main()
{
  println("----------------------------------");
  println(PLUGIN_NAME + " " + PLUGIN_VERSION);
  println(PLUGIN_COPYRIGHT);
  println("----------------------------------");
  Register(VrayProxyCreator);
}
 


PLUGIN_ID

const var PLUGIN_ID = 1024004;

Jedes Plugin in CINEMA 4D (egal, ob in C++ oder in Coffee geschrieben) muss eine einzigartige ID haben. Die ID, die im Quellcode von "VrayProxy Creator" eingetragen ist, ist bei www.plugincafe.comfür dieses Plugin registriert, und sollte nicht geändert werden.

Eine Ausnahme wäre, wenn das Plugin zu einer gänzlich neuen Version weiterentwickelt wird, die es als eigenständiges Produkt kennzeichnet. In diesem Fall müsste eine neue Plugin-ID registriert werden.


VRAY_..._ID

const var VRAY_EXPORTERTAG_ID = 1023051;    // Retrieved from BaseTag::GetType()
const var VRAY_PROXYOBJECT_ID = 1021309;    // Retrieved from BaseObject::GetType()

Die IDs des Vray MeshExporter Tags und des Vray Proxy Objekts wurden ganz einfach in einem kurzen Coffee-Skript ermittelt, wobei die folgenden Methoden zum Einsatz kamen:

BaseTag::GetType();
BaseObject::GetType();

Das ist übrigens eine gute Methode, die IDs von Pluginobjekten und -Tags zu ermitteln, um sie in eigenen Plugins oder Skripten erzeugen zu können.


Dateiliste

Insgesamt werden nur 2 Dateien benötigt:

CreateVrayProxy.cof
Die eigentliche Plugin-Datei, die den Code enthält.
CreateVrayProxy.tif
Ein kleines Bild im TIFF-Format. Es enthält das Icon (Symbol) des Plugins, welches im Plugin-Menü und ggf. in einer Werkzeugleiste angezeigt wird.


Installation / Dateistruktur

Die beiden Dateien werden folgendermaßen installiert:



+ MAXON
+ CINEMA 4D Rx
 + plugins
  + VrayProxyCreator
    - CreateVrayProxy.cof
    - CreateVrayProxy.tif 

Eine Alternative ist, das Plugin direkt in den Ordner von VrayForC4D, "VrayBridge", zu kopieren.
In dem Fall erscheint VrayProxy Creator im Plugin-Menü von VrayForC4D.



+ MAXON
+ CINEMA 4D Rx
 + plugins
  + VrayBridge
    - CreateVrayProxy.cof
    - CreateVrayProxy.tif 

Sobald die .cof-Datei und die .tif-Datei im richtigen Verzeichnis liegen, kann CINEMA 4D gestartet werden. Das Plugin wird gleich beim Programmstart registriert. Ob das geklappt hat, sieht man sowohl daran, ob es im Plugin-Menü auftaucht, als auch an den Textausgaben in der Console.


Anwendung

Einfach das Objekt selektieren, für welches man einen Proxy erzeugen möchte. Dann das Plugin aus dem Plugins-Menü starten. Jetzt wird gefragt, ob man die Original-Hierarchie des Objekts beibehalten möchte. In den meisten Fällen, ist "Nein" hier die klügere Antwort (die VrayProxies verheddern sich gerne mal mit ihren Materialien, wenn man sie hierarchisch verschachtelt).


Bekannte Bugs

  • Wird eine Szene geladen, in der bereits ein Objekt selektiert ist; und dann wird direkt das Plugin ausgeführt, kommt es u.U. zum Einfrieren von CINEMA 4D.

Grund: Unbekannt
Workaround: Zuerst irgendein anderes Objekt selektieren


Verbesserungsvorschläge

  • Multiselektionen auswerten: Mehrere (hierarchisch gleich gestellte) Objekte sollen selektiert und gleichzeitig in Proxies umgewandelt werden.

Lösungsansatz: Den gesamten Inhalt der Funktion Execute() in einer Schleife über mehrere selektierte Objekte iterieren.
Stolperstein: Sind mehrere Objekte selektiert, die einander untergeordnet sind, oder sich auch nur im gleichen Hierarchiezweig befinden, kann es evtl. zu Problemen kommen (muss aber nicht)
Status: Bisher nicht implementiert


Downloads

Das fertige Plugin inklusive Icon kann hier heruntergeladen werden:

Ein kurzes Demo-Video der Anwendung:


Hinweise & Lizenz

  • VrayProxy Creator ist OpenSource.
  • Es wird keine Garantie auf fehlerfreie Funktion, oder Gewährleistung bei Schäden bzw. Datenverlust gegeben.
  • Das Plugin funktioniert natürlich nur mit einer installierten Vollversion von VrayForC4D 1.1.
Persönliche Werkzeuge