PDA

View Full Version : Accessing keys of a Curve Node



bazsa73
03-18-2017, 10:50 AM
Hello Guys,
I tried to google this up but couldn't find any reference, so the question is:
How do I access envelopes/channels of a node, namingly the envelopes of a Curve node created inside the Displacement node editor?
Is it possible at all?
Thanks in advance for any answer.

Diepgroen
03-18-2017, 09:33 PM
I think most if not all channel envelopes can be accessed through Python. But I might be wrong.
If you can activate the envelope i think LWPython can access it, read it and manipulate it. I find it really tricky though.

You will need to make use of these functions and classes:

classes


lwsdk.LWInterfaceInfo()
lwsdk.LWItemInfo()
lwsdk.LWChannelInfo()
lwsdk.LWEnvelopeFuncs()

functions/ methods



lwsdk.LWInterfaceInfo().selected_items()
lwsdk.LWItemInfo().chanGroup()
lwsdk.LWChannelInfo().nextGroup()
lwsdk.LWChannelInfo().channelName()


LWEnvelopeFuncs() has about 21 methods to work with. With these you can read and manipulate the keys and tailor your script to your needs.

The tricky part is getting to the value you want to manipulate, which in your case is the curve node envelope value. Using the lwsdk.LWItemInfo().chanGroup() and lwsdk.LWChannelInfo().nextGroup() is the key to travel down the subgroup list.

Image

136309

Object.CurveNode.CurveRed.Key.Value


you will need to loop through 3 subgroups in this example:


SelectedObject = lwsdk.LWInterfaceInfo().selected_items()

for x in range(0, len(SelectedObject)):
channelGroup = lwsdk.LWItemInfo().chanGroup(selectedObject) #object
channelGroup = lwsdk.LWChannelInfo().nextGroup(channelgroup, None) #subgroup CurveNode
channelGroup = lwsdk.LWChannelInfo().nextGroup(channelgroup, None) #subgroup CurveRed
channelGroup = lwsdk.LWChannelInfo().nextGroup(channelgroup, None) #subgroup Key
channel = lwsdk.LWChannelInfo().nextChannel(channelgroup, None) #subgroup Value
channelName = lwsdk.LWChannelInfo().channelName(channel)

while channel != None:
channelName = lwsdk.LWChannelInfo().channelName(channel)

if channelName == "Value":
# your magical script here

channel = lwsdk.LWChannelInfo().nextChannel(channelgroup, channel) #subgroup Value


Hope this gets you on the right track.

bazsa73
03-19-2017, 01:10 AM
Thanks a lot, I give it a try.

bazsa73
03-19-2017, 10:30 AM
I can reach now the Curve node inside the displacement. I want to control the Curve keys using a few Nulls so I don't have to setup expressions


def findEnv(self, itemType):
id = lwsdk.LWItemInfo().first( itemType, None )
groupID = lwsdk.LWItemInfo().chanGroup( id )
parent = None
while groupID:
if groupID != None:
groupName = str ( lwsdk.LWChannelInfo().groupName(groupID) ) #group name
print ("groupID: " + groupName)
if 'Curve' in groupName:
print 'Curve node'
chan = lwsdk.LWChannelInfo().nextChannel(groupID,parent)
while chan:
channelName = lwsdk.LWChannelInfo().channelName(chan)
nextchan = lwsdk.LWChannelInfo().nextChannel(groupID, chan)
print("channelName:" + channelName)
chan = nextchan

nextid = lwsdk.LWChannelInfo().nextGroup(groupID,parent)
parent = groupID
groupID = nextid


chinfo = lwsdk.LWChannelInfo()
chan = chinfo.nextChannel(groupID, None)
while chan:
channelName = chinfo.channelName(chan)
nextchan = chinfo.nextChannel(groupID, chan)
print("channelName:" + channelName)
chan = nextchan

ernpchan
03-19-2017, 10:43 AM
I want to control the Curve keys using a few Nulls so I don't have to setup expressions


What do you mean? How would you control the envelope without an expression? And further control specific keyframes?

bazsa73
03-19-2017, 12:12 PM
What do you mean? How would you control the envelope without an expression? And further control specific keyframes?
I dont want to write for each frigging key in the curve an expression. I want one master expression which handles all the keys in the curve.

Diepgroen
03-20-2017, 03:58 AM
I dont want to write for each frigging key in the curve an expression. I want one master expression which handles all the keys in the curve.

If I understand correctly, you would like to attach an expression the old-fashioned way (in the Expressions tab in the Graph Editor) to all selected keys in a single-shot? I don't really see any information how to attach expressions directly to the expressions tab in the graph editor. But than again you can write clever code in python to do all this. But there are no examples of this. It's up to you i think to come up with something like that, Told you it was tricksy :)

Diepgroen
03-20-2017, 04:05 AM
If I understand correctly, you would like to attach an expression the old-fashioned way (in the Expressions tab in the Graph Editor) to all selected keys in a single-shot?

Correction: sorry i meant, expressions get attached to channels not keys.

bazsa73
03-20-2017, 11:58 AM
If I understand correctly, you would like to attach an expression the old-fashioned way (in the Expressions tab in the Graph Editor) to all selected keys in a single-shot? I don't really see any information how to attach expressions directly to the expressions tab in the graph editor. But than again you can write clever code in python to do all this. But there are no examples of this. It's up to you i think to come up with something like that, Told you it was tricksy :)
I tell you my problem first which has started this whole issue. I do this video mapping on a building, it is very wide.
I build geometry on the existing geometry from several parts and I use DPkit part move on it to do different motion graphic stuff. I control the parts via Curve nodes.
Typically one curve contains 4 keys at least and each key has a position and a value envelope. That's already 8 things to control. I want to write a script which handles
this for me. Let's say some sort of master plugin which evaluates on a per frame basis and adjusts the keys accordingly.

Diepgroen
03-21-2017, 02:43 AM
I tell you my problem first which has started this whole issue. I do this video mapping on a building, it is very wide. I build geometry on the existing geometry from several parts and I use DPkit part move on it to do different motion graphic stuff. I control the parts via Curve nodes.
Typically one curve contains 4 keys at least and each key has a position and a value envelope. That's already 8 things to control. I want to write a script which handles this for me. Let's say some sort of master plugin which evaluates on a per frame basis and adjusts the keys accordingly.


I tell you my problem first which has started this whole issue. I do this video mapping on a building, it is very wide.
I build geometry on the existing geometry from several parts and I use DPkit part move on it to do different motion graphic stuff. I control the parts via Curve nodes. Typically one curve contains 4 keys at least and each key has a position and a value envelope. That's already 8 things to control. I want to write a script which handles this for me. Let's say some sort of master plugin which evaluates on a per frame basis and adjusts the keys accordingly.

I won't be much help to you at my level of coding, sorry.

At least we know now that it's not about the Expressions Tab and attaching literal LWExpressions via Python. Because i think that part was not possible to my knowledge. But at least you got the channel you where looking for. Hope you can figure it out. If you do, let us know how you solved this problem.

bazsa73
03-21-2017, 12:32 PM
I won't be much help to you at my level of coding, sorry.

At least we know now that it's not about the Expressions Tab and attaching literal LWExpressions via Python. Because i think that part was not possible to my knowledge. But at least you got the channel you where looking for. Hope you can figure it out. If you do, let us know how you solved this problem.
Thanks for your efforts dude. Maybe this is just way too difficult issue to deal with but I dont give up on it. Thanks again.

bazsa73
03-26-2017, 04:33 AM
I can reach the channel but I can't figure out how to attach the expression to it. Darn.
In order to test this script one needs to create a deformational nodal setup for any object on the Deform tab under node editor adding a Curve node.
In this case the Alpha channel is used so tick its envelopes, any of them will be ok. 1 is enough.



import sys
import lwsdk
import random
import math

__author__ = "Bazsa"
__date__ = "2017"
__copyright__ = "Bazsa"
__version__ = "0.1b"
__maintainer__ = "Bazsa"
__email__ = "[email protected]"
__status__ = "beta"
__lwver__ = "11"
serverClasses = { lwsdk.LWCAMERA_HCLASS: 'CameraHandler', \
lwsdk.LWCUSTOMOBJ_HCLASS: 'CustomObjHandler', \
lwsdk.LWDISPLACEMENT_HCLASS: 'DisplacementHandler', \
lwsdk.LWIMAGEFILTER_HCLASS: 'ImageFilterHandler', \
lwsdk.LWINSTANCER_HCLASS: 'InstancerHandler', \
lwsdk.LWITEMMOTION_HCLASS: 'ItemMotionHandler', \
lwsdk.LWLIGHT_HCLASS: 'LightHandler', \
lwsdk.LWOBJREPLACEMENT_HCLASS: 'ObjReplacementHandler' }


class addexpr(lwsdk.IGeneric):

def __init__(self, context):
super(addexpr, self).__init__()
#LWGeneric -------------------------------------------
itemType = lwsdk.LWI_OBJECT
id = lwsdk.LWItemInfo().first( itemType, None )

groupID = lwsdk.LWItemInfo().chanGroup( id )
prev = None

chinfo = lwsdk.LWChannelInfo()

subgroup = chinfo.nextGroup(groupID,prev)

while subgroup:
if subgroup != None:
groupName = str ( chinfo.groupName(subgroup) ) #group name
print ("groupID: " + groupName)
if 'Curve' in groupName:
curveprev = None
subgroupID = subgroup
curvesubgroup = chinfo.nextGroup(subgroupID,curveprev)
while curvesubgroup:
if curvesubgroup != None:
groupName = str ( chinfo.groupName(curvesubgroup) ) #group name
print ("subgroupID: " + groupName)

if 'Alpha' in groupName:
alphaprev = None
alphagroupID = curvesubgroup
alphasubgroup = chinfo.nextGroup(alphagroupID,alphaprev)
while alphasubgroup:
if alphasubgroup != None:
groupName = str ( chinfo.groupName(alphasubgroup) ) #group name
print ("subgroupID: " + groupName)
chan = lwsdk.LWChannelInfo().nextChannel(alphasubgroup,No ne)
if chan != None:
channelName = lwsdk.LWChannelInfo().channelName(chan)
print("channelName:" + channelName)
channelEnvelope =lwsdk.LWChannelInfo().channelEnvelope(chan)
cmd = "GE_CreateExpression " + "chExpr " + "([csild.Position.X])"
lwsdk.command(cmd)
cmd = "GE_AttachExpression " + "PalaceWindowsOnly:Layer2.Curve (1).Alpha.Key (1).Pos" + " chExpr"
#cmd = "GE_AttachExpression " + str(channelEnvelope) + " chExpr"
lwsdk.command(cmd)
alphasubgroup = chinfo.nextGroup(alphagroupID,alphasubgroup)

curvesubgroup = chinfo.nextGroup(subgroupID,curvesubgroup)


prev = groupID
groupID = subgroup
subgroup = chinfo.nextGroup(groupID,prev)


# while groupID:
# if groupID != None:
# groupName = str ( lwsdk.LWChannelInfo().groupName(groupID) ) #group name
# print ("groupID: " + groupName)

# nextid = lwsdk.LWChannelInfo().nextGroup(previous,groupID)
# previous = groupID
# groupID = nextid

# chan = lwsdk.LWChannelInfo().nextChannel(groupID,None)
# while chan:
# channelName = lwsdk.LWChannelInfo().channelName(chan)
# print("channelName:" + channelName)
# nextchan = lwsdk.LWChannelInfo().nextChannel(groupID, chan)
# chan = nextchan

# cmd = "GE_CreateExpression " + "fasz " + "([csild.Position.X])"
# lwsdk.command(cmd)
# cmd = "GE_AttachExpression " + "PalaceWindowsOnly:Layer2.Curve(1).Alpha.Key(2) " + "fasz"
# lwsdk.command(cmd)

# def recursiveChannelWalk(parent,groupID):
# while groupID:
# if groupID != None:
# groupName = str ( lwsdk.LWChannelInfo().groupName(groupID) ) #group name
# print ("groupID: " + groupName)

# groupID = lwsdk.LWChannelInfo().nextGroup(parent,groupID)

# parent = lwsdk.LWChannelInfo().groupParent(groupID)
# recursiveChannelWalk(parent,groupID)


ServerTagInfo = [
( "addexpr", lwsdk.SRVTAG_USERNAME | lwsdk.LANGID_USENGLISH ),
( "addexpr", lwsdk.SRVTAG_BUTTONNAME | lwsdk.LANGID_USENGLISH ),
( "Utilities/Python", lwsdk.SRVTAG_MENU | lwsdk.LANGID_USENGLISH )
]

ServerRecord = { lwsdk.GenericFactory("addexpr", addexpr) : ServerTagInfo }

Diepgroen
03-26-2017, 07:30 AM
I can reach the channel but I can't figure out how to attach the expression to it. Darn.
In order to test this script one needs to create a deformational nodal setup for any object on the Deform tab under node editor adding a Curve node.
In this case the Alpha channel is used so tick its envelopes, any of them will be ok. 1 is enough.

That's good progress Bazsa! I had it all wrong ofcourse. You can indeed attach Expressions.

GE_CreateExpression sname sexpression
GE_AttachExpression schannelname sexpressionname
GE_AttachExpressionID xchannelid sexpressionname

Your commands are not recognising the Expressions?

bazsa73
03-26-2017, 10:31 AM
That's good progress Bazsa! I had it all wrong ofcourse. You can indeed attach Expressions.

GE_CreateExpression sname sexpression
GE_AttachExpression schannelname sexpressionname
GE_AttachExpressionID xchannelid sexpressionname

Your commands are not recognising the Expressions?
Cheers,
Dude, it works on an ordinary Camera.Position.X channel like a charm. I just run the script and I see the dot in the graph editor indicating
that a script has been attached to it. But this uncommon Curve node key envelope channel just doesn't behave in a similar manner. Is it due to the spaces in the name?
Just can't get my head around it. Darn.

Diepgroen
03-26-2017, 12:30 PM
Cheers,
Dude, it works on an ordinary Camera.Position.X channel like a charm. I just run the script and I see the dot in the graph editor indicating
that a script has been attached to it. But this uncommon Curve node key envelope channel just doesn't behave in a similar manner. Is it due to the spaces in the name?
Just can't get my head around it. Darn. You are almost there, man! You got at least the Camera.Position.X to work. If you are not reaching the value of the curve node is because of a typo in the name. Because you are putting the literal name yourself it might be incorrect somehow. Don't know for sure. But looking at the image i posted before there is a double dot (..) in the name.

Might that be causing trouble?

bazsa73
03-26-2017, 12:34 PM
You are almost there, man! You got at least the Camera.Position.X to work. If you are not reaching the value of the curve node is because of a typo in the name. Because you are putting the literal name yourself it might be incorrect somehow. Don't know for sure. But looking at the image i posted before there is a double dot (..) in the name.

Might that be causing trouble?
I tried the wildest combinations :D, some made Layout crash but still nothing. GE_AttachExpression should take Channel ID as a parameter which I have but that doesn't work either.

edit:
Only GE_CreateExpression works. AttachExpression doesn't.

Diepgroen
03-26-2017, 12:50 PM
I tried the wildest combinations :D, some made Layout crash but still nothing. GE_AttachExpression should take Channel ID as a parameter which I have but that doesn't work either.

edit:
Only GE_CreateExpression works. AttachExpression doesn't.

You might be right, maybe it's something not obvious at all. One thing is clear you have a few variables to account for: sname, sexpression, schannelname, sexpressionname, xchannelid, 5 of them. tricky

Diepgroen
03-26-2017, 12:55 PM
GE_AttachExpression should take Channel ID as a parameter Wait GE_AttachExpression should only take schannelname sexpressionname, not the id

bazsa73
03-26-2017, 01:38 PM
I try it with a different object with a simpler name. Must exist a some solution to it.

bazsa73
03-26-2017, 01:51 PM
Wait GE_AttachExpression should only take schannelname sexpressionname, not the id
https://books.google.hu/books?id=czrtfbzjQ7oC&pg=PA536&lpg=PA536&dq=lightwave+GE_AttachExpression&source=bl&ots=uR0iXKJoVg&sig=jYUncuF5mMb6wPaGJl3uWoHp98Q&hl=en&sa=X&ved=0ahUKEwjs0Zn_6vTSAhXoBZoKHeX3C-MQ6AEIGjAA#v=onepage&q=lightwave%20GE_AttachExpression&f=false
looky, on page 537 the note with small typo, the author explains smg about "" charactert, but is it still valid in python?

Diepgroen
03-27-2017, 01:44 AM
https://books.google.hu/books?id=czrtfbzjQ7oC&pg=PA536&lpg=PA536&dq=lightwave+GE_AttachExpression&source=bl&ots=uR0iXKJoVg&sig=jYUncuF5mMb6wPaGJl3uWoHp98Q&hl=en&sa=X&ved=0ahUKEwjs0Zn_6vTSAhXoBZoKHeX3C-MQ6AEIGjAA#v=onepage&q=lightwave%20GE_AttachExpression&f=false
looky, on page 537 the note with small typo, the author explains smg about "" charactert, but is it still valid in python?


Thank you for confusing me further with LScript :) I think you found what's causing the error. Spaces!!!! You are not using spaces in your GE_Create, but you do use spaces in your GE_Attach. which surely is the source.
What I can see is that strExp (book example) is a string variable with spaces in it. And the autor does say if expressions, names and channelnames have spaces use double quote characters. How this translates to Python i don't really know.

What your actually doing i think is this (GE_AttachExpression schannelname badvariable badvariable sexpressionname) if i compare Your "PalaceWindowsOnly:Layer2.Curve (1).Alpha.Key (1).Pos" it has 2 spaces in Curve (1) and Key (1). Could that be the problem?

bazsa73
03-27-2017, 10:33 AM
Sorry for confusing but actually a commandinput command is a short Lscript and there is scarce references on this topic throughout the interweb.
I dont know what is the problem but it works with an ordinary channel like Camera.Position.X. I tested it, I can even display a channel in the graph editor but these
cumbersome subchannels do not want to cooperate. Strange thing. Maybe I should report this to the developers.

Ryan Roye
04-03-2017, 09:28 AM
AttachExpression doesn't.

It does, it just for some reason requires quotes where you don't expect them.

Example: This script works. It takes your selected item and makes the Y channel affect the bank channel (move the object up or down after running this script to see the effect).



import lwsdk

# LW ID as seen by python script
UserSelection = lwsdk.LWInterfaceInfo().selected_items()[0]

# LW Hexadecimal identifier, used in commands
UserSelectionID = lwsdk.itemid_to_str(UserSelection)

# Name of the item as seen by the user.
UserSelectionName = lwsdk.LWItemInfo().name(UserSelection)

# CreateExpression format:
# GE_CreateExpression NameOfExpression Expression
# GE_AttachExpression "ChannelYouWantToAffect" NameOfExpression

lwsdk.command("GE_CreateExpression z" + UserSelectionID + " Value + [" + UserSelectionName + ".Position.Y]*100")
lwsdk.command("GE_AttachExpression \"" + UserSelectionName + ".Rotation.B\" " + "z" + UserSelectionID)

# These print statement shows the syntax of the create/attach expression commands without variable placeholders.
# It is very strict, any errors will result in either crashing or nothing happening.

# Also, notice I put the letter "Z" in front of the ID name, as expression names cannot consist entirely of numbers.
print "GE_CreateExpression z" + UserSelectionID + " Value + [" + UserSelectionName + ".Position.Y]*100"
print "GE_AttachExpression \"" + UserSelectionName + ".Rotation.B\" " + "z" + UserSelectionID

bazsa73
04-03-2017, 12:12 PM
Hello Ryan, thanks for stopping by. I just wonder how to attach script to a channel with this name: [Unweldbox.Curve (1).Alpha.Key (2).Pos]
Ordinary transform channels are working for me too. I can attach a script to a Position channel without problem but not to the this Curve node Key.