IC Python API:Using Temp Data
- Main article: RL Python Samples.
This article will demonstrate the use of the temporary file system to read and write impermanent data. This is crucial for plugins that are distributed to a wider audience and array of machines, due to the ability to circumvent authorization settings and administrative control for a consistent data storage system that works every time, regardless of individual environment settings.
Required Modules & Global Variables
Besides the fundamental Reallusion Python module, we'll also need Pyside2 to build the user interface, and os for file handling. tempfile will be used to read/write temporary files and subprocess for browsing the directory that the files are stored into (subprocess is a Windows only command).
import RLPy
import os
import tempfile
import subprocess
from PySide2 import *
from PySide2.shiboken2 import wrapInstance
temp_file_path = tempfile.gettempdir() + "/ic_personal_memo.tmp"
Notice that we have a global variable to store the temp file path, because we will need to access this same variable in various stages of the script. Notice also how this variable relies on tempfile to locate the temporary directory where data files are usually accessible.
Handling Temporary Data
This section will be split into three essential parts: saving, loading, and browsing temporary data.
Saving Temporary Data
In order to write data to the temporary directory, we'll need the following code snippet (hooked to the Save Personal Memo button later):
def save_temp_file():
f = open(temp_file_path, "w")
f.write(widget.inputMessage.text())
f.close()
widget.message.setText("Your memo has been saved.")
Notice that we print out a confirmation message straight to the custom UI. This will be explained in more details below.
Loading Temporary Data
On the other hand, we'll need to read the temporary data and make use of it:
def load_temp_file():
if os.path.isfile(temp_file_path):
f = open(temp_file_path, "r")
data = f.read()
f.close()
if len(data) > 0: # If text data exists
widget.inputMessage.setText(data)
widget.message.setText("Hello again, here is your last memo message:")
Browsing the Temp Directory
We'll also add a convenient function to browse temporary directory. If the temp data exists, then select it, otherwise, just open the temp directory for perusal. We will hook this function to the Open Memo Location... button later.
def open_temp_directory():
if os.path.isfile(temp_file_path): # If the temp file exists, select it in explorer
file_path = temp_file_path.replace('/', '\\')
subprocess.Popen(f'explorer /select, "{file_path}"')
else: # If the temp file doesn't exist, then open the temp directory with nothing selected
os.startfile(tempfile.gettempdir())
Updating the User Interface
Let's also create a callback function to provide feedback while working with the UI
def on_text_changed():
if len(widget.inputMessage.text()) > 0:
widget.message.setText("Remember to save your personal memo!")
else:
widget.message.setText("Write a short one-line memo to yourself:")
Building the User Interface
Let's load the configured QT UI file. You can download Memo.ui here -make sure this UI file is placed in the same script directory. We will also call the load function mentioned above to automatically read any existing temp data (from a previous sesssion).
# Create the dialog window in iClone
window = RLPy.RUi.CreateRDialog()
window.SetWindowTitle("Personal Memo")
# Give QT functionalities to the window
dialog = wrapInstance(int(window.GetWindow()), QtWidgets.QDialog)
dialog.setFixedWidth(280)
# Read the QT UI file from location and deploy as widget
ui = QtCore.QFile(os.path.dirname(__file__) + "/memo.ui")
ui.open(QtCore.QFile.ReadOnly)
widget = QtUiTools.QUiLoader().load(ui)
ui.close()
dialog.layout().addWidget(widget)
# Add functionality to the UI
widget.openTempDirectory.clicked.connect(open_temp_directory)
widget.saveTempFile.clicked.connect(save_temp_file)
widget.inputMessage.textChanged.connect(on_text_changed)
window.Show()
load_temp_file()
Everything Put Together
You can copy and paste the following code into a PY file and load it into iClone via Script > Load Python. Make sure to have the .ui file in the same directory.
import RLPy
import os
import tempfile
import subprocess
from PySide2 import *
from PySide2.shiboken2 import wrapInstance
temp_file_path = tempfile.gettempdir() + "/ic_personal_memo.tmp"
def save_temp_file():
f = open(temp_file_path, "w")
f.write(widget.inputMessage.text())
f.close()
widget.message.setText("Your memo has been saved.")
def load_temp_file():
if os.path.isfile(temp_file_path):
f = open(temp_file_path, "r")
data = f.read()
f.close()
if len(data) > 0: # If text data exists
widget.inputMessage.setText(data)
widget.message.setText("Hello again, here is your last memo message:")
def open_temp_directory():
if os.path.isfile(temp_file_path): # If the temp file exists, select it in explorer
file_path = temp_file_path.replace('/', '\\')
subprocess.Popen(f'explorer /select, "{file_path}"')
else: # If the temp file doesn't exist, then open the temp directory with nothing selected
os.startfile(tempfile.gettempdir())
def on_text_changed():
if len(widget.inputMessage.text()) > 0:
widget.message.setText("Remember to save your personal memo!")
else:
widget.message.setText("Write a short one-line memo to yourself:")
# Create the dialog window in iClone
window = RLPy.RUi.CreateRDialog()
window.SetWindowTitle("Personal Memo")
# Give QT functionalities to the window
dialog = wrapInstance(int(window.GetWindow()), QtWidgets.QDialog)
dialog.setFixedWidth(280)
# Read the QT UI file from location and deploy as widget
ui = QtCore.QFile(os.path.dirname(__file__) + "/memo.ui")
ui.open(QtCore.QFile.ReadOnly)
widget = QtUiTools.QUiLoader().load(ui)
ui.close()
dialog.layout().addWidget(widget)
# Add functionality to the UI
widget.openTempDirectory.clicked.connect(open_temp_directory)
widget.saveTempFile.clicked.connect(save_temp_file)
widget.inputMessage.textChanged.connect(on_text_changed)
window.Show()
load_temp_file()
APIs Used
You can research the following references for the APIs deployed in this code.