IC Python API:Controlling A Simple Prop

From Reallusion Wiki!
Revision as of 01:23, 9 April 2019 by Chuck (RL) (Talk | contribs) (Move / Rotate / Scale)

Jump to: navigation, search
Main article: iClone Python API.

In this lesson, you'll learn how to load a file, add a transform key, change material parameters and render to video.

Note: To follow along with the lesson, simply copy and past the code segments below into a .py file and load it into iClone.

Loading iProp from the iClone Template Directory

Python support the loading of all iClone file formats. However, we'll need to find the file in the first place and by querying the windows registry keys we can find the path to where the iProps may reside. The following example does just this by finding the path location for the default iClone "Template" directory. Then we can append the sub-folders to this path right down to the file itself for loading.

import os, RLPy
from winreg import *

#-- Get iClone 7 default template path --#
Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
RawKey = OpenKey(Registry, r"SOFTWARE\Reallusion\iClone\7.0")
ic_template_path = os.path.abspath(QueryValueEx(RawKey, "Template Data" )[0])

#-- Load Box_001.iProp --#
RLPy.RFileIO.LoadFile(ic_template_path + "//iClone Template//Props//3D Blocks//Box_001.iProp")

Move / Rotate / Scale

In order to apply transformations, we'll need to reference the prop that was loaded from the previous step ("Box_001.iProp"). We do this by casting it into a variable which we can then use to get control of it's "Transform" property. Then we'll need to reference the "Transform" data block, in order to control ingredients within this data block such as position, rotation, and scale. Anytime we set the arguments of the data block which contain float and integer values, we must clear it with the "RVariant" class which acts like a union for most common data types. This is so that we can avoid type errors due to the dynamic nature of Python. All rotations are performed in radians in iClone, however, because degrees is often what we're used to, we can resort to the handy "math.radians" to help us convert degrees to radians.

This function helps to simplify the following formula: angle in degrees = angle in radians * 180 / pi.

import os, RLPy, math
from winreg import *

#-- Get iClone 7 default template path --#
Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
RawKey = OpenKey(Registry, r"SOFTWARE\Reallusion\iClone\7.0")
ic_template_path = os.path.abspath(QueryValueEx(RawKey, "Template Data" )[0])

#-- Load Box_001.iProp --#
RLPy.RFileIO.LoadFile(ic_template_path + "//iClone Template//Props//3D Blocks//Box_001.iProp")

#-- Get Prop --#
prop = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box_001")

#-- Get Transform Control and Data --#
ts_control = prop.GetControl("Transform")
ts_data_block = ts_control.GetDataBlock()

#-- Set Position X = 100 --#
ts_data_block.SetData("Position/PositionX", RLPy.RTime(0), RLPy.RVariant(100))

#-- Set Rotation X = 20 degree --#
ts_data_block.SetData("Rotation/RotationX", RLPy.RTime(0), RLPy.RVariant(math.radians(20)))

#-- Set Scale X = 2 --#
ts_data_block.SetData("Scale/ScaleX", RLPy.RTime(0), RLPy.RVariant(2))

Change Material and Playback

Let's try animating the box's material properties. We do this by referencing the main material on this prop by passing it's mesh name into the "GetMaterialNames" method. Because mesh and materials are stored in lists, we'll need to grab the initial index of each list: "mesh_list[0]" and "material_list[0]". Once we have the mesh and material names, we can pass those arguments into the "AddDiffuseKey" method and set the timing for the keys with "RLPy.RTime" and set a diffuse color with "RLPy.RRgb". After setting the material diffuse keys, we can command the scene to perform a play back using "RLPy.RGlobal.Play" with a start and end frame.

Code:
import os, RLPy, math
from winreg import *

#-- Get iClone 7 default template path --#
Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
RawKey = OpenKey(Registry, r"SOFTWARE\Reallusion\iClone\7.0")
ic_template_path = os.path.abspath(QueryValueEx(RawKey, "Template Data" )[0])

#-- Load Box_001.iProp --#
RLPy.RFileIO.LoadFile(ic_template_path + "//iClone Template//Props//3D Blocks//Box_001.iProp")

#-- Get Prop --#
prop = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box_001")

#-- Get Material from Prop --#
material_component = prop.GetMaterialComponent()
mesh_list = prop.GetMeshNames()
mesh_name = mesh_list[0]

material_list = material_component.GetMaterialNames(mesh_name)
material_name = material_list[0]

#-- Add diffuse key --#
material_component.AddDiffuseKey(RLPy.RTime(0), mesh_name, material_name, RLPy.RRgb.RED)
material_component.AddDiffuseKey(RLPy.RTime(1000), mesh_name, material_name, RLPy.RRgb.GREEN)
material_component.AddDiffuseKey(RLPy.RTime(2000), mesh_name, material_name, RLPy.RRgb.BLUE)

RLPy.RGlobal.Play(RLPy.RTime(0), RLPy.RTime(2000)) 

Add Key and Play

Now, let's see about animating the box, this time we'll have to get the control of the "Transform" component to access its data block. Then we can "SetData" on the data block and key it's "Position/PositionX" with a "RLPy.RTime" timeline value and the value for it's X position in world space with the "RLPy.RVariant" data type union class. Lastly, we can view the playback with the "RLPy.RGlobal.Play" command and feed it the start and end frames with "RLPy.RTime".

Code:
import os, RLPy, math
from winreg import *

#-- Get iClone 7 default template path --#
Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
RawKey = OpenKey(Registry, r"SOFTWARE\Reallusion\iClone\7.0")
ic_template_path = os.path.abspath(QueryValueEx(RawKey, "Template Data" )[0])

#-- Load Box_001.iProp --#
RLPy.RFileIO.LoadFile(ic_template_path + "//iClone Template//Props//3D Blocks//Box_001.iProp")

#-- Get Prop --#
prop = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box_001")

#-- Get Transform Control and Data --#
ts_control = prop.GetControl("Transform")
ts_data_block = ts_control.GetDataBlock()

#-- Time 0s set X transform Key to 100 --#
ts_data_block.SetData("Position/PositionX", RLPy.RTime(0), RLPy.RVariant(100))

#-- Time 1s set X transform Key to 200 --#
ts_data_block.SetData("Position/PositionX", RLPy.RTime(1000), RLPy.RVariant(200))

#-- Time 2s set X transform Key to 300 --#
ts_data_block.SetData("Position/PositionX", RLPy.RTime(2000), RLPy.RVariant(300))

RLPy.RGlobal.Play(RLPy.RTime(0), RLPy.RTime(2000))

Render

Let's render the animation out into video. Using the exact code segment above, instead of calling "RLPy.RGlobal.Play", we replace it with "RLPy.RGlobal.RenderVideo" instead. This function will render the scene according to the current project render settings (Render > Render Video). This should output a video with the box moving in the x-axis.

Code:
import os, RLPy, math
from winreg import *

#-- Get iClone 7 default template path --#
Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
RawKey = OpenKey(Registry, r"SOFTWARE\Reallusion\iClone\7.0")
ic_template_path = os.path.abspath(QueryValueEx(RawKey, "Template Data" )[0])

#-- Load Box_001.iProp --#
RLPy.RFileIO.LoadFile(ic_template_path + "//iClone Template//Props//3D Blocks//Box_001.iProp")

#-- Get Prop --#
prop = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box_001")

#-- Get Transform Control and Data --#
ts_control = prop.GetControl("Transform")
ts_data_block = ts_control.GetDataBlock()

#-- Time 0s set X transform Key to 100 --#
ts_data_block.SetData("Position/PositionX", RLPy.RTime(0), RLPy.RVariant(100))

#-- Time 1s set X transform Key to 200 --#
ts_data_block.SetData("Position/PositionX", RLPy.RTime(1000), RLPy.RVariant(200))

#-- Time 2s set X transform Key to 300 --#
ts_data_block.SetData("Position/PositionX", RLPy.RTime(2000), RLPy.RVariant(300))

RLPy.RGlobal.RenderVideo()