Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Register
    • Login
    1. Home
    2. s_bach
    3. Posts
    S
    • Profile
    • Following 0
    • Followers 0
    • Topics 2
    • Posts 257
    • Best 128
    • Controversial 0
    • Groups 0

    Posts made by s_bach

    • RE: Example of ObjectData in Maxon API only?

      Hello,

      this is not possible. ObjectData is a class of the "classic" API. The Maxon API has no equivalent counterpart.

      You get an overview over plugin types here: Plugin Types.

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • Goodbye

      Hello,

      at the end of this week, I will leave Maxon for a new direction in my life.

      In the last five years, I tried to give you the best answers to your questions and to provide you with documentation and examples that would make your daily life easier.

      During my time here, I met remarkable developers and learned about their projects. I learned a lot by working with you here on the forum, via mail or in person. Especially, I want to thank Riccardo, Maxime and Manuel for being great colleagues and an amazing team. Be assured that this team will continue to work with great commitment to make sure you get the support you need.

      I wish you all the best.
      Sebastian

      posted in News & Information
      S
      s_bach
    • RE: A strange error

      Hello,

      please use tags and the Q&A system when posting questions.

      What version of Cinema 4D and the SDK are you using?

      You can enable utility functions like NewObjClear() by enabling this setting in your projectdefinition.txt file

      C4D=true
      

      and re-creating the project files. See Project Tool.

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Copy shader from one material to another

      InsertShader() and the parameter do NOT need the shader type. They desire an actual shader instance. You can create a clone of the original shader with GetClone().

      See also BaseShader Manual.

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Best Practices for Reporting Errors to Users?

      Hello,

      there is no "official" way of handling or reporting errors in Python scripts. You can do whatever fits your needs or the needs of your user best. Why do you think the console is not useful to users?

      The only thing to consider are general best practices regarding software design. E.g. to only show a (modal) dialog when you know that a user is interacting with the software, not in some sub-function.

      Another philosophical discussion is, what actually is an error? An error should be returned by a function that failed; but what does that mean? What should happen if an error is detected? (Here is some video about this topic I just recently watched:

      )

      For argument's sake, lets say an error is when something in your code, you are 100% sure should and must work, didn't work. So your program shuts down, if such such an "error" was detected.

      In your example, LoadDialog() is a function that - in my opinion - cannot fail. Either the user selects a folder or he presses "Cancel". Both are fine results. And if the user tells you to abort, you can simply exit your program.

      Similarly, when the user selects the wrong file type, that's not a program error. Compare that with a user entering a wrong password somewhere - that is not an error, but something to expect. Providing feedback to the user and handling errors are two different things.

      def handleError(error):
          print(error)
          c4d.gui.MessageDialog(error)
      
      def getImagePathFromUserInteraction():
          res = c4d.storage.LoadDialog(
              type=c4d.FILESELECTTYPE_IMAGES,
              title="Select an image in the folder you want to bulk rename",
              flags=c4d.FILESELECT_LOAD
          )
          
          if res == None:
              return False
          
          return res
      
          
      def main():
      
          # UI interaction
          res = getImagePathFromUserInteraction()
          
          if res == False:
              # nothing to do, lets go home
              print("script aborted by user")
              return
          
          # do actual work 
      
          try:
              doSomething(res)
              doSomethingElse(res)
              
          except ValueError as error:
              handleError(error)
              return
          
          # show result in the UI
          c4d.gui.MessageDialog(res)
      

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Changing the syntax from "SetString" to "Brackets" type

      @bentraje You find also some information in this discussion: Miscellaneous questions about "BaseContainer","DescID" etc

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Make Button Invisible And Still Occupies Space?

      I don't know why you think you need two groups.

      You can simply have one group that you flush and re-fill on demand. In that re-fill, you can replace anything with that static text placeholder as shown above:

      self.LayoutFlushGroup(1000)
      
      flags = c4d.BFH_LEFT | c4d.BFV_TOP
      width = c4d.gui.SizePix(100)
      height = c4d.gui.SizePix(100)
      
      if self.mode == True:
          # add bitmap button
          settings = c4d.BaseContainer()
          settings.SetBool(c4d.BITMAPBUTTON_BUTTON, False)
      
          bitmapButtonGUI = self.AddCustomGui(1001, c4d.CUSTOMGUI_BITMAPBUTTON, "", flags, width, height, settings)
      
          if bitmapButtonGUI is not None:
              icon = c4d.gui.GetIcon(c4d.Ocube)
              bmp = icon["bmp"]
              subBitmap = c4d.bitmaps.BaseBitmap()
              bmp.CopyPartTo(subBitmap, icon["x"], icon["y"], icon["w"], icon["h"] )
              bitmapButtonGUI.SetImage(subBitmap, True, False)
      
      else:
          # add placeholder with the size of the bitmap button
          self.AddStaticText(999, flags, width, height)
      
      self.LayoutChanged(1000)
      

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Make Button Invisible And Still Occupies Space?

      Hello,

      what exactly do you mean with "button"?

      A standard button (AddButton()), a bitmap button or a custom GeUserArea based gadget?

      @lasselauch 's idea to use Enable() is, I guess, the easiest way to achieve what you want. But what is the overall behaviour of your dialog? Is the user able to resize it; can the width or height or your GUI elements changes based on resizing the dialog? Do your UI elements have a minimum or fixed size?

      If the element has fixed size, you can insert an empty static text element with the desired dimensions in place of the original element when rebuilding your layout.

      self.AddStaticText(999,c4d.BFH_LEFT | c4d.BFV_TOP, c4d.gui.SizePix(100), c4d.gui.SizePix(100))
      

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: UA is update too often

      Hello,

      as always, efficiency is the result of good software design. One way of speeding things up is to use caches.

      DrawMsg() is called by Cinema whenever Cinema things something might have changed. I don't think you can do anything about that.

      You have to make sure that within DrawMsg() you only draw and do nothing else. Why are you loading the bitmap in the context of DrawMsg()? Why are you scaling the images in the context of DrawMsg()? Why not earlier?

      I guess at some point, your program knowns what images to display. At that point you could load all these (scaled) images into a cache. Then in DrawMsg(), you can simply access the data in that cache.

      Compare e.g. BaseShader.InitRender() which is used to do all the heavy lifting, so that BaseShader.Sample() can be fast.

      Depending on the reason for the redraw, you could optimize further. E.g. you could use a GeClipMap to draw whatever you want into a BaseBitmap and simply draw that BaseBitmap in the context of DrawMsg().

      Speed is the result of software design. Caches can help, but of course they increase code complexity and memory footprint.

      Best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Plugin not found after switching layout

      The ID used with GeDialog::Open() and RestoreLayout() is typically the plugin ID of the CommandData plugin.

      See e.g. activeobject.cpp

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Create VRay material

      Hello,

      sorry, but this it NOT how to create a "c4d material".

      Cinema 4D has multiple, different materials. All materials are based on BaseMaterial. Thus, any material can be created using the c4d.BaseMaterial constructor and the appropriate ID:

      # create Cheen material
      material = c4d.BaseMaterial(c4d.Mcheen)
      doc.InsertMaterial(material)
      c4d.EventAdd()
      

      The Cinema 4D standard material is a special case. It can be created using BaseMaterial . But there is also a dedicated class, that can be used as well: c4d.Material.

      # create standard material
      material = c4d.BaseMaterial(c4d.Mmaterial)
      material.SetName("first material")
      doc.InsertMaterial(material)
      
      # create standard material the other way
      material2 = c4d.Material()
      material2.SetName("second material")
      doc.InsertMaterial(material2)
      

      To create a VRay material, you need the ID of that material to use it with c4d.BaseMaterial. I don't have VRay here, but you can easily obtain that ID from a already created material using GetType().

      # get the currently selected material
      mat = doc.GetActiveMaterial()
      if mat is not None:
          # print type ID
          print(mat.GetType())
      

      You find more information in the C++ docs: BaseMaterial Manual

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: How to properly use OpenSSL for local validation

      Just FYI: you find that information regarding ./res/libs/win64 in the documentation: Development for Microsoft Window

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: R21 Windows System Error

      Hello,

      as Riccardo has pointed out, AdditionalIncludeDirectories has nothing to do with DLLs. It is used to define search paths for header files. See Additional include directories. It was never valid.

      Also, looking at the error, the plugin was installed into the C:/Program Files folder. In R21, there is no reason to install plugins there; one can install plugins at any location and just tell Cinema 4D the plugin path.

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: How can i set custom Databases paths in prefs with python?

      Hello,

      this particular preferences plugin only loads its data when needed. To trigger that, you can call GetDescription() which will internally load the data.

      plugin.GetDescription(c4d.DESCFLAGS_DESC_0)
      
      # Get existing paths
      dbPaths = plugin[c4d.PREF_DATABASE_PATHS]
      

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: How can i set custom Databases paths in prefs with python?

      Hello,

      these paths are accessed with a preference plugin. You can access that plugin:

      plugin = c4d.plugins.FindPlugin(1040566)
      
      paths = plugin[c4d.PREF_DATABASE_PATHS]
      
      # print paths
      print(paths)
      
      # add a path
      paths = paths + "\n" + "X:\someting" 
      plugin[c4d.PREF_DATABASE_PATHS] = paths
      
      c4d.EventAdd()
      

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Get the Button GadgetID Directly Under the Mouse?

      Hi,

      I think you you mean the gadget under the mouse, do you?

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Get mode (object, face, edge, point) with python

      Hello,

      the edit mode is stored with the current BaseDocument and accessed with GetMode(). See also IsEditMode().

      if doc.GetMode() != c4d.Mmodel:
          return
      

      best wishes,
      Sebastian

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: Communication between DescriptionTool and GeUserArea

      My thoughts on this: as always, this is a question on software design and the correct level of abstraction. The question is not how do different plugins communicate with each other, but how do different parts of a software communicate with each other. And how is software structured to make that communication efficient and clear.

      The typical modern approaches are patterns like Model-View-Controller or Model-View-Presenter.

      In such models, you don't "send data around". Your UI updates the model. And an update of the model triggers an update or (other parts of the) UI.

      So in your example, the interaction with the DescriptionToolData would write data into the model. And the GeUserArea would read that data from the model. The only question is how you trigger that update process; and that depends on what exactly you are doing in what cases Cinema allows to update the UI.

      best wishes,
      Sebastian

      posted in General Talk
      S
      s_bach
    • RE: Take Viewport Screenshot

      Hello,

      just FYI: GetDocPreviewBitmap() returns the image that is stored in the c4d file and that is used as a thumbnail image. It is created when the scene is saved; it has nothing to do with the current viewport image.

      posted in Cinema 4D SDK
      S
      s_bach
    • RE: GetGeneralLicensingInformation() in TeamRender Client fails

      Well, what error does GetGeneralLicensingInformation() return? You can check the error message: Error Class

      posted in Cinema 4D SDK
      S
      s_bach