サービスで Qt シグナルを使用する方法について説明します。
ビデオのキャプション: VRED Pro の Python スクリプト作成に関するチュートリアルへようこそ。Christopher といいます。今日は、Qt シグナルを使用して VRED のイベントに反応する方法を説明します。
Qt シグナルとは何でしょうか?Qt シグナルは、VRED でも使用される Qt フレームワークに実装されています。シグナルはソフトウェアの異なる部分を通信する方法であるため、たとえばユーザ インタフェースはプログラムの論理層と通信し、情報を交換することができます。VRED では、データが変更された場合、またはより一般的には、ユーザが反応する可能性のあるイベントが発生した場合に、同じ方法を使用して Python スクリプトにシグナルを送信します。スクリプトを作成するときに、VRED サービスのシグナルに接続し、そのシグナルがトリガされた場合にアクションを実行できます。
一般的な使用例とは、どのようなものなのでしょうか?API バージョン 2 では、オートデスクはあらゆる種類の操作に使用できる多くのシグナルを導入しました。たとえば、注釈サービス内に、注釈が作成または削除されたときにスクリプトに通知するシグナルがあります。シーングラフに対してノードが追加または削除されたことを通知するシグナルもあります。これは、シーングラフが変更されたときにキャッシュの検索を自動的に再構築する場合に便利です。すべてのライトが検証された場合に通知するシグナルもあります。
VR セッションでは、ユーザがセッションに参加またはセッションから退出したときに通知するシグナルが使用されます。そのため、カスタム ユーザ インタフェースでその情報を表示したり、接続されている VR ユーザを 3D 空間に表示することができます。6 つの例は、オートデスクの公式サンプルに基づいており、シグナルを使用して VR セッションの概要マップを更新し、ユーザを 3D 空間に配置する方法を示しています。
独自のスクリプトでシグナルを使用する方法を見てみましょう。シグナルは API バージョン 2 のサービスの一部であるため、ドキュメントに目を通してシグナルを提供するサービスを見つけることができます。たとえば、vrAnnotationService
ドキュメントにはサブ セクションがあり、シグナルはパラメータとともにリストされています。
この例では、注釈サービスでこれらのシグナルに接続しています。最初に、各シグナルのコールバック関数を作成します。これらの関数は、このシグナルがトリガされるたびに呼び出されます。この場合、注釈の作成、追加、削除、および注釈の表示の変更を行う場合のコールバック関数があります。
このドキュメントには、シグナルによって渡されるデータが記載されています。たとえば、createAnnotation
シグナルは作成された注釈を渡し、visibility パラメータは注釈が表示に設定されているかどうかを示します。次の行では、シグナルの接続関数を使用してこれらのシグナルに接続し、コールバック関数の名前をパラメータとして使用します。このコードを実行して注釈を追加すると、シグナルがトリガされ、それによって生成されたメッセージがターミナルに出力されます。
次に、シーングラフ内の変更をリッスンして、キャッシュの検索のリビルドを自動的にトリガする方法について説明します。シーングラフ内のノードを動的に検索するスクリプトがある場合、検索キャッシュを使用してノードの検索操作を高速化し、パフォーマンスを向上させることができます。この例では、変更したすべてのノードのリストを入力パラメータ「nodes」として使用する、コールバック関数「nodesChanged」を作成します。
この関数では、最初にキャッシュをクリアしてからリビルドします。次の行では、シーングラフに追加されたノードやシーングラフから削除されたノードがあるかどうかを示すシグナル(つまり、「nodesAdded」や「nodesRemoved」シグナル)に接続します。これで、シーングラフ内でコードを実行してノードを変更すると、検索キャッシュが常に自動的にリビルドされます。
サービスのシグナル以外にも、VRED にはシステム メッセージのリッスンに使用できる便利なシグナルがあります。たとえば、新しいシーンが作成されたとき、またはシーンが保存される前に反応することができます。最後の例では、いわゆる vrMessageService
に接続して、すべての種類のシステム メッセージをリッスンします。これらのメッセージの完全なリストについては、vrController
モジュールのドキュメントを参照してください。
vrMessageService
は、システム イベントが発生するたびにコードを送信します。これは、これらのシステム メッセージの 1 つに変換されます。このコード例では、vrMessageService
がシグナルをトリガするたびに、対応するメッセージ コードがターミナルに出力されます。たとえば、カメラを選択すると、「SELECTED_CAMERA」というメッセージがトリガされます。
以上です。今日の説明はこれで終わりです。VRED で Qt シグナルを使用する準備ができたことを願っています。ご参加いただき、ありがとうございました。またお会いしましょう。
「チュートリアル 10: サービスで Qt シグナルを使用する方法」のビデオ用の Python スクリプトの例を示します。
以下のファイルが含まれた ZIP ファイルをダウンロードするには、ここをクリックしてください。
# Example 1.0
# Connecting to service signals
# vrAttachmentService
def annotationCreatedCallback(annotation):
print("Created annotation", annotation)
def annotationAddedCallback():
print("Added annotation")
def annotationsDeletedCallback():
print("Deleted annotation")
def annotationsShowChangedCallback(visible):
print("Annotations are visible: ", visible)
`vrAnnotationService`.annotationCreated.connect(annotationCreatedCallback)
`vrAnnotationService`.annotationsAdded.connect(annotationAddedCallback)
`vrAnnotationService`.annotationsDeleted.connect(annotationsDeletedCallback)
`vrAnnotationService`.showAnnotationsChanged.connect(annotationsShowChangedCallback)
# vrNodeService
def nodesChanged(nodes):
print("Nodes changed: Rebuilding find cache...")
vrNodeService.clearFindCache()
vrNodeService.initFindCache()
vrNodeService.nodesAdded.connect(nodesChanged)
vrNodeService.nodesRemoved.connect(nodesChanged)
# Listening to general object changes
def propertyChanged(obj, propertyName):
print("object name: {}, property name: {}".format(obj.getName(), propertyName))
vrObjectService.propertyChanged.connect(propertyChanged)
# https://knowledge.autodesk.com/support/vred-products/learn-explore/caas/CloudHelp/cloudhelp/2021/ENU/VRED/files/Python-Documentation/Python-Examples/VRED-Python-Documentation-Python-Examples-Visualize-user-positions-html.html
# This scripts shows an overview of user positions in a collaboration sesion
class UserMap(vrAEBase):
def __init__(self):
vrAEBase.__init__(self)
self.spheres = {}
self.addLoop()
# callback sesson start/stop
vrSessionService.sessionJoined.connect(self.started)
vrSessionService.sessionLeft.connect(self.ended)
# callback user joins/leaves session
vrSessionService.userArrives.connect(self.userArrived)
vrSessionService.userLeaves.connect(self.userLeaves)
def loop(self):
# this is my local camera position
myPos = getTransformNodeTranslation(vrSessionService.getUser().getHeadNode(),True)
for user in vrSessionService.getRemoteUsers():
sphere = self.spheres[user.getUserId()]
# this is the users head transformation node
pos = getTransformNodeTranslation(user.getHeadNode(),True)
# move indicator for user position
setTransformNodeTranslation(sphere,(pos.x()-myPos.x())/100,(pos.y()-myPos.y())/100,-500,False)
def started(self):
self.group = createNode("Group", "UserMap", vrCameraService.getActiveCamera())
self.plane = createCylinder(2, 100, 50, True, True, True, .0, .1, .0)
self.setTransparent(self.plane)
addChilds(self.group,[self.plane])
color = vrSessionService.getUser().getUserColor()
sphere = createSphere(3, 2, color.redF(), color.greenF(), color.blueF())
addChilds(self.group,[sphere])
setTransformNodeTranslation(sphere,0,0,-500,False)
setTransformNodeRotation(self.plane, 90, 0, 0)
setTransformNodeTranslation(self.plane, 0, 0, -500, False)
self.setActive(True)
def ended(self):
subChilds(self.group,[self.plane])
subChilds(vrCameraService.getActiveCamera(),[self.group])
self.setActive(False)
def userArrived(self,user):
color = user.getUserColor()
sphere = createSphere(2, 2, color.redF(), color.greenF(), color.blueF())
addChilds(self.group,[sphere])
self.spheres[user.getUserId()] = sphere
def userLeaves(self,user):
sphere = self.spheres[user.getUserId()]
subChilds(self.group,[sphere])
def setTransparent(self,node):
node.getMaterial().fields().setVec3f("seeThrough",.95,.95,.95)
map = UserMap()
# Utilizing `vrMessageService`
def receivedMessage(message_id, args):
messages = (
'VRED_MSG_ARGV',
'VRED_MSG_CHANGED_CAMERA_UP',
'VRED_MSG_CHANGED_MATERIAL',
'VRED_MSG_CHANGED_PB_PARAMETERS',
'VRED_MSG_CHANGED_SCENEGRAPH',
'VRED_MSG_CONVERT_OSF_FILE',
'VRED_MSG_DESELECTED_NODE',
'VRED_MSG_EXPORTED_FILE',
'VRED_MSG_IDLE',
'VRED_MSG_IMPORTED_FILE',
'VRED_MSG_INIT',
'VRED_MSG_KEY_PRESSED',
'VRED_MSG_KEY_RELEASED',
'VRED_MSG_LOADED_GEOMETRY',
'VRED_MSG_LOOP',
'VRED_MSG_NEW_SCENE',
'VRED_MSG_NONE',
'VRED_MSG_PRENEW_SCENE',
'VRED_MSG_PRE_QUIT',
'VRED_MSG_PROJECT',
'VRED_MSG_PROJECT_LOADED',
'VRED_MSG_PROJECT_MERGED',
'VRED_MSG_SAVED_GEOMETRY',
'VRED_MSG_SELECTED_CAMERA',
'VRED_MSG_SELECTED_LIGHT',
'VRED_MSG_SELECTED_MATERIAL',
'VRED_MSG_SELECTED_NODE',
'VRED_MSG_SWITCH_MATERIAL_CHANGED',
'VRED_MSG_UPDATE_UI',
'VRED_MSG_USER',
)
# Print the message that was signaled
for message in messages:
if message_id == getattr(vrController, message):
print(message)
# Listen specifically to the SELECTED CAMERA message
if message_id == vrController.VRED_MSG_SELECTED_CAMERA:
print("Camera selected!")
`vrMessageService`.message.connect(receivedMessage)