Isotropix Forums

General python data collecting questions

Clarisse Scripting related topics

General python data collecting questions

Unread postby DarkNemos » Thu Jun 28, 2018 11:11 pm

Hi guys,

I have a few general questions about writing python in clarisse that i would like to clarify. I understand that clarisse is using a C++ python wrapper in order to manipulate data, hence all the data structures are C++ like. My knowledge of C++ is on a very basic level but i do understand arrays and how they work on some level.

What is most confusing for me is how to get elements based on a certain criteria. When i say elements i mean anything that you could find in the clarisse scene.

Finding an object based on a name seems to be pretty easy. For example:

objects = ix.api.OfObjectVector() # not sure but i think it creates an empty object of type vector?
ix.application.get_matching_objects(objects, "*", "Light") # fills in the object with the objects matching

The problem for me starts when i want to find an object that belongs to something. For example i want to get all the objects that are in a 3d layer?

It seems to me that the code is different if you want to find:

- all objects connected to an image
- all objects connected to a layer 3d
- all objects in a group
- all object in a context
- all shaders connected to a shader group

... and so on.

Do i have to write recursive functions to walk through step by step collecting data or is there a more elegant way?

Can somebody please point me to the logic of searching and finding the right data in the right way?

Also i could not find anything in the documentation regarding what is: ix.api.OfContextSet(), OfContextArray(), OfObjectSet(), OfObjectArray() and so on. And also how to add to them.

When i want to manipulate a layer for example do i work with the object or do i work with the module?

Sorry if it was too many questions, i am just not used to writting code in a clarisse way :)

Thanks !
DarkNemos
 
Posts: 4
Joined: Sun Nov 19, 2017 4:16 am

Re: General python data collecting questions

Unread postby bvaldes » Mon Jul 09, 2018 2:27 pm

Hi,

There is different way to do depending on what you are looking for. A good start is to have a good understanding on how Clarisse works first.
I will try to answer at your question one by one.

1 - all objects connected to an image / all objects connected to a layer 3d
To get the connection (input or output), there is a menu for that: Edit > Select > Input/output recursively
All the menu in clarisse are written in python except windows. You can find the script in ClarisseInstall/python/menus/main_menu
Take a look to this example:

python code

# get the image
image = ix.get_item("project://scene/image")
# To get the inputs of this image, you have to select it
ix.selection.select(str(image)) # This function need an string not a Clarisse item, so you have to convert the item to string
ix.application.select_all_dependencies() # select all the connections to this node

# Now we have to deal with the selection
for i in range(ix,selection.get_count())
print ix.selection[i] # display the name of the object at the position `i` in the selection list

2 - all objects in a group
The result of a group is contained in the `references` attribute. So in python we have to get the content of this attribute to get the content of the group.

python code

# Get the group
group = ix.get_item("project://scene/group")

# Get the attribute that contain the result objects of a group
result_attr = group.get_attribute("references")
for i in range(result_attr.get_value_count()): # result_attr.get_value_count() correspond to the number of items in the result list
print result_attr.get_object(i) # display the name of the object at the position `i` in the selection list

3 - all objects in a context

python code

# Get the context
ctx = ix.get_item("project://scene")

# We have to create some arrays that will content the objects in the context
objects_array = ix.api.OfObjectArray(ctx.get_object_count()) # ctx.get_object_count() correspond to the number of items in the context

ctx.get_objects(objects_array) # this function get all the items in the context and fill the array `objects_array` of them

for i in range(ctx.get_object_count()):
print objects_array[i]

This script is quite simple and allow you to get only the first level. If you want it recursive, you can use the following function:

python code

def getSubContext(context = ix.get_current_context(), recursive = True):
result = []
context = ix.get_item(str(context))
sub_contexts = []
for i in range(context.get_context_count()):
result.append(context.get_context(i))
sub_contexts.append(context.get_context(i))
if recursive:
while len(sub_contexts)>0:
workOn = sub_contexts
sub_contexts = []
for context in workOn:
for i in range(context.get_context_count()):
sub_contexts.append(context.get_context(i))
result.append(context.get_context(i))
return result

def getItems(context = ix.get_current_context(), kind = None, recursive=True):
result = []
workOn = [ix.get_item(str(context))]
vItems = ix.api.OfItemVector()
if recursive:
for subContext in getSubContext(workOn[0], recursive = True):
workOn.append(subContext)

for context in workOn:
if (context.get_object_count()):
objects_array = ix.api.OfObjectArray(context.get_object_count())
context.get_objects(objects_array)
for i_obj in range(context.get_object_count()):
if kind is not None:
if objects_array[i_obj].is_kindof(kind):
vItems.add(objects_array[i_obj])
else:
vItems.add(objects_array[i_obj])

for item in vItems:
result.append(item.get_full_name())
return result

print getItems("project://scene") # display the list of all items in the context give as parameter and its subcontext


4 - all shaders connected to a shader group
You can't connect several shaders to a single shading group. The rule is simple: 1 shading group => 1 shader.
In Clarisse the shaders are listed in the attribute materials of an item. If the item has several shading group, it has the corresponding number of entry in the materials attribute. The materials attribute is hidden to be more clear in the Attribute editor and avoid user to do things that he shouldn't :D . Moreover, in python you don't need to see something to access it:

python code

box = ix.cmds.CreateObject("box", "GeometryBox") # Create a box
# The module of a Clarisse item is the brain of the item. It contain all the logic of the item.
# If you don't get the module, you are only working on the interface (attributes for example)
boxModule = box.get_module()

for i in range(boxModule.get_shading_group_count()): # get_shading_group_count() gives the number of shading groups of the item
# boxModule.get_shading_group(i) is the shading group at the position `i`
# the attribute materials of the box is invisible and contain the list of all materials applied to the item (each material has an index to correspond to a shading group)
print boxModule.get_shading_group(i) + ":" + str(box.get_attribute("materials").get_object(i)) # display the name of a SG and the material applied to it



As you see there isn't one answer for all these questions. The forum is here for that too, when you are stuck in a problem, you can always ask.
I hope that I answered to your question, if you need more info, feel free to ask

Best regards,
Benoit
Benoit VALDES
Isotropix
Clarisse QA
User avatar
bvaldes
 
Posts: 240
Joined: Mon Sep 26, 2016 11:44 am


Return to Scripting