TUTORIAL 2: Python funtion sleection via Menu interface for the absolute beginner
Get your hands wet for the second time...
2. Select all the code under Method 1
3. Copy-Paste into a text file and name as main.py
4. Save this file into the directory OpenPlugin/MyFolder, wher "MyFolder" is a placeholder for any name you want to use.
The openPlugin directory shall be under Bin64 directory
5. Open iClone
7. Congratulations: you just created and run a main Python script that will be run everytime iClone starts!!!
What happened in there ?
1. import xxx
Same explanation as the TUTORIAL 1 above.
Now, 2 libraries shall be imported: Reallusion class of objects and the "pyside2" library, which is used to convert the Qt library into Python objects.
Note that an explicit importing of teh PySide2 library is MANDATORY otherwise iClone not see them, that is, the following likes of code are
are necessary from PySide2.QtWidgets import QMainWindow, QMenu
from PySide2.shiboken2 import wrapInstance
2. def initialize_plugin()
The name of the function suggests that it is run when iClone initializes the Python engine and the corresponding event is caught only by a Python code executed within the main.py code.
Note that the entry point of a loaded Python code is "run_script()" and if omitted, nothing happens in a loaded plug-in.
The same is valid for the "main.py" code, loaded at the start-up, but this time the event triggers the "initialize_plugin()" function.
3. ic_dlg = PySide2.shiboken2.wrapInstance(int(RLPy.RUi.GetMainWindow()), PySide2.QtWidgets.QMainWindow)
Here things start to get complicated...
Let's start from the output of this line of code: "ic_dlg" is an "handle" (you can think of it as a way to reference an object for further actions) in Python language and environment to iClone main window.
This is the result of following "tools":
3a. "shiboken2" is a tool to connects objects within C++ language into Python objects. The wrapFunction() method creates a Python wrapper for a C++ object instantiated at a given memory address.
In this case the object is iClone window, whos handle is returned by RLPy.RUi.GetMainWindow() function and whose type is defined within Qt library.
3b. "PySide2" is a library that connects the a Qt object into a Python object: iClone main window has now been transformed into a Python object!
4. plugin_menu = ic_dlg.menuBar().findChild(PySide2.QtWidgets.QMenu, "pysample_menu")
This line of code takes the handle to the iClone main window object and using some of the methods available for this object, checks whether a menu group called "pysample_menu" already exists.
The output of this funtion is an "handle" to this menu group.
Note that every operation on the GUI (Graphic user interface) always passes through the pyside2 library, because this is the way to connect the Qt library to our Python world
5. if (plugin_menu == None):
plugin_menu = PySide2.shiboken2.wrapInstance(int(RLPy.RUi.AddMenu("Python Samples", RLPy.EMenu_Plugins)), PySide2.QtWidgets.QMenu)
plugin_menu.setObjectName("pysample_menu")
These lines should be enough clear.
If no menu group called "pysample_menu" exists, then the hanlde has a "null" value, which in Python is represented by the keyword "None",
In this case, a new menu group, which sahll display the text "Python samples" when shown.
This is the name of the menu gorup displayed in iClone window.
The menu group object (i.e. the element that "lives" within the Python world) has also a name and the 3rd line of code calls it "pysample_menu".
In summary, these 3 lines of code check whether any menu object called "pysample_code" alerady exits, and, if it does not exists, a new menu group object is created, renamed as "pysample_code" and set to display the text "Python samples" whne shown.
Note the indentation: the code indented under the "if" statement is executed if the confition is true.
The code line 6, decribed hereunder, is not part of the "if" block because it has a lesser indentation.
Python uses this mechanism to enforce the lazy programmers to use indentation...
Note also that the "if" statement msut end with a ':' (colon)
6. hello_world_action = plugin_menu.addAction("Hello World")
This line of code fills the menu group that we just created with 1 item, called "Hello world" and returns an handle (called "hello_world_action") to this item.
This handle is used in the next line to set what does it happens when this item is selcted...
7. hello_world_action.triggered.connect(show_dialog)
This code sets which function shall be run when the menu item "hello_world_action"is triggered, i.e. selected
The function is show_dialog() and obviously shall be defined somewhere...
8. def show_dialog():
RLPy.RUi.ShowMessageBox("Your First Python Plugin", "Hello World", RLPy.EMsgButton_Ok)
Here is our function!
It does the same (except writing in the Python console) as the function "run_script()" of teh example above: it creates a window and display the message "Hello world".
A button is also created to close the window.
Refer to the Tutorial 1 above for more details about this line of code.