I just had time to check this hence the holidays.
This works with the correct ID (1036219 = Redshift) the nodes render my "cleaned" C4D file again.
Thank you very much @m_magalhaes
kind regards
mogh
Industrial Designer, Product Visualization, a slight itch for scripting.
I just had time to check this hence the holidays.
This works with the correct ID (1036219 = Redshift) the nodes render my "cleaned" C4D file again.
Thank you very much @m_magalhaes
kind regards
mogh
Thanks you for your reply,
interesting never noticed that there is a post effekt called redshift in the standard renderer . will need to check that, I always swith from physical to redshift and back.
the id is probably just the post effect not the redshift plugin ID I posted. - anyway
if I could solve the problem by deleting the post effect i am happy also
will check
anyway thanks
Dear developpers,
I ran into a problem at work where remains of a plugin ( 'Redshift' (ID 1036219)) prevents me to render on my renderfarm. FYI the scene has no shader nor Objects which relate to Redshift anymore, I also copied everything to a new file the Renderfarm still throws a plugin error.
My Idea is to write a script myself to delete remaining Plugin Data which is probabbly just a basecontainer with the ID.
So how do I search for the basecontainer by ID and delete it (which could be wrong/dangerous but this is my idea at the moment)
thank you for your time
kind regards
mogh
Thanks for the reply, Wicked.
interessting, but not what i hoped for ... ;-)
kepp on chrunching
did sent email with raw data
kind regards
mogh
@zipit said in Option to wait for c4d to catch up with script ? Memory wise and EventAdd?:
I would invite you to provide some test data
You can reproduce a heavy data import by putting my object sent to you into a cloner (5x1x5 ... or even more) and convert it (C). No need to send hundreds of megabites through email.
Use your script not my mess if you like.
kind regards
mogh
I am building of your script from here on. Thank You.
FYI zipit:
While your def get_nodes_by_name(doc, patterns)
might be saver and more sound it takes 10x longer then my version to collect all axis ... (which is not the slow party of the script and could be neglegted - I was just buffled by the profiling i ran)
kind regards
mogh
slightly,
the waiting is now in the beginning, with no or sporadic statusbar updates in between and some waiting at the end.
While this seems fine in a generall sense hence the script now takes its time more reasonably, its a bummer that I cannot inform the user about the status of the script in a meaningfull manner.
C4D "hangs and calculates" and is fnished at some point. If I did not know better I would suspect C4D to be crashed and kill it as a user.
I suspect that the c4d.utils.SendModelingCommand
does not allow a better solution at this point and only a selfmade C++ version would.
Also my hopes for a faster script are shattered, hence the simplified script you posted takes more or less the same time (console reports 10sec but its actually 20seconds) as my 5 year old callcomand script (also 20 seconds) which is a bummer.
I am still a bit lost on how to pursue my "optimzing scripts" endeavor at this point. (which is off topic here).
nevertheless, thank you for your time
kind regards
mogh
thank you zipit,
as I am totally fine with a less heavy version (from the other thread) I would mark this as solved.
I still want to Thank you for all the other people which might need the actuall NormalTag manipulation in the future.
kind regards
mogh
hi zipit, no worries,
thank you for your time!
Yes it is misterious, thats why I asked so vague. You can reproduce a heavy data import by putting my object sent to you into a cloner (5x1x5) and convert it (CSO) -
Running the below script takes about 4 seconds to run and about 1Minute plus to display with the same weird finished but not fnished behavior.
Use below script, set your C4D to only have one window otherwise I have status bar issues!
The status bar displays when its fnished with main()
the console lags behind but displays 4 secons !
Latest Version, difference to the slim version is mainly with some quality of live code.
by the way, scripts running for 1hour + are no strangers here - we often start them over night ... thats kinda normal the behavior is not
kind regards mogh
#!py3
import c4d, sys, os, math
from c4d import gui
from c4d.documents import GetActiveDocument
#Version 1.5
import cProfile, pstats
#import time
def profile(func):
# A simple profiling decorator.
profiler = cProfile.Profile()
def wrapper(*args, **kwargs):
result = None
try:
result = profiler.runcall(func, *args, **kwargs)
except Exception as error:
raise error
finally:
stats = pstats.Stats(profiler)
# To get the full profile do this.
stats.strip_dirs().sort_stats("cumtime").print_stats()
t = round(stats.total_tt, 3)
#print (f"{func.__name__} took {t} sec.\n")
return result
return wrapper
#@profile
def gime_time (milliseconds):
hours,milliseconds = divmod(milliseconds, 3600000)
minutes, milliseconds = divmod(milliseconds, 60000)
seconds = float(milliseconds) / 1000
s = "%i:%02i:%06.3f" % (hours, minutes, seconds)
return s
#@profile
def GetNextObject(op):
if not op: return
if op.GetDown(): return op.GetDown()
while op.GetUp() and not op.GetNext():
op = op.GetUp()
return op.GetNext()
#@profile
def get_all_objects (op):
allachsen_list = list()
all_objects_list = list()
while op:
if op.GetName() == 'Achsen-Objekt' or op.GetName() == 'Axis' :
allachsen_list.append(op)
all_objects_list.append(op)
op = GetNextObject(op)
#return {'all_objects_list' : all_objects}, allachsen
return all_objects_list, allachsen_list
#@profile
def statusbar (counter, secondcounter):
#print (secondcounter, int((100*secondcounter)/counter) )
if int((100*secondcounter)/counter) in [10,20,30,40,50,60,70,80,90,100]:
#print("Textupdate at: ", int((100*secondcounter)/counter))
c4d.StatusSetText ('%s - %s Objects are processed.' %(secondcounter, counter))
c4d.StatusSetBar(int(100*secondcounter/counter)) #statusbar
#c4d.gui.GeUpdateUI()
def savetorun(checkSelection = False):
try:
doc = GetActiveDocument()
except Exception as e:
print (e)
raise TypeError("No Active Document!")
exit()
return False
try:
op = doc.GetFirstObject()
except Exception as e:
print (e)
c4d.StatusSetText ('No Objects, nothing to do here.')
raise TypeError("No Objects, nothing to do here.")
exit()
return False
selected = None
if checkSelection == True:
selected = doc.GetActiveObject()
if selected == None:
c4d.StatusSetText ('No Object/s selected, nothing to do here.')
print ("No Object/s selected, nothing to do here.")
exit()
return False
return doc, op, selected
def savedoc(doc):
path = doc.GetDocumentPath()
name = doc.GetDocumentName()
name = name[ :-4 ] + "_conectedaxis.c4d"
filename = os.path.join(path, name)
saveflags = (c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST | c4d.SAVEDOCUMENTFLAGS_DIALOGSALLOWED)
c4d.documents.SaveDocument(doc, filename, saveflags, format=c4d.FORMAT_C4DEXPORT)
#@profile
def JoinCommand(doc, op):
""" Apply a join command to the object passe as argument
:param op: the object to apply current state to object to.
:type: BaseObject
:return: the result of the command or raise an error if command failed
:rtype: BaseObject
"""
# null = c4d.BaseObject(c4d.Onull)
# #for o in op.GetChildren:
# op.InsertUnder(null)
#settings = c4d.BaseContainer()
#settings[c4d.MDATA_JOIN_MERGE_SELTAGS] = True
# bc = settings,
res = c4d.utils.SendModelingCommand(command = c4d.MCOMMAND_JOIN,
list = [op],
mode = c4d.MODELINGCOMMANDMODE_ALL,
doc = doc)
# Cheks if the command didn't failed
if res is False:
raise TypeError("return value of Join command is not valid")
elif res is True:
print ("Command successful. But no object.")
elif isinstance(res, list):
#if c4d.GetC4DVersion() < 21000: res[0].SetAbsPos(c4d.Vector())
op.Remove()
return res[0] # Returns the first item containing the object of the list. ??? GetClone() ???
#@profile
def set_point_object_transform(node, transform):
"""Sets the global transform of a point object while keeping its points in place.
Args:
node (c4d.PointObject): The point object to move the axis for.
transform (c4d.Matrix): The new global transform for the object.
Raises:
TypeError: When node or transform are not of specified type.
"""
if (not isinstance(node, c4d.PointObject) or
not isinstance(transform, c4d.Matrix)):
msg = f"Illegal argument types: {type(node)}{type(transform)}"
raise TypeError(msg)
#mg = node.GetMg()
# Move the points in the global frame and then into the new frame.
points = [p * ~transform for p in node.GetAllPoints()]
# Set the points and stuff ;)
node.SetAllPoints(points)
node.Message(c4d.MSG_UPDATE)
node.SetMg(transform)
#@profile
def joinmanagment(n):
# n "Axis" null will be not alive in a few steps get everything we need from it
if n.GetUp() :
parent = n.GetUp()
else:
print ("No Parent To Axis Null. Probably not save to run this sript anyway.")
c4d.StatusClear()
c4d.StatusSetText ('No Parent found! - Probalby mo CAD import Doc. Script Stopped.')
exit()
return False
newobject = JoinCommand(doc, n) # combine the poly objects
if not newobject.IsAlive():
raise TypeError("Object is not alive.")
return False
newobject.SetName(str(parent.GetName()))
newobject.InsertUnder(parent)
set_point_object_transform(newobject, n.GetMg()) # set points with global matrix from parent n "Axis"
#@profile
def main():
c4d.CallCommand(13957) # Konsole löschen
now = c4d.GeGetTimer() # start stopwatch
# Savetorun: Set True to check for slected objects and get them returned or throw an error, otherwise slected is None.
doc, op , selected = savetorun()
c4d.StatusSetSpin()
all_objects, allachsen = get_all_objects(op) # get two lists
null_counter = len(allachsen)
if null_counter == 0: # check if found something to do.
c4d.StatusClear()
c4d.StatusSetText ('No Axis Objects found, nothing to do here.')
print ("No Axis Objects found, nothing to do here.")
exit()
counter = len(all_objects)
secondcounter = 0
print (counter,' Objects' ,'\n' ,null_counter,' Nulls and their children to connect' ,'\n' ,'----------------------------------------------------' )
c4d.StatusSetText ('%s Objects are processed.' %(null_counter))
for n in allachsen:
secondcounter += 1
statusbar(null_counter, secondcounter)
joinmanagment(n)
#if joinmanagment(n) == False: break
print ('----------------------------------------------------')
print ('END OF SCRIPT %s ms ' %(gime_time(c4d.GeGetTimer() - now)) )
#savedoc(doc)
c4d.StatusClear()
c4d.StatusSetText ('Script finished - C4D needs a while to diplay the new viewport?!')
c4d.EventAdd() # update cinema 4d
return True
if __name__=='__main__':
main()