Difference between revisions of "IC Python API:Controlling A Simple Prop"

From Reallusion Wiki!
Jump to: navigation, search
m (Loading iProp from the iClone Template Directory)
m (Change Material and Playback)
 
(4 intermediate revisions by the same user not shown)
Line 29: Line 29:
 
This function helps to simplify the following formula: '''angle in degrees = angle in radians * 180 / pi'''.
 
This function helps to simplify the following formula: '''angle in degrees = angle in radians * 180 / pi'''.
  
{{code|<nowiki>
+
<syntaxhighlight lang="Python">
 
import os, RLPy, math
 
import os, RLPy, math
 
from winreg import *
 
from winreg import *
Line 56: Line 56:
 
#-- Set Scale X = 2 --#
 
#-- Set Scale X = 2 --#
 
ts_data_block.SetData("Scale/ScaleX", RLPy.RTime(0), RLPy.RVariant(2))
 
ts_data_block.SetData("Scale/ScaleX", RLPy.RTime(0), RLPy.RVariant(2))
</nowiki>}}
+
</syntaxhighlight>
  
 
== Change Material and Playback ==
 
== Change Material and Playback ==
Line 62: Line 62:
 
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.
 
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|<nowiki>
+
<syntaxhighlight lang="Python">
 
import os, RLPy, math
 
import os, RLPy, math
 
from winreg import *
 
from winreg import *
  
#-- Get iClone 7 default template path --#
+
# Get iClone 7 default template path
 
Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
 
Registry = ConnectRegistry(None, HKEY_LOCAL_MACHINE)
 
RawKey = OpenKey(Registry, r"SOFTWARE\Reallusion\iClone\7.0")
 
RawKey = OpenKey(Registry, r"SOFTWARE\Reallusion\iClone\7.0")
 
ic_template_path = os.path.abspath(QueryValueEx(RawKey, "Template Data" )[0])
 
ic_template_path = os.path.abspath(QueryValueEx(RawKey, "Template Data" )[0])
  
#-- Load Box_001.iProp --#
+
# Load Box_001.iProp
 
RLPy.RFileIO.LoadFile(ic_template_path + "//iClone Template//Props//3D Blocks//Box_001.iProp")
 
RLPy.RFileIO.LoadFile(ic_template_path + "//iClone Template//Props//3D Blocks//Box_001.iProp")
  
#-- Get Prop --#
+
# Get Prop
 
prop = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box_001")
 
prop = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box_001")
  
#-- Get Material from Prop --#
+
# Get Material from Prop
 
material_component = prop.GetMaterialComponent()
 
material_component = prop.GetMaterialComponent()
 
mesh_list = prop.GetMeshNames()
 
mesh_list = prop.GetMeshNames()
Line 85: Line 85:
 
material_name = material_list[0]
 
material_name = material_list[0]
  
#-- Add diffuse key --#
+
# Create a key for reuse
material_component.AddDiffuseKey(RLPy.RTime(0), mesh_name, material_name, RLPy.RRgb.RED)
+
key = RLPy.RKey()
material_component.AddDiffuseKey(RLPy.RTime(1000), mesh_name, material_name, RLPy.RRgb.GREEN)
+
key.SetTime(RLPy.RTime(0))
material_component.AddDiffuseKey(RLPy.RTime(2000), mesh_name, material_name, RLPy.RRgb.BLUE)
+
key.SetTransitionType(RLPy.ETransitionType_Linear)
 +
key.SetTransitionStrength(50)
  
RLPy.RGlobal.Play(RLPy.RTime(0), RLPy.RTime(2000))  
+
# Add Diffuse keys
</nowiki>}}
+
material_component.AddDiffuseKey(key, mesh_name, material_name, RLPy.RRgb.RED)
 +
key.SetTime(RLPy.RTime(1000))
 +
material_component.AddDiffuseKey(key, mesh_name, material_name, RLPy.RRgb.GREEN)
 +
key.SetTime(RLPy.RTime(2000))
 +
material_component.AddDiffuseKey(key, mesh_name, material_name, RLPy.RRgb.BLUE)
 +
 
 +
RLPy.RGlobal.Play(RLPy.RTime(0), RLPy.RTime(2000))
 +
</syntaxhighlight>
  
 
== Add Key and Play ==
 
== Add Key and Play ==
Line 97: Line 105:
 
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".
 
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|<nowiki>
+
<syntaxhighlight lang="Python">
 
import os, RLPy, math
 
import os, RLPy, math
 
from winreg import *
 
from winreg import *
Line 126: Line 134:
  
 
RLPy.RGlobal.Play(RLPy.RTime(0), RLPy.RTime(2000))
 
RLPy.RGlobal.Play(RLPy.RTime(0), RLPy.RTime(2000))
</nowiki>}}
+
</syntaxhighlight>
  
 
== Render ==
 
== Render ==
Line 132: Line 140:
 
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.
 
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|<nowiki>
+
<syntaxhighlight lang="Python">
 
import os, RLPy, math
 
import os, RLPy, math
 
from winreg import *
 
from winreg import *
Line 161: Line 169:
  
 
RLPy.RGlobal.RenderVideo()
 
RLPy.RGlobal.RenderVideo()
</nowiki>}}
+
</syntaxhighlight>

Latest revision as of 02:01, 13 May 2019

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.

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]

# Create a key for reuse
key = RLPy.RKey()
key.SetTime(RLPy.RTime(0))
key.SetTransitionType(RLPy.ETransitionType_Linear)
key.SetTransitionStrength(50)

# Add Diffuse keys
material_component.AddDiffuseKey(key, mesh_name, material_name, RLPy.RRgb.RED)
key.SetTime(RLPy.RTime(1000))
material_component.AddDiffuseKey(key, mesh_name, material_name, RLPy.RRgb.GREEN)
key.SetTime(RLPy.RTime(2000))
material_component.AddDiffuseKey(key, 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".

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.

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()