PageRenderTime 81ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/blender-addon-live-editing/live-editing/operators/SetupLiveEditingSceneOperator.py

https://gitlab.com/sat-metalab/InSituImmersiveAuthoring
Python | 308 lines | 214 code | 45 blank | 49 comment | 68 complexity | aec1fadfd1ba9dd9be020e3cecd2c3a4 MD5 | raw file
  1. import bpy
  2. import os
  3. from math import acos, pi, sqrt
  4. from bpy.types import Operator
  5. from mathutils import Color, Matrix, Euler
  6. from ..LiveEditor import LiveEditor
  7. class SetupLiveEditingSceneOperator(Operator):
  8. """Setup Live Editing Scene"""
  9. bl_idname = "live_editing.setup_scene"
  10. bl_label = "Setup Scene"
  11. def lock_helper(self, helper, hide=True):
  12. helper.live_editing.lock = True
  13. helper.hide = hide
  14. helper.hide_select = True
  15. helper.hide_render = True
  16. helper.lock_location = True, True, True
  17. helper.lock_rotation = True, True, True
  18. helper.lock_scale = True, True, True
  19. def set_camera_view(self):
  20. for window in bpy.context.window_manager.windows:
  21. screen = window.screen
  22. for area in screen.areas:
  23. if area.type == 'VIEW_3D' and area.spaces[0].camera == bpy.context.scene.camera:
  24. if area.spaces[0].region_3d.view_perspective != 'CAMERA':
  25. area.spaces[0].region_3d.view_perspective = 'CAMERA'
  26. # Fit the camera view to the 3d view
  27. v3d = area.regions[4]
  28. r3d = area.spaces[0].region_3d
  29. r3d.view_camera_offset[0] = 0.0
  30. r3d.view_camera_offset[1] = 0.0
  31. a1 = v3d.width / v3d.height
  32. a2 = bpy.context.scene.render.resolution_x / bpy.context.scene.render.resolution_y
  33. if a2 < a1:
  34. r3d.view_camera_zoom = 50 * (2 * sqrt(a2 / a1) - sqrt(2))
  35. else:
  36. r3d.view_camera_zoom = 29.29
  37. def execute(self, context):
  38. current_file_path = os.path.dirname(os.path.abspath(__file__))
  39. preferences = bpy.context.user_preferences.addons[__package__.split('.')[0]].preferences
  40. # region World
  41. # New scenes don't get World automatically
  42. world = bpy.context.scene.world
  43. if world is None:
  44. if len(bpy.data.worlds) == 0:
  45. bpy.ops.world.new()
  46. bpy.context.scene.world = bpy.data.worlds[0]
  47. # world = bpy.context.scene.world
  48. # endregion
  49. # region Pod
  50. name = preferences.projection.pod
  51. pod = bpy.data.objects.get(name)
  52. if pod is None:
  53. pod = bpy.data.objects.new(name, None)
  54. if bpy.context.scene.objects.get(name) is None:
  55. bpy.context.scene.objects.link(pod)
  56. self.lock_helper(pod)
  57. pod.matrix_world = Matrix.Identity(4)
  58. # endregion
  59. # region Shelf
  60. name = LiveEditor.shelf_group
  61. shelf = bpy.data.objects.get(name)
  62. if shelf is None:
  63. shelf = bpy.data.objects.new(name, None)
  64. if bpy.context.scene.objects.get(name) is None:
  65. bpy.context.scene.objects.link(shelf)
  66. self.lock_helper(shelf, False)
  67. shelf.matrix_world = Matrix.Identity(4)
  68. shelf.parent = pod
  69. #endregion
  70. # region Controllers
  71. # Link the vive controller model
  72. with bpy.data.libraries.load(
  73. filepath=current_file_path + "/../assets/controllers/Vive Controller.blend",
  74. link=False
  75. ) as (data_from, data_to):
  76. data_to.objects = [name for name in data_from.objects if name.startswith("Vive")]
  77. with bpy.data.libraries.load(
  78. filepath=current_file_path + "/../assets/controllers/Vive Controller.blend",
  79. link=True
  80. ) as (data_from, data_to):
  81. data_to.meshes = [name for name in data_from.meshes if name.startswith("Vive")]
  82. data_to.materials = [name for name in data_from.materials if name.startswith("Vive")]
  83. data_to.textures = [name for name in data_from.textures if name.startswith("Vive")]
  84. name = "[Controllers]"
  85. controllers = bpy.data.objects.get(name)
  86. if controllers is None:
  87. controllers = bpy.data.objects.new(name, None)
  88. if bpy.context.scene.objects.get(name) is None:
  89. bpy.context.scene.objects.link(controllers)
  90. self.lock_helper(controllers)
  91. controllers.matrix_world = Matrix.Identity(4)
  92. controllers.parent = pod
  93. # 3D Controllers
  94. controller3d1 = bpy.data.objects.get("Vive Controller 1")
  95. self.lock_helper(controller3d1)
  96. controller3d1.parent = controllers
  97. controller3d1_children = [ob for ob in bpy.data.objects if ob.parent == controller3d1]
  98. if bpy.context.scene.objects.get(controller3d1.name) is None:
  99. bpy.context.scene.objects.link(controller3d1)
  100. for child in controller3d1_children:
  101. self.lock_helper(child)
  102. if bpy.context.scene.objects.get(child.name) is None:
  103. bpy.context.scene.objects.link(child)
  104. controller3d2 = bpy.data.objects.get("Vive Controller 2")
  105. self.lock_helper(controller3d2)
  106. controller3d2.parent = controllers
  107. controller3d2_children = [ob for ob in bpy.data.objects if ob.parent == controller3d2]
  108. if bpy.context.scene.objects.get(controller3d2.name) is None:
  109. bpy.context.scene.objects.link(controller3d2)
  110. for child in controller3d2_children:
  111. self.lock_helper(child)
  112. if bpy.context.scene.objects.get(child.name) is None:
  113. bpy.context.scene.objects.link(child)
  114. # region Controller 1
  115. name = preferences.vrpn.controller_1
  116. controller1 = bpy.data.objects.get(name)
  117. if controller1 is None:
  118. controller1 = bpy.data.objects.new(name, None)
  119. if bpy.context.scene.objects.get(name) is None:
  120. bpy.context.scene.objects.link(controller1)
  121. self.lock_helper(controller1)
  122. controller1.matrix_world = Matrix.Identity(4)
  123. controller1.parent = controllers
  124. controller1.show_name = True
  125. # endregion
  126. # region Controller 2
  127. name = preferences.vrpn.controller_2
  128. controller2 = bpy.data.objects.get(name)
  129. if controller2 is None:
  130. controller2 = bpy.data.objects.new(name, None)
  131. if bpy.context.scene.objects.get(name) is None:
  132. bpy.context.scene.objects.link(controller2)
  133. self.lock_helper(controller2)
  134. controller2.matrix_world = Matrix.Identity(4)
  135. controller2.parent = controllers
  136. controller2.show_name = True
  137. # endregion
  138. # endregion
  139. # region Cameras
  140. name = "[Cameras]"
  141. cameras = bpy.data.objects.get(name)
  142. if cameras is None:
  143. cameras = bpy.data.objects.new(name, None)
  144. if bpy.context.scene.objects.get(name) is None:
  145. bpy.context.scene.objects.link(cameras)
  146. self.lock_helper(cameras)
  147. cameras.matrix_world = Matrix.Identity(4)
  148. cameras.parent = pod
  149. # region Main Camera
  150. # The main camera can be used for rendering animations but is not used directly in situ.
  151. # It only serves as an animatable object that the pod follows. The camera visualized
  152. # in situ is the pod camera.
  153. name = preferences.projection.camera
  154. camera_data = bpy.data.cameras.get(name)
  155. if camera_data is None:
  156. camera_data = bpy.data.cameras.new(name)
  157. camera = bpy.data.objects.get(name)
  158. if camera is None:
  159. camera = bpy.data.objects.new(name, camera_data)
  160. else:
  161. camera.data = camera_data
  162. if bpy.context.scene.objects.get(name) is None:
  163. bpy.context.scene.objects.link(camera)
  164. self.lock_helper(camera)
  165. camera.matrix_world = Matrix.Identity(4)
  166. camera.rotation_euler.x = pi / 2
  167. # endregion
  168. # region Pod Camera
  169. # Actual POV of the insitu editing session. Can move freely (with the pod) in the space
  170. # or follow the animated main camera
  171. name = preferences.projection.pod_camera
  172. camera_data = bpy.data.cameras.get(name)
  173. if camera_data is None:
  174. camera_data = bpy.data.cameras.new(name)
  175. pod_camera = bpy.data.objects.get(name)
  176. if pod_camera is None:
  177. pod_camera = bpy.data.objects.new(name, camera_data)
  178. else:
  179. pod_camera.data = camera_data
  180. if bpy.context.scene.objects.get(name) is None:
  181. bpy.context.scene.objects.link(pod_camera)
  182. self.lock_helper(pod_camera)
  183. pod_camera.matrix_world = preferences.projection.pod_camera_rotation.to_matrix().to_4x4() * Matrix.Identity(4)
  184. pod_camera.rotation_euler.x = pi/2
  185. pod_camera.parent = cameras
  186. # Set the pod camera as the satie reference if satie is present
  187. satie_addon = bpy.context.user_preferences.addons.get('satie')
  188. if satie_addon:
  189. satie_addon.preferences.listener = name
  190. # Setup in immersive view addon (if available)
  191. if bpy.context.user_preferences.addons.get('immersive-viewport') is not None:
  192. bpy.context.user_preferences.addons['immersive-viewport'].preferences.anchorObject = name
  193. # endregion
  194. # region Cursor Camera
  195. name = preferences.projection.cursor_camera
  196. camera_data = bpy.data.cameras.get(name)
  197. if camera_data is None:
  198. camera_data = bpy.data.cameras.new(name)
  199. camera_data.lens = 10.0
  200. cursor_camera = bpy.data.objects.get(name)
  201. if cursor_camera is None:
  202. cursor_camera = bpy.data.objects.new(name, camera_data)
  203. else:
  204. cursor_camera.data = camera_data
  205. if bpy.context.scene.objects.get(name) is None:
  206. bpy.context.scene.objects.link(cursor_camera)
  207. self.lock_helper(cursor_camera)
  208. cursor_camera.matrix_world = Matrix.Identity(4)
  209. # cursor_camera.rotation_euler.x = pi/2
  210. cursor_camera.parent = cameras
  211. # endregion
  212. # endregion
  213. # region Mesh
  214. name = "[Mesh]"
  215. mesh = bpy.data.objects.get(name)
  216. if mesh is None:
  217. mesh = bpy.data.objects.new(name, None)
  218. if bpy.context.scene.objects.get(name) is None:
  219. bpy.context.scene.objects.link(mesh)
  220. self.lock_helper(mesh)
  221. mesh.matrix_world = Matrix.Identity(4)
  222. mesh.parent = pod
  223. # region Sample Mesh
  224. name = preferences.projection.mesh
  225. dome_mesh = bpy.data.objects.get(name)
  226. if dome_mesh is None:
  227. bpy.ops.mesh.primitive_ico_sphere_add(location=(0.00, 0.00, 0.00), size=10, subdivisions=4, enter_editmode=True)
  228. bpy.ops.mesh.flip_normals()
  229. bpy.ops.object.editmode_toggle()
  230. dome_mesh = bpy.context.object
  231. dome_mesh.name = name
  232. if bpy.context.scene.objects.get(name) is None:
  233. bpy.context.scene.objects.link(dome_mesh)
  234. self.lock_helper(dome_mesh)
  235. dome_mesh.draw_type = 'WIRE'
  236. dome_mesh.matrix_world = Matrix.Identity(4)
  237. dome_mesh.parent = mesh
  238. # endregion
  239. # endregion
  240. # region Libraries
  241. # Link the material library
  242. with bpy.data.libraries.load(filepath=current_file_path+"/../assets/materials.blend", link=True) as (data_from, data_to):
  243. data_to.materials = [name for name in data_from.materials if name.startswith("Mat_")]
  244. # Link the models library
  245. with bpy.data.libraries.load(filepath=current_file_path+"/../assets/models.blend", link=True) as (data_from, data_to):
  246. data_to.meshes = [name for name in data_from.meshes if name.startswith("Model_")]
  247. data_to.materials = [name for name in data_from.materials if name.startswith("Mat_")]
  248. # endregion
  249. # region Rendering
  250. # Activate GLSL rendering
  251. bpy.context.scene.game_settings.material_mode = 'GLSL'
  252. # Set CURSOR Camera as the rendering camera
  253. bpy.context.scene.camera = bpy.data.objects[preferences.projection.cursor_camera]
  254. # Make sure the 3d view is rendered with the current bpy.context.scene.camera
  255. self.set_camera_view()
  256. # endregion
  257. # Reset the matrix world to the saved value if there is one
  258. saved_pod_matrix = bpy.context.scene.live_editing.saved_pod_matrix
  259. if saved_pod_matrix:
  260. pod.matrix_world = saved_pod_matrix
  261. # Flag as setup so that we can use it
  262. bpy.context.scene.live_editing.setup = True
  263. return {'FINISHED'}