Snippets
Donovan Keith C4D Python SDK Python Spline Generator Object Input Example (WARNING: Not fully functional)
Created by
Donovan Keith
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | """Scale Spline Object
Takes a child-spline as input and scaled it's point's down by 50%. Tangents are unaffected.
v0.0.1
by Donovan Keith <donovanskeith@gmail.com>
Usage Instructions
------------------
1. Save in a file called ScaleSplineObject.pyp
2. Place in C4D Plugins director
3. Restart C4D
4. Plugins > Scale Spline Object
5. Add an NSide spline
6. Make the NSide spline a child of the Scale Spline Object.
Outstanding Issues
-------------------
- [ ] Nested child objects aren't properly hidden. To recreate:
ScaleSpline
|
-- Scale Spline
|
-- NSide
- [ ] GetDirty() probably needs to be reimplemented.
"""
# =====================================================================================================================#
# Imports
# =====================================================================================================================#
import c4d
# =====================================================================================================================#
# Class Definitions
# =====================================================================================================================#
class ScaleSplineObject(c4d.plugins.ObjectData):
PLUGIN_ID = 1038342 # TODO: Replace with your own ID from PluginCafe.com
def __init__(self):
self.last_child = None
def Init(self, op):
return True
def ConversionCommand(self, op, command_id):
"""Allows you to easily perform a MakeEditable or CSTO on an object.
reference: http://www.plugincafe.com/forum/forum_posts.asp?TID=5232
Returns early if op is a Spline
"""
if op is None:
return
op_clone = op.GetClone()
if op_clone is None:
return
# Is it a spline? No need to convert.
if op_clone.CheckType(c4d.Ospline):
return op_clone
# Perform the MakeEditable or CSTO in temporary document
temp_doc = c4d.documents.BaseDocument()
if not temp_doc:
return
temp_doc.InsertObject(op_clone)
result_list = c4d.utils.SendModelingCommand(command=command_id,
list=[op_clone],
doc=temp_doc)
# Did anything go wrong? Bail
if not result_list:
return
# Return the first object in the result list
return result_list[0]
def MakeEditable(self, op):
"""Returns a clone of `op` that's been made editable. Can return None."""
return self.ConversionCommand(op, command_id=c4d.MCOMMAND_MAKEEDITABLE)
def CurrentStateToObject(self, op):
"""Returns a clone of the current state of `op`. Can return None."""
return self.ConversionCommand(op, command_id=c4d.MCOMMAND_CURRENTSTATETOOBJECT)
def GetAsSpline(self, op):
"""Clones object as a c4d.Ospline - using the following priority
* Object if Spline
* Object Made Editable, if Spline
* Current State to Object, if Spline
Note: MakeEditable won't account for deformed splines, however, it will give you a spline
with fewer points which is preferable to CSTO for a lot of modeling operations.
"""
if op is None:
return
# Return op if it's a spline
if op.CheckType(c4d.Ospline):
return op.GetClone()
# Make it editable if it is.
made_editable = self.MakeEditable(op)
if made_editable is not None:
if made_editable.CheckType(c4d.Ospline):
return made_editable
# Peform a CSTO if need be
# TODO: See if this ever actually executes, probably doesn't
current_state = self.CurrentStateToObject(op)
if current_state is not None:
if current_state.CheckType(c4d.Ospline):
return current_state
def LocalizeSpline(self, op, spline):
"""Converts all of `spline`'s point to local space for `op`
This is necessary because GetContour assumes the spline is in the same
location as the object itself.
"""
# Verify Inputs
if (op is None) or (spline is None):
return
# Get points
spline_points = spline.GetAllPoints()
if not spline_points:
return
has_tangents = (spline.GetTangentCount() > 0)
spline_tangents = []
# Retrieve matrices for conversion math
spline_mg = spline.GetMg()
if not spline_mg:
return
op_mg = op.GetMg()
if not op_mg:
return
inverse_op_mg = ~op_mg
# Localize all points
for i, spline_point in enumerate(spline_points):
global_point = spline_point * spline_mg
local_point = global_point * inverse_op_mg
spline_points[i] = local_point
# Calculate new tangent positions
if has_tangents:
# Get tangents for point
tangent = spline.GetTangent(i)
vl = tangent["vl"]
vr = tangent["vr"]
# Transform tangents into their global locales
global_vl = (spline_point + vl) * spline_mg
global_vr = (spline_point + vr) * spline_mg
# Transform tangents from global points to point-local vectors.
vl = (global_vl * inverse_op_mg) - local_point
vr = (global_vr * inverse_op_mg) - local_point
# Store the updated points & tangents.
spline_tangents.append((vl, vr))
spline.SetTangent(i, vl, vr)
# Neutralize spline's Matrix
spline.SetMg(op_mg)
# Restore spline to previous positions
spline.SetAllPoints(spline_points)
# Update tangent positions as well
for i, tangent in enumerate(spline_tangents):
vl, vr = tangent
spline.SetTangent(i, vl, vr)
def CheckDirty(self, op, doc):
"""Marks the object as dirty if it's child object has been modified."""
if not op:
return
# Is there a new or missing child object?
child = op.GetDown()
if child != self.last_child:
# Dirty!
self.last_child = child
op.SetDirty(c4d.DIRTY_DATA)
return
# Can't do anythng without a child object.
if child is None:
return
# Has the child ben modified?
if child.IsDirty(c4d.DIRTYFLAGS_MATRIX |
c4d.DIRTYFLAGS_DATA |
c4d.DIRTYFLAGS_CHILDREN):
# Dirty!
op.SetDirty(c4d.DIRTYFLAGS_DATA)
def ModifySpline(self, spline):
"""Scales all spline points down by 50%"""
point_scaling_factor = 0.5
if spline is None:
return
spline_points = spline.GetAllPoints()
if spline_points is None:
return
for i, spline_point in enumerate(spline_points):
spline_points[i] = spline_point * point_scaling_factor
spline.SetAllPoints(spline_points)
def GetContour(self, op, doc, lod, bt):
"""Return the result of the generator spline."""
# Create an Empty Spline
if not op:
return
# Retrieve the child input object
child = op.GetDown()
if child is None:
return
# Tell C4D the child is a generator input object and should be hidden.
child.Touch()
# Get the child input object as a spline clone we can modify.
result_spline = self.GetAsSpline(child)
if result_spline is None:
return
# Scale down the spline points.
self.ModifySpline(result_spline)
# Ensure the spline points are localized to this generator's PSR.
self.LocalizeSpline(op, result_spline)
return result_spline
# =====================================================================================================================#
# Registration
# =====================================================================================================================#
if __name__ == "__main__":
c4d.plugins.RegisterObjectPlugin(id=ScaleSplineObject.PLUGIN_ID,
str="ScaleSplineObject",
g=ScaleSplineObject,
description=None,
icon=None,
info=c4d.OBJECT_GENERATOR | c4d.OBJECT_INPUT | c4d.OBJECT_ISSPLINE)
|
Comments (0)
You can clone a snippet to your computer for local editing. Learn more.