Jump to content

Hey guys, check out new PolyGnome tool for Cinema 4D from our long-time member C4DS. You can find PolyGnome in our Store and we hope you like it!! :cowboypistol:

Cinema 4D Plugins

SolarPH

UserData ID Scanning

Recommended Posts

SolarPH    6

I have successfully added a UserData using python.

 

Now, I need to have an object to scan if the object dragged into the link field have the userdata that I have assigned.

 

For this project, I used UserData ID 200.

 

I have some Trial and Error, but nothing work.

 

The closest one I have been is within this script:

 

import c4d

 

def main():
    
    objlink = obj[c4d.ID_USERDATA,2]
    
    if [c4d.ID_USERDATA,200] in objlink.GetUserDataContainer():
        print "Success"
    else:
        print "Failed"

 

but it always prints "Failed" instead of "Success" even that the linked object have a User Data with ID 200.

 

What did I get wrong with the code?

 

If you want to check the file, here it is:

 

UserDataScan.c4d

 

The Cube have the UserData ID 200, while the Cylinder does not have UserData ID 200.

The Null is the one who needs the linked object.

Share this post


Link to post
Share on other sites

Abyss    19

@SolarPH

 

Interesting.

 

Well first of all to find out whats wrong you can print out what objlink.GetUserDataContainer() returns and print out what [c4d.ID_USERDATA,200] returns.

They return different types.

 

the first is a list of tuples and the other is a list of two numbers. That's why it is not working.

What you can do is first to try and extract the number you are looking for in the list of tuples

once you have that you extract the number from the list as well and then simply compare if they are the same.

 

In this case you dont have the extract the number from the list since you know what value you are looking for. its 200. so you can simple compare the first extracted number to 200.

 

Hope this all makes sense.

 

Here is the code. it should work.

 

def main():
    
    objlinktemp = obj[c4d.ID_USERDATA,2]

    tup = objlinktemp.GetUserDataContainer() # returns list of tuples
    tup2 = [x[0] for x in tup] # returns the first tuple list
    tup3 = ([x[1] for x in tup2]) # returns the second tuple number which is the id

    while True:
        try:
            idnum = tup3[0].id     #returns objects first userID number
            if idnum == 200:
                print "Success the object id 200"
            else:
                print "Failed the object id is not 200"
            break
        except IndexError:
            print "No user id input in the object"
            break

Share this post


Link to post
Share on other sites
SolarPH    6
Just now, Abyss said:

@SolarPH

 

Interesting.

 

Well first of all to find out whats wrong you can print out what objlink.GetUserDataContainer() returns and print out what [c4d.ID_USERDATA,200] returns.

They return different types.

 

the first is a list of tuples and the other is a list of two numbers. That's why it is not working.

What you can do is first to try and extract the number you are looking for in the list of tuples

once you have that you extract the number from the list as well and then simply compare if they are the same.

 

In this case you dont have the extract the number from the list since you know what value you are looking for. its 200. so you can simple compare the first extracted number to 200.

 

Hope this all makes sense.

 

Here is the code. it should work.

 

def main():
    
    objlinktemp = obj[c4d.ID_USERDATA,2]

    tup = objlinktemp.GetUserDataContainer() # returns list of tuples
    tup2 = [x[0] for x in tup] # returns the first tuple list
    tup3 = ([x[1] for x in tup2]) # returns the second tuple number which is the id

    while True:
        try:
            idnum = tup3[0].id     #returns objects first userID number
            if idnum == 200:
                print "Success the object id 200"
            else:
                print "Failed the object id is not 200"
            break
        except IndexError:
            print "No user id input in the object"
            break

Thanks for replying!

 

I will test your code.

Share this post


Link to post
Share on other sites
SolarPH    6

@Abyss

 

I have tested your code.

 

Yes, it works, but has a downside.

 

It only scans the first tuple, so the script will not work as expected.

Share this post


Link to post
Share on other sites
Abyss    19
1 minute ago, SolarPH said:

@Abyss

 

I have tested your code.

 

Yes, it works, but has a downside.

 

It only scans the first tuple, so the script will not work as expected.

What do you mean it only scans the first tuple? It doesnt .

Do you mean it only scans the first the user data? 

 

You can easily fix that and have it scan the second if there is a second one or even third, fourth, fifth.

 

 

If you want to check if an object with multiple user data inputs has any input with the id 200 . you can do that too. As it is now. it checks if the first user data input is equal to 200 and it also checks if there is a user data input at all. if not it will also return false

Share this post


Link to post
Share on other sites
SolarPH    6
Just now, Abyss said:

What do you mean it only scans the first tuple? It doesnt .

Do you mean it only scans the first the user data? 

 

You can easily fix that and have it scan the second if there is a second one or even third, fourth, fifth.

 

 

If you want to check if an object with multiple user data inputs has any input with the id 200 . you can do that too. As it is now. it checks if the first user data input is equal to 200 and it also checks if there is a user data input at all. if not it will also return false

For the example you gave, it did only scanned the first user data in the manager.

 

Also, it always works in any range of user data count.

 

Btw, I have some modifications with your script, and searched for python codes for extracting user data IDs, and revising it, I have hit the code that I wanted.

 

import c4d
#Welcome to the world of Python

 

image.thumb.png.2eae8701bddfbe96d953230c147ab437.png


def main():
    
    objlink = obj[c4d.ID_USERDATA,1]
    
    OBJ_A = objlink.GetUserDataContainer()
    
    print OBJ_A
    
    OBJ_B = [x[0] for x in OBJ_A]
    
    print OBJ_B
    
    OBJ_C = [x[1].id for x in OBJ_B]
    
    print OBJ_C
    
    if 200 in OBJ_C:
        print "Success"
    else:
        print "Failed"

 

OBJ_A extracted all the User Data entries from the object linked

OBJ_B extracted the first tuple entries from all the tuples available

OBJ_C extracted the actual IDs of all User Data entries from OBJ_B

 

Since I have accomplished this step, the next one is to clear the object field if the linked object either don't have the ID number, or have an Invalid Object ID from User Data 200, since it uses Static Text userdata subtype.

Edited by SolarPH

Share this post


Link to post
Share on other sites
Abyss    19
18 minutes ago, SolarPH said:

For the example you gave, it did only scanned the first user data in the manager.

 

Also, it always works in any range of user data count.

 

Btw, I have some modifications with your script, and searched for python codes for extracting user data IDs, and revising it, I have hit the code that I wanted.

 

import c4d
#Welcome to the world of Python

 

image.thumb.png.2eae8701bddfbe96d953230c147ab437.png


def main():
    
    objlink = obj[c4d.ID_USERDATA,1]
    
    OBJ_A = objlink.GetUserDataContainer()
    
    print OBJ_A
    
    OBJ_B = [x[0] for x in OBJ_A]
    
    print OBJ_B
    
    OBJ_C = [x[1].id for x in OBJ_B]
    
    print OBJ_C
    
    if 200 in OBJ_C:
        print "Success"
    else:
        print "Failed"

 

OBJ_A extracted all the User Data entries from the object linked

OBJ_B extracted the first tuple entries from all the tuples available

OBJ_C extracted the actual IDs of all User Data entries from OBJ_B

 

Since I have accomplished this step, the next one is to clear the object field if the linked object either don't have the ID number, or have an Invalid Object ID from User Data 200, since it uses Static Text userdata subtype.

What exactly did you change in this one that does make it work? it basically is the same setup.

 

I had only added an extra feature under try. To see if there is a user data present at all. 

With the script you added here you cant see that. You are looking for ID 200 and if that isnt there you simply have it return as failed. But then you dont know whether it failed because the user data number on the object isnt equal to 200 or that here is no user data at all or perhaps even a different error. 

Share this post


Link to post
Share on other sites
SolarPH    6
On 9/11/2017 at 9:57 PM, Abyss said:

objlinktemp = obj[c4d.ID_USERDATA,2]

    tup = objlinktemp.GetUserDataContainer() # returns list of tuples
    tup2 = [x[0] for x in tup] # returns the first tuple list
    tup3 = ([x[1] for x in tup2]) # returns the second tuple number which is the id

    while True:
        try:
            idnum = tup3[0].id     #returns objects first userID number

This line from your script might be the cause.

 

idnum == tup3[0].id     #which returns the first User Data ID on topmost of the UserData Manager

 

instead of:

 

tup3 = [x[1].id for x in tup2]     #which returns a list of all UserData ID that exist within an object linked

On 9/11/2017 at 9:57 PM, Abyss said:

if idnum == 200:
                print "Success the object id 200"
            else:
                print "Failed the object id is not 200"
            break
        except IndexError:
            print "No user id input in the object"
            break

since you made this condition for the final result, it will fail if UserData that have the ID 200 is in any position other that the first.

 

The list of values for userdata is in order depends on how they were ordered in the object

Share this post


Link to post
Share on other sites
Abyss    19
12 minutes ago, SolarPH said:

This line from your script might be the cause.

 

idnum == tup3[0].id     #which returns the first User Data ID on topmost of the UserData Manager

 

instead of:

 

tup3 = [x[1].id for x in tup2]     #which returns a list of all UserData ID that exist within an object linked

Alright I guess you are right. That does indeed return a list of all the userdata not just the first one.

 

And your next step is?

 

you want to clear the remove the object from the object user data input? the object link.

if the id is not 200. or if OBJ_C returns an empty list

Share this post


Link to post
Share on other sites
SolarPH    6
Just now, Abyss said:

Alright I guess you are right. That does indeed return a list of all the userdata not just the first one.

 

And your next step is?

 

you want to clear the remove the object from the object user data input? the object link.

if the id is not 200. or if OBJ_C returns an empty list

I think I should change the next step, since I think I can assign a link input named NullPort, which is an empty link field.

 

The next step now is to make the script compatible at some range, like IDs 200, 201, and 202

 

For my current project, I do have 3 object classifications:

 

1 . Interactive Block (BLOCK_REGISTRY)

2. Structure (STRUCTURE_REGISTRY)

3. Item (ITEM_REGISTRY)

 

If you are familiar with Minecraft rigs or the game itself, the Interactive block will be with my redstone rig, the Structure with my End rig, and Item for the Item Frame rig, which is also in my redstone rig pack.

 

I need one of the IDs to be present, if none does, the object field will be cleared by this line:

 

obj[c4d.ID_USERDATA,1] == NullPort

 

which obj is the source, and NullPort is the input port with an empty link field.

 

I have this now in the ID assignments:

 

DATA_REGISTRY = 200

 

I changed the lines in the condition with this:

 

if DATA_REGISTRY not in OBJ_C:

          obj[c4d.ID_USERDATA,1] == NullPort

 

I tried to change the ID assignment to this:

 

DATA_REGISTRY = [200, 201, 202]     #First Attempt

DATA_REGISTRY = 200 or 201 or 202     #Second Attempt

 

On the first attempt, nothing worked, but also no error

On the second attempt, only 200 worked, others didn't, and still no error

Share this post


Link to post
Share on other sites
Abyss    19
37 minutes ago, SolarPH said:

I think I should change the next step, since I think I can assign a link input named NullPort, which is an empty link field.

 

The next step now is to make the script compatible at some range, like IDs 200, 201, and 202

 

For my current project, I do have 3 object classifications:

 

1 . Interactive Block (BLOCK_REGISTRY)

2. Structure (STRUCTURE_REGISTRY)

3. Item (ITEM_REGISTRY)

 

If you are familiar with Minecraft rigs or the game itself, the Interactive block will be with my redstone rig, the Structure with my End rig, and Item for the Item Frame rig, which is also in my redstone rig pack.

 

I need one of the IDs to be present, if none does, the object field will be cleared by this line:

 

obj[c4d.ID_USERDATA,1] == NullPort

 

which obj is the source, and NullPort is the input port with an empty link field.

 

I have this now in the ID assignments:

 

DATA_REGISTRY = 200

 

I changed the lines in the condition with this:

 

if DATA_REGISTRY not in OBJ_C:

          obj[c4d.ID_USERDATA,1] == NullPort

 

I tried to change the ID assignment to this:

 

DATA_REGISTRY = [200, 201, 202]     #First Attempt

DATA_REGISTRY = 200 or 201 or 202     #Second Attempt

 

On the first attempt, nothing worked, but also no error

On the second attempt, only 200 worked, others didn't, and still no error

 

DATA_REGISTRY = [203,200,202,201] # any order
 

print any((True for x in DATA_REGISTRY if x in OBJ_C))

 

_________

 

so something like this

 

    lst = [200,201,202,203,204]
    DATA_REGISTRY = any((True for x in lst if x in OBJ_C))
    
    if DATA_REGISTRY is True:
        print "yay"
    else:
        print "nay"

 

 

Share this post


Link to post
Share on other sites
SolarPH    6
Just now, Abyss said:

print any((True for x in DATA_REGISTRY if x in OBJ_C))

it prints out True even if I changed the "True" with "x"

 

but I can't find out how should I use it as a boole result for an if-else statement

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Recently Browsing   0 members

    No registered users viewing this page.

×