/ tags.py
tags.py
  1  from abc import ABC, abstractmethod
  2  from DreamTalk.constants import WHITE
  3  import c4d
  4  
  5  
  6  class Tag():
  7  
  8      def __init__(self, target=None, name=None):
  9          self.document = c4d.documents.GetActiveDocument()  # get document
 10          self.specify_tag_type()
 11          self.set_tag_properties()
 12          self.set_name(name)
 13          self.apply_to_object(target)
 14          self.set_unique_desc_ids()
 15  
 16      def set_name(self, name):
 17          if name:
 18              self.obj.SetName(name)
 19  
 20      @abstractmethod
 21      def specify_tag_type(self):
 22          pass
 23  
 24      def apply_to_object(self, target):
 25          target.obj.InsertTag(self.obj)
 26          self.linked_object = target
 27  
 28      def set_tag_properties(self):
 29          pass
 30  
 31      def set_unique_desc_ids(self):
 32          pass
 33  
 34  
 35  class MaterialTag(Tag):
 36  
 37      def __init__(self, material=None, **kwargs):
 38          super().__init__(**kwargs)
 39          self.link_to_material(material)
 40  
 41      @ abstractmethod
 42      def specify_tag_type(self):
 43          pass
 44  
 45      @ abstractmethod
 46      def link_to_material(self):
 47          pass
 48  
 49      @ abstractmethod
 50      def set_tag_properties(self):
 51          pass
 52  
 53  
 54  class SketchTag(MaterialTag):
 55  
 56      def __init__(self, outline=False, folds=False, creases=False, border=False, contour=False, splines=True,
 57                   hidden_material=True,
 58                   contour_position=2, contour_spacing_mode=1, contour_spacing=15,
 59                   **kwargs):
 60          """
 61          Create a Sketch Style tag for Sketch & Toon rendering.
 62  
 63          Args:
 64              outline: Enable outline rendering
 65              folds: Enable fold lines
 66              creases: Enable crease lines
 67              border: Enable border lines
 68              contour: Enable contour lines
 69              splines: Enable spline rendering
 70              hidden_material: Control hidden line rendering:
 71                  - True (default): Use same material for hidden lines (solid look)
 72                  - False/None: No hidden material (X-ray see-through effect)
 73                  - Material object: Use specific material for hidden lines
 74              contour_position: Contour position mode (0=World, 1=Camera, 2=ObjectZ, etc.) Default 2 (ObjectZ)
 75              contour_spacing_mode: 0=Relative, 1=Absolute. Default 1 (Absolute)
 76              contour_spacing: Spacing value in cm (default 15)
 77              **kwargs: Parent class arguments (target, material, name)
 78          """
 79          self.outline = outline
 80          self.folds = folds
 81          self.creases = creases
 82          self.border = border
 83          self.contour = contour
 84          self.splines = splines
 85          self.hidden_material = hidden_material
 86          self.contour_position = contour_position
 87          self.contour_spacing_mode = contour_spacing_mode
 88          self.contour_spacing = contour_spacing
 89          super().__init__(**kwargs)
 90  
 91      def specify_tag_type(self):
 92          self.obj = c4d.BaseTag(1011012)  # create sketch tag
 93  
 94      def link_to_material(self, material):
 95          # Visible material - always set
 96          self.obj[c4d.OUTLINEMAT_LINE_DEFAULT_MAT_V] = material.obj
 97  
 98          # Hidden material - configurable
 99          if self.hidden_material is True:
100              # Default: use same material for hidden lines (solid look)
101              self.obj[c4d.OUTLINEMAT_LINE_DEFAULT_MAT_H] = material.obj
102          elif self.hidden_material is False or self.hidden_material is None:
103              # X-ray effect: no hidden material (see-through)
104              self.obj[c4d.OUTLINEMAT_LINE_DEFAULT_MAT_H] = None
105          else:
106              # Custom hidden material provided
107              self.obj[c4d.OUTLINEMAT_LINE_DEFAULT_MAT_H] = self.hidden_material.obj
108  
109          self.linked_material = material
110          material.linked_tag = self
111  
112      def set_tag_properties(self):
113          # Line type enables
114          self.obj[c4d.OUTLINEMAT_LINE_SPLINES] = self.splines
115          self.obj[c4d.OUTLINEMAT_LINE_FOLD] = self.folds
116          self.obj[c4d.OUTLINEMAT_LINE_CREASE] = self.creases
117          self.obj[c4d.OUTLINEMAT_LINE_BORDER] = self.border
118          self.obj[c4d.OUTLINEMAT_LINE_CONTOUR] = self.contour
119          self.obj[c4d.OUTLINEMAT_LINE_OUTLINE] = self.outline
120          # Contour settings
121          self.obj[c4d.OUTLINEMAT_LINE_CONTOUR_POSITION] = self.contour_position
122          self.obj[c4d.OUTLINEMAT_LINE_CONTOUR_POSITION_SPACING] = self.contour_spacing_mode
123          self.obj[c4d.OUTLINEMAT_LINE_CONTOUR_POSITION_SPACE] = self.contour_spacing
124  
125      def set_unique_desc_ids(self):
126          self.desc_ids = {
127              "render_splines": c4d.DescID(c4d.DescLevel(c4d.OUTLINEMAT_LINE_SPLINES, c4d.DTYPE_BOOL, 0))
128          }
129  
130  
131  
132  class FillTag(MaterialTag):
133  
134      def specify_tag_type(self):
135          self.obj = c4d.BaseTag(c4d.Ttexture)  # create fill tag
136  
137      def link_to_material(self, material):
138          self.obj.SetMaterial(material.obj)
139          self.linked_material = material
140          material.linked_tag = self
141  
142      def set_tag_properties(self):
143          pass
144  
145  
146  class XPressoTag(Tag):
147  
148      def __init__(self, priority=0, priority_mode="animation", **kwargs):
149          super().__init__(**kwargs)
150          self.set_priority(priority, mode=priority_mode)
151  
152      def specify_tag_type(self):
153          self.obj = c4d.BaseTag(c4d.Texpresso)
154  
155      def set_priority(self, value, mode="animation"):
156          # define priority modes
157          modes = {
158              "initial": c4d.CYCLE_INITIAL,
159              "animation": c4d.CYCLE_ANIMATION,
160              "expression": c4d.CYCLE_EXPRESSION
161          }
162          # set execution priority
163          priority_data = self.obj[c4d.EXPRESSION_PRIORITY]
164          # set priority value
165          priority_data.SetPriorityValue(c4d.PRIORITYVALUE_PRIORITY, value)
166          # set mode to initial
167          priority_data.SetPriorityValue(c4d.PRIORITYVALUE_MODE, modes[mode])
168          self.obj[c4d.EXPRESSION_PRIORITY] = priority_data
169  
170  
171  class TargetTag(Tag):
172  
173      def __init__(self, focus_point=None, **kwargs):
174          self.focus_point = focus_point
175          super().__init__(**kwargs)
176          self.set_target(self.focus_point)
177  
178      def specify_tag_type(self):
179          self.obj = c4d.BaseTag(c4d.Ttargetexpression)
180  
181      def set_target(self, target):
182          """Set the target object for this tag to look at.
183  
184          Args:
185              target: A DreamTalk object (with .obj attribute) or c4d.BaseObject
186          """
187          if hasattr(target, 'obj'):
188              self.obj[c4d.TARGETEXPRESSIONTAG_LINK] = target.obj
189          else:
190              self.obj[c4d.TARGETEXPRESSIONTAG_LINK] = target
191          self.focus_point = target
192  
193  
194  class AlignToSplineTag(Tag):
195  
196      def __init__(self, spline=None, tangential=True, **kwargs):
197          self.spline = spline
198          self.tangential = tangential
199          super().__init__(**kwargs)
200          self.set_spline()
201  
202      def specify_tag_type(self):
203          self.obj = c4d.BaseTag(c4d.Taligntospline)
204  
205      def set_spline(self):
206          self.obj[c4d.ALIGNTOSPLINETAG_LINK] = self.spline.obj
207          self.obj[c4d.ALIGNTOSPLINETAG_TANGENTIAL] = self.tangential
208  
209      def set_unique_desc_ids(self):
210          self.desc_ids = {
211              "position": c4d.DescID(c4d.DescLevel(c4d.ALIGNTOSPLINETAG_POSITION, c4d.DTYPE_REAL, 0)),
212          }