서비스에서 QT 신호를 사용해 작업하는 방법에 대해 알아봅니다.
동영상 캡션: 안녕하세요. VRED Pro를 위한 Python 스크립팅 튜토리얼에 오신 것을 환영합니다. 저는 크리스토퍼라고 하며, 오늘은 VRED에서 Qt 신호를 사용하여 이벤트에 대응하는 방법을 소개하겠습니다.
그렇다면 Qt 신호란 무엇일까요? Qt 신호는 VRED에서도 사용하는 Qt 프레임워크에서 구현됩니다. 신호는 소프트웨어의 각기 다른 부분 간에 통신하는 방법입니다. 예를 들어 사용자 인터페이스는 프로그램의 논리 레이어와 통신하고 정보를 교환할 수 있습니다. VRED에서도 데이터가 변경되거나, 보다 일반적으로 사용자의 반응을 요구하는 이벤트가 발생하는 경우 Python 스크립트에 신호를 보낼 때 동일한 방법이 사용됩니다. 스크립트를 작성할 때 VRED 서비스의 신호에 연결할 수 있으며 해당 신호가 트리거되는 경우 동작을 수행할 수 있습니다.
일반적인 활용 사례는 어떻게 될까요? API 버전 2의 경우 오토데스크는 모든 종류의 작업에 사용할 수 있는 많은 신호를 도입했습니다. 예를 들어 주석 서비스에는 주석이 작성되거나 삭제될 때 스크립트에 알리는 신호가 있습니다. 장면 그래프에서 노드를 추가 또는 제거할 때 표시되는 신호도 있습니다. 이 기능은 장면 그래프가 변경될 때 찾기 캐시를 자동으로 다시 구성하려는 경우 유용할 수 있습니다. 모든 라이트의 유효성이 검사되면 알려 주는 신호도 있습니다.
VR 세션은 사용자가 세션에 참여하거나 세션에서 나갈 때 신호를 사용하여 알려 줍니다. 따라서 사용자화된 사용자 인터페이스에 해당 정보를 표시하거나 3D 공간에서 연결된 VR 사용자를 표시할 수 있습니다. 6가지 샘플은 공식 오토데스크 예시에서 가져온 것으로, 신호를 사용하여 VR 세션의 개요 맵을 업데이트하고 3D 공간에 사용자를 배치하는 방법을 보여 줍니다.
스크립트에서 신호를 사용하는 방법을 알아보겠습니다. 신호는 API 버전 2 서비스의 일부이므로, 해당 설명서를 검색하면 신호를 제공하는 서비스가 있는지 알아볼 수 있습니다. 예를 들어 vrAnnotationService 설명서에는 신호가 해당 매개변수와 함께 나열되는 하위 섹션이 있습니다.
이 예에서는 주석 서비스에서 이러한 신호에 연결합니다. 먼저 각 신호에 대한 콜백 함수를 작성합니다. 이 함수는 신호가 트리거될 때마다 호출되는 함수입니다. 이 경우 주석이 작성, 추가, 삭제될 때와 주석의 가시성이 변경된 시점에 대한 콜백 함수가 있습니다.
설명서에는 신호를 통해 전달되는 데이터가 정리되어 있습니다. 예를 들어 createAnnotation 신호는 작성된 주석을 전달하고 가시성 매개변수는 주석이 표시되도록 설정되어 있는지를 알려 줍니다. 다음 몇 개 행에서는 신호의 연결 기능을 사용하여 이러한 신호에 연결하고 콜백 함수의 이름을 매개변수로 사용합니다. 이 코드를 실행하고 주석을 추가하면 신호가 트리거되고 터미널에 메시지가 출력되어야 합니다.
다음으로, 장면 그래프에서 변경 사항을 수신하여 찾기 캐시를 자동으로 재생성하는 방법을 보여 드리겠습니다. 찾기 캐시는 노드의 찾기 작업 속도를 높이는 데 사용되며, 장면 그래프에서 동적으로 노드를 찾는 데 사용되는 스크립트가 있는 경우 성능을 향상시킬 수 있습니다. 이 예에서는 변경된 모든 노드의 목록인 입력 매개변수 nodes를 사용하여 "nodes changed" 콜백 함수를 작성합니다.
이 함수에서는 먼저 캐시를 지운 다음 재생성합니다. 다음 행에서는 노드가 추가되었거나 장면 그래프에서 제거되었음을 알리는 신호, 즉 "nodes added" 및 "nodes removed" 신호에 연결합니다. 이제 코드를 실행하고 장면 그래프에서 노드를 변경하면 찾기 캐시가 항상 자동으로 다시 구성됩니다.
서비스의 신호와는 별개로 VRED에는 시스템 메시지를 수신하는 데 사용할 수 있는 다른 유용한 신호가 있습니다. 예를 들어 장면이 저장되기 전이나 새 장면이 만들어질 때 반응할 수 있습니다. 마지막 예에서는 vrMessageService라는 신호에 연결하여 모든 종류의 시스템 메시지를 수신합니다. 이러한 메시지의 전체 목록은 vrController 모듈의 설명서에서 확인할 수 있습니다.
vrMessageService는 시스템 이벤트가 발생할 때마다 코드를 전송하고 이는 이러한 시스템 메시지 중 하나로 변환됩니다. 이 코드 예제에서는 vrMessageService가 신호를 트리거할 때마다 해당 메시지 코드가 터미널에 출력됩니다. 예를 들어 카메라를 선택하면 "SELECTED_CAMERA" 메시지가 트리거됩니다.
좋습니다. 오늘은 이것으로 마치겠습니다. 이제 VRED에서 Qt 신호를 사용할 준비가 되었기를 바랍니다. 참여해 주셔서 감사하며 다음에 뵙겠습니다!
다음은 튜토리얼 10: 서비스에서 QT 신호를 사용해 작업하는 방법 동영상과 함께 제공되는 예제 Python 스크립트입니다.
이러한 파일을 압축하여 다운로드하려면 여기를 클릭하십시오.
# 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)