diff --git a/space_view3d_virtual_reality/hmd/__init__.py b/space_view3d_virtual_reality/hmd/__init__.py index f5559fd72bdd20b618b9c2fbc543ec6d06cb72c7..66b3d0d43ffaa68dc10ead28aa21346005fcb37e 100644 --- a/space_view3d_virtual_reality/hmd/__init__.py +++ b/space_view3d_virtual_reality/hmd/__init__.py @@ -8,18 +8,22 @@ from mathutils import ( import gpu +VERBOSE = True + # ############################################################ # Data structs # ############################################################ -def HMD(display_backend): +def HMD(display_backend, error_callback): """ return the head mounted display device class (defined in another file) - :param display_backend: asdasd + :param display_backend: backend engine :type display_backend: str + :param error_callback: error handler + :type error_callback: func(message, is_fatal) """ from .oculus import Oculus from .debug import Debug @@ -32,22 +36,7 @@ def HMD(display_backend): if display_backend not in displays: assert False, "Display Backend \"{0}\" not implemented".format(display_backend) - return displays[display_backend]() - - -# ############################################################ -# Data structs -# ############################################################ - -class HMD_Data: - status = None - projection_matrix = Matrix.Identity(4) - modelview_matrix = Matrix.Identity(4) - interpupillary_distance = Vector((0.0, 0.0)) - width = 0 - height = 0 - framebuffer_object = 0 - color_object = 0 + return displays[display_backend](error_callback) # ############################################################ @@ -58,6 +47,7 @@ class HMD_Base: __slots__ = { "_name", "_current_eye", + "_error_callback", "_width", "_height", "_projection_matrix", @@ -69,8 +59,9 @@ class HMD_Base: "_modelview_matrix", } - def __init__(self, name): + def __init__(self, name, error_callback): self._name = name + self._error_callback = error_callback self._current_eye = 0 self._width = 0 self._height = 0 @@ -165,10 +156,29 @@ class HMD_Base: except Exception as E: print(E) + def error(self, function, exception, is_fatal): + """ + Handle error messages + """ + if VERBOSE: + print("ADD-ON :: {0}() : {1}".format(function, exception)) + import sys + traceback = sys.exc_info() + + if traceback and traceback[0]: + print(traceback[0]) + + if hasattr(exception, "strerror"): + message = exception.strerror + else: + message = str(exception) + + # send the error the interface + self._error_callback(message, is_fatal) + def updateMatrices(self, context): """ Update OpenGL drawing matrices """ TODO - diff --git a/space_view3d_virtual_reality/hmd/debug.py b/space_view3d_virtual_reality/hmd/debug.py index d7df7df511275104cef01d95187aa208137304df..34d34973a2f62613f0c5234e48e4ab35770b51c3 100644 --- a/space_view3d_virtual_reality/hmd/debug.py +++ b/space_view3d_virtual_reality/hmd/debug.py @@ -5,7 +5,7 @@ Debug Debug device for testing """ -from . import HMD_Base, HMD_Data +from . import HMD_Base VERBOSE = False @@ -15,8 +15,8 @@ def print_debug(*args): class Debug(HMD_Base): - def __init__(self): - super(Debug, self).__init__('Debug') + def __init__(self, error_callback): + super(Debug, self).__init__('Debug', error_callback) def isConnected(self): """ diff --git a/space_view3d_virtual_reality/hmd/oculus.py b/space_view3d_virtual_reality/hmd/oculus.py index 3b7783142fc66c3446caab52bb57d0263716a146..aba0cb4f6551cfdcf432561f941426d7773290c9 100644 --- a/space_view3d_virtual_reality/hmd/oculus.py +++ b/space_view3d_virtual_reality/hmd/oculus.py @@ -21,8 +21,8 @@ from ..lib import ( ) class Oculus(HMD_Base): - def __init__(self): - super(Oculus, self).__init__('Oculus') + def __init__(self, error_callback): + super(Oculus, self).__init__('Oculus', error_callback) checkModule('oculus_sdk_bridge') def isConnected(self): @@ -32,13 +32,12 @@ class Oculus(HMD_Base): :return: return True if the device is connected :rtype: bool """ - from bridge.oculus import HMD - try: + from bridge.oculus import HMD return HMD.isConnected() except Exception as E: - print(E) + self.error("isConnected", E, True) return False def init(self): @@ -66,7 +65,7 @@ class Oculus(HMD_Base): raise Exception("Failed to setup HMD") except Exception as E: - print(E) + self.error("init", E, True) self._hmd = None return False @@ -77,15 +76,21 @@ class Oculus(HMD_Base): """ Get fresh tracking data """ + try: + data = self._hmd.update() - data = self._hmd.update() + self._head_transformation = Matrix(data[0]) + self._eye_pose[0] = Vector(data[1]) + self._eye_pose[1] = Vector(data[2]) - self._head_transformation = Matrix(data[0]) - self._eye_pose[0] = Vector(data[1]) - self._eye_pose[1] = Vector(data[2]) + # update matrices + super(Oculus, self).loop(context) - # update matrices - super(Oculus, self).loop(context) + except Exception as E: + self.error("look", E, False) + return False + + return True def frameReady(self): """ @@ -93,15 +98,17 @@ class Oculus(HMD_Base): """ try: self._hmd.frameReady() + except Exception as E: + self.error("frameReady", E, False) return False + return True + def quit(self): """ Garbage collection """ - del self._hmd self._hmd = None - return super(Oculus, self).quit() diff --git a/space_view3d_virtual_reality/operator.py b/space_view3d_virtual_reality/operator.py index e0dfdd3189bd7ede6269e860cc270274044a0d5f..d79b3668ee0ec4924a5507fdf6a44e77083d303e 100644 --- a/space_view3d_virtual_reality/operator.py +++ b/space_view3d_virtual_reality/operator.py @@ -23,11 +23,9 @@ class VirtualRealityDisplayOperator(bpy.types.Operator): bl_label = "Toggle Virtual Reality Display" bl_description = "" - _gl_data = None + _hmd = None _timer = None _handle = None - _width = 1920 - _height = 1080 _area_hash = -1 action = bpy.props.EnumProperty( @@ -99,7 +97,10 @@ class VirtualRealityDisplayOperator(bpy.types.Operator): """garbage collect""" # change it so the original modal operator will clean things up wm = context.window_manager - wm.virtual_reality.is_enabled = False + vr = wm.virtual_reality + + vr.is_enabled = False + vr.error_message = "" def _quit(self, context): """actual quit""" @@ -113,9 +114,11 @@ class VirtualRealityDisplayOperator(bpy.types.Operator): bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW') del self._handle - self._hmd.quit() self._preview.quit() + if self._hmd: + self._hmd.quit() + # cleanup viewport if context.area: context.area.tag_redraw() @@ -125,10 +128,13 @@ class VirtualRealityDisplayOperator(bpy.types.Operator): Initialize the callbacks and the external devices """ wm = context.window_manager - wm.virtual_reality.is_enabled = True + vr = wm.virtual_reality + + vr.is_enabled = True + vr.error_message = "" display_backend = getDisplayBackend(context) - self._hmd = HMD(display_backend) + self._hmd = HMD(display_backend, self._error_callback) self._preview = Preview() if not self._hmd.isConnected(): @@ -182,6 +188,20 @@ class VirtualRealityDisplayOperator(bpy.types.Operator): vr = wm.virtual_reality self._preview.loop(vr.preview_scale) + def _error_callback(self, message, is_fatal): + """ + Error handler, called from HMD class + """ + context = bpy.context + wm = context.window_manager + vr = wm.virtual_reality + + if is_fatal: + self.report({'ERROR'}, message) + self.quit(context) + + vr.error_message = message + # ############################################################ # Global Properties @@ -201,6 +221,10 @@ class VirtualRealityInfo(bpy.types.PropertyGroup): subtype='PERCENTAGE', ) + error_message = bpy.props.StringProperty( + name="Error Message", + ) + # ############################################################ # Callbacks @@ -215,7 +239,10 @@ def virtual_reality_load_pre(dummy): @persistent def virtual_reality_load_post(dummy): wm = bpy.context.window_manager - wm.virtual_reality.is_enabled = False + vr = wm.virtual_reality + + vr.is_enabled = False + vr.error_message = "" # ############################################################ diff --git a/space_view3d_virtual_reality/ui.py b/space_view3d_virtual_reality/ui.py index 1f50d503bd36ea3f84d3356152e259f7b1229608..7c215a38666f525a45197f8224e4e75c2f5a1fc6 100644 --- a/space_view3d_virtual_reality/ui.py +++ b/space_view3d_virtual_reality/ui.py @@ -27,6 +27,8 @@ class VirtualRealityPanel(bpy.types.Panel): col.separator() col.prop(vr, "preview_scale", text="Preview") + col.label(text=vr.error_message) + # ############################################################ # Un/Registration