[Closed] [SOLVED] Scripted controller self reference mystery on animated spline
I am playing with scripted controllers . According to the help files I am able to set the text input of a textobject by adding a scripted controller to the kerning controller of said textobject
b=box name: "ControlBox" wirecolor:blue
t=text name: "ControlledText" wirecolor:red
t.baseobject.renderable=true --set the shape to renderable
theCtrl = float_script() --create a float script controller
theCtrl.addNode "TheText" t --add a variable, connect to theText node
theCtrl.addNode "TheBox" b --add a variable, connect to the Box node
--Set the expression to assign the height of the box as string to the
--.text property of the text shape, then return 0 on the next line:
theCtrl.SetExpression "TheText.text = TheBox.height as string\n0"
t.kerning.controller=theCtrl --assign the controller to the kerning
So far so good, this all works as explained.
However, when I try to control the points of a spline by adding a float_script() to one of the variables, say the angle controller of the spline, and then reference the spline itself in this script to set the points I get an “Illegal self reference in scripted controller” warning. See code and variables below.
knotCount = numknots cableObject 1
for i=1 to knotCount do
(
knotPos = pointA.pos + (((pointB.pos - pointA.pos)/(knotCount-1))*i-1)
setknotPoint cableObject 1 i knotPos
)
updateShape cableObject
)
where the variables in the script controller are:
cableObject = my line
pointA = 1st helper
pointB = 2nd helper
Not very surprising you would say, but why does that message not show up on the textobject example? A similar self reference is made there in the line 5 and 10!
I’ve been playing with this for two hours now, but I cannot seem to get it working properly. I can accept the self reference limitation, and I can work around that I’m sure. But if there is an explanation or a loophole somewhere I would love to know about it
You can get self boject by function, and operate whith them after
fn fn_GetSelf =( (refs.dependentNodes (refs.dependents this)[1])[1] )
_self_ = fn_GetSelf ()
Unfortunately, that is not the case for settings spline knots on a renderable spline. Wrapping up a quick script attached to the angle parameter of the spline will give the illegal self reference warning. I think this is because the value needs to be evaluated for renderable spline radial values to work.
fn fn_GetSelf =( (refs.dependentNodes (refs.dependents this)[1])[1] )
_self_ = fn_GetSelf ()
setknotPoint _self_ 1 1 pointA.pos
setknotPoint _self_ 1 2 pointB.pos
updateShape _self_
0
However, when I set this script to the angle2 variable, which is used by the rectangular renderable spline shape, the script works, but crashes when I add modifiers to the spline.
You see, there seem to be some halfway loopholes, and I am wondering if there is more information about this.
for example… how to use it in scripted controller
controller example – from Autodesk help
plugin Point3Controller Point3Controller_example
name:"Point3Controller Example"
classID:#(0x47db14ff, 0x4e9b5f9f)
(
parameters pblock
(
offset_value type:#point3 animatable:true
valueController type:#maxobject subAnim:true
)
fn fn_GetSelf =( (refs.dependentNodes (refs.dependents this)[1])[1] )
on getValue do
(
valueController.value + offset_value
)
on setValue val relVal commit do
(
_self_ = fn_GetSelf ()
val -= _self_.scale --- this for example
SetControllerValue valueController val commit #absolute
)
on create do
(
valueController = NewDefaultPoint3Controller()
isLeaf=true
)
)
Ok, I see that working yes. Thanks for replying so far.
Maybe I should have clarified my challenge. I am trying to modify a spline in such a way that it is changing shape according to a scripted controller and remains renderable.
Since this should also work in the renderfarm I am trying to avoid having to use scripted plugins, as they are not saved in the scene and I would have to distribute them across all render slaves. At least, this is what I am assuming.
Are there ways around the illegal self reference issue outside of using scripted plugins?
But why script controller?
There’s MasterPointController in Spline and all verts can and will get (at least) pos. controllers if you decide to animate those.
There’s also Spline IK Control Modifier for animating verts thru other (helper) objects…
Yes, those are valid options too, although animating the spline IK controls would require me to add helpers to the scene which might add up real quick on multiple splines. And as we know, helpers are a bit slower in the viewport.
Never played with MasterPointController though, so that might be interesting.
I still think it doesn’t make sense that, as I mentioned in my first post, the self reference works on the textobject example, but doesn’t on my spline example. What is the difference there?
---- create spline with any number of knots (set tangents to corner)
---- create 2 dummies
---- names "Line001" "Dummy001" "Dummy002"
splCA = attributes splCA
(
parameters main
(
pnts type:#NodeTab TabSize:2
)
fn fn_GetSelf =( (refs.dependentNodes (refs.dependents this)[1])[1] )
fn updSpline =(
self_ = fn_GetSelf()
knotCount = numknots self_ 1
for i=1 to knotCount do
(
knotPos = pnts[1].pos + (((pnts[2].pos - pnts[1].pos)/(knotCount-1))*i-1)
setknotPoint self_ 1 i knotPos
)
updateShape self_
)
)
CustAttributes.add $Line001 splCA
$Line001.pnts = #($Dummy001,$Dummy002)
$Dummy001.scale.controller = scale_script()
$Dummy001.scale.controller.addNode "sp" $Line001
$Dummy001.scale.controller.script = "sp.updSpline ()
[1, 1, 1]"
$Dummy002.scale.controller = scale_script()
$Dummy002.scale.controller.addNode "sp" $Line001
$Dummy002.scale.controller.script = "sp.updSpline ()
[1, 1, 1]"
what about something like this?
delete objects
gc()
p1 = point name:#pt_1 pos:[50,25,0]
p2 = point name:#pt_2 pos:[-50,25,0]
rect = Rectangle width:100 length:50
convertToSplineShape rect
rect.render_sides.controller = float_script()
rect.render_sides.controller.addobject "owner" (reftargmonitor reftarg:rect)
rect.render_sides.controller.addNode "p1" p1
rect.render_sides.controller.addNode "p2" p2
rect.render_sides.controller.script = "
self = owner.reftarg
setKnotPoint self 1 1 p1.pos
setKnotPoint self 1 2 p2.pos
updateShape self
12
"
And yet you have this in script:
pointA = 1st helper
pointB = 2nd helper