ah got it, thanks for the quick explanation!
so without super i would call SetFloat in an endless loop, because it returns itself.
Best posts made by datamilch
-
RE: set only the value of a dialog gadget
-
how to track if the document has changed?
hi there,
i have a command plugin that is dependent on the state of the active document. so i want to track if the document has changed.
there seems to be no dedicated core message. so i tried the following. but it gives me "basedocument is not alive", which makes senes in a way. but how can i make it work?
class MyDialog( ... doc_old = None ... def CoreMessage(self, cid, msg): doc = c4d.documents.GetActiveDocument() if cid == c4d.EVMSG_CHANGE: if doc != self.doc_old: print ("doc changed") self.doc_old = doc
thanks,
sebastian -
save/keep cache of generator plugin
hi there,
i've built a python generator, where i use its cache unless some parameters are dirty. when close and reopen the scene, the cache is gone and has to be rebuild. in principal, is there (not too complicated) way to keep/save these caches inside the scene?
would this be possible with a python generator or a proper plugin?
i'm using python.to be a bit more specific: by clicking a checkbox on the python generator, i do a cloth simulation in a temp doc. the result of the sim is convertet to polygons and returned by the python generator. the simulation is not super heavy, but it woud be nice if i could avoid the recalculation. so i'd like to store the point data in the scene/generator. i'd like to avoid external files too, if possible.
my code is a bit long at the moment, i would post a shorter version, if you say it should be possible ...
best, sebastian
Latest posts made by datamilch
-
RE: Knowing if a font exists
for my use case i will probably have a fallback solution with web-save or system fonts like this:
import platform system_name = platform.system() if system_name == "Windows": font_name = "Consolas" elif system_name == "Darwin": font_name = "Menlo" elif system_name == "Linux": font_name = "DejaVu Sans Mono"
-
RE: Knowing if a font exists
hi @ferdinand exactly what i needed , thanks!
the fontchek seems solid so far.did a bid of testing, the check with c4d.bitmaps.GeClipMap.GetFontDescription()
seems only to work for the c4d.GE_FONT_NAME_POSTSCRIPT parameter. not with c4d.GE_FONT_NAME_FAMILY or c4d.GE_FONT_NAME_DISPLAY ... maybe because they could be ambiguous?then it was a bit unclear how the postscript names are constructed. i created a font-selector-user-data to print the ps-names of the selected font. these names could then be used to check if a font exists on another system. i just hope, these names are consistent across platfoms.
the fontdata definiton still feels a bit unclear to me in respect to which values are needed or not. the ps-name alone will not work to define a fontdata. a single name in font[500] might work. ... in my test i used the bc returned by c4d.bitmaps.GeClipMap.GetFontDescription().
here is some test code i used in a python generator:
import c4d doc: c4d.documents.BaseDocument # The document the object `op` is contained in. op: c4d.BaseObject # The Python generator object holding this code. def main() -> c4d.BaseObject: fontdata = op[c4d.ID_USERDATA,1] # font selector data field font: c4d.BaseContainer = fontdata.GetFont() print( "==============================" ) print( font[500] ) print( font[501] ) print( font[502] ) print( font[503] ) print( font[508]," <- ps name" ) print( font[509] ) print( "------------" ) # store the ps name for later font_ps_name = font[508] # we are testing the font, that we just selected in the user data - so it should always exist check_bc: c4d.BaseContainer | None = c4d.bitmaps.GeClipMap.GetFontDescription(font[508], c4d.GE_FONT_NAME_POSTSCRIPT) if not check_bc: print(f"508 nope") else: print(f"508 exists" ) print( "------------" ) print( check_bc[500] ) print( check_bc[502] ) print( check_bc[503] ) print( check_bc[504] ) print( check_bc[509] ) print( "------------" ) # testing with spline text # -------------------------------------------------------- # defing a font only with its ps-name will not work - yields default font bc_font = c4d.BaseContainer() bc_font.SetString(508, font_ps_name) # using the data returned by GetFontDescription() works fontdata = c4d.FontData() fontdata.SetFont( check_bc ) text_spline = c4d.BaseObject( c4d.Osplinetext ) text_spline[c4d.PRIM_TEXT_TEXT] = "Text 0123" text_spline[c4d.PRIM_TEXT_FONT] = fontdata return text_spline
-
Knowing if a font exists
hi there,
i'd like to know if there is any way to know if the font i entered is valid / exists on the pc of the user.
i can set the font 'Arial', but if i set a non existing font like 'Whatever', there will be a fallback to the default font. i tried to get some feedback, if this has happend, but i can not figure out how.this is my current code in a python generator:
import c4d doc: c4d.documents.BaseDocument op: c4d.BaseObject def main() -> c4d.BaseObject: text = op[c4d.ID_USERDATA,2] # temp doc # ---------------------------------------------------------- temp_doc: c4d.documents.BaseDocument = c4d.documents.BaseDocument() temp_doc.SetName("temp_doc") temp_null = c4d.BaseObject( c4d.Onull ) temp_doc.InsertObject( temp_null ) # create text spline # ---------------------------------------------------------- text_spline = c4d.BaseObject( c4d.Osplinetext ) text_spline[c4d.PRIM_TEXT_TEXT] = text text_spline[c4d.PRIM_TEXT_ALIGN] = 1 text_spline[c4d.PRIM_TEXT_HEIGHT] = 1 text_spline[c4d.PRIM_PLANE] = 2 bc_font = c4d.BaseContainer() #bc_font.SetString(500, 'Arial') bc_font.SetString(500, 'Consolasssss') bc_font.SetInt32(502, 700) # weight fontdata = c4d.FontData() fontdata.SetFont( bc_font ) text_spline[c4d.PRIM_TEXT_FONT] = fontdata # font check in temp doc # ---------------------------------------------------------- text_spline.GetClone().InsertUnder( temp_null ) temp_doc.ExecutePasses( c4d.threading.GeGetCurrentThread(), True, True, True, c4d.BUILDFLAGS_NONE ) text_spline_2 = temp_null.GetDown() fontdata_check = text_spline_2[c4d.PRIM_TEXT_FONT] font_check = fontdata_check.GetFont() print( font_check[500] ) # will print the non existing font name, not the fallback default font return text_spline
-
save/keep cache of generator plugin
hi there,
i've built a python generator, where i use its cache unless some parameters are dirty. when close and reopen the scene, the cache is gone and has to be rebuild. in principal, is there (not too complicated) way to keep/save these caches inside the scene?
would this be possible with a python generator or a proper plugin?
i'm using python.to be a bit more specific: by clicking a checkbox on the python generator, i do a cloth simulation in a temp doc. the result of the sim is convertet to polygons and returned by the python generator. the simulation is not super heavy, but it woud be nice if i could avoid the recalculation. so i'd like to store the point data in the scene/generator. i'd like to avoid external files too, if possible.
my code is a bit long at the moment, i would post a shorter version, if you say it should be possible ...
best, sebastian -
RE: SAVEDOCUMENTFLAGS_AUTOSAVE still added to the recent file list?
@ferdinand said in SAVEDOCUMENTFLAGS_AUTOSAVE still added to the recent file list?:
But please provide instructions on how to use your code when required in the future.
oh shit, i'm so sorry. you're right. completly missed this one.
...
and of cause thanks for the explaination / clarification. -
SAVEDOCUMENTFLAGS_AUTOSAVE still added to the recent file list?
hi there,
i recreated the autosave functionality (and tweeked the post-fix a bit) to be able to trigger it on demand.
then i noticed the saved files still show up in the recent file list, even though i added the SAVEDOCUMENTFLAGS_AUTOSAVE flag. the documentation says this should not happen. adding SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST makes it work.
is this correct or a bug or something else wrong with my code?cheers sebastian
import c4d, os, datetime doc: c4d.documents.BaseDocument # The currently active document. op: c4d.BaseObject | None # The primary selected object in `doc`. Can be `None`. def main() -> None: # autosave doc_path = doc.GetDocumentPath() doc_name = doc.GetDocumentName() now = datetime.datetime.now().strftime("%Y%d%m_%H%M%S") doc_name_post_fix = f"{doc_name}@export_{now}" prefs = c4d.GetWorldContainerInstance() ausosave_on = prefs[c4d.WPREF_AUTOSAVE_ENABLE] ausosave_dest = prefs[c4d.WPREF_AUTOSAVE_DEST] # 0=project, 1=custom, 2=user if ausosave_on: if ausosave_dest==0: if not doc_path: #print( "no doc path, fallback to user" ) doc_path = c4d.storage.GeGetStartupWritePath() save_path = os.path.join( doc_path, "backup", doc_name_post_fix ) if ausosave_dest==1: doc_path = prefs[c4d.WPREF_AUTOSAVE_DEST_PATH] if not os.path.isdir(doc_path): #print( "no custom path, fallback to user" ) doc_path = c4d.storage.GeGetStartupWritePath() doc_path = os.path.join( doc_path, "backup") save_path = os.path.join( doc_path, doc_name_post_fix ) if ausosave_dest==2: doc_path = c4d.storage.GeGetStartupWritePath() save_path = os.path.join( doc_path, "backup", doc_name_post_fix ) #print( save_path ) res = c4d.documents.SaveDocument(doc, save_path, saveflags=c4d.SAVEDOCUMENTFLAGS_AUTOSAVE | c4d.SAVEDOCUMENTFLAGS_DONTADDTORECENTLIST, format=c4d.FORMAT_C4DEXPORT) if not res: print( "error writing autosave on export" ) if __name__ == '__main__': main()
-
RE: Docked Dialog Problem with width of CUSTOMGUI_FILENAME
hi, thanks for the info.
i just updated to 2025.2.0 ... but i suppose the fix is not in this one yet? not sure when the release date was ... -
RE: Docked Dialog Problem with width of CUSTOMGUI_FILENAME
Thanks for the preliminary feedback.
I'll wait patiently -
Docked Dialog Problem with width of CUSTOMGUI_FILENAME
hi there,
i'm working on a command plugin with gedialog, that i want to dock in the layout.
one of the gui elements is AddCustomGui c4d.CUSTOMGUI_FILENAME.
the paths that are stored can be quite long.
the problem is, that the dialog wants to show the complete string, which makes the dialog extremely wide.
this only happens when the dialog is docked. then i can not scale the dialog smaller then the length of the string/filename.
if the dialog is not docked i can scale it smaller and the overflowing string is hidden.
sadly AddCustomGui has no properties initw and inith. i tried some combinations of flags but had no success.
am i missing something?i could place the element in a scrollgroup, but then the "open document" button might be hidden in the part that is scrolled away.
any other options or workarouds?cheers, sebastian
here is the code
import c4d, typing ID_PLUGIN_CMD: int = 1025245 class MainDialog(c4d.gui.GeDialog): ID_GRP_MAIN = 1000 ID_TEXT_1 = 1001 ID_TEXT_2 = 1002 extra_long_str = "this is some realy looooooooooooooooooooooooooooooooong text" def __init__(self) -> None: super().__init__() def InitValues(self) -> bool: return super().InitValues() def CreateLayout(self) -> bool: self.SetTitle("My Dialog") self.GroupBegin(id=self.ID_GRP_MAIN, flags=c4d.BFH_SCALEFIT, cols=1) self.GroupSpace(spacex=5, spacey=5) self.GroupBegin(id=0, flags=c4d.BFH_SCALEFIT, cols=2) self.AddStaticText(0, c4d.BFH_LEFT, name="path", initw=0 ) bc = c4d.BaseContainer() self.AddCustomGui(self.ID_TEXT_1, c4d.CUSTOMGUI_FILENAME, '' ,c4d.BFH_SCALEFIT, 0, 0, bc,) self.AddStaticText(0, c4d.BFH_LEFT, name="text", initw=0 ) self.AddEditText(self.ID_TEXT_2, c4d.BFH_FIT, 20,10 ) self.GroupEnd() self.GroupEnd() self.SetString( id=self.ID_TEXT_1, value=self.extra_long_str ) self.SetString( id=self.ID_TEXT_2, value=self.extra_long_str ) return super().CreateLayout() def Command(self, cid: int, msg: c4d.BaseContainer) -> bool: return super().Command(cid, msg) class DialogManagerCommand (c4d.plugins.CommandData): dialog: typing.Optional[MainDialog] = None def Execute(self, doc: c4d.documents.BaseDocument) -> bool: if self.dialog is None: self.dialog = MainDialog() if self.dialog.IsOpen() and not self.dialog.GetFolding(): self.dialog.SetFolding(True) else: self.dialog.Open(c4d.DLG_TYPE_ASYNC, ID_PLUGIN_CMD, -2, -2, defaultw=300, defaulth=200) return True def RestoreLayout(self, secret: any) -> bool: if self.dialog is None: self.dialog = MainDialog() return self.dialog.Restore(ID_PLUGIN_CMD, secret) def GetState(self, doc: c4d.documents.BaseDocument) -> int: result: int = c4d.CMD_ENABLED if self.dialog: if self.dialog.IsOpen() and not self.dialog.GetFolding(): result |= c4d.CMD_VALUE return result def RegisterPlugin() -> bool: return c4d.plugins.RegisterCommandPlugin( id=ID_PLUGIN_CMD, str="filename_test_01", info=c4d.PLUGINFLAG_SMALLNODE, icon=None, help="", dat=DialogManagerCommand()) def main(): if not RegisterPlugin(): raise RuntimeError( f"Failed to register {DialogManagerCommand} plugin." ) if __name__ == '__main__': main()
-
RE: Message from Object or Tag to CommandData/GeDialog Plugin
oh well ... tried option B) as planned.
a python tag tracks the dirty status of some objects and starts a c4d.SpecialEventAdd(). this is received as a core message in my dialog. but when i go looking for the dirty objects, they are not dirty anymore.
my workaround for now is, to have a str userdata on the pyhon tag. once the tag detects a dirty object, it writes its name into the str userdata. my dialog can then read the name of the object and find it. feels quite cumbersome but works for now.would there be a better/more hidden way to store the data?