On 22/11/2017 at 05:51, xxxxxxxx wrote:
Hi,
i currently try to write a script that takes all top-level hierarchy elements and converts them into Xrefs, just like the 'Convert the selection to Xref', when right-clicking an object.
I found out that the 'Convert selection to Xref' option is a plugin that if used in code, also opens up the save dialog.
Is there a way to achieve the same functionality without opening the user dialog? Or is it possible to interact with the save dialog so that the user does not need to click anything during the process ?
In my current script, i do not use the Pluging. My current script copies all objects into seperate c4d scenes and saves them, and creates Xrefs for all of them. Unfortunetaly, i did not consider the materials since i wrote the script using simple cubes.. So this script does not work as intended.
Here it is:
import os
import c4d
from c4d import gui
from c4d import documents
from c4d import storage
from c4d import plugins
#An iterator, taking the first top level element of a hierarchy and iterating as long as elements are left
class ItemIterator:
def __init__(self, firstObject) :
self.firstObject = firstObject
self.currentObject = firstObject
def __iter__(self) :
return self
def next(self) :
if self.currentObject == None:
raise StopIteration
else:
toReturn = self.currentObject
self.currentObject = self.currentObject.GetNext()
return toReturn
#Identifiers for the layout
BUTTON_CONVERT = 1
BUTTON_CANCEL = 2
BUTTON_GROUP = 3
TEXT_FIRST_LINE = 4
TEXT_SECOND_LINE = 5
#A class containing the GUI of the save dialog
class SaveDialog(gui.GeDialog) :
#Creates the Layout of the GUI when invoked
def CreateLayout(self) :
self.SetTitle("Conversion to XRef")
self.AddStaticText(TEXT_FIRST_LINE, c4d.BFH_CENTER, name = "All top level objects will be saved into separate scenes.\n")
self.AddStaticText(TEXT_SECOND_LINE, c4d.BFH_CENTER, name = "A new scene containing all these objects as XRefs will be created\n")
self.GroupBegin(BUTTON_GROUP, c4d.BFH_CENTER, 2, 1)
self.AddButton(BUTTON_CONVERT, c4d.BFH_SCALE, name = "Convert")
self.AddButton(BUTTON_CANCEL, c4d.BFH_SCALE, name = "Cancel")
self.GroupEnd()
self.ok = False
return True
#Invokes the suitable function for the cancel and the convert button of the layout.
def Command(self, id, msg) :
if id == BUTTON_CANCEL:
self.Close()
if id == BUTTON_CONVERT:
convert()
self.Close()
return True
def convert() :
activeDocument = documents.GetActiveDocument()
documentPath = activeDocument[c4d.DOCUMENT_PATH]
#Check whether the current scene is saved, so that a relative path can be used for the xrefs and the new scene.
if len(documentPath) == 0:
gui.MessageDialog("Please save the actual project, so that the xrefs are saved to the appropriate position")
return
#Generate the path for the xrefs, and check whether a folder already exists. If so tell the user to move/delete.
#This way no merging of data has to be performed.
saveDirectory = os.path.join(documentPath, "xrefs")
if not os.path.exists(saveDirectory) :
os.makedirs(saveDirectory)
else:
gui.MessageDialog("There is already an 'xref' folder in existence. Please delete or move it.")
return
firstObject = activeDocument.GetFirstObject()
itemIterator = ItemIterator(firstObject)
finalXrefDocument = c4d.documents.BaseDocument()
counter = 0
generatedDocuments = []
for item in itemIterator:
#Create new scene and insert a copy of the item into it.
generatedDocuments.append(c4d.documents.BaseDocument())
print counter
for material in activeDocument.GetMaterials() :
generatedDocuments[counter].InsertMaterial(material)
generatedDocuments[counter].SetDocumentName(item.GetName())
documentName = generatedDocuments[counter].GetDocumentName() + ".c4d"
itemClone = item.GetClone()
generatedDocuments[counter].InsertObject(itemClone)
#Generate the complete part to where to save the scene.
completePath = os.path.join(saveDirectory, documentName)
c4d.documents.SaveDocument(generatedDocuments[counter], completePath, c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, c4d.FORMAT_C4DEXPORT)
#Construct the xref in the final scene.
op = c4d.BaseObject(c4d.Oxref)
finalXrefDocument.InsertObject(op)
#Set the name and the reference file of the xref.
op.SetParameter(c4d.ID_CA_XREF_FILE, completePath, c4d.DESCFLAGS_SET_USERINTERACTION)
op.SetName(item.GetName())
counter = counter + 1
#Save the scene containing the xrefs.
convertedScenePath = os.path.join(documentPath, "ConvertedScene.c4d")
documents.SaveDocument(finalXrefDocument, convertedScenePath, c4d.SAVEDOCUMENTFLAGS_0, c4d.FORMAT_C4DEXPORT)
documents.InsertBaseDocument(finalXrefDocument)
#Working, but stupid, fix.
#Iterate through the new scene.
newActiveDocument = documents.GetActiveDocument()
newFirstObject = newActiveDocument.GetFirstObject()
newItemIterator = ItemIterator(newFirstObject)
#Rename the elements and Undo the Change afterwards, so they become editable.
newActiveDocument.StartUndo()
for newItem in newItemIterator:
newActiveDocument.AddUndo(c4d.UNDOTYPE_CHANGE, newItem)
newItem.SetName("BLAA")
newActiveDocument.EndUndo()
newActiveDocument.DoUndo()
c4d.EventAdd()
gui.MessageDialog("Conversion successful.")
if __name__=='__main__':
#Open up the save dialog.
saveDialog = SaveDialog()
saveDialog.Open(c4d.DLG_TYPE_MODAL, defaultw = 300)
Any help would be appreciated!