Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python 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
    • Login
    1. Maxon Developers Forum
    2. mogh
    M
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 34
    • Posts 151
    • Groups 0

    mogh

    @mogh

    Industrial Designer, Product Visualization, a slight itch for scripting.

    9
    Reputation
    99
    Profile views
    151
    Posts
    0
    Followers
    0
    Following
    Joined
    Last Online
    Location South Germany

    mogh Unfollow Follow

    Best posts made by mogh

    • RE: How to setup c4d.utils.ViewportSelect() and GetNearestPoint to work

      @m_magalhaes

      This morning: uff more learning and work.
      This Afternoon lets try this code ... mind blown ... thank you !

      I'll mark this as solved hence I think ist a good way to close a thread with a working prototype for others to learn.

      Thank You again, @zipit & @m_magalhaes
      mogh

      posted in Cinema 4D SDK
      M
      mogh
    • RE: Open source wrapper for Octane/Redshift/Arnold/Vray/Corona in Cinema 4D.

      Wow ... good stuff
      My c4d Programing slowed down this year, but this might be something I want to use some day ...

      posted in General Talk
      M
      mogh
    • RE: Table With TreeViewCustomGui with no Tree Icon

      @mikeudin

      In my case setting this to true hides them.

      customgui.SetBool(c4d.TREEVIEW_HIDE_LINES, True) # True if no lines should be drawn.

      kind regards
      mogh

      posted in Cinema 4D SDK
      M
      mogh
    • RE: Metadata Supported for FBX Imports?

      Just additional reinforcement.

      We talk here a lot of Metadata in CAD files for Digital Twins, so a universal handling of "additional" data not processed by cinema is an area to explore at Maxon !

      posted in General Talk
      M
      mogh
    • RE: Layers checker

      Beginner solution:
      If you do not need a certain layer you could also implement the call comand "Delete unused layers"
      Its not pretty but beats any convulated self written code if it is not called to often.

      c4d.CallCommand(100004760) # Remove unused layers

      cheers
      mogh

      posted in Cinema 4D SDK
      M
      mogh
    • RE: How can I make a simple input form for my Python script?

      ... while the Team probalby will ask you to provide more context / detail ... have you looked at the sdk examples ?

      https://github.com/PluginCafe/cinema4d_py_sdk_extended/tree/master/scripts/03_application_development/gui/dialog

      kind regards

      posted in Cinema 4D SDK
      M
      mogh
    • RE: Dialog Menu

      EDIT:
      Sorry this was not what I thought I have a dual Dialog example somewhere but not at hand ...

      *This is an Subdialog Example from the SDK.

      Github Subdialog

      hope that is in line what you are searching.*
      Cheers mogh

      posted in Cinema 4D SDK
      M
      mogh
    • RE: Quicktab SDK Example

      Here is my latest Example Code, I will check for R2023.1 on Monday.
      selecting FFFF and DDDD results in GUI weirdness ... on R20

      Update: Also on 2023.1 I get this UI glitch ... selecting KKKKK / LLLLLL (last ones)

      Update 2: fiddled a little bit with the IDs (the class has an offset now so the ids are unique) and Layoutchange() no updated on the glitch when selecting the KKKK + X elements.

      2023-03-27-Window_000269.png

      import c4d # pyright: ignore[reportMissingImports]
      import json
      import os
      from collections import OrderedDict
      
      DEBUG = True
      
      # Ids used in our Dialog
      ID_MAINGROUP = 1000  # ID used for the Group that holds all the other group representing the tab content
      ID_QUICKTAB_BAR = 1001  # ID for the quicktab customGui
      
      ID_LOADDEFAULT_MAT_ASIGN = 1003
      ID_CREATE_MATERIALS = 1004
      BUTTON_PRINT_TEXT = 1005  # ID used for the Print text Button
      BUTTON_PRINT_SELECTED = 1006  # ID used for the Print Selected Button
      BUTTON_FLUSH_ALL = 1007  # ID used for the Flush All Button
      BUTTON_ADD = 1008  # ID used for the Add Button
      BUTTON_REMOVE = 1009  # ID used for the Remove Button
      
      # Id used in our SubDialog
      ID_QUICKTAB_BASE_GROUP = 5000
      
      # Defines the ID for the string to be displayed
      CUSTOM_GROUP_ID_TEXT_BASE = 4000  
      
      DEFAULT_FLAGS = c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT
      DEFAULT_SPACE = (5, 5, 5, 5)
      DEFAULT_BORDER_STYLE =c4d.BORDER_NONE
      
      LAYOUT_DEBUG = True
      if LAYOUT_DEBUG is True:
          DEFAULT_BORDER_STYLE = c4d.BORDER_BLACK
      
      GENERATOR_START_ID = 2000
      def plusone_id():
          n = GENERATOR_START_ID
          while n < GENERATOR_START_ID+999:
              yield n
              n += 1
      
      some_json = '{"AAAAAAA 85": ["a part_num_1","a part_num_2","a part_num_3"],"BBBBB 40": ["b part_num_4","b part_num_5"],"CCCCCCC": ["c part_num_6","c part_num_7","c part_num_8","c part_num_9"],"DDDDDD": ["d part_num_6","d part_num_7","d part_num_8","d part_num_9"],"FFFFF": ["f Plane"],"GGGGGGG": ["g part_num_6","g part_num_7","g part_num_8","g part_num_9"],"HHHHHHHH": ["h part_num_6","h part_num_7","h part_num_8","h part_num_9"],"IIIIII": ["i part_num_6","i part_num_7","i part_num_8","i part_num_9"],"JJJJJJJJJ": ["j part_num_6","j part_num_7","j part_num_8","j part_num_9"],"KKKKKKKK": ["k part_num_6","k part_num_7","k part_num_8","k part_num_9"],"LLLLLLLLL": ["l part_num_6","l part_num_7","l part_num_8","l part_num_9"],"MMMMMM": ["m part_num_6","m part_num_7","m part_num_8","m part_num_9"]}'
      
      ### Json
      #####################################################################################
      
      def read_parts_json(json_file_path):
          #with open(json_file_path) as f: data = json.load(f)
          data = json.loads(some_json)
      
          materials = {}
          for material_id, part_numbers in data.items():
              materials[material_id] = part_numbers
          
          material_ids = list(data.keys())
          return material_ids, materials
      
      class CustomGroup(c4d.gui.SubDialog):
          """A SubDialog to display the passed string, its used as example for the actual content of a Tab"""
          
          def __init__(self, material, parts, offset):
      
              self._material = material
              self._parts = '\n'.join(parts)
              self.gui_id = CUSTOM_GROUP_ID_TEXT_BASE + offset
      
          def CreateLayout(self):
              
              self.GroupBegin(self.gui_id + 4, flags=c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, cols=1, rows=2, title=self.gui_id)
              self.GroupBorder(DEFAULT_BORDER_STYLE)
              self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
              self.AddStaticText(self.gui_id + 1 , flags=c4d.BFH_LEFT | c4d.BFV_TOP | c4d.BFH_FIT | c4d.BFV_FIT, name=self._material)
              #self.AddStaticText(self.gui_id + 2 , flags=c4d.BFH_LEFT | c4d.BFV_TOP | c4d.BFH_FIT | c4d.BFV_FIT, name=self.gui_id)
              self.AddMultiLineEditText(self.gui_id + 3, flags=c4d.BFH_LEFT | c4d.BFV_TOP | c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, initw=0, inith=0, style=0)
              self.SetString(self.gui_id + 3, value=self._parts)
              self.GroupEnd()
              #for i, parts in enumerate(self._parts):
              #    self.AddStaticText(self.gui_id + i, c4d.BFH_SCALEFIT, name=parts)
              return True
      
      
      class MyDialog(c4d.gui.GeDialog):
      
          def __init__(self, items=[]):
      
              # this is from the linkbox example from ferdinand
              super(MyDialog, self).__init__() 
      
              # will be link box
              self._items = [] 
              self._doc = None 
              self._hasCreateLayout = False
              self.Items = items
      
              self._quickTab = None  # Stores the quicktab custom GUI
              self._tabList = OrderedDict()  # Stores the TabName and the SubDialog that represents each tab of the QuickTab
      
          def _DrawQuickTabGroup(self):
              """ Creates and draws all the SubDialog for each tab, 
                  take care it does not hide these according to a selection state.
      
              Returns: 
                  True if success otherwise False.
              """
      
              # Checks if the quicktab is defined
              if self._quickTab is None:
                  return False
      
              # Flush the content of the group that holds all ours SubDialogs
              self.LayoutFlushGroup(ID_MAINGROUP)
              #self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
      
              # Iterates over the number of tab to create and attach the correct SubDialog
              for tabId, (tabName, tabGui) in enumerate(self._tabList.items()):
                  self.AddSubDialog(ID_QUICKTAB_BASE_GROUP + tabId, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0)
                  self.AttachSubDialog(tabGui, ID_QUICKTAB_BASE_GROUP + tabId)
      
              # Notifies the content of the MainGroup has changed
              self.LayoutChanged(ID_MAINGROUP)
      
              return True
      
      
          def GetActiveTabs(self):
              """Retrieves two list of currently selected tabs from the self._quickTab.
      
              Returns:
                  list(int), list(name): The first list, contains tabs Id (from self._quickTab the dict) and the second list contains all names of the selected tabs.
              """
              # Checks if the quicktab is defined
              if self._quickTab is None:
                  return False, False
      
              returnIds = []
              returnNames = []
      
              for tabId, (tabName, tabGui) in enumerate(self._tabList.items()):
                  if self._quickTab.IsSelected(tabId):
                      returnIds.append(tabId)
                      returnNames.append(tabName)
      
              return returnIds, returnNames
      
      
          def DisplayCorrectGroup(self):
              """Hides all unused groups and display the correct one.
      
              Returns: 
                  True if success otherwise False.
              """
              # Retrieves the selected tab
              activeIds, activeNames = self.GetActiveTabs()
              
              print("Display Correct Group")
              print(activeIds)
      
              # Iterates each CustomGui and defines if they are hidden or not
              for tabId in range(len(self._tabList)):
                  toDisplay = tabId in activeIds
                  #print("activeIds: ", activeIds, "current: ", ID_QUICKTAB_BASE_GROUP, tabId, " -> toDisplay: ", toDisplay)
                  self.HideElement(ID_QUICKTAB_BASE_GROUP + tabId, not toDisplay)
      
      
              # Notifies the content of the MainGroup has changed
              self.LayoutChanged(ID_MAINGROUP)
              
              return True
      
          def AppendTab(self, tabName, content, active=True):
              """Appends a tab to the current quicktab with the associated content to be displayed.
      
              Args:
                  tabName (str): The name the tab should have.
                  content (c4d.gui.SubDialog): The SubDialog to be drawn/linked when the tab is selected.
                  active (bool, optional): If True, the inserted tab will be selected. Defaults to True.
      
              Returns:
                  True if success otherwise False.
              """
              # Checks if the quicktab is defined
              if self._quickTab is None:
                  return False
      
              # Adds the tab entry n the quicktab
              self._quickTab.AppendString(len(self._tabList), tabName, active)
      
              # Updates our current tabList with tabName and the Subdialog to be linked
              self._tabList.update({tabName: content})
      
              """ I uncommented below because it resulted in a lot of gui calls 
                  It seems to work fine just calling self.DisplayCorrectGroup() at the right places
                  not inside here hence this functionis called for each tab
              """
      
              # Retrieves the current selected tab
              #previousActiveId, previousActiveName = self.GetActiveTabs()
      
              # Draws the quicktab SubDialog (in order to have the new one drawn)
              #self._DrawQuickTabGroup()
      
              # Defines the just added tab according state
              #self._quickTab.Select(len(self._tabList) - 1, active)
      
              # Defines previous active tab
              #for tabId in previousActiveId: self._quickTab.Select(tabId, True)
      
              # Display only the selected tab and hides all others
              #self.DisplayCorrectGroup()
      
              return True
      
          def FlushAllTabs(self):
              """Removes all tabs and their content from the GUI.
      
              Returns: 
                  True if success otherwise False.
              """
              # Checks if the quicktab is defined
              if self._quickTab is None:
                  return False
      
              # Removes all the tabs
              self._quickTab.ClearStrings()
      
              # Removes all the customGui
              for tabId in range(len(self._tabList)):
                  self.RemoveElement(ID_QUICKTAB_BASE_GROUP + tabId)
      
              # Reinitializes the stored tablist to an empty dict
              self._tabList = OrderedDict()
      
              # Flush the content of the group that holds all ours SubDialogs
              self.LayoutFlushGroup(ID_MAINGROUP)
              # Notifies the content of the MainGroup has changed
              self.LayoutChanged(ID_MAINGROUP)
      
              return True
      
          def RemoveTab(self, tabNameToRemove):
              """Removes a tab by its name
      
              Args:
                  tabNameToRemove (str): The tab to remove.
      
              Returns:
                  True if success otherwise False.
              """
              # Checks if the quicktab is defined
              if self._quickTab is None:
                  return False
      
              # Copies the tabList
              newDict = OrderedDict(self._tabList)
      
              # Checks if the entry exist
              if tabNameToRemove not in newDict:
                  return True
      
              # Removes the entry we want to delete
              del newDict[tabNameToRemove]
      
              # Removes all groups
              self.FlushAllTabs()
      
              # Re-adds all the one from our copy
              for tabName, tabGui in newDict.items():
                  self.AppendTab(tabName, tabGui)
      
              return True
      
          def CreateLayout(self):
              """This Method is called automatically when Cinema 4D Create the Layout (display) of the Dialog."""
      
              # Creates a QuickTab Custom Gui
              bc = c4d.BaseContainer()
              bc.SetInt32(c4d.QUICKTAB_BAR, 0) # (0=off, 1=on, 2=non-bold, 3=special separator look)
              bc.SetString(c4d.QUICKTAB_BARTITLE, "Title")
              bc.SetBool(c4d.QUICKTAB_SPRINGINGFOLDERS, True) # if we can get link fields usefull
              bc.SetBool(c4d.QUICKTAB_SHOWSINGLE, False)
              bc.SetBool(c4d.QUICKTAB_NOMULTISELECT, False)
              bc.SetBool(c4d.QUICKTAB_SEPARATOR, True)
      
              self.GroupBegin(next(plusone_id()), c4d.BFH_SCALEFIT | c4d.BFV_TOP | c4d.BFV_FIT, 0, 0, 'ID_QUICKTAB_BAR', 0)
              #self.GroupBorderNoTitle(borderstyle=DEFAULT_BORDER_STYLE)
              self.GroupBorder(DEFAULT_BORDER_STYLE)
              self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
              self._quickTab = self.AddCustomGui(ID_QUICKTAB_BAR, c4d.CUSTOMGUI_QUICKTAB, 'the tabs', c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, bc)
              #self.AddStaticText(id=next(plusone_id()), flags=c4d.BFV_CENTER | c4d.BFV_SCALE | c4d.BFH_CENTER | c4d.BFH_SCALE, name="tabs")
              #print("layout cusrom gui: ", self._quickTab)
              self.GroupEnd()
      
              # Creates a group that will contain all the group representing each tab
              self.GroupBegin(ID_MAINGROUP, flags=c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, cols=10, rows=10, title='ID_MAINGROUP')
              #self.GroupBorderNoTitle(borderstyle=DEFAULT_BORDER_STYLE)
              self.GroupBorder(DEFAULT_BORDER_STYLE)
              self.GroupBorderSpace(left=5, top=5, right=5, bottom=5)
              self.AddStaticText(id=next(plusone_id()), flags=c4d.BFV_CENTER | c4d.BFV_SCALE | c4d.BFH_CENTER | c4d.BFH_SCALE, name="main")
              self.GroupEnd()
              
              # dummy group to spread vertically
              if self.GroupBegin(id=next(plusone_id()),  flags=c4d.BFH_FIT | c4d.BFV_FIT): #cols=1, rows=1,
                  self.GroupBorderSpace(left=0, top=0, right=0, bottom=0)
                  self.GroupBorderNoTitle(borderstyle=DEFAULT_BORDER_STYLE)
                  self.AddStaticText(id=next(plusone_id()), flags=c4d.BFV_CENTER | c4d.BFV_SCALE | c4d.BFH_CENTER | c4d.BFH_SCALE, name="")
                  self.GroupEnd()
      
              # Creates a group with button in order to do some operation with the QuickTab CustomGUI
              if self.GroupBegin(next(plusone_id()), c4d.BFH_SCALEFIT | c4d.BFV_BOTTOM, 4, 1, '', 0):
                  self.AddButton(ID_LOADDEFAULT_MAT_ASIGN, c4d.BFH_SCALEFIT, name="Populate")
                  self.AddButton(BUTTON_PRINT_TEXT, c4d.BFH_SCALEFIT, name="Print text")
                  self.AddButton(BUTTON_PRINT_SELECTED, c4d.BFH_SCALEFIT, name="Print Selected")
                  self.AddButton(BUTTON_FLUSH_ALL, c4d.BFH_SCALEFIT, name="Flush All")
                  #self.AddButton(BUTTON_ADD, c4d.BFH_SCALEFIT, name="Add")
                  #self.AddButton(BUTTON_REMOVE, c4d.BFH_SCALEFIT, name="Remove")
                  self.GroupEnd()
              
              return True
      
          def InitValues(self):
              """This Method is called automatically after the GUI is initialized."""
              # Creates the first Tab
              #cg1 = CustomGroup(["This is the first Tab", "Just dummy text here"])
              #self.AppendTab("First Tab", cg1, True)
      
              # Creates the second Tab
              #cg2 = CustomGroup(["This is the second Tab", "Just another dummy text here"])
              #self.AppendTab("Second Tab", cg2, False)
              #return True
          
              return super(MyDialog, self).InitValues()
      
          def Command(self, id, msg):
              """This Method is called automatically when the user clicks on a gadget and/or changes its value this function will be called.
               It is also called when a string menu item is selected.
      
              Args:
                  id: The ID of the gadget that triggered the event.
                  msg: The original message container
      
              Returns:
                  False if there was an error, otherwise True.
              """
      
              # If the user interacts with the quicktab, we make sure to display the CustomGUI linked to the active one
              if id == ID_QUICKTAB_BAR and self._quickTab:
                  print("user interacted with tab")
                  self.DisplayCorrectGroup()
                  c4d.EventAdd()
                  return True
      
              # Displays all the Tab name
              if id == BUTTON_PRINT_TEXT:
                  print([key for key in self._tabList])
                  return True
      
              # Displays the ID and name of the selected tab
              if id == BUTTON_PRINT_SELECTED:
                  print(self.GetActiveTabs())
      
              # Removes all tabs
              if id == BUTTON_FLUSH_ALL:
                  self.FlushAllTabs()
      
              """        
              # Adds a new Tab to the quicktab
              if id == BUTTON_ADD:
                  cg3 = CustomGroup(["This is the third Tab"])
                  self.AppendTab("Third Tab", cg3, True)
      
              # Removes the first tab of the quicktab
              if id == BUTTON_REMOVE:
                  self.RemoveTab("First Tab")
              """
      
              if id == ID_LOADDEFAULT_MAT_ASIGN:
                  self.Populate()
      
              return True
          
      
          def Populate(self):
              doc = c4d.documents.GetActiveDocument()
              directory, _ = os.path.split(__file__)
              poart_json_file = os.path.join(directory, "default_asignment.json")
              material_ids, materials_dict = read_parts_json(poart_json_file)
      
              self.FlushAllTabs() # clear the GUI
      
              print( str( material_ids))
              print("-"*80)
              
              offset=0
              
              for material_id in materials_dict:
                  part_list = materials_dict[material_id]
      
                  #print( str(material_id), str(part_list) )
      
                  ### Tabs
                  ##############################################
                  
                  tab_Content = CustomGroup(str(material_id), part_list, offset)
                  self.AppendTab(str(material_id), tab_Content, True)
                  offset += 10
              
              print("-"*80)
              self._DrawQuickTabGroup()
              c4d.EventAdd()    
            
      
      # Main function
      def main():
          
          if DEBUG:
              c4d.CallCommand(13957)  # clear console
          
          # Initializes a QuickTabDialogExample Dialog
          diag = MyDialog()
      
          # Opens the Dialog in modal mode
          diag.Open(dlgtype=c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=960, defaulth=600)
      
      
      # Execute main()
      if __name__ == '__main__':
          main()
      
      posted in Cinema 4D SDK
      M
      mogh
    • RE: How to create UV of obj.

      I use this to Thank You Ferdinand.

      This is how I imagine an SDK example should look like .... a simplest version , an altered simple version and a complex touching the boundaries of the subject.
      I am thankful and praise your work .... !

      cheers mogh

      posted in Cinema 4D SDK
      M
      mogh

    Latest posts made by mogh

    • RE: Usage of SplineHelp.InitSplineWith() regarding flags -> returned data

      Hey ferdinand,

      I mixed different questions - I'll keep to the theoretical part to keep the Post relevant to the original question.

      I appreciate the informative post as always. 😳

      Parametric concept of a spline is clear to me -> that's why i asked about "C4D can not get more precise than a 0° degree line object ?" which was formulated to lose as 0° is mathematical problematic? and I know 0.1 would be better. sorry about that.
      The tip about spline 'Adaptive' setting was a good hint, I never use it in work so I forgot about it.

      So to summarize regarding my question.

      The Line object always samples what the user has set in the spline settings and not by a unknown internal setting (for example to give good viewport performance, or nice equal sections)
      And its a better fit for my application, hence there is no "linear transport" shenanigans going on.
      And if I want to display a high resolution of my calculation, I make an internal copy of that spline and edit the spline settings, instead of sampling a low division spline with spline helper.

      Normalization / Jagged lines:
      I use Menger-Krümmung. -> will open a new topic.
      Your code might come in handy when I'll extend the plugin to polygon meshes.
      ...
      ...
      ...

      Remark

      as humans cannot see that level of detail.

      I have to disagree on this topic. As a tell tale we import CAD data here into C4D to evaluate the work of the engineers.

      Not long ago I said to our surface engineer. "take a look at the end of that surface something feels off, it looks like the surface is lifting" -> The engineer reportet back "you just spoted a 0.001mm surface deviation of an unconstrained spline ending I did not set."

      We could argue that the seen result was in fact not 0.001mm but perhaps to surface setup more than 1mm, (or by some rounding error C4D normal tag shading where continuous and then stagnant for 1 pixel) but my point is settings in precision are important and carry through till the final product. Even though a setting of 0.1° for a spline might might be unsuitable in most cases (rendering, performance, ...) it is not for evaluation.

      So even C4D and all that rounding / conversion / floating point precision might look like unrealiable, unecessary or even esotheric it caries through to a certain degree and its more reliable than you think.

      (Yes we evaluate in the original CAD Program, but the tale is that I saw something even after importing it into C4D)

      As reference to why I need this:

      Blender Plugin: Surface Diagnostics - Josef Ludvík Böhm

      Thank You

      posted in Cinema 4D SDK
      M
      mogh
    • RE: Usage of SplineHelp.InitSplineWith() regarding flags -> returned data

      Thank you ferdinand,

      I will implement my own "tagent" / "colinear" ending then, and not use this flag.

      @ferdinand said in Usage of SplineHelp.InitSplineWith() regarding flags -> returned data:

      As a warning: All the spline helpers implement parallel transport, which can make their output for curvature tasks undesirable (as it messes with what is the mathematical tangent of a spline in favour of what humans would expect. When you are at a loss about what I am talking about, search the forum for parallel transport and my username, the topic has come up multiple times in the past). It might be better to get the LineObject of a spline, i.e., its current discrete form, and do all the math based on its vertices.

      Aha ... thank you - this explains why I get so different from spline-helpers tangent and cross tangent. Could also corelate to my "noisy" sampling with splinehelper (see screen below)
      My question other topic but same context would be how to get a more high resolution Line-Object. We talked about this in an early stage about this, but my code wasn't mature enough to be sure. -> Is the short answer C4D can not get more precise than a 0° degree line object ?

      Screenshot line object Bezier 0° degree (for enough resolution). Nice plot but resolution enough? Probably not for edge cases like flatish dips.
      2025-10-27-Cinema 4D 2025.2.1 - [Untitled 1 _] - Main_001065.png 2025-10-27-Cinema 4D 2025.2.1 - [Untitled 1 _] - Main_001066.png

      Splinehelper 200x samples not moving average smoothed. The noise starts to show at about double the resolution of a line object ...
      2924215d-9db8-49a5-acc6-375c68d04b31-image.png

      Should I open another Topic?
      thank you again

      posted in Cinema 4D SDK
      M
      mogh
    • Usage of SplineHelp.InitSplineWith() regarding flags -> returned data

      Dear community,

      Returned Data of Flag c4d.SPLINEHELPFLAGS_CONTINUECURVE unclear.

      I've read that the SplineHelp() has flag called c4d.SPLINEHELPFLAGS_CONTINUECURVE.
      While the written explanation is clear to me :
      Continue the curvature of an existing spline at the end points.

      Its unclear to me how to utilize the data or even how the data I get is different from a "normal" helper.

      Reason of interest: I am coding a "Curvature" displaying Tag Plugin atm.

      thank you for your time.
      cheers mogh

      C4D Python SDK - Splinehelper

      posted in Cinema 4D SDK python
      M
      mogh
    • RE: Broken Push Notifications

      Hm, interesting, It works now,

      either you did something or the solution is to post a comment to trigger it. Anyway Thanks.
      Cheers mogh

      posted in News & Information
      M
      mogh
    • RE: Broken Push Notifications

      I still have the same problem. "No push" no "unread toppics". Clearing my Browser Chache does nothing.

      any idea ?
      cheers mogh

      posted in News & Information
      M
      mogh
    • RE: How to create UV of obj.

      I use this to Thank You Ferdinand.

      This is how I imagine an SDK example should look like .... a simplest version , an altered simple version and a complex touching the boundaries of the subject.
      I am thankful and praise your work .... !

      cheers mogh

      posted in Cinema 4D SDK
      M
      mogh
    • RE: How to receive the high definition / Interpolation version of a spline?

      Ok Understood,

      Ok I guess that explains my "nice" comb from the cache and my jagged flip/flop . sometimes zero comb from the "full" matrix normal ...

      I also have different tangents from manually "calculating" them then v3, v2. But I will make a "sanity" check this weekend (feed manual matrixes into my code instead of spline "point" matrixes), before I post about this.

      Thanks Ferdinand
      I'll divide and conquer away.

      posted in Cinema 4D SDK
      M
      mogh
    • RE: How to receive the high definition / Interpolation version of a spline?

      @ferdinand
      Thank you for your answer, exactly what i need, I am trying to incorporate the additional data but get weird results.

      Is there a switch up /typo in the above code I get m.v3 <-> m.v1 ? meaning v1 is the normal ?

      Is there a page in the SDK besides the "Matrix" one that explains the additional values and their features ?

      Thank you for your Time.
      mogh

      posted in Cinema 4D SDK
      M
      mogh
    • RE: TagData Plugin with Gui not using *.res

      Understood Thanks.

      posted in Cinema 4D SDK
      M
      mogh
    • RE: How to receive the high definition / Interpolation version of a spline?

      Ok I guess I have been vague what my issue is.

      from the above helper I only get the points the spline is set to (eg. adaptive 5°) but I perhaps want more points in between. That of course only makes sense in certain scenarios but even though if the spline is a straight line there must be a solution to get points in between.

      Example different adaptive degree values and the resulting points displayed as lines on the spline - Spline is a copy so no altering of the gizmos.
      2025-02-18-Cinema 4D 2025.1.2 - [Untitled 2 _] - Main_000813.png

      sorry to be so basic
      mogh

      posted in Cinema 4D SDK
      M
      mogh