VrayProxy Creator (Coffee-Plugin)
Aus CINEMA 4D Wiki
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:
- CoffeePlugin_VrayProxyCreator (10 KBytes)
Ein kurzes Demo-Video der Anwendung:
- CoffeePlugin_VrayProxyCreator_demo (2,2 MBytes)
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.
