VR: Initial Virtual Reality support - Milestone 1, Scene Inspection
NOTE: While most of the milestone 1 goals are there, a few smaller features and improvements are still to be done. Big picture of this milestone: Initial, OpenXR-based virtual reality support for users and foundation for advanced use cases. Maniphest Task: https://developer.blender.org/T71347 The tasks contains more information about this milestone. To be clear: This is not a feature rich VR implementation, it's focused on the initial scene inspection use case. We intentionally focused on that, further features like controller support are part of the next milestone. - How to use? Instructions on how to use this are here: https://wiki.blender.org/wiki/User:Severin/GSoC-2019/How_to_Test These will be updated and moved to a more official place (likely the manual) soon. Currently Windows Mixed Reality and Oculus devices are usable. Valve/HTC headsets don't support the OpenXR standard yet and hence, do not work with this implementation. --------------- This is the C-side implementation of the features added for initial VR support as per milestone 1. A "VR Scene Inspection" Add-on will be committed separately, to expose the VR functionality in the UI. It also adds some further features for milestone 1, namely a landmarking system (stored view locations in the VR space) Main additions/features: * Support for rendering viewports to an HMD, with good performance. * Option to sync the VR view perspective with a fully interactive, regular 3D View (VR-Mirror). * Option to disable positional tracking. Keeps the current position (calculated based on the VR eye center pose) when enabled while a VR session is running. * Some regular viewport settings for the VR view * RNA/Python-API to query and set VR session state information. * WM-XR: Layer tying Ghost-XR to the Blender specific APIs/data * wmSurface API: drawable, non-window container (manages Ghost-OpenGL and GPU context) * DNA/RNA for management of VR session settings * `--debug-xr` and `--debug-xr-time` commandline options * Utility batch & config file for using the Oculus runtime on Windows. * Most VR data is runtime only. The exception is user settings which are saved to files (`XrSessionSettings`). * VR support can be disabled through the `WITH_XR_OPENXR` compiler flag. For architecture and code documentation, see https://wiki.blender.org/wiki/Source/Interface/XR. --------------- A few thank you's: * A huge shoutout to Ray Molenkamp for his help during the project - it would have not been that successful without him! * Sebastian Koenig and Simeon Conzendorf for testing and feedback! * The reviewers, especially Brecht Van Lommel! * Dalai Felinto for pushing and managing me to get this done ;) * The OpenXR working group for providing an open standard. I think we're the first bigger application to adopt OpenXR. Congratulations to them and ourselves :) This project started as a Google Summer of Code 2019 project - "Core Support of Virtual Reality Headsets through OpenXR" (see https://wiki.blender.org/wiki/User:Severin/GSoC-2019/). Some further information, including ideas for further improvements can be found in the final GSoC report: https://wiki.blender.org/wiki/User:Severin/GSoC-2019/Final_Report Differential Revisions: D6193, D7098 Reviewed by: Brecht Van Lommel, Jeroen Bakker
This commit is contained in:
@@ -186,8 +186,7 @@ if(APPLE)
|
||||
option(WITH_XR_OPENXR "Enable VR features through the OpenXR specification" OFF)
|
||||
mark_as_advanced(WITH_XR_OPENXR)
|
||||
else()
|
||||
# Disabled until there's more than just the build system stuff. Should be enabled soon.
|
||||
option(WITH_XR_OPENXR "Enable VR features through the OpenXR specification" OFF)
|
||||
option(WITH_XR_OPENXR "Enable VR features through the OpenXR specification" ON)
|
||||
endif()
|
||||
|
||||
# Compositor
|
||||
|
||||
@@ -377,6 +377,9 @@ if(WITH_XR_OPENXR)
|
||||
list(APPEND INC_SYS
|
||||
${XR_OPENXR_SDK_INCLUDE_DIR}
|
||||
)
|
||||
list(APPEND LIB
|
||||
${XR_OPENXR_SDK_LIBRARIES}
|
||||
)
|
||||
|
||||
set(XR_PLATFORM_DEFINES -DXR_USE_GRAPHICS_API_OPENGL)
|
||||
|
||||
|
||||
@@ -756,6 +756,18 @@ extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthan
|
||||
*/
|
||||
extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
|
||||
|
||||
/**
|
||||
* Get the OpenGL framebuffer handle that serves as a default framebuffer.
|
||||
*/
|
||||
extern unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle);
|
||||
|
||||
/**
|
||||
* Returns whether a context is rendered upside down compared to OpenGL. This only needs to be
|
||||
* called if there's a non-OpenGL context, which is really the exception.
|
||||
* So generally, this does not need to be called.
|
||||
*/
|
||||
extern int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle);
|
||||
|
||||
/**
|
||||
* Get the OpenGL framebuffer handle that serves as a default framebuffer.
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,15 @@ class GHOST_IContext {
|
||||
*/
|
||||
virtual GHOST_TSuccess releaseDrawingContext() = 0;
|
||||
|
||||
virtual unsigned int getDefaultFramebuffer() = 0;
|
||||
|
||||
virtual GHOST_TSuccess swapBuffers() = 0;
|
||||
|
||||
/**
|
||||
* Returns if the window is rendered upside down compared to OpenGL.
|
||||
*/
|
||||
virtual bool isUpsideDown() const = 0;
|
||||
|
||||
#ifdef WITH_CXX_GUARDEDALLOC
|
||||
MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
|
||||
#endif
|
||||
|
||||
@@ -598,6 +598,8 @@ typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_T
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
|
||||
struct GHOST_XrError;
|
||||
struct GHOST_XrDrawViewInfo;
|
||||
/**
|
||||
* The XR view (i.e. the OpenXR runtime) may require a different graphics library than OpenGL. An
|
||||
* offscreen texture of the viewport will then be drawn into using OpenGL, but the final texture
|
||||
@@ -605,7 +607,7 @@ typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__ *task, GHOST_T
|
||||
*
|
||||
* This enum defines the possible graphics bindings to attempt to enable.
|
||||
*/
|
||||
typedef enum {
|
||||
typedef enum GHOST_TXrGraphicsBinding {
|
||||
GHOST_kXrGraphicsUnknown = 0,
|
||||
GHOST_kXrGraphicsOpenGL,
|
||||
# ifdef WIN32
|
||||
@@ -614,6 +616,16 @@ typedef enum {
|
||||
/* For later */
|
||||
// GHOST_kXrGraphicsVulkan,
|
||||
} GHOST_TXrGraphicsBinding;
|
||||
|
||||
typedef void (*GHOST_XrErrorHandlerFn)(const struct GHOST_XrError *);
|
||||
|
||||
typedef void (*GHOST_XrSessionExitFn)(void *customdata);
|
||||
|
||||
typedef void *(*GHOST_XrGraphicsContextBindFn)(enum GHOST_TXrGraphicsBinding graphics_lib);
|
||||
typedef void (*GHOST_XrGraphicsContextUnbindFn)(enum GHOST_TXrGraphicsBinding graphics_lib,
|
||||
GHOST_ContextHandle graphics_context);
|
||||
typedef void (*GHOST_XrDrawViewFn)(const struct GHOST_XrDrawViewInfo *draw_view, void *customdata);
|
||||
|
||||
/* An array of GHOST_TXrGraphicsBinding items defining the candidate bindings to use. The first
|
||||
* available candidate will be chosen, so order defines priority. */
|
||||
typedef const GHOST_TXrGraphicsBinding *GHOST_XrGraphicsBindingCandidates;
|
||||
@@ -638,13 +650,17 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
GHOST_XrPose base_pose;
|
||||
|
||||
GHOST_XrSessionExitFn exit_fn;
|
||||
void *exit_customdata;
|
||||
} GHOST_XrSessionBeginInfo;
|
||||
|
||||
typedef struct {
|
||||
typedef struct GHOST_XrDrawViewInfo {
|
||||
int ofsx, ofsy;
|
||||
int width, height;
|
||||
|
||||
GHOST_XrPose pose;
|
||||
GHOST_XrPose eye_pose;
|
||||
GHOST_XrPose local_pose;
|
||||
|
||||
struct {
|
||||
float angle_left, angle_right;
|
||||
@@ -655,19 +671,12 @@ typedef struct {
|
||||
char expects_srgb_buffer;
|
||||
} GHOST_XrDrawViewInfo;
|
||||
|
||||
typedef struct {
|
||||
typedef struct GHOST_XrError {
|
||||
const char *user_message;
|
||||
|
||||
void *customdata;
|
||||
} GHOST_XrError;
|
||||
|
||||
typedef void (*GHOST_XrErrorHandlerFn)(const GHOST_XrError *);
|
||||
|
||||
typedef void *(*GHOST_XrGraphicsContextBindFn)(GHOST_TXrGraphicsBinding graphics_lib);
|
||||
typedef void (*GHOST_XrGraphicsContextUnbindFn)(GHOST_TXrGraphicsBinding graphics_lib,
|
||||
void *graphics_context);
|
||||
typedef void (*GHOST_XrDrawViewFn)(const GHOST_XrDrawViewInfo *draw_view, void *customdata);
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __GHOST_TYPES_H__
|
||||
|
||||
@@ -709,6 +709,20 @@ GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
|
||||
return context->releaseDrawingContext();
|
||||
}
|
||||
|
||||
unsigned int GHOST_GetContextDefaultOpenGLFramebuffer(GHOST_ContextHandle contexthandle)
|
||||
{
|
||||
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||
|
||||
return context->getDefaultFramebuffer();
|
||||
}
|
||||
|
||||
int GHOST_isUpsideDownContext(GHOST_ContextHandle contexthandle)
|
||||
{
|
||||
GHOST_IContext *context = (GHOST_IContext *)contexthandle;
|
||||
|
||||
return context->isUpsideDown();
|
||||
}
|
||||
|
||||
unsigned int GHOST_GetDefaultOpenGLFramebuffer(GHOST_WindowHandle windowhandle)
|
||||
{
|
||||
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
|
||||
|
||||
@@ -119,6 +119,14 @@ class GHOST_Context : public GHOST_IContext {
|
||||
return m_stereoVisual;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the window is rendered upside down compared to OpenGL.
|
||||
*/
|
||||
inline bool isUpsideDown() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the OpenGL framebuffer associated with the OpenGL context
|
||||
* \return The ID of an OpenGL framebuffer object.
|
||||
|
||||
@@ -41,6 +41,8 @@ class GHOST_IXrGraphicsBinding {
|
||||
#endif
|
||||
} oxr_binding;
|
||||
|
||||
virtual ~GHOST_IXrGraphicsBinding() = default;
|
||||
|
||||
/**
|
||||
* Does __not__ require this object is initialized (can be called prior to
|
||||
* #initFromGhostContext). It's actually meant to be called first.
|
||||
|
||||
@@ -454,10 +454,12 @@ GHOST_TXrGraphicsBinding GHOST_XrContext::determineGraphicsBindingTypeToEnable(
|
||||
|
||||
void GHOST_XrContext::startSession(const GHOST_XrSessionBeginInfo *begin_info)
|
||||
{
|
||||
m_custom_funcs.session_exit_fn = begin_info->exit_fn;
|
||||
m_custom_funcs.session_exit_customdata = begin_info->exit_customdata;
|
||||
|
||||
if (m_session == nullptr) {
|
||||
m_session = std::unique_ptr<GHOST_XrSession>(new GHOST_XrSession(this));
|
||||
}
|
||||
|
||||
m_session->start(begin_info);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,9 @@ struct GHOST_XrCustomFuncs {
|
||||
/** Function to release (possibly free) a graphics context. */
|
||||
GHOST_XrGraphicsContextUnbindFn gpu_ctx_unbind_fn = nullptr;
|
||||
|
||||
GHOST_XrSessionExitFn session_exit_fn = nullptr;
|
||||
void *session_exit_customdata = nullptr;
|
||||
|
||||
/** Custom per-view draw function for Blender side drawing. */
|
||||
GHOST_XrDrawViewFn draw_view_fn = nullptr;
|
||||
};
|
||||
|
||||
@@ -116,6 +116,8 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
||||
oxr_binding.glx.glxDrawable = ctx_glx->m_window;
|
||||
oxr_binding.glx.glxContext = ctx_glx->m_context;
|
||||
oxr_binding.glx.visualid = visual_info->visualid;
|
||||
|
||||
XFree(visual_info);
|
||||
#elif defined(WIN32)
|
||||
GHOST_ContextWGL *ctx_wgl = static_cast<GHOST_ContextWGL *>(ghost_ctx);
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ struct OpenXRSessionData {
|
||||
/* Only stereo rendering supported now. */
|
||||
const XrViewConfigurationType view_type = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
|
||||
XrSpace reference_space;
|
||||
XrSpace view_space;
|
||||
std::vector<XrView> views;
|
||||
std::vector<std::unique_ptr<GHOST_XrSwapchain>> swapchains;
|
||||
};
|
||||
@@ -81,6 +82,8 @@ GHOST_XrSession::~GHOST_XrSession()
|
||||
|
||||
m_oxr->session = XR_NULL_HANDLE;
|
||||
m_oxr->session_state = XR_SESSION_STATE_UNKNOWN;
|
||||
|
||||
m_context->getCustomFuncs().session_exit_fn(m_context->getCustomFuncs().session_exit_customdata);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +110,7 @@ void GHOST_XrSession::initSystem()
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static void create_reference_space(OpenXRSessionData *oxr, const GHOST_XrPose *base_pose)
|
||||
static void create_reference_spaces(OpenXRSessionData *oxr, const GHOST_XrPose *base_pose)
|
||||
{
|
||||
XrReferenceSpaceCreateInfo create_info = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO};
|
||||
create_info.poseInReferenceSpace.orientation.w = 1.0f;
|
||||
@@ -138,6 +141,10 @@ static void create_reference_space(OpenXRSessionData *oxr, const GHOST_XrPose *b
|
||||
|
||||
CHECK_XR(xrCreateReferenceSpace(oxr->session, &create_info, &oxr->reference_space),
|
||||
"Failed to create reference space.");
|
||||
|
||||
create_info.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
|
||||
CHECK_XR(xrCreateReferenceSpace(oxr->session, &create_info, &oxr->view_space),
|
||||
"Failed to create view reference space.");
|
||||
}
|
||||
|
||||
void GHOST_XrSession::start(const GHOST_XrSessionBeginInfo *begin_info)
|
||||
@@ -184,7 +191,7 @@ void GHOST_XrSession::start(const GHOST_XrSessionBeginInfo *begin_info)
|
||||
"detailed error information to the command line.");
|
||||
|
||||
prepareDrawing();
|
||||
create_reference_space(m_oxr.get(), &begin_info->base_pose);
|
||||
create_reference_spaces(m_oxr.get(), &begin_info->base_pose);
|
||||
}
|
||||
|
||||
void GHOST_XrSession::requestEnd()
|
||||
@@ -343,16 +350,22 @@ void GHOST_XrSession::draw(void *draw_customdata)
|
||||
endFrameDrawing(&layers);
|
||||
}
|
||||
|
||||
static void copy_openxr_pose_to_ghost_pose(const XrPosef &oxr_pose, GHOST_XrPose &r_ghost_pose)
|
||||
{
|
||||
/* Set and convert to Blender coodinate space. */
|
||||
r_ghost_pose.position[0] = oxr_pose.position.x;
|
||||
r_ghost_pose.position[1] = oxr_pose.position.y;
|
||||
r_ghost_pose.position[2] = oxr_pose.position.z;
|
||||
r_ghost_pose.orientation_quat[0] = oxr_pose.orientation.w;
|
||||
r_ghost_pose.orientation_quat[1] = oxr_pose.orientation.x;
|
||||
r_ghost_pose.orientation_quat[2] = oxr_pose.orientation.y;
|
||||
r_ghost_pose.orientation_quat[3] = oxr_pose.orientation.z;
|
||||
}
|
||||
|
||||
static void ghost_xr_draw_view_info_from_view(const XrView &view, GHOST_XrDrawViewInfo &r_info)
|
||||
{
|
||||
/* Set and convert to Blender coodinate space. */
|
||||
r_info.pose.position[0] = view.pose.position.x;
|
||||
r_info.pose.position[1] = view.pose.position.y;
|
||||
r_info.pose.position[2] = view.pose.position.z;
|
||||
r_info.pose.orientation_quat[0] = view.pose.orientation.w;
|
||||
r_info.pose.orientation_quat[1] = view.pose.orientation.x;
|
||||
r_info.pose.orientation_quat[2] = view.pose.orientation.y;
|
||||
r_info.pose.orientation_quat[3] = view.pose.orientation.z;
|
||||
copy_openxr_pose_to_ghost_pose(view.pose, r_info.eye_pose);
|
||||
|
||||
r_info.fov.angle_left = view.fov.angleLeft;
|
||||
r_info.fov.angle_right = view.fov.angleRight;
|
||||
@@ -370,6 +383,7 @@ static bool ghost_xr_draw_view_expects_srgb_buffer(const GHOST_XrContext *contex
|
||||
|
||||
void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
|
||||
XrCompositionLayerProjectionView &r_proj_layer_view,
|
||||
XrSpaceLocation &view_location,
|
||||
XrView &view,
|
||||
void *draw_customdata)
|
||||
{
|
||||
@@ -386,6 +400,7 @@ void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
|
||||
draw_view_info.ofsy = r_proj_layer_view.subImage.imageRect.offset.y;
|
||||
draw_view_info.width = r_proj_layer_view.subImage.imageRect.extent.width;
|
||||
draw_view_info.height = r_proj_layer_view.subImage.imageRect.extent.height;
|
||||
copy_openxr_pose_to_ghost_pose(view_location.pose, draw_view_info.local_pose);
|
||||
ghost_xr_draw_view_info_from_view(view, draw_view_info);
|
||||
|
||||
/* Draw! */
|
||||
@@ -401,6 +416,7 @@ XrCompositionLayerProjection GHOST_XrSession::drawLayer(
|
||||
XrViewLocateInfo viewloc_info = {XR_TYPE_VIEW_LOCATE_INFO};
|
||||
XrViewState view_state = {XR_TYPE_VIEW_STATE};
|
||||
XrCompositionLayerProjection layer = {XR_TYPE_COMPOSITION_LAYER_PROJECTION};
|
||||
XrSpaceLocation view_location{XR_TYPE_SPACE_LOCATION};
|
||||
uint32_t view_count;
|
||||
|
||||
viewloc_info.viewConfigurationType = m_oxr->view_type;
|
||||
@@ -416,11 +432,17 @@ XrCompositionLayerProjection GHOST_XrSession::drawLayer(
|
||||
"Failed to query frame view and projection state.");
|
||||
assert(m_oxr->swapchains.size() == view_count);
|
||||
|
||||
CHECK_XR(
|
||||
xrLocateSpace(
|
||||
m_oxr->view_space, m_oxr->reference_space, viewloc_info.displayTime, &view_location),
|
||||
"Failed to query frame view space");
|
||||
|
||||
r_proj_layer_views.resize(view_count);
|
||||
|
||||
for (uint32_t view_idx = 0; view_idx < view_count; view_idx++) {
|
||||
drawView(*m_oxr->swapchains[view_idx],
|
||||
r_proj_layer_views[view_idx],
|
||||
view_location,
|
||||
m_oxr->views[view_idx],
|
||||
draw_customdata);
|
||||
}
|
||||
@@ -479,7 +501,8 @@ void GHOST_XrSession::unbindGraphicsContext()
|
||||
{
|
||||
const GHOST_XrCustomFuncs &custom_funcs = m_context->getCustomFuncs();
|
||||
if (custom_funcs.gpu_ctx_unbind_fn) {
|
||||
custom_funcs.gpu_ctx_unbind_fn(m_context->getGraphicsBindingType(), m_gpu_ctx);
|
||||
custom_funcs.gpu_ctx_unbind_fn(m_context->getGraphicsBindingType(),
|
||||
(GHOST_ContextHandle)m_gpu_ctx);
|
||||
}
|
||||
m_gpu_ctx = nullptr;
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
#include <memory>
|
||||
|
||||
class GHOST_XrContext;
|
||||
class GHOST_XrSwapchain;
|
||||
struct OpenXRSessionData;
|
||||
struct GHOST_XrDrawInfo;
|
||||
struct GHOST_XrSwapchain;
|
||||
|
||||
class GHOST_XrSession {
|
||||
public:
|
||||
@@ -74,6 +74,7 @@ class GHOST_XrSession {
|
||||
std::vector<XrCompositionLayerProjectionView> &r_proj_layer_views, void *draw_customdata);
|
||||
void drawView(GHOST_XrSwapchain &swapchain,
|
||||
XrCompositionLayerProjectionView &r_proj_layer_view,
|
||||
XrSpaceLocation &view_location,
|
||||
XrView &view,
|
||||
void *draw_customdata);
|
||||
void beginFrameDrawing();
|
||||
|
||||
14
release/windows/batch/blender_oculus.cmd
Normal file
14
release/windows/batch/blender_oculus.cmd
Normal file
@@ -0,0 +1,14 @@
|
||||
@echo off
|
||||
|
||||
REM Helper setting hints to get the OpenXR preview support enabled for Oculus.
|
||||
REM Of course this is not meant as a permanent solution. Oculus will likely provide a better setup at some point.
|
||||
|
||||
echo Starting Blender with Oculus OpenXR support. This assumes the Oculus runtime
|
||||
echo is installed in the default location. If this is not the case, please adjust
|
||||
echo the path inside oculus.json.
|
||||
echo.
|
||||
echo Note that OpenXR support in Oculus is considered a preview. Use with care!
|
||||
echo.
|
||||
pause
|
||||
set XR_RUNTIME_JSON=%~dp0oculus.json
|
||||
blender
|
||||
9
release/windows/batch/oculus.json
Normal file
9
release/windows/batch/oculus.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"file_format_version": "1.0.0",
|
||||
"runtime":
|
||||
{
|
||||
"api_version": "1.0",
|
||||
"name": "Oculus OpenXR",
|
||||
"library_path": "c:\\Program Files\\Oculus\\Support\\oculus-runtime\\LibOVRRT64_1.dll"
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,7 @@ set(SRC_DNA_INC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_windowmanager_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_workspace_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_world_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_xr_types.h
|
||||
)
|
||||
|
||||
add_subdirectory(datatoc)
|
||||
|
||||
@@ -153,6 +153,8 @@ enum {
|
||||
G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/
|
||||
G_DEBUG_GPU_SHADERS = (1 << 18), /* GLSL shaders */
|
||||
G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 19), /* force gpu workarounds bypassing detections. */
|
||||
G_DEBUG_XR = (1 << 20), /* XR/OpenXR messages */
|
||||
G_DEBUG_XR_TIME = (1 << 21), /* XR/OpenXR timing messages */
|
||||
|
||||
G_DEBUG_GHOST = (1 << 20), /* Debug GHOST module. */
|
||||
};
|
||||
|
||||
@@ -667,6 +667,10 @@ if(WITH_TBB)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_XR_OPENXR)
|
||||
add_definitions(-DWITH_XR_OPENXR)
|
||||
endif()
|
||||
|
||||
# # Warnings as errors, this is too strict!
|
||||
# if(MSVC)
|
||||
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
|
||||
|
||||
@@ -2680,7 +2680,8 @@ void BKE_object_workob_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *o
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the global transformation \a mat to the \a ob using a relative parent space if supplied.
|
||||
* Applies the global transformation \a mat to the \a ob using a relative parent space if
|
||||
* supplied.
|
||||
*
|
||||
* \param mat: the global transformation mat that the object should be set object to.
|
||||
* \param parent: the parent space in which this object will be set relative to
|
||||
@@ -3183,7 +3184,8 @@ typedef struct ObTfmBack {
|
||||
float obmat[4][4];
|
||||
/** inverse result of parent, so that object doesn't 'stick' to parent. */
|
||||
float parentinv[4][4];
|
||||
/** inverse result of constraints. doesn't include effect of parent or object local transform. */
|
||||
/** inverse result of constraints. doesn't include effect of parent or object local transform.
|
||||
*/
|
||||
float constinv[4][4];
|
||||
/** inverse matrix of 'obmat' for during render, temporally: ipokeys of transform. */
|
||||
float imat[4][4];
|
||||
|
||||
@@ -636,6 +636,13 @@ void perspective_m4(float mat[4][4],
|
||||
const float top,
|
||||
const float nearClip,
|
||||
const float farClip);
|
||||
void perspective_m4_fov(float mat[4][4],
|
||||
const float angle_left,
|
||||
const float angle_right,
|
||||
const float angle_up,
|
||||
const float angle_down,
|
||||
const float nearClip,
|
||||
const float farClip);
|
||||
void orthographic_m4(float mat[4][4],
|
||||
const float left,
|
||||
const float right,
|
||||
|
||||
@@ -4709,6 +4709,25 @@ void perspective_m4(float mat[4][4],
|
||||
mat[3][3] = 0.0f;
|
||||
}
|
||||
|
||||
void perspective_m4_fov(float mat[4][4],
|
||||
const float angle_left,
|
||||
const float angle_right,
|
||||
const float angle_up,
|
||||
const float angle_down,
|
||||
const float nearClip,
|
||||
const float farClip)
|
||||
{
|
||||
const float tan_angle_left = tanf(angle_left);
|
||||
const float tan_angle_right = tanf(angle_right);
|
||||
const float tan_angle_bottom = tanf(angle_up);
|
||||
const float tan_angle_top = tanf(angle_down);
|
||||
|
||||
perspective_m4(
|
||||
mat, tan_angle_left, tan_angle_right, tan_angle_top, tan_angle_bottom, nearClip, farClip);
|
||||
mat[0][0] /= nearClip;
|
||||
mat[1][1] /= nearClip;
|
||||
}
|
||||
|
||||
/* translate a matrix created by orthographic_m4 or perspective_m4 in XY coords
|
||||
* (used to jitter the view) */
|
||||
void window_translate_m4(float winmat[4][4], float perspmat[4][4], const float x, const float y)
|
||||
|
||||
@@ -7187,6 +7187,7 @@ static void direct_link_region(FileData *fd, ARegion *region, int spacetype)
|
||||
rv3d->smooth_timer = NULL;
|
||||
|
||||
rv3d->rflag &= ~(RV3D_NAVIGATING | RV3D_PAINTING);
|
||||
rv3d->runtime_viewlock = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7277,7 +7278,10 @@ static void direct_link_area(FileData *fd, ScrArea *area)
|
||||
direct_link_gpencil(fd, v3d->gpd);
|
||||
}
|
||||
v3d->localvd = newdataadr(fd, v3d->localvd);
|
||||
|
||||
/* Runtime data */
|
||||
v3d->runtime.properties_storage = NULL;
|
||||
v3d->runtime.flag = 0;
|
||||
|
||||
/* render can be quite heavy, set to solid on load */
|
||||
if (v3d->shading.type == OB_RENDER) {
|
||||
@@ -7657,6 +7661,23 @@ static bool direct_link_area_map(FileData *fd, ScrAreaMap *area_map)
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name XR-data
|
||||
* \{ */
|
||||
|
||||
static void direct_link_wm_xr_data(FileData *fd, wmXrData *xr_data)
|
||||
{
|
||||
direct_link_view3dshading(fd, &xr_data->session_settings.shading);
|
||||
}
|
||||
|
||||
static void lib_link_wm_xr_data(FileData *fd, ID *parent_id, wmXrData *xr_data)
|
||||
{
|
||||
xr_data->session_settings.base_pose_object = newlibadr(
|
||||
fd, parent_id->lib, xr_data->session_settings.base_pose_object);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Read ID: Window Manager
|
||||
* \{ */
|
||||
@@ -7710,6 +7731,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
|
||||
}
|
||||
}
|
||||
|
||||
direct_link_wm_xr_data(fd, &wm->xr);
|
||||
|
||||
BLI_listbase_clear(&wm->timers);
|
||||
BLI_listbase_clear(&wm->operators);
|
||||
BLI_listbase_clear(&wm->paintcursors);
|
||||
@@ -7724,6 +7747,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
|
||||
|
||||
wm->message_bus = NULL;
|
||||
|
||||
wm->xr.runtime = NULL;
|
||||
|
||||
BLI_listbase_clear(&wm->jobs);
|
||||
BLI_listbase_clear(&wm->drags);
|
||||
|
||||
@@ -7747,6 +7772,8 @@ static void lib_link_windowmanager(FileData *fd, Main *UNUSED(bmain), wmWindowMa
|
||||
for (ScrArea *area = win->global_areas.areabase.first; area; area = area->next) {
|
||||
lib_link_area(fd, &wm->id, area);
|
||||
}
|
||||
|
||||
lib_link_wm_xr_data(fd, &wm->id, &wm->xr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7911,6 +7938,12 @@ static void lib_link_main_data_restore(struct IDNameLib_Map *id_map, Main *newma
|
||||
FOREACH_MAIN_ID_END;
|
||||
}
|
||||
|
||||
static void lib_link_wm_xr_data_restore(struct IDNameLib_Map *id_map, wmXrData *xr_data)
|
||||
{
|
||||
xr_data->session_settings.base_pose_object = restore_pointer_by_name(
|
||||
id_map, (ID *)xr_data->session_settings.base_pose_object, USER_REAL);
|
||||
}
|
||||
|
||||
static void lib_link_window_scene_data_restore(wmWindow *win, Scene *scene, ViewLayer *view_layer)
|
||||
{
|
||||
bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
|
||||
@@ -8241,6 +8274,8 @@ void blo_lib_link_restore(Main *oldmain,
|
||||
BLI_assert(win->screen == NULL);
|
||||
}
|
||||
|
||||
lib_link_wm_xr_data_restore(id_map, &curwm->xr);
|
||||
|
||||
/* Restore all ID pointers in Main database itself
|
||||
* (especially IDProperties might point to some word-space of other 'weirdly unchanged' ID
|
||||
* pointers, see T69146).
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
@@ -4845,5 +4847,21 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_find(fd->filesdna, "XrSessionSettings")) {
|
||||
for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
|
||||
const View3D *v3d_default = DNA_struct_default_get(View3D);
|
||||
|
||||
wm->xr.session_settings.shading = v3d_default->shading;
|
||||
/* Don't rotate light with the viewer by default, make it fixed. */
|
||||
wm->xr.session_settings.shading.flag |= V3D_SHADING_WORLD_ORIENTATION;
|
||||
wm->xr.session_settings.draw_flags = (V3D_OFSDRAW_SHOW_GRIDFLOOR |
|
||||
V3D_OFSDRAW_SHOW_ANNOTATION);
|
||||
wm->xr.session_settings.clip_start = v3d_default->clip_start;
|
||||
wm->xr.session_settings.clip_end = v3d_default->clip_end;
|
||||
|
||||
wm->xr.session_settings.flag = XR_SESSION_USE_POSITION_TRACKING;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2820,6 +2820,11 @@ static void write_gpencil(WriteData *wd, bGPdata *gpd)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_wm_xr_data(WriteData *wd, wmXrData *xr_data)
|
||||
{
|
||||
write_view3dshading(wd, &xr_data->session_settings.shading);
|
||||
}
|
||||
|
||||
static void write_region(WriteData *wd, ARegion *region, int spacetype)
|
||||
{
|
||||
writestruct(wd, DATA, ARegion, 1, region);
|
||||
@@ -3066,6 +3071,7 @@ static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
|
||||
{
|
||||
writestruct(wd, ID_WM, wmWindowManager, 1, wm);
|
||||
write_iddata(wd, &wm->id);
|
||||
write_wm_xr_data(wd, &wm->xr);
|
||||
|
||||
for (wmWindow *win = wm->windows.first; win; win = win->next) {
|
||||
#ifndef WITH_GLOBAL_AREA_WRITING
|
||||
|
||||
@@ -390,4 +390,8 @@ if(WITH_FREESTYLE)
|
||||
add_definitions(-DWITH_FREESTYLE)
|
||||
endif()
|
||||
|
||||
if(WITH_XR_OPENXR)
|
||||
add_definitions(-DWITH_XR_OPENXR)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
@@ -93,6 +93,7 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
|
||||
struct RenderEngineType *engine_type,
|
||||
struct ARegion *region,
|
||||
struct View3D *v3d,
|
||||
const bool is_image_render,
|
||||
const bool draw_background,
|
||||
const bool do_color_management,
|
||||
struct GPUOffScreen *ofs,
|
||||
@@ -139,6 +140,14 @@ void DRW_opengl_context_destroy(void);
|
||||
void DRW_opengl_context_enable(void);
|
||||
void DRW_opengl_context_disable(void);
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
/* XXX see comment on DRW_xr_opengl_context_get() */
|
||||
void *DRW_xr_opengl_context_get(void);
|
||||
void *DRW_xr_gpu_context_get(void);
|
||||
void DRW_xr_drawing_begin(void);
|
||||
void DRW_xr_drawing_end(void);
|
||||
#endif
|
||||
|
||||
/* For garbage collection */
|
||||
void DRW_cache_free_old_batches(struct Main *bmain);
|
||||
|
||||
|
||||
@@ -562,7 +562,7 @@ static void drw_viewport_var_init(void)
|
||||
DRW_view_camtexco_set(DST.view_default, rv3d->viewcamtexcofac);
|
||||
|
||||
if (DST.draw_ctx.sh_cfg == GPU_SHADER_CFG_CLIPPED) {
|
||||
int plane_len = (rv3d->viewlock & RV3D_BOXCLIP) ? 4 : 6;
|
||||
int plane_len = (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) ? 4 : 6;
|
||||
DRW_view_clip_planes_set(DST.view_default, rv3d->clip, plane_len);
|
||||
}
|
||||
|
||||
@@ -1554,6 +1554,7 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
|
||||
RenderEngineType *engine_type,
|
||||
ARegion *region,
|
||||
View3D *v3d,
|
||||
const bool is_image_render,
|
||||
const bool draw_background,
|
||||
const bool do_color_management,
|
||||
GPUOffScreen *ofs,
|
||||
@@ -1569,7 +1570,7 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
|
||||
|
||||
/* Reset before using it. */
|
||||
drw_state_prepare_clean_for_draw(&DST);
|
||||
DST.options.is_image_render = true;
|
||||
DST.options.is_image_render = is_image_render;
|
||||
DST.options.do_color_management = do_color_management;
|
||||
DST.options.draw_background = draw_background;
|
||||
DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, render_viewport, NULL);
|
||||
@@ -2829,4 +2830,39 @@ void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context))
|
||||
GPU_context_active_set(NULL);
|
||||
}
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
|
||||
/* XXX
|
||||
* There should really be no such getter, but for VR we currently can't easily avoid it. OpenXR
|
||||
* needs some low level info for the OpenGL context that will be used for submitting the
|
||||
* final framebuffer. VR could in theory create its own context, but that would mean we have to
|
||||
* switch to it just to submit the final frame, which has notable performance impact.
|
||||
*
|
||||
* We could "inject" a context through DRW_opengl_render_context_enable(), but that would have to
|
||||
* work from the main thread, which is tricky to get working too. The preferable solution would be
|
||||
* using a separate thread for VR drawing where a single context can stay active. */
|
||||
void *DRW_xr_opengl_context_get(void)
|
||||
{
|
||||
return DST.gl_context;
|
||||
}
|
||||
|
||||
/* XXX See comment on DRW_xr_opengl_context_get(). */
|
||||
void *DRW_xr_gpu_context_get(void)
|
||||
{
|
||||
return DST.gpu_context;
|
||||
}
|
||||
|
||||
/* XXX See comment on DRW_xr_opengl_context_get(). */
|
||||
void DRW_xr_drawing_begin(void)
|
||||
{
|
||||
BLI_ticket_mutex_lock(DST.gl_context_mutex);
|
||||
}
|
||||
|
||||
/* XXX See comment on DRW_xr_opengl_context_get(). */
|
||||
void DRW_xr_drawing_end(void)
|
||||
{
|
||||
BLI_ticket_mutex_unlock(DST.gl_context_mutex);
|
||||
}
|
||||
|
||||
#endif
|
||||
/** \} */
|
||||
|
||||
@@ -561,6 +561,9 @@ struct RegionView3D *ED_view3d_context_rv3d(struct bContext *C);
|
||||
bool ED_view3d_context_user_region(struct bContext *C,
|
||||
struct View3D **r_v3d,
|
||||
struct ARegion **r_ar);
|
||||
bool ED_view3d_area_user_region(const struct ScrArea *sa,
|
||||
const struct View3D *v3d,
|
||||
struct ARegion **r_ar);
|
||||
bool ED_operator_rv3d_user_region_poll(struct bContext *C);
|
||||
|
||||
void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d);
|
||||
@@ -584,7 +587,8 @@ void ED_draw_object_facemap(struct Depsgraph *depsgraph,
|
||||
struct RenderEngineType *ED_view3d_engine_type(const struct Scene *scene, int drawtype);
|
||||
|
||||
bool ED_view3d_context_activate(struct bContext *C);
|
||||
void ED_view3d_draw_setup_view(struct wmWindow *win,
|
||||
void ED_view3d_draw_setup_view(const struct wmWindowManager *wm,
|
||||
struct wmWindow *win,
|
||||
struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct ARegion *region,
|
||||
@@ -730,6 +734,18 @@ void ED_view3d_buttons_region_layout_ex(const struct bContext *C,
|
||||
bool ED_view3d_local_collections_set(struct Main *bmain, struct View3D *v3d);
|
||||
void ED_view3d_local_collections_reset(struct bContext *C, const bool reset_all);
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
void ED_view3d_xr_mirror_update(const struct ScrArea *area,
|
||||
const struct View3D *v3d,
|
||||
const bool enable);
|
||||
void ED_view3d_xr_shading_update(struct wmWindowManager *wm,
|
||||
const View3D *v3d,
|
||||
const struct Scene *scene);
|
||||
bool ED_view3d_is_region_xr_mirror_active(const struct wmWindowManager *wm,
|
||||
const struct View3D *v3d,
|
||||
const struct ARegion *region);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -51,12 +51,31 @@ void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph,
|
||||
int winy,
|
||||
float viewmat[4][4],
|
||||
float winmat[4][4],
|
||||
bool is_image_render,
|
||||
bool do_sky,
|
||||
bool is_persp,
|
||||
const char *viewname,
|
||||
const bool do_color_management,
|
||||
struct GPUOffScreen *ofs,
|
||||
struct GPUViewport *viewport);
|
||||
void ED_view3d_draw_offscreen_simple(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct View3DShading *shading_override,
|
||||
int drawtype,
|
||||
int winx,
|
||||
int winy,
|
||||
unsigned int draw_flags,
|
||||
float viewmat[4][4],
|
||||
float winmat[4][4],
|
||||
float clip_start,
|
||||
float clip_end,
|
||||
bool is_image_render,
|
||||
bool do_sky,
|
||||
bool is_persp,
|
||||
const char *viewname,
|
||||
const bool do_color_management,
|
||||
struct GPUOffScreen *ofs,
|
||||
struct GPUViewport *viewport);
|
||||
|
||||
struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
|
||||
@@ -3818,6 +3818,7 @@ static void region_quadview_init_rv3d(
|
||||
}
|
||||
|
||||
rv3d->viewlock = viewlock;
|
||||
rv3d->runtime_viewlock = 0;
|
||||
rv3d->view = view;
|
||||
rv3d->view_axis_roll = RV3D_VIEW_AXIS_ROLL_0;
|
||||
rv3d->persp = persp;
|
||||
@@ -3915,7 +3916,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
const char viewlock = (rv3d->viewlock_quad & RV3D_VIEWLOCK_INIT) ?
|
||||
(rv3d->viewlock_quad & ~RV3D_VIEWLOCK_INIT) :
|
||||
RV3D_LOCKED;
|
||||
RV3D_LOCK_ROTATION;
|
||||
|
||||
region_quadview_init_rv3d(
|
||||
sa, region, viewlock, ED_view3d_lock_view_from_index(index_qsplit++), RV3D_ORTHO);
|
||||
|
||||
@@ -1239,6 +1239,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
||||
return;
|
||||
}
|
||||
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
@@ -1443,7 +1444,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
||||
|
||||
/* Draw 3D brush cursor. */
|
||||
GPU_matrix_push_projection();
|
||||
ED_view3d_draw_setup_view(CTX_wm_window(C),
|
||||
ED_view3d_draw_setup_view(wm,
|
||||
CTX_wm_window(C),
|
||||
CTX_data_depsgraph_pointer(C),
|
||||
CTX_data_scene(C),
|
||||
region,
|
||||
@@ -1537,7 +1539,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
||||
!is_multires) {
|
||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->deform_modifiers_active) {
|
||||
GPU_matrix_push_projection();
|
||||
ED_view3d_draw_setup_view(CTX_wm_window(C),
|
||||
ED_view3d_draw_setup_view(wm,
|
||||
CTX_wm_window(C),
|
||||
CTX_data_depsgraph_pointer(C),
|
||||
CTX_data_scene(C),
|
||||
region,
|
||||
@@ -1556,7 +1559,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_MULTIPLANE_SCRAPE &&
|
||||
brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW && !ss->cache->first_time) {
|
||||
GPU_matrix_push_projection();
|
||||
ED_view3d_draw_setup_view(CTX_wm_window(C),
|
||||
ED_view3d_draw_setup_view(wm,
|
||||
CTX_wm_window(C),
|
||||
CTX_data_depsgraph_pointer(C),
|
||||
CTX_data_scene(C),
|
||||
region,
|
||||
@@ -1573,7 +1577,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
|
||||
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_CLOTH && !ss->cache->first_time) {
|
||||
GPU_matrix_push_projection();
|
||||
ED_view3d_draw_setup_view(CTX_wm_window(C),
|
||||
ED_view3d_draw_setup_view(CTX_wm_manager(C),
|
||||
CTX_wm_window(C),
|
||||
CTX_data_depsgraph_pointer(C),
|
||||
CTX_data_scene(C),
|
||||
region,
|
||||
|
||||
@@ -94,6 +94,10 @@ if(WITH_FREESTYLE)
|
||||
add_definitions(-DWITH_FREESTYLE)
|
||||
endif()
|
||||
|
||||
if(WITH_XR_OPENXR)
|
||||
add_definitions(-DWITH_XR_OPENXR)
|
||||
endif()
|
||||
|
||||
blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# Needed so we can use dna_type_offsets.h for defaults initialization.
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_icons.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_lattice.h"
|
||||
@@ -114,38 +115,14 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
|
||||
if (region) {
|
||||
RegionView3D *rv3d;
|
||||
if ((region->regiontype == RGN_TYPE_WINDOW) && (rv3d = region->regiondata) &&
|
||||
(rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
(rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
|
||||
*r_v3d = v3d;
|
||||
*r_ar = region;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
ARegion *ar_unlock_user = NULL;
|
||||
ARegion *ar_unlock = NULL;
|
||||
for (region = sa->regionbase.first; region; region = region->next) {
|
||||
/* find the first unlocked rv3d */
|
||||
if (region->regiondata && region->regiontype == RGN_TYPE_WINDOW) {
|
||||
rv3d = region->regiondata;
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
ar_unlock = region;
|
||||
if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
|
||||
ar_unlock_user = region;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* camera/perspective view get priority when the active region is locked */
|
||||
if (ar_unlock_user) {
|
||||
if (ED_view3d_area_user_region(sa, v3d, r_ar)) {
|
||||
*r_v3d = v3d;
|
||||
*r_ar = ar_unlock_user;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ar_unlock) {
|
||||
*r_v3d = v3d;
|
||||
*r_ar = ar_unlock;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -155,6 +132,47 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to #ED_view3d_context_user_region() but does not use context. Always performs a lookup.
|
||||
* Also works if \a v3d is not the active space.
|
||||
*/
|
||||
bool ED_view3d_area_user_region(const ScrArea *sa, const View3D *v3d, ARegion **r_ar)
|
||||
{
|
||||
RegionView3D *rv3d = NULL;
|
||||
ARegion *ar_unlock_user = NULL;
|
||||
ARegion *ar_unlock = NULL;
|
||||
const ListBase *region_list = (v3d == sa->spacedata.first) ? &sa->regionbase : &v3d->regionbase;
|
||||
|
||||
BLI_assert(v3d->spacetype == SPACE_VIEW3D);
|
||||
|
||||
for (ARegion *region = region_list->first; region; region = region->next) {
|
||||
/* find the first unlocked rv3d */
|
||||
if (region->regiondata && region->regiontype == RGN_TYPE_WINDOW) {
|
||||
rv3d = region->regiondata;
|
||||
if ((rv3d->viewlock & RV3D_LOCK_ROTATION) == 0) {
|
||||
ar_unlock = region;
|
||||
if (rv3d->persp == RV3D_PERSP || rv3d->persp == RV3D_CAMOB) {
|
||||
ar_unlock_user = region;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* camera/perspective view get priority when the active region is locked */
|
||||
if (ar_unlock_user) {
|
||||
*r_ar = ar_unlock_user;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ar_unlock) {
|
||||
*r_ar = ar_unlock;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Most of the time this isn't needed since you could assume the view matrix was
|
||||
* set while drawing, however when functions like mesh_foreachScreenVert are
|
||||
* called by selection tools, we can't be sure this object was the last.
|
||||
@@ -333,9 +351,11 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
|
||||
v3dn->localvd = NULL;
|
||||
v3dn->runtime.properties_storage = NULL;
|
||||
}
|
||||
/* Only one View3D is allowed to have this flag! */
|
||||
v3dn->runtime.flag &= ~V3D_RUNTIME_XR_SESSION_ROOT;
|
||||
|
||||
v3dn->local_collections_uuid = 0;
|
||||
v3dn->flag &= ~V3D_LOCAL_COLLECTIONS;
|
||||
v3dn->flag &= ~(V3D_LOCAL_COLLECTIONS | V3D_XR_SESSION_MIRROR);
|
||||
|
||||
if (v3dn->shading.type == OB_RENDER) {
|
||||
v3dn->shading.type = OB_SOLID;
|
||||
@@ -715,6 +735,13 @@ static void view3d_main_region_listener(
|
||||
if (ELEM(wmn->data, ND_UNDO)) {
|
||||
WM_gizmomap_tag_refresh(gzmap);
|
||||
}
|
||||
else if (ELEM(wmn->data, ND_XR_DATA_CHANGED)) {
|
||||
/* Only cause a redraw if this a VR session mirror. Should more features be added that
|
||||
* require redraws, we could pass something to wmn->reference, e.g. the flag value. */
|
||||
if (v3d->flag & V3D_XR_SESSION_MIRROR) {
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NC_ANIMATION:
|
||||
switch (wmn->data) {
|
||||
@@ -912,6 +939,11 @@ static void view3d_main_region_listener(
|
||||
if (wmn->subtype == NS_VIEW3D_GPU) {
|
||||
rv3d->rflag |= RV3D_GPULIGHT_UPDATE;
|
||||
}
|
||||
#ifdef WITH_XR_OPENXR
|
||||
else if (wmn->subtype == NS_VIEW3D_SHADING) {
|
||||
ED_view3d_xr_shading_update(G_MAIN->wm.first, v3d, scene);
|
||||
}
|
||||
#endif
|
||||
ED_region_tag_redraw(region);
|
||||
WM_gizmomap_tag_refresh(gzmap);
|
||||
}
|
||||
@@ -1374,6 +1406,11 @@ static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
break;
|
||||
case NC_WM:
|
||||
if (wmn->data == ND_XR_DATA_CHANGED) {
|
||||
ED_region_tag_redraw(region);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -317,10 +317,35 @@ static void view3d_stereo3d_setup(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
static void view3d_xr_mirror_setup(const wmWindowManager *wm,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
View3D *v3d,
|
||||
ARegion *region,
|
||||
const rcti *rect)
|
||||
{
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
float viewmat[4][4];
|
||||
const float lens_old = v3d->lens;
|
||||
|
||||
if (!WM_xr_session_state_viewer_pose_matrix_info_get(&wm->xr, viewmat, &v3d->lens)) {
|
||||
/* Can't get info from XR session, use fallback values. */
|
||||
copy_m4_m4(viewmat, rv3d->viewmat);
|
||||
v3d->lens = lens_old;
|
||||
}
|
||||
view3d_main_region_setup_view(depsgraph, scene, v3d, region, viewmat, NULL, rect);
|
||||
|
||||
/* Reset overridden View3D data */
|
||||
v3d->lens = lens_old;
|
||||
}
|
||||
#endif /* WITH_XR_OPENXR */
|
||||
|
||||
/**
|
||||
* Set the correct matrices
|
||||
*/
|
||||
void ED_view3d_draw_setup_view(wmWindow *win,
|
||||
void ED_view3d_draw_setup_view(const wmWindowManager *wm,
|
||||
wmWindow *win,
|
||||
Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
ARegion *region,
|
||||
@@ -331,13 +356,23 @@ void ED_view3d_draw_setup_view(wmWindow *win,
|
||||
{
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
/* Setup the view matrix. */
|
||||
if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
|
||||
if (ED_view3d_is_region_xr_mirror_active(wm, v3d, region)) {
|
||||
view3d_xr_mirror_setup(wm, depsgraph, scene, v3d, region, rect);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (view3d_stereo3d_active(win, scene, v3d, rv3d)) {
|
||||
view3d_stereo3d_setup(depsgraph, scene, v3d, region, rect);
|
||||
}
|
||||
else {
|
||||
view3d_main_region_setup_view(depsgraph, scene, v3d, region, viewmat, winmat, rect);
|
||||
}
|
||||
|
||||
#ifndef WITH_XR_OPENXR
|
||||
UNUSED_VARS(wm);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -803,7 +838,8 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bo
|
||||
UI_Theme_Store(&theme_state);
|
||||
UI_SetTheme(SPACE_VIEW3D, RGN_TYPE_WINDOW);
|
||||
|
||||
ED_view3d_draw_setup_view(NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
|
||||
ED_view3d_draw_setup_view(
|
||||
G_MAIN->wm.first, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
|
||||
|
||||
GPU_clear(GPU_DEPTH_BIT);
|
||||
|
||||
@@ -1481,7 +1517,7 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((rv3d->viewlock & RV3D_LOCKED) == 0) &&
|
||||
if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) &&
|
||||
(rv3d->persp != RV3D_CAMOB)) {
|
||||
/* TODO: draw something else (but not this) during fly mode */
|
||||
draw_rotation_guide(rv3d);
|
||||
@@ -1552,7 +1588,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region)
|
||||
|
||||
static void view3d_draw_view(const bContext *C, ARegion *region)
|
||||
{
|
||||
ED_view3d_draw_setup_view(CTX_wm_window(C),
|
||||
ED_view3d_draw_setup_view(CTX_wm_manager(C),
|
||||
CTX_wm_window(C),
|
||||
CTX_data_expect_evaluated_depsgraph(C),
|
||||
CTX_data_scene(C),
|
||||
region,
|
||||
@@ -1641,6 +1678,7 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
|
||||
int winy,
|
||||
float viewmat[4][4],
|
||||
float winmat[4][4],
|
||||
bool is_image_render,
|
||||
bool do_sky,
|
||||
bool UNUSED(is_persp),
|
||||
const char *viewname,
|
||||
@@ -1690,8 +1728,15 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
|
||||
}
|
||||
|
||||
/* main drawing call */
|
||||
DRW_draw_render_loop_offscreen(
|
||||
depsgraph, engine_type, region, v3d, do_sky, do_color_management, ofs, viewport);
|
||||
DRW_draw_render_loop_offscreen(depsgraph,
|
||||
engine_type,
|
||||
region,
|
||||
v3d,
|
||||
is_image_render,
|
||||
do_sky,
|
||||
do_color_management,
|
||||
ofs,
|
||||
viewport);
|
||||
|
||||
/* restore size */
|
||||
region->winx = bwinx;
|
||||
@@ -1706,6 +1751,94 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
|
||||
G.f &= ~G_FLAG_RENDER_VIEWPORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates own fake 3d views (wrapping #ED_view3d_draw_offscreen). Similar too
|
||||
* #ED_view_draw_offscreen_imbuf_simple, but takes view/projection matrices as arguments.
|
||||
*/
|
||||
void ED_view3d_draw_offscreen_simple(Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
View3DShading *shading_override,
|
||||
int drawtype,
|
||||
int winx,
|
||||
int winy,
|
||||
uint draw_flags,
|
||||
float viewmat[4][4],
|
||||
float winmat[4][4],
|
||||
float clip_start,
|
||||
float clip_end,
|
||||
bool is_image_render,
|
||||
bool do_sky,
|
||||
bool is_persp,
|
||||
const char *viewname,
|
||||
const bool do_color_management,
|
||||
GPUOffScreen *ofs,
|
||||
GPUViewport *viewport)
|
||||
{
|
||||
View3D v3d = {NULL};
|
||||
ARegion ar = {NULL};
|
||||
RegionView3D rv3d = {{{0}}};
|
||||
|
||||
v3d.regionbase.first = v3d.regionbase.last = &ar;
|
||||
ar.regiondata = &rv3d;
|
||||
ar.regiontype = RGN_TYPE_WINDOW;
|
||||
|
||||
View3DShading *source_shading_settings = &scene->display.shading;
|
||||
if (draw_flags & V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS && shading_override != NULL) {
|
||||
source_shading_settings = shading_override;
|
||||
}
|
||||
memcpy(&v3d.shading, source_shading_settings, sizeof(View3DShading));
|
||||
v3d.shading.type = drawtype;
|
||||
|
||||
if (shading_override) {
|
||||
/* Pass. */
|
||||
}
|
||||
else if (drawtype == OB_MATERIAL) {
|
||||
v3d.shading.flag = V3D_SHADING_SCENE_WORLD | V3D_SHADING_SCENE_LIGHTS;
|
||||
}
|
||||
|
||||
if (draw_flags & V3D_OFSDRAW_SHOW_ANNOTATION) {
|
||||
v3d.flag2 |= V3D_SHOW_ANNOTATION;
|
||||
}
|
||||
if (draw_flags & V3D_OFSDRAW_SHOW_GRIDFLOOR) {
|
||||
v3d.gridflag |= V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y;
|
||||
v3d.grid = 1.0f;
|
||||
v3d.gridlines = 16;
|
||||
v3d.gridsubdiv = 10;
|
||||
|
||||
/* Show grid, disable other overlays (set all available _HIDE_ flags). */
|
||||
v3d.overlay.flag |= V3D_OVERLAY_HIDE_CURSOR | V3D_OVERLAY_HIDE_TEXT |
|
||||
V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_BONES |
|
||||
V3D_OVERLAY_HIDE_OBJECT_XTRAS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
|
||||
v3d.flag |= V3D_HIDE_HELPLINES;
|
||||
}
|
||||
else {
|
||||
v3d.flag2 = V3D_HIDE_OVERLAYS;
|
||||
}
|
||||
|
||||
rv3d.persp = RV3D_PERSP;
|
||||
v3d.clip_start = clip_start;
|
||||
v3d.clip_end = clip_end;
|
||||
/* Actually not used since we pass in the projection matrix. */
|
||||
v3d.lens = 0;
|
||||
|
||||
ED_view3d_draw_offscreen(depsgraph,
|
||||
scene,
|
||||
drawtype,
|
||||
&v3d,
|
||||
&ar,
|
||||
winx,
|
||||
winy,
|
||||
viewmat,
|
||||
winmat,
|
||||
is_image_render,
|
||||
do_sky,
|
||||
is_persp,
|
||||
viewname,
|
||||
do_color_management,
|
||||
ofs,
|
||||
viewport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility func for ED_view3d_draw_offscreen
|
||||
*
|
||||
@@ -1815,6 +1948,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
|
||||
sizey,
|
||||
NULL,
|
||||
winmat,
|
||||
true,
|
||||
draw_sky,
|
||||
!is_ortho,
|
||||
viewname,
|
||||
@@ -1902,6 +2036,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
|
||||
if (draw_flags & V3D_OFSDRAW_SHOW_ANNOTATION) {
|
||||
v3d.flag2 |= V3D_SHOW_ANNOTATION;
|
||||
}
|
||||
if (draw_flags & V3D_OFSDRAW_SHOW_GRIDFLOOR) {
|
||||
v3d.gridflag |= V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y;
|
||||
}
|
||||
|
||||
v3d.shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
|
||||
|
||||
@@ -2212,7 +2349,7 @@ float view3d_depth_near(ViewDepths *d)
|
||||
void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d)
|
||||
{
|
||||
/* Setup view matrix. */
|
||||
ED_view3d_draw_setup_view(NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
|
||||
ED_view3d_draw_setup_view(NULL, NULL, depsgraph, scene, region, v3d, NULL, NULL, NULL);
|
||||
|
||||
GPU_clear(GPU_DEPTH_BIT);
|
||||
|
||||
|
||||
@@ -85,6 +85,52 @@ enum {
|
||||
HAS_ROTATE = (1 << 0),
|
||||
};
|
||||
|
||||
/* test for unlocked camera view in quad view */
|
||||
static bool view3d_camera_user_poll(bContext *C)
|
||||
{
|
||||
View3D *v3d;
|
||||
ARegion *region;
|
||||
|
||||
if (ED_view3d_context_user_region(C, &v3d, ®ion)) {
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
if ((rv3d->persp == RV3D_CAMOB) && !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool view3d_lock_poll(bContext *C)
|
||||
{
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
if (v3d) {
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
if (rv3d) {
|
||||
return ED_view3d_offset_lock_check(v3d, rv3d);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool view3d_pan_poll(bContext *C)
|
||||
{
|
||||
if (ED_operator_region_view3d_active(C)) {
|
||||
const RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool view3d_zoom_or_dolly_poll(bContext *C)
|
||||
{
|
||||
if (ED_operator_region_view3d_active(C)) {
|
||||
const RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
return !(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generic View Operator Properties
|
||||
* \{ */
|
||||
@@ -935,7 +981,7 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
vod = op->customdata;
|
||||
|
||||
/* poll should check but in some cases fails, see poll func for details */
|
||||
if (vod->rv3d->viewlock & RV3D_LOCKED) {
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) {
|
||||
viewops_data_free(C, op);
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
@@ -983,34 +1029,6 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
/* test for unlocked camera view in quad view */
|
||||
static bool view3d_camera_user_poll(bContext *C)
|
||||
{
|
||||
View3D *v3d;
|
||||
ARegion *region;
|
||||
|
||||
if (ED_view3d_context_user_region(C, &v3d, ®ion)) {
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
if (rv3d->persp == RV3D_CAMOB) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool view3d_lock_poll(bContext *C)
|
||||
{
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
if (v3d) {
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
if (rv3d) {
|
||||
return ED_view3d_offset_lock_check(v3d, rv3d);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void viewrotate_cancel(bContext *C, wmOperator *op)
|
||||
{
|
||||
viewops_data_free(C, op);
|
||||
@@ -1051,7 +1069,7 @@ static bool ndof_has_translate(const wmNDOFMotionData *ndof,
|
||||
|
||||
static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d)
|
||||
{
|
||||
return !is_zero_v3(ndof->rvec) && ((rv3d->viewlock & RV3D_LOCKED) == 0);
|
||||
return !is_zero_v3(ndof->rvec) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1159,7 +1177,7 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof,
|
||||
/* move center of view opposite of hand motion (this is camera mode, not object mode) */
|
||||
sub_v3_v3(rv3d->ofs, pan_vec);
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(sa, region);
|
||||
}
|
||||
}
|
||||
@@ -1176,7 +1194,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof,
|
||||
|
||||
float view_inv[4];
|
||||
|
||||
BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
|
||||
BLI_assert((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0);
|
||||
|
||||
ED_view3d_persp_ensure(vod->depsgraph, v3d, region);
|
||||
|
||||
@@ -1400,7 +1418,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
const bool has_rotation = ndof_has_rotate(ndof, rv3d);
|
||||
/* if we can't rotate, fallback to translate (locked axis views) */
|
||||
const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) &&
|
||||
(rv3d->viewlock & RV3D_LOCKED);
|
||||
(RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION);
|
||||
const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp;
|
||||
|
||||
if (has_translate || has_zoom) {
|
||||
@@ -1732,7 +1750,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
|
||||
|
||||
add_v3_v3(vod->rv3d->ofs, dvec);
|
||||
|
||||
if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(vod->sa, vod->region);
|
||||
}
|
||||
}
|
||||
@@ -1807,12 +1825,17 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
|
||||
/* makes op->customdata */
|
||||
viewops_data_alloc(C, op);
|
||||
vod = op->customdata;
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_LOCATION) {
|
||||
viewops_data_free(C, op);
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
viewops_data_create(C,
|
||||
op,
|
||||
event,
|
||||
(viewops_flag_from_prefs() & ~VIEWOPS_FLAG_ORBIT_SELECT) |
|
||||
(use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
|
||||
vod = op->customdata;
|
||||
|
||||
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->region);
|
||||
|
||||
@@ -2165,7 +2188,7 @@ static void viewzoom_apply_3d(ViewOpsData *vod,
|
||||
/* these limits were in old code too */
|
||||
CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
|
||||
|
||||
if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(vod->sa, vod->region);
|
||||
}
|
||||
|
||||
@@ -2318,7 +2341,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(sa, region);
|
||||
}
|
||||
|
||||
@@ -2416,7 +2439,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
|
||||
ot->invoke = viewzoom_invoke;
|
||||
ot->exec = viewzoom_exec;
|
||||
ot->modal = viewzoom_modal;
|
||||
ot->poll = ED_operator_region_view3d_active;
|
||||
ot->poll = view3d_zoom_or_dolly_poll;
|
||||
ot->cancel = viewzoom_cancel;
|
||||
|
||||
/* flags */
|
||||
@@ -2514,7 +2537,7 @@ static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_
|
||||
view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, zfac);
|
||||
}
|
||||
|
||||
if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(vod->sa, vod->region);
|
||||
}
|
||||
|
||||
@@ -2612,7 +2635,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
|
||||
|
||||
view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f);
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(sa, region);
|
||||
}
|
||||
|
||||
@@ -2641,7 +2664,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
vod = op->customdata;
|
||||
|
||||
/* poll should check but in some cases fails, see poll func for details */
|
||||
if (vod->rv3d->viewlock & RV3D_LOCKED) {
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_LOCK_ROTATION) {
|
||||
viewops_data_free(C, op);
|
||||
return OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
@@ -3121,7 +3144,7 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = viewselected_exec;
|
||||
ot->poll = ED_operator_region_view3d_active;
|
||||
ot->poll = view3d_zoom_or_dolly_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = 0;
|
||||
@@ -3265,7 +3288,7 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = viewcenter_cursor_exec;
|
||||
ot->poll = ED_operator_view3d_active;
|
||||
ot->poll = view3d_pan_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = 0;
|
||||
@@ -3317,7 +3340,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = viewcenter_pick_invoke;
|
||||
ot->poll = ED_operator_view3d_active;
|
||||
ot->poll = view3d_pan_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = 0;
|
||||
@@ -3701,7 +3724,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
|
||||
.dist = &new_dist,
|
||||
});
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(CTX_wm_area(C), region);
|
||||
}
|
||||
|
||||
@@ -3721,7 +3744,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
|
||||
ot->modal = WM_gesture_box_modal;
|
||||
ot->cancel = WM_gesture_box_cancel;
|
||||
|
||||
ot->poll = ED_operator_region_view3d_active;
|
||||
ot->poll = view3d_zoom_or_dolly_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = 0;
|
||||
@@ -3834,7 +3857,7 @@ static void axis_set_view(bContext *C,
|
||||
rv3d->view_axis_roll = view_axis_roll;
|
||||
}
|
||||
|
||||
if (rv3d->viewlock & RV3D_LOCKED) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) {
|
||||
ED_region_tag_redraw(region);
|
||||
return;
|
||||
}
|
||||
@@ -4058,7 +4081,7 @@ static int view_camera_exec(bContext *C, wmOperator *op)
|
||||
|
||||
ED_view3d_smooth_view_force_finish(C, v3d, region);
|
||||
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
|
||||
/* lastview - */
|
||||
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
@@ -4207,7 +4230,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
|
||||
RV3D_VIEW_USER;
|
||||
orbitdir = RNA_enum_get(op->ptr, "type");
|
||||
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) && (view_opposite == RV3D_VIEW_USER)) {
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) && (view_opposite == RV3D_VIEW_USER)) {
|
||||
/* no NULL check is needed, poll checks */
|
||||
ED_view3d_context_user_region(C, &v3d, ®ion);
|
||||
rv3d = region->regiondata;
|
||||
@@ -4215,7 +4238,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
|
||||
|
||||
ED_view3d_smooth_view_force_finish(C, v3d, region);
|
||||
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0 || (view_opposite != RV3D_VIEW_USER)) {
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0 || (view_opposite != RV3D_VIEW_USER)) {
|
||||
if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) {
|
||||
int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
|
||||
float quat_mul[4];
|
||||
@@ -4352,7 +4375,7 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
|
||||
vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
|
||||
}
|
||||
|
||||
if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(vod->sa, vod->region);
|
||||
}
|
||||
|
||||
@@ -4621,7 +4644,7 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = viewpan_invoke;
|
||||
ot->poll = ED_operator_region_view3d_active;
|
||||
ot->poll = view3d_pan_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = 0;
|
||||
@@ -4647,7 +4670,8 @@ static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
ED_view3d_context_user_region(C, &v3d_dummy, ®ion);
|
||||
rv3d = region->regiondata;
|
||||
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
/* Could add a separate lock flag for locking persp. */
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
|
||||
if (rv3d->persp != RV3D_ORTHO) {
|
||||
rv3d->persp = RV3D_ORTHO;
|
||||
}
|
||||
|
||||
@@ -1039,7 +1039,7 @@ static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
FlyInfo *fly;
|
||||
|
||||
if (rv3d->viewlock & RV3D_LOCKED) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,14 +252,14 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
|
||||
(navgroup->state.rect_visible.ymax == rect_visible->ymax) &&
|
||||
(navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
|
||||
(navgroup->state.rv3d.is_camera == (rv3d->persp == RV3D_CAMOB)) &&
|
||||
(navgroup->state.rv3d.viewlock == rv3d->viewlock)) {
|
||||
(navgroup->state.rv3d.viewlock == RV3D_LOCK_FLAGS(rv3d))) {
|
||||
return;
|
||||
}
|
||||
|
||||
navgroup->state.rect_visible = *rect_visible;
|
||||
navgroup->state.rv3d.is_persp = rv3d->is_persp;
|
||||
navgroup->state.rv3d.is_camera = (rv3d->persp == RV3D_CAMOB);
|
||||
navgroup->state.rv3d.viewlock = rv3d->viewlock;
|
||||
navgroup->state.rv3d.viewlock = RV3D_LOCK_FLAGS(rv3d);
|
||||
|
||||
const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0;
|
||||
const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO);
|
||||
@@ -296,7 +296,6 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
|
||||
}
|
||||
|
||||
/* RV3D_LOCKED or Camera: only show supported buttons. */
|
||||
if (show_rotate_gizmo) {
|
||||
gz = navgroup->gz_array[GZ_INDEX_ROTATE];
|
||||
gz->matrix_basis[3][0] = co_rotate[0];
|
||||
@@ -306,26 +305,30 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g
|
||||
|
||||
if (show_navigate) {
|
||||
int icon_mini_slot = 0;
|
||||
gz = navgroup->gz_array[GZ_INDEX_ZOOM];
|
||||
gz->matrix_basis[3][0] = roundf(co[0]);
|
||||
gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
|
||||
|
||||
gz = navgroup->gz_array[GZ_INDEX_MOVE];
|
||||
gz->matrix_basis[3][0] = roundf(co[0]);
|
||||
gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
|
||||
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
gz = navgroup->gz_array[GZ_INDEX_CAMERA];
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ZOOM_AND_DOLLY) == 0) {
|
||||
gz = navgroup->gz_array[GZ_INDEX_ZOOM];
|
||||
gz->matrix_basis[3][0] = roundf(co[0]);
|
||||
gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
|
||||
}
|
||||
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_LOCATION) == 0) {
|
||||
gz = navgroup->gz_array[GZ_INDEX_MOVE];
|
||||
gz->matrix_basis[3][0] = roundf(co[0]);
|
||||
gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
|
||||
}
|
||||
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
|
||||
gz = navgroup->gz_array[GZ_INDEX_CAMERA];
|
||||
gz->matrix_basis[3][0] = co[0];
|
||||
gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
|
||||
|
||||
if (navgroup->state.rv3d.is_camera == false) {
|
||||
gz = navgroup->gz_array[rv3d->is_persp ? GZ_INDEX_PERSP : GZ_INDEX_ORTHO];
|
||||
gz->matrix_basis[3][0] = roundf(co[0]);
|
||||
gz->matrix_basis[3][1] = roundf(co[1] - (icon_offset_mini * icon_mini_slot++));
|
||||
gz->matrix_basis[3][0] = co[0];
|
||||
gz->matrix_basis[3][1] = co[1] - (icon_offset_mini * icon_mini_slot++);
|
||||
WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,7 +459,7 @@ bool ED_view3d_persp_ensure(const Depsgraph *depsgraph, View3D *v3d, ARegion *re
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
|
||||
|
||||
BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
|
||||
BLI_assert((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0);
|
||||
|
||||
if (ED_view3d_camera_lock_check(v3d, rv3d)) {
|
||||
return false;
|
||||
@@ -679,7 +679,7 @@ static void view3d_boxview_clip(ScrArea *sa)
|
||||
if (region->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXCLIP) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) {
|
||||
if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
|
||||
if (region->winx > region->winy) {
|
||||
x1 = rv3d->dist;
|
||||
@@ -751,7 +751,7 @@ static void view3d_boxview_clip(ScrArea *sa)
|
||||
if (region->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXCLIP) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXCLIP) {
|
||||
rv3d->rflag |= RV3D_CLIPPING;
|
||||
memcpy(rv3d->clip, clip, sizeof(clip));
|
||||
if (rv3d->clipbb) {
|
||||
@@ -822,10 +822,10 @@ void view3d_boxview_sync(ScrArea *sa, ARegion *region)
|
||||
if (artest != region && artest->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3dtest = artest->regiondata;
|
||||
|
||||
if (rv3dtest->viewlock & RV3D_LOCKED) {
|
||||
if (RV3D_LOCK_FLAGS(rv3dtest) & RV3D_LOCK_ROTATION) {
|
||||
rv3dtest->dist = rv3d->dist;
|
||||
view3d_boxview_sync_axis(rv3dtest, rv3d);
|
||||
clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
|
||||
clip |= RV3D_LOCK_FLAGS(rv3dtest) & RV3D_BOXCLIP;
|
||||
|
||||
ED_region_tag_redraw(artest);
|
||||
}
|
||||
@@ -848,12 +848,12 @@ void view3d_boxview_copy(ScrArea *sa, ARegion *region)
|
||||
if (artest != region && artest->regiontype == RGN_TYPE_WINDOW) {
|
||||
RegionView3D *rv3dtest = artest->regiondata;
|
||||
|
||||
if (rv3dtest->viewlock) {
|
||||
if (RV3D_LOCK_FLAGS(rv3dtest)) {
|
||||
rv3dtest->dist = rv3d->dist;
|
||||
copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
|
||||
ED_region_tag_redraw(artest);
|
||||
|
||||
clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
|
||||
clip |= ((RV3D_LOCK_FLAGS(rv3dtest) & RV3D_BOXCLIP) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -874,7 +874,7 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *region, bool do_clip)
|
||||
* properties are always being edited, weak */
|
||||
viewlock = rv3d->viewlock;
|
||||
|
||||
if ((viewlock & RV3D_LOCKED) == 0) {
|
||||
if ((viewlock & RV3D_LOCK_ROTATION) == 0) {
|
||||
do_clip = (viewlock & RV3D_BOXCLIP) != 0;
|
||||
viewlock = 0;
|
||||
}
|
||||
@@ -899,12 +899,12 @@ void ED_view3d_quadview_update(ScrArea *sa, ARegion *region, bool do_clip)
|
||||
}
|
||||
}
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
|
||||
}
|
||||
|
||||
/* ensure locked regions have an axis, locked user views don't make much sense */
|
||||
if (viewlock & RV3D_LOCKED) {
|
||||
if (viewlock & RV3D_LOCK_ROTATION) {
|
||||
int index_qsplit = 0;
|
||||
for (region = sa->regionbase.first; region; region = region->next) {
|
||||
if (region->alignment == RGN_ALIGN_QSPLIT) {
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_layer.h"
|
||||
@@ -228,7 +229,7 @@ void ED_view3d_smooth_view_ex(
|
||||
ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
|
||||
}
|
||||
/* grid draw as floor */
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
|
||||
/* use existing if exists, means multiple calls to smooth view
|
||||
* wont loose the original 'view' setting */
|
||||
rv3d->view = RV3D_VIEW_USER;
|
||||
@@ -291,7 +292,7 @@ void ED_view3d_smooth_view_ex(
|
||||
ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d);
|
||||
}
|
||||
|
||||
if (rv3d->viewlock & RV3D_BOXVIEW) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
|
||||
view3d_boxview_copy(sa, region);
|
||||
}
|
||||
|
||||
@@ -344,7 +345,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, b
|
||||
ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
|
||||
}
|
||||
|
||||
if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
|
||||
rv3d->view = sms->org_view;
|
||||
}
|
||||
|
||||
@@ -384,7 +385,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, b
|
||||
WM_event_add_mousemove(CTX_wm_window(C));
|
||||
}
|
||||
|
||||
if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) {
|
||||
if (sync_boxview && (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW)) {
|
||||
view3d_boxview_copy(CTX_wm_area(C), region);
|
||||
}
|
||||
|
||||
@@ -494,7 +495,7 @@ static bool view3d_camera_to_view_poll(bContext *C)
|
||||
if (ED_view3d_context_user_region(C, &v3d, ®ion)) {
|
||||
RegionView3D *rv3d = region->regiondata;
|
||||
if (v3d && v3d->camera && !ID_IS_LINKED(v3d->camera)) {
|
||||
if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) {
|
||||
if (rv3d && (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) == 0) {
|
||||
if (rv3d->persp != RV3D_CAMOB) {
|
||||
return 1;
|
||||
}
|
||||
@@ -826,7 +827,7 @@ void view3d_viewmatrix_set(Depsgraph *depsgraph,
|
||||
bool use_lock_ofs = false;
|
||||
|
||||
/* should be moved to better initialize later on XXX */
|
||||
if (rv3d->viewlock & RV3D_LOCKED) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) {
|
||||
ED_view3d_lock(rv3d);
|
||||
}
|
||||
|
||||
@@ -991,6 +992,7 @@ int view3d_opengl_select(ViewContext *vc,
|
||||
eV3DSelectObjectFilter select_filter)
|
||||
{
|
||||
struct bThemeState theme_state;
|
||||
const wmWindowManager *wm = CTX_wm_manager(vc->C);
|
||||
Depsgraph *depsgraph = vc->depsgraph;
|
||||
Scene *scene = vc->scene;
|
||||
View3D *v3d = vc->v3d;
|
||||
@@ -1097,7 +1099,7 @@ int view3d_opengl_select(ViewContext *vc,
|
||||
/* Important we use the 'viewmat' and don't re-calculate since
|
||||
* the object & bone view locking takes 'rect' into account, see: T51629. */
|
||||
ED_view3d_draw_setup_view(
|
||||
vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, &rect);
|
||||
wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, &rect);
|
||||
|
||||
if (!XRAY_ACTIVE(v3d)) {
|
||||
GPU_depth_test(true);
|
||||
@@ -1165,7 +1167,8 @@ int view3d_opengl_select(ViewContext *vc,
|
||||
}
|
||||
|
||||
G.f &= ~G_FLAG_PICKSEL;
|
||||
ED_view3d_draw_setup_view(vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, NULL);
|
||||
ED_view3d_draw_setup_view(
|
||||
wm, vc->win, depsgraph, scene, region, v3d, vc->rv3d->viewmat, NULL, NULL);
|
||||
|
||||
if (!XRAY_ACTIVE(v3d)) {
|
||||
GPU_depth_test(false);
|
||||
@@ -1684,3 +1687,83 @@ void ED_view3d_local_collections_reset(struct bContext *C, const bool reset_all)
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name XR Functionality
|
||||
* \{ */
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
|
||||
static void view3d_xr_mirror_begin(RegionView3D *rv3d)
|
||||
{
|
||||
/* If there is no session yet, changes below should not be applied! */
|
||||
BLI_assert(WM_xr_session_exists(&((wmWindowManager *)G_MAIN->wm.first)->xr));
|
||||
|
||||
rv3d->runtime_viewlock |= RV3D_LOCK_ANY_TRANSFORM;
|
||||
/* Force perspective view. This isn't reset but that's not really an issue. */
|
||||
rv3d->persp = RV3D_PERSP;
|
||||
}
|
||||
|
||||
static void view3d_xr_mirror_end(RegionView3D *rv3d)
|
||||
{
|
||||
rv3d->runtime_viewlock &= ~RV3D_LOCK_ANY_TRANSFORM;
|
||||
}
|
||||
|
||||
void ED_view3d_xr_mirror_update(const ScrArea *area, const View3D *v3d, const bool enable)
|
||||
{
|
||||
ARegion *region_rv3d;
|
||||
|
||||
BLI_assert(v3d->spacetype == SPACE_VIEW3D);
|
||||
|
||||
if (ED_view3d_area_user_region(area, v3d, ®ion_rv3d)) {
|
||||
if (enable) {
|
||||
view3d_xr_mirror_begin(region_rv3d->regiondata);
|
||||
}
|
||||
else {
|
||||
view3d_xr_mirror_end(region_rv3d->regiondata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ED_view3d_xr_shading_update(wmWindowManager *wm, const View3D *v3d, const Scene *scene)
|
||||
{
|
||||
if (v3d->runtime.flag & V3D_RUNTIME_XR_SESSION_ROOT) {
|
||||
View3DShading *xr_shading = &wm->xr.session_settings.shading;
|
||||
|
||||
BLI_assert(WM_xr_session_exists(&wm->xr));
|
||||
|
||||
if (v3d->shading.type == OB_RENDER) {
|
||||
if (!(BKE_scene_uses_blender_workbench(scene) || BKE_scene_uses_blender_eevee(scene))) {
|
||||
/* Keep old shading while using Cycles or another engine, they are typically not usable in
|
||||
* VR. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (xr_shading->prop) {
|
||||
IDP_FreeProperty(xr_shading->prop);
|
||||
xr_shading->prop = NULL;
|
||||
}
|
||||
|
||||
/* Copy shading from View3D to VR view. */
|
||||
*xr_shading = v3d->shading;
|
||||
if (v3d->shading.prop) {
|
||||
xr_shading->prop = IDP_CopyProperty(xr_shading->prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ED_view3d_is_region_xr_mirror_active(const wmWindowManager *wm,
|
||||
const View3D *v3d,
|
||||
const ARegion *region)
|
||||
{
|
||||
return (v3d->flag & V3D_XR_SESSION_MIRROR) &&
|
||||
/* The free region (e.g. the camera region in quad-view) is always the last in the list
|
||||
base. We don't want any other to be affected. */
|
||||
!region->next && //
|
||||
WM_xr_session_is_ready(&wm->xr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -1347,7 +1347,7 @@ static int walk_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
WalkInfo *walk;
|
||||
|
||||
if (rv3d->viewlock & RV3D_LOCKED) {
|
||||
if (RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ANY_TRANSFORM) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,9 @@ GPUViewport *GPU_viewport_create(void);
|
||||
void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
|
||||
void GPU_viewport_unbind(GPUViewport *viewport);
|
||||
void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect);
|
||||
void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
|
||||
const rcti *rect,
|
||||
bool display_colorspace);
|
||||
void GPU_viewport_free(GPUViewport *viewport);
|
||||
|
||||
void GPU_viewport_colorspace_set(GPUViewport *viewport,
|
||||
|
||||
@@ -532,7 +532,13 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
|
||||
/**
|
||||
* Version of #GPU_viewport_draw_to_screen() that lets caller decide if display colorspace
|
||||
* transform should be performed.
|
||||
*/
|
||||
void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
|
||||
const rcti *rect,
|
||||
bool display_colorspace)
|
||||
{
|
||||
DefaultFramebufferList *dfbl = viewport->fbl;
|
||||
DefaultTextureList *dtxl = viewport->txl;
|
||||
@@ -545,18 +551,22 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
|
||||
const float w = (float)GPU_texture_width(color);
|
||||
const float h = (float)GPU_texture_height(color);
|
||||
|
||||
BLI_assert(w == BLI_rcti_size_x(rect) + 1);
|
||||
BLI_assert(h == BLI_rcti_size_y(rect) + 1);
|
||||
/* We allow rects with min/max swapped, but we also need coorectly assigned coordinates. */
|
||||
rcti sanitized_rect = *rect;
|
||||
BLI_rcti_sanitize(&sanitized_rect);
|
||||
|
||||
BLI_assert(w == BLI_rcti_size_x(&sanitized_rect) + 1);
|
||||
BLI_assert(h == BLI_rcti_size_y(&sanitized_rect) + 1);
|
||||
|
||||
/* wmOrtho for the screen has this same offset */
|
||||
const float halfx = GLA_PIXEL_OFS / w;
|
||||
const float halfy = GLA_PIXEL_OFS / h;
|
||||
|
||||
rctf pos_rect = {
|
||||
.xmin = rect->xmin,
|
||||
.ymin = rect->ymin,
|
||||
.xmax = rect->xmin + w,
|
||||
.ymax = rect->ymin + h,
|
||||
.xmin = sanitized_rect.xmin,
|
||||
.ymin = sanitized_rect.ymin,
|
||||
.xmax = sanitized_rect.xmin + w,
|
||||
.ymax = sanitized_rect.ymin + h,
|
||||
};
|
||||
|
||||
rctf uv_rect = {
|
||||
@@ -565,8 +575,28 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
|
||||
.xmax = halfx + 1.0f,
|
||||
.ymax = halfy + 1.0f,
|
||||
};
|
||||
/* Mirror the UV rect in case axis-swapped drawing is requested (by passing a rect with min and
|
||||
* max values swapped). */
|
||||
if (BLI_rcti_size_x(rect) < 0) {
|
||||
SWAP(float, uv_rect.xmin, uv_rect.xmax);
|
||||
}
|
||||
if (BLI_rcti_size_y(rect) < 0) {
|
||||
SWAP(float, uv_rect.ymin, uv_rect.ymax);
|
||||
}
|
||||
|
||||
gpu_viewport_draw_colormanaged(viewport, &pos_rect, &uv_rect, true);
|
||||
gpu_viewport_draw_colormanaged(viewport, &pos_rect, &uv_rect, display_colorspace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge and draw the buffers of \a viewport into the currently active framebuffer, performing
|
||||
* color transform to display space.
|
||||
*
|
||||
* \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done with
|
||||
* inversed axis coordinates (upside down or sideways).
|
||||
*/
|
||||
void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
|
||||
{
|
||||
GPU_viewport_draw_to_screen_ex(viewport, rect, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,7 @@ typedef enum eV3DOffscreenDrawFlag {
|
||||
V3D_OFSDRAW_NONE = (0),
|
||||
V3D_OFSDRAW_SHOW_ANNOTATION = (1 << 0),
|
||||
V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS = (1 << 1),
|
||||
V3D_OFSDRAW_SHOW_GRIDFLOOR = (1 << 2),
|
||||
} eV3DOffscreenDrawFlag;
|
||||
|
||||
/** #View3DShading.light */
|
||||
|
||||
@@ -106,10 +106,12 @@ typedef struct RegionView3D {
|
||||
char persp;
|
||||
char view;
|
||||
char view_axis_roll;
|
||||
char viewlock;
|
||||
char viewlock; /* Should usually be accessed with RV3D_LOCK_FLAGS()! */
|
||||
/** Options for runtime only locking (cleared on file read) */
|
||||
char runtime_viewlock; /* Should usually be accessed with RV3D_LOCK_FLAGS()! */
|
||||
/** Options for quadview (store while out of quad view). */
|
||||
char viewlock_quad;
|
||||
char _pad[2];
|
||||
char _pad[1];
|
||||
/** Normalized offset for locked view: (-1, -1) bottom left, (1, 1) upper right. */
|
||||
float ofs_lock[2];
|
||||
|
||||
@@ -232,6 +234,10 @@ typedef struct View3DOverlay {
|
||||
typedef struct View3D_Runtime {
|
||||
/** Nkey panel stores stuff here. */
|
||||
void *properties_storage;
|
||||
/** Runtime only flags. */
|
||||
int flag;
|
||||
|
||||
char _pad1[4];
|
||||
} View3D_Runtime;
|
||||
|
||||
/** 3D ViewPort Struct. */
|
||||
@@ -342,6 +348,7 @@ typedef struct View3D {
|
||||
#define V3D_FLAG_UNUSED_1 (1 << 1) /* cleared */
|
||||
#define V3D_HIDE_HELPLINES (1 << 2)
|
||||
#define V3D_INVALID_BACKBUF (1 << 3)
|
||||
#define V3D_XR_SESSION_MIRROR (1 << 4)
|
||||
|
||||
#define V3D_FLAG_UNUSED_10 (1 << 10) /* cleared */
|
||||
#define V3D_SELECT_OUTLINE (1 << 11)
|
||||
@@ -349,6 +356,12 @@ typedef struct View3D {
|
||||
#define V3D_GLOBAL_STATS (1 << 13)
|
||||
#define V3D_DRAW_CENTERS (1 << 15)
|
||||
|
||||
/** #View3D_Runtime.flag */
|
||||
enum {
|
||||
/** The 3D view which the XR session was created in is flagged with this. */
|
||||
V3D_RUNTIME_XR_SESSION_ROOT = (1 << 0),
|
||||
};
|
||||
|
||||
/** #RegionView3D.persp */
|
||||
#define RV3D_ORTHO 0
|
||||
#define RV3D_PERSP 1
|
||||
@@ -367,9 +380,19 @@ typedef struct View3D {
|
||||
#define RV3D_ZOFFSET_DISABLED 64
|
||||
|
||||
/** #RegionView3D.viewlock */
|
||||
#define RV3D_LOCKED (1 << 0)
|
||||
#define RV3D_BOXVIEW (1 << 1)
|
||||
#define RV3D_BOXCLIP (1 << 2)
|
||||
enum {
|
||||
RV3D_LOCK_ROTATION = (1 << 0),
|
||||
RV3D_BOXVIEW = (1 << 1),
|
||||
RV3D_BOXCLIP = (1 << 2),
|
||||
RV3D_LOCK_LOCATION = (1 << 3),
|
||||
RV3D_LOCK_ZOOM_AND_DOLLY = (1 << 4),
|
||||
|
||||
RV3D_LOCK_ANY_TRANSFORM = (RV3D_LOCK_LOCATION | RV3D_LOCK_ROTATION | RV3D_LOCK_ZOOM_AND_DOLLY),
|
||||
};
|
||||
|
||||
/* Bitwise OR of the regular lock-flags with runtime only lock-flags. */
|
||||
#define RV3D_LOCK_FLAGS(rv3d) ((rv3d)->viewlock | ((rv3d)->runtime_viewlock))
|
||||
|
||||
/** #RegionView3D.viewlock_quad */
|
||||
#define RV3D_VIEWLOCK_INIT (1 << 7)
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_vec_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
#include "DNA_xr_types.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
|
||||
@@ -119,6 +120,16 @@ typedef struct ReportTimerInfo {
|
||||
float widthfac;
|
||||
} ReportTimerInfo;
|
||||
|
||||
//#ifdef WITH_XR_OPENXR
|
||||
typedef struct wmXrData {
|
||||
/** Runtime information for managing Blender specific behaviors. */
|
||||
struct wmXrRuntimeData *runtime;
|
||||
/** Permanent session settings (draw mode, feature toggles, etc). Stored in files and accessible
|
||||
* even before the session runs. */
|
||||
XrSessionSettings session_settings;
|
||||
} wmXrData;
|
||||
//#endif
|
||||
|
||||
/* reports need to be before wmWindowManager */
|
||||
|
||||
/* windowmanager is saved, tag WMAN */
|
||||
@@ -180,6 +191,9 @@ typedef struct wmWindowManager {
|
||||
|
||||
struct wmMsgBus *message_bus;
|
||||
|
||||
//#ifdef WITH_XR_OPENXR
|
||||
wmXrData xr;
|
||||
//#endif
|
||||
} wmWindowManager;
|
||||
|
||||
/* wmWindowManager.initialized */
|
||||
|
||||
58
source/blender/makesdna/DNA_xr_types.h
Normal file
58
source/blender/makesdna/DNA_xr_types.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup DNA
|
||||
*/
|
||||
|
||||
#ifndef __DNA_XR_TYPES_H__
|
||||
#define __DNA_XR_TYPES_H__
|
||||
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
typedef struct XrSessionSettings {
|
||||
/** Shading settings, struct shared with 3D-View so settings are the same. */
|
||||
struct View3DShading shading;
|
||||
|
||||
char _pad[7];
|
||||
|
||||
char base_pose_type; /* eXRSessionBasePoseType */
|
||||
/** Object to take the location and rotation as base position from. */
|
||||
Object *base_pose_object;
|
||||
float base_pose_location[3];
|
||||
float base_pose_angle;
|
||||
|
||||
/** View3D draw flags (V3D_OFSDRAW_NONE, V3D_OFSDRAW_SHOW_ANNOTATION, ...). */
|
||||
char draw_flags;
|
||||
char _pad2[3];
|
||||
|
||||
/** Clipping distance. */
|
||||
float clip_start, clip_end;
|
||||
|
||||
int flag;
|
||||
} XrSessionSettings;
|
||||
|
||||
typedef enum eXrSessionFlag {
|
||||
XR_SESSION_USE_POSITION_TRACKING = (1 << 0),
|
||||
} eXrSessionFlag;
|
||||
|
||||
typedef enum eXRSessionBasePoseType {
|
||||
XR_BASE_POSE_SCENE_CAMERA = 0,
|
||||
XR_BASE_POSE_OBJECT = 1,
|
||||
XR_BASE_POSE_CUSTOM = 2,
|
||||
} eXRSessionBasePoseType;
|
||||
|
||||
#endif /* __DNA_XR_TYPES_H__ */
|
||||
@@ -132,6 +132,7 @@ static const char *includefiles[] = {
|
||||
"DNA_workspace_types.h",
|
||||
"DNA_lightprobe_types.h",
|
||||
"DNA_curveprofile_types.h",
|
||||
"DNA_xr_types.h",
|
||||
|
||||
/* see comment above before editing! */
|
||||
|
||||
@@ -1598,6 +1599,7 @@ int main(int argc, char **argv)
|
||||
#include "DNA_workspace_types.h"
|
||||
#include "DNA_lightprobe_types.h"
|
||||
#include "DNA_curveprofile_types.h"
|
||||
#include "DNA_xr_types.h"
|
||||
|
||||
/* end of list */
|
||||
|
||||
|
||||
@@ -694,6 +694,8 @@ extern StructRNA RNA_WorkSpace;
|
||||
extern StructRNA RNA_World;
|
||||
extern StructRNA RNA_WorldLighting;
|
||||
extern StructRNA RNA_WorldMistSettings;
|
||||
extern StructRNA RNA_XrSessionSettings;
|
||||
extern StructRNA RNA_XrSessionState;
|
||||
extern StructRNA RNA_uiPopover;
|
||||
extern StructRNA RNA_wmOwnerIDs;
|
||||
|
||||
|
||||
@@ -92,6 +92,7 @@ set(DEFSRC
|
||||
rna_wm_gizmo.c
|
||||
rna_workspace.c
|
||||
rna_world.c
|
||||
rna_xr.c
|
||||
)
|
||||
|
||||
set(APISRC
|
||||
@@ -325,6 +326,10 @@ if(WITH_INPUT_NDOF)
|
||||
add_definitions(-DWITH_INPUT_NDOF)
|
||||
endif()
|
||||
|
||||
if(WITH_XR_OPENXR)
|
||||
add_definitions(-DWITH_XR_OPENXR)
|
||||
endif()
|
||||
|
||||
# Build makesrna executable
|
||||
blender_include_dirs(
|
||||
.
|
||||
|
||||
@@ -4312,6 +4312,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
||||
{"rna_movieclip.c", NULL, RNA_def_movieclip},
|
||||
{"rna_tracking.c", NULL, RNA_def_tracking},
|
||||
{"rna_mask.c", NULL, RNA_def_mask},
|
||||
{"rna_xr.c", NULL, RNA_def_xr},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -205,6 +205,7 @@ void RNA_def_world(struct BlenderRNA *brna);
|
||||
void RNA_def_movieclip(struct BlenderRNA *brna);
|
||||
void RNA_def_tracking(struct BlenderRNA *brna);
|
||||
void RNA_def_mask(struct BlenderRNA *brna);
|
||||
void RNA_def_xr(struct BlenderRNA *brna);
|
||||
|
||||
/* Common Define functions */
|
||||
|
||||
|
||||
@@ -997,7 +997,7 @@ static IDProperty *rna_View3DShading_idprops(PointerRNA *ptr, bool create)
|
||||
static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA *ptr)
|
||||
{
|
||||
ID *id = ptr->owner_id;
|
||||
if (GS(id->name) == ID_SCE) {
|
||||
if (GS(id->name) != ID_SCR) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1333,6 +1333,25 @@ static const EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf(bContext *C
|
||||
}
|
||||
}
|
||||
|
||||
static void rna_SpaceView3D_mirror_xr_session_update(Main *main,
|
||||
Scene *UNUSED(scene),
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
const wmWindowManager *wm = main->wm.first;
|
||||
|
||||
/* Handle mirror toggling while there is a session already. */
|
||||
if (WM_xr_session_exists(&wm->xr)) {
|
||||
const View3D *v3d = ptr->data;
|
||||
const ScrArea *area = rna_area_from_space(ptr);
|
||||
ED_view3d_xr_mirror_update(area, v3d, v3d->flag & V3D_XR_SESSION_MIRROR);
|
||||
}
|
||||
|
||||
# else
|
||||
UNUSED_VARS(main, ptr);
|
||||
# endif
|
||||
}
|
||||
|
||||
static int rna_SpaceView3D_icon_from_show_object_viewport_get(PointerRNA *ptr)
|
||||
{
|
||||
const View3D *v3d = (View3D *)ptr->data;
|
||||
@@ -3166,19 +3185,20 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
"rna_3DViewShading_type_itemf");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Viewport Shading", "Method to display/shade objects in the 3D View");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_3DViewShading_type_update");
|
||||
RNA_def_property_update(
|
||||
prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, "rna_3DViewShading_type_update");
|
||||
|
||||
prop = RNA_def_property(srna, "light", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "light");
|
||||
RNA_def_property_enum_items(prop, rna_enum_viewport_lighting_items);
|
||||
RNA_def_property_ui_text(prop, "Lighting", "Lighting Method for Solid/Texture Viewport Shading");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_object_outline", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_OBJECT_OUTLINE);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Outline", "Show Object Outline");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "studio_light", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_enum_studio_light_items);
|
||||
@@ -3188,45 +3208,45 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
"rna_View3DShading_studio_light_set",
|
||||
"rna_View3DShading_studio_light_itemf");
|
||||
RNA_def_property_ui_text(prop, "Studiolight", "Studio lighting setup");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_world_space_lighting", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_WORLD_ORIENTATION);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "World Space Lighting", "Make the lighting fixed and not follow the camera");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_backface_culling", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_BACKFACE_CULLING);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Backface Culling", "Use back face culling to hide the back side of faces");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_cavity", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_CAVITY);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Cavity", "Show Cavity");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "cavity_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, cavity_type_items);
|
||||
RNA_def_property_ui_text(prop, "Cavity Type", "Way to draw the cavity shading");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "curvature_ridge_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "curvature_ridge_factor");
|
||||
RNA_def_property_ui_text(prop, "Curvature Ridge", "Factor for the curvature ridges");
|
||||
RNA_def_property_range(prop, 0.0f, 2.0f);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "curvature_valley_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "curvature_valley_factor");
|
||||
RNA_def_property_ui_text(prop, "Curvature Valley", "Factor for the curvature valleys");
|
||||
RNA_def_property_range(prop, 0.0f, 2.0f);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "cavity_ridge_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "cavity_ridge_factor");
|
||||
@@ -3234,7 +3254,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0f, 250.0f);
|
||||
RNA_def_property_ui_range(prop, 0.00f, 2.5f, 1, 3);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "cavity_valley_factor", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "cavity_valley_factor");
|
||||
@@ -3242,7 +3262,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0f, 250.0f);
|
||||
RNA_def_property_ui_range(prop, 0.00f, 2.5f, 1, 3);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "selected_studio_light", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "StudioLight");
|
||||
@@ -3259,7 +3279,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
prop, "Studiolight Rotation", "Rotation of the studiolight around the Z-Axis");
|
||||
RNA_def_property_range(prop, -M_PI, M_PI);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "studiolight_intensity", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "studiolight_intensity");
|
||||
@@ -3267,7 +3287,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Strength", "Strength of the studiolight");
|
||||
RNA_def_property_range(prop, 0.0f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 2.0f, 1, 3);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "studiolight_background_alpha", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "studiolight_background");
|
||||
@@ -3275,7 +3295,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "studiolight_background_blur", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "studiolight_blur");
|
||||
@@ -3284,7 +3304,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 2);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "color_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "color_type");
|
||||
@@ -3292,64 +3312,65 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_View3DShading_color_type_itemf");
|
||||
RNA_def_property_ui_text(prop, "Color", "Color Type");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_GPencil_update");
|
||||
RNA_def_property_update(
|
||||
prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, "rna_GPencil_update");
|
||||
|
||||
prop = RNA_def_property(srna, "wireframe_color_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "wire_color_type");
|
||||
RNA_def_property_enum_items(prop, rna_enum_shading_color_type_items);
|
||||
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_View3DShading_color_type_itemf");
|
||||
RNA_def_property_ui_text(prop, "Color", "Color Type");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "single_color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "single_color");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Color", "Color for single color mode");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "background_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, background_type_items);
|
||||
RNA_def_property_ui_text(prop, "Background", "Way to draw the background");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "background_color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Background Color", "Color for custom background color");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_shadows", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SHADOW);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Shadow", "Show Shadow");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_xray", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_XRAY);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Show X-Ray", "Show whole scene transparent");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_xray_wireframe", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_XRAY_WIREFRAME);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Show X-Ray", "Show whole scene transparent");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "xray_alpha", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "xray_alpha");
|
||||
RNA_def_property_ui_text(prop, "X-Ray Alpha", "Amount of alpha to use");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "xray_alpha_wireframe", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "xray_alpha_wire");
|
||||
RNA_def_property_ui_text(prop, "X-Ray Alpha", "Amount of alpha to use");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_DEPTH_OF_FIELD);
|
||||
@@ -3358,46 +3379,46 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
prop,
|
||||
"Depth Of Field",
|
||||
"Use depth of field on viewport using the values from the active camera");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_scene_lights", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SCENE_LIGHTS);
|
||||
RNA_def_property_boolean_default(prop, false);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Scene Lights", "Render lights and light probes of the scene");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_scene_world", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SCENE_WORLD);
|
||||
RNA_def_property_boolean_default(prop, false);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Scene World", "Use scene world for lighting");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_scene_lights_render", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SCENE_LIGHTS_RENDER);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Scene Lights", "Render lights and light probes of the scene");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_scene_world_render", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SCENE_WORLD_RENDER);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Scene World", "Use scene world for lighting");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_specular_highlight", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_SHADING_SPECULAR_HIGHLIGHT);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Specular Highlights", "Render specular highlights");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "object_outline_color", PROP_FLOAT, PROP_COLOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "object_outline_color");
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Outline Color", "Color for object outline");
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "shadow_intensity", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "shadow_intensity");
|
||||
@@ -3405,7 +3426,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||
RNA_def_property_ui_range(prop, 0.00f, 1.0f, 1, 3);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "render_pass", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "render_pass");
|
||||
@@ -3413,7 +3434,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Render Pass", "Render Pass to show in the viewport");
|
||||
RNA_def_property_enum_funcs(
|
||||
prop, "rna_3DViewShading_render_pass_get", NULL, "rna_3DViewShading_render_pass_itemf");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D | NS_VIEW3D_SHADING, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_space_view3d_overlay(BlenderRNA *brna)
|
||||
@@ -4189,6 +4210,15 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Volume Alpha", "Opacity (alpha) of the cameras' frustum volume");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "mirror_xr_session", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", V3D_XR_SESSION_MIRROR);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Mirror VR Session",
|
||||
"Synchronize the viewer perspective of virtual reality sessions with this 3D viewport");
|
||||
RNA_def_property_update(
|
||||
prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_mirror_xr_session_update");
|
||||
|
||||
{
|
||||
struct {
|
||||
const char *name;
|
||||
@@ -4268,7 +4298,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
|
||||
RNA_def_struct_ui_text(srna, "3D View Region", "3D View region data");
|
||||
|
||||
prop = RNA_def_property(srna, "lock_rotation", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_LOCKED);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "viewlock", RV3D_LOCK_ROTATION);
|
||||
RNA_def_property_ui_text(prop, "Lock", "Lock view rotation in side views");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_RegionView3D_quadview_update");
|
||||
|
||||
|
||||
@@ -1266,6 +1266,20 @@ static void rna_wmClipboard_set(PointerRNA *UNUSED(ptr), const char *value)
|
||||
WM_clipboard_text_set((void *)value, false);
|
||||
}
|
||||
|
||||
static PointerRNA rna_WindowManager_xr_session_state_get(PointerRNA *ptr)
|
||||
{
|
||||
wmWindowManager *wm = ptr->data;
|
||||
struct wmXrSessionState *state =
|
||||
# ifdef WITH_XR_OPENXR
|
||||
WM_xr_session_state_handle_get(&wm->xr);
|
||||
# else
|
||||
NULL;
|
||||
UNUSED_VAR(wm);
|
||||
# endif
|
||||
|
||||
return rna_pointer_inherit_refine(ptr, &RNA_XrSessionState, state);
|
||||
}
|
||||
|
||||
# ifdef WITH_PYTHON
|
||||
|
||||
static bool rna_operator_poll_cb(bContext *C, wmOperatorType *ot)
|
||||
@@ -2484,6 +2498,18 @@ static void rna_def_windowmanager(BlenderRNA *brna)
|
||||
prop, "rna_wmClipboard_get", "rna_wmClipboard_length", "rna_wmClipboard_set");
|
||||
RNA_def_property_ui_text(prop, "Text Clipboard", "");
|
||||
|
||||
prop = RNA_def_property(srna, "xr_session_settings", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "xr.session_settings");
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_ui_text(prop, "XR Session Settings", "");
|
||||
|
||||
prop = RNA_def_property(srna, "xr_session_state", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "XrSessionState");
|
||||
RNA_def_property_pointer_funcs(prop, "rna_WindowManager_xr_session_state_get", NULL, NULL, NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "XR Session State", "Runtime state information about the VR session");
|
||||
|
||||
RNA_api_wm(srna);
|
||||
}
|
||||
|
||||
|
||||
@@ -1376,6 +1376,12 @@ static void rna_def_gizmogroup(BlenderRNA *brna)
|
||||
0,
|
||||
"Tool Init",
|
||||
"Postpone running until tool operator run (when used with a tool)"},
|
||||
{WM_GIZMOGROUPTYPE_VR_REDRAWS,
|
||||
"VR_REDRAWS",
|
||||
0,
|
||||
"VR Redraws",
|
||||
"The gizmos are made for use with virtual reality sessions and require special redraw "
|
||||
"management"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
|
||||
|
||||
229
source/blender/makesrna/intern/rna_xr.c
Normal file
229
source/blender/makesrna/intern/rna_xr.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup RNA
|
||||
*/
|
||||
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_xr_types.h"
|
||||
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "rna_internal.h"
|
||||
|
||||
#ifdef RNA_RUNTIME
|
||||
|
||||
# include "BLI_math.h"
|
||||
|
||||
# include "WM_api.h"
|
||||
|
||||
static bool rna_XrSessionState_is_running(bContext *C)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
return WM_xr_session_is_ready(&wm->xr);
|
||||
# else
|
||||
UNUSED_VARS(C);
|
||||
return false;
|
||||
# endif
|
||||
}
|
||||
|
||||
# ifdef WITH_XR_OPENXR
|
||||
static wmXrData *rna_XrSessionState_wm_xr_data_get(PointerRNA *ptr)
|
||||
{
|
||||
/* Callers could also get XrSessionState pointer through ptr->data, but prefer if we just
|
||||
* consistently pass wmXrData pointers to the WM_xr_xxx() API. */
|
||||
|
||||
BLI_assert(ptr->type == &RNA_XrSessionState);
|
||||
|
||||
wmWindowManager *wm = (wmWindowManager *)ptr->owner_id;
|
||||
BLI_assert(wm && (GS(wm->id.name) == ID_WM));
|
||||
|
||||
return &wm->xr;
|
||||
}
|
||||
# endif
|
||||
|
||||
static void rna_XrSessionState_viewer_pose_location_get(PointerRNA *ptr, float *r_values)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
|
||||
WM_xr_session_state_viewer_pose_location_get(xr, r_values);
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
zero_v3(r_values);
|
||||
# endif
|
||||
}
|
||||
|
||||
static void rna_XrSessionState_viewer_pose_rotation_get(PointerRNA *ptr, float *r_values)
|
||||
{
|
||||
# ifdef WITH_XR_OPENXR
|
||||
const wmXrData *xr = rna_XrSessionState_wm_xr_data_get(ptr);
|
||||
WM_xr_session_state_viewer_pose_rotation_get(xr, r_values);
|
||||
# else
|
||||
UNUSED_VARS(ptr);
|
||||
unit_qt(r_values);
|
||||
# endif
|
||||
}
|
||||
|
||||
#else /* RNA_RUNTIME */
|
||||
|
||||
static void rna_def_xr_session_settings(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
static const EnumPropertyItem base_pose_types[] = {
|
||||
{XR_BASE_POSE_SCENE_CAMERA,
|
||||
"SCENE_CAMERA",
|
||||
0,
|
||||
"Scene Camera",
|
||||
"Follow the active scene camera to define the VR view's base pose"},
|
||||
{XR_BASE_POSE_OBJECT,
|
||||
"OBJECT",
|
||||
0,
|
||||
"Object",
|
||||
"Follow the transformation of an object to define the VR view's base pose"},
|
||||
{XR_BASE_POSE_CUSTOM,
|
||||
"CUSTOM",
|
||||
0,
|
||||
"Custom",
|
||||
"Follow a custom transformation to define the VR view's base pose"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
srna = RNA_def_struct(brna, "XrSessionSettings", NULL);
|
||||
RNA_def_struct_ui_text(srna, "XR Session Settings", "");
|
||||
|
||||
prop = RNA_def_property(srna, "shading", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_NEVER_NULL);
|
||||
RNA_def_property_ui_text(prop, "Shading Settings", "");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
prop = RNA_def_property(srna, "base_pose_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_enum_items(prop, base_pose_types);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Base Pose Type",
|
||||
"Define where the location and rotation for the VR view come from, to which "
|
||||
"translation and rotation deltas from the VR headset will be applied to");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "base_pose_object", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Base Pose Object",
|
||||
"Object to take the location and rotation to which translation and "
|
||||
"rotation deltas from the VR headset will be applied to");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "base_pose_location", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Base Pose Location",
|
||||
"Coordinates to apply translation deltas from the VR headset to");
|
||||
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "base_pose_angle", PROP_FLOAT, PROP_AXISANGLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Base Pose Angle",
|
||||
"Rotation angle around the Z-Axis to apply the rotation deltas from the VR headset to");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_floor", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "draw_flags", V3D_OFSDRAW_SHOW_GRIDFLOOR);
|
||||
RNA_def_property_ui_text(prop, "Display Grid Floor", "Show the ground plane grid");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "draw_flags", V3D_OFSDRAW_SHOW_ANNOTATION);
|
||||
RNA_def_property_ui_text(prop, "Show Annotation", "Show annotations for this view");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "clip_start", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
|
||||
RNA_def_property_ui_text(prop, "Clip Start", "VR viewport near clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "clip_end", PROP_FLOAT, PROP_DISTANCE);
|
||||
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 10, 3);
|
||||
RNA_def_property_ui_text(prop, "Clip End", "VR viewport far clipping distance");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "use_positional_tracking", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", XR_SESSION_USE_POSITION_TRACKING);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Positional Tracking",
|
||||
"Allow VR headsets to affect the location in virtual space, in addition to the rotation");
|
||||
RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_xr_session_state(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm, *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, "XrSessionState", NULL);
|
||||
RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
|
||||
RNA_def_struct_ui_text(srna, "Session State", "Runtime state information about the VR session");
|
||||
|
||||
func = RNA_def_function(srna, "is_running", "rna_XrSessionState_is_running");
|
||||
RNA_def_function_ui_description(func, "Query if the VR session is currently running");
|
||||
RNA_def_function_flag(func, FUNC_NO_SELF);
|
||||
parm = RNA_def_pointer(func, "context", "Context", "", "");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
|
||||
parm = RNA_def_boolean(func, "result", 0, "Result", "");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
prop = RNA_def_property(srna, "viewer_pose_location", PROP_FLOAT, PROP_TRANSLATION);
|
||||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_float_funcs(prop, "rna_XrSessionState_viewer_pose_location_get", NULL, NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Viewer Pose Location",
|
||||
"Last known location of the viewer pose (center between the eyes) in world space");
|
||||
|
||||
prop = RNA_def_property(srna, "viewer_pose_rotation", PROP_FLOAT, PROP_QUATERNION);
|
||||
RNA_def_property_array(prop, 4);
|
||||
RNA_def_property_float_funcs(prop, "rna_XrSessionState_viewer_pose_rotation_get", NULL, NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Viewer Pose Rotation",
|
||||
"Last known rotation of the viewer pose (center between the eyes) in world space");
|
||||
}
|
||||
|
||||
void RNA_def_xr(BlenderRNA *brna)
|
||||
{
|
||||
RNA_define_animate_sdna(false);
|
||||
|
||||
rna_def_xr_session_settings(brna);
|
||||
rna_def_xr_session_state(brna);
|
||||
|
||||
RNA_define_animate_sdna(true);
|
||||
}
|
||||
|
||||
#endif /* RNA_RUNTIME */
|
||||
@@ -257,6 +257,7 @@ static PyObject *bpygpu_offscreen_draw_view3d(BPyGPUOffScreen *self,
|
||||
(float(*)[4])py_mat_projection->matrix,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"",
|
||||
false,
|
||||
self->ofs,
|
||||
|
||||
@@ -75,6 +75,7 @@ set(SRC
|
||||
intern/wm_splash_screen.c
|
||||
intern/wm_stereo.c
|
||||
intern/wm_subwindow.c
|
||||
intern/wm_surface.c
|
||||
intern/wm_toolsystem.c
|
||||
intern/wm_tooltip.c
|
||||
intern/wm_uilist_type.c
|
||||
@@ -101,6 +102,7 @@ set(SRC
|
||||
wm_event_system.h
|
||||
wm_event_types.h
|
||||
wm_files.h
|
||||
wm_surface.h
|
||||
wm_window.h
|
||||
intern/wm_platform_support.h
|
||||
intern/wm_window_private.h
|
||||
@@ -187,4 +189,11 @@ if(WITH_COMPOSITOR)
|
||||
add_definitions(-DWITH_COMPOSITOR)
|
||||
endif()
|
||||
|
||||
if(WITH_XR_OPENXR)
|
||||
add_definitions(-DWITH_XR_OPENXR)
|
||||
list(APPEND SRC
|
||||
intern/wm_xr.c
|
||||
)
|
||||
endif()
|
||||
|
||||
blender_add_lib_nolist(bf_windowmanager "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
@@ -156,6 +156,10 @@ void *WM_opengl_context_create(void);
|
||||
void WM_opengl_context_dispose(void *context);
|
||||
void WM_opengl_context_activate(void *context);
|
||||
void WM_opengl_context_release(void *context);
|
||||
#ifdef WIN32
|
||||
void *WM_directx_context_create(void);
|
||||
void WM_directx_context_dispose(void *context);
|
||||
#endif
|
||||
|
||||
struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
|
||||
struct wmWindow *WM_window_open_temp(struct bContext *C,
|
||||
@@ -867,6 +871,18 @@ void WM_generic_callback_free(struct wmGenericCallback *callback);
|
||||
|
||||
void WM_generic_user_data_free(struct wmGenericUserData *user_data);
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
/* wm_xr.c */
|
||||
bool WM_xr_session_exists(const wmXrData *xr);
|
||||
bool WM_xr_session_is_ready(const wmXrData *xr);
|
||||
struct wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr);
|
||||
bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3]);
|
||||
bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4]);
|
||||
bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr,
|
||||
float r_viewmat[4][4],
|
||||
float *r_focal_len);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -310,6 +310,7 @@ typedef struct wmNotifier {
|
||||
#define ND_HISTORY (4 << 16)
|
||||
#define ND_JOB (5 << 16)
|
||||
#define ND_UNDO (6 << 16)
|
||||
#define ND_XR_DATA_CHANGED (7 << 17)
|
||||
|
||||
/* NC_SCREEN */
|
||||
#define ND_LAYOUTBROWSE (1 << 16)
|
||||
@@ -437,6 +438,7 @@ typedef struct wmNotifier {
|
||||
|
||||
/* subtype 3d view editing */
|
||||
#define NS_VIEW3D_GPU (16 << 8)
|
||||
#define NS_VIEW3D_SHADING (16 << 9)
|
||||
|
||||
/* action classification */
|
||||
#define NOTE_ACTION (0x000000FF)
|
||||
|
||||
@@ -139,6 +139,13 @@ typedef enum eWM_GizmoFlagGroupTypeFlag {
|
||||
* with click drag events by popping up under the cursor and catching the tweak event.
|
||||
*/
|
||||
WM_GIZMOGROUPTYPE_DELAY_REFRESH_FOR_TWEAK = (1 << 8),
|
||||
|
||||
/**
|
||||
* Cause continuous redraws, i.e. set the region redraw flag on every main loop itertion. This
|
||||
* should really be avoided by using proper region redraw tagging, notifiers and the message-bus,
|
||||
* however for VR it's sometimes needed.
|
||||
*/
|
||||
WM_GIZMOGROUPTYPE_VR_REDRAWS = (1 << 9),
|
||||
} eWM_GizmoFlagGroupTypeFlag;
|
||||
|
||||
/**
|
||||
|
||||
@@ -576,6 +576,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
||||
const int co[2],
|
||||
const int hotspot)
|
||||
{
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
View3D *v3d = sa->spacedata.first;
|
||||
@@ -588,7 +589,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
||||
BLI_rcti_init_pt_radius(&rect, co, hotspot);
|
||||
|
||||
ED_view3d_draw_setup_view(
|
||||
CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect);
|
||||
wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, &rect);
|
||||
|
||||
bool use_select_bias = false;
|
||||
|
||||
@@ -608,7 +609,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
||||
}
|
||||
|
||||
ED_view3d_draw_setup_view(
|
||||
CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL);
|
||||
wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, NULL, NULL, NULL);
|
||||
|
||||
if (use_select_bias && (hits > 1)) {
|
||||
float co_direction[3];
|
||||
|
||||
@@ -379,6 +379,11 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm)
|
||||
wm_autosave_timer_ended(wm);
|
||||
}
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
/* May send notifier, so do before freeing notifier queue. */
|
||||
wm_xr_exit(wm);
|
||||
#endif
|
||||
|
||||
while ((win = BLI_pophead(&wm->windows))) {
|
||||
/* prevent draw clear to use screen */
|
||||
BKE_workspace_active_set(win->workspace_hook, NULL);
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "wm_draw.h"
|
||||
#include "wm_window.h"
|
||||
#include "wm_event_system.h"
|
||||
#include "wm_surface.h"
|
||||
|
||||
#ifdef WITH_OPENSUBDIV
|
||||
# include "BKE_subsurf.h"
|
||||
@@ -186,7 +187,10 @@ static void wm_area_mark_invalid_backbuf(ScrArea *sa)
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_region_test_gizmo_do_draw(ARegion *region, bool tag_redraw)
|
||||
static void wm_region_test_gizmo_do_draw(bContext *C,
|
||||
ScrArea *sa,
|
||||
ARegion *region,
|
||||
bool tag_redraw)
|
||||
{
|
||||
if (region->gizmo_map == NULL) {
|
||||
return;
|
||||
@@ -195,10 +199,26 @@ static void wm_region_test_gizmo_do_draw(ARegion *region, bool tag_redraw)
|
||||
wmGizmoMap *gzmap = region->gizmo_map;
|
||||
for (wmGizmoGroup *gzgroup = WM_gizmomap_group_list(gzmap)->first; gzgroup;
|
||||
gzgroup = gzgroup->next) {
|
||||
if (tag_redraw && (gzgroup->type->flag & WM_GIZMOGROUPTYPE_VR_REDRAWS)) {
|
||||
ScrArea *ctx_sa = CTX_wm_area(C);
|
||||
ARegion *ctx_ar = CTX_wm_region(C);
|
||||
|
||||
CTX_wm_area_set(C, sa);
|
||||
CTX_wm_region_set(C, region);
|
||||
|
||||
if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
|
||||
ED_region_tag_redraw_editor_overlays(region);
|
||||
}
|
||||
|
||||
/* Reset. */
|
||||
CTX_wm_area_set(C, ctx_sa);
|
||||
CTX_wm_region_set(C, ctx_ar);
|
||||
}
|
||||
|
||||
for (wmGizmo *gz = gzgroup->gizmos.first; gz; gz = gz->next) {
|
||||
if (gz->do_draw) {
|
||||
if (tag_redraw) {
|
||||
ED_region_tag_redraw_no_rebuild(region);
|
||||
ED_region_tag_redraw_editor_overlays(region);
|
||||
}
|
||||
gz->do_draw = false;
|
||||
}
|
||||
@@ -237,6 +257,19 @@ static void wm_region_test_render_do_draw(const Scene *scene,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
static void wm_region_test_xr_do_draw(const wmWindowManager *wm,
|
||||
const ScrArea *area,
|
||||
ARegion *region)
|
||||
{
|
||||
if ((area->spacetype == SPACE_VIEW3D) && (region->regiontype == RGN_TYPE_WINDOW)) {
|
||||
if (ED_view3d_is_region_xr_mirror_active(wm, area->spacedata.first, region)) {
|
||||
ED_region_tag_redraw_no_rebuild(region);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool wm_region_use_viewport_by_type(short space_type, short region_type)
|
||||
{
|
||||
return (ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE) && region_type == RGN_TYPE_WINDOW);
|
||||
@@ -836,11 +869,26 @@ static void wm_draw_window(bContext *C, wmWindow *win)
|
||||
screen->do_draw = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw offscreen contexts not bound to a specific window.
|
||||
*/
|
||||
static void wm_draw_surface(bContext *C, wmSurface *surface)
|
||||
{
|
||||
wm_window_clear_drawable(CTX_wm_manager(C));
|
||||
wm_surface_make_drawable(surface);
|
||||
|
||||
surface->draw(C);
|
||||
|
||||
/* Avoid interference with window drawable */
|
||||
wm_surface_clear_drawable();
|
||||
}
|
||||
|
||||
/****************** main update call **********************/
|
||||
|
||||
/* quick test to prevent changing window drawable */
|
||||
static bool wm_draw_update_test_window(Main *bmain, wmWindow *win)
|
||||
static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win)
|
||||
{
|
||||
const wmWindowManager *wm = CTX_wm_manager(C);
|
||||
Scene *scene = WM_window_get_active_scene(win);
|
||||
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
|
||||
struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true);
|
||||
@@ -861,8 +909,11 @@ static bool wm_draw_update_test_window(Main *bmain, wmWindow *win)
|
||||
ED_screen_areas_iter(win, screen, sa)
|
||||
{
|
||||
for (region = sa->regionbase.first; region; region = region->next) {
|
||||
wm_region_test_gizmo_do_draw(region, true);
|
||||
wm_region_test_gizmo_do_draw(C, sa, region, true);
|
||||
wm_region_test_render_do_draw(scene, depsgraph, sa, region);
|
||||
#ifdef WITH_XR_OPENXR
|
||||
wm_region_test_xr_do_draw(wm, sa, region);
|
||||
#endif
|
||||
|
||||
if (region->visible && region->do_draw) {
|
||||
do_draw = true;
|
||||
@@ -890,19 +941,23 @@ static bool wm_draw_update_test_window(Main *bmain, wmWindow *win)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef WITH_XR_OPENXR
|
||||
UNUSED_VARS(wm);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Clear drawing flags, after drawing is complete so any draw flags set during
|
||||
* drawing don't cause any additional redraws. */
|
||||
static void wm_draw_update_clear_window(wmWindow *win)
|
||||
static void wm_draw_update_clear_window(bContext *C, wmWindow *win)
|
||||
{
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
|
||||
ED_screen_areas_iter(win, screen, sa)
|
||||
{
|
||||
for (ARegion *region = sa->regionbase.first; region; region = region->next) {
|
||||
wm_region_test_gizmo_do_draw(region, false);
|
||||
wm_region_test_gizmo_do_draw(C, sa, region, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -944,10 +999,10 @@ void wm_draw_update(bContext *C)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (wm_draw_update_test_window(bmain, win)) {
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
CTX_wm_window_set(C, win);
|
||||
|
||||
CTX_wm_window_set(C, win);
|
||||
if (wm_draw_update_test_window(bmain, C, win)) {
|
||||
bScreen *screen = WM_window_get_active_screen(win);
|
||||
|
||||
/* sets context window+screen */
|
||||
wm_window_make_drawable(wm, win);
|
||||
@@ -956,13 +1011,16 @@ void wm_draw_update(bContext *C)
|
||||
ED_screen_ensure_updated(wm, win, screen);
|
||||
|
||||
wm_draw_window(C, win);
|
||||
wm_draw_update_clear_window(win);
|
||||
wm_draw_update_clear_window(C, win);
|
||||
|
||||
wm_window_swap_buffers(win);
|
||||
|
||||
CTX_wm_window_set(C, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
CTX_wm_window_set(C, NULL);
|
||||
|
||||
/* Draw non-windows (surfaces) */
|
||||
wm_surfaces_iter(C, wm_draw_surface);
|
||||
}
|
||||
|
||||
void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(region))
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
#include "wm_event_system.h"
|
||||
#include "wm.h"
|
||||
#include "wm_files.h"
|
||||
#include "wm_surface.h"
|
||||
#include "wm_window.h"
|
||||
#include "wm_platform_support.h"
|
||||
|
||||
@@ -534,6 +535,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
|
||||
BKE_materials_exit();
|
||||
|
||||
wm_operatortype_free();
|
||||
wm_surfaces_free();
|
||||
wm_dropbox_free();
|
||||
WM_menutype_free();
|
||||
WM_uilisttype_free();
|
||||
|
||||
@@ -3645,6 +3645,84 @@ static void WM_OT_stereo3d_set(wmOperatorType *ot)
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
|
||||
static void wm_xr_session_update_screen(Main *bmain, const wmXrData *xr_data)
|
||||
{
|
||||
const bool session_exists = WM_xr_session_exists(xr_data);
|
||||
|
||||
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
|
||||
for (ScrArea *area = screen->areabase.first; area; area = area->next) {
|
||||
for (SpaceLink *slink = area->spacedata.first; slink; slink = slink->next) {
|
||||
if (slink->spacetype == SPACE_VIEW3D) {
|
||||
View3D *v3d = (View3D *)slink;
|
||||
|
||||
if (v3d->flag & V3D_XR_SESSION_MIRROR) {
|
||||
ED_view3d_xr_mirror_update(area, v3d, session_exists);
|
||||
}
|
||||
|
||||
if (session_exists) {
|
||||
wmWindowManager *wm = bmain->wm.first;
|
||||
const Scene *scene = WM_windows_scene_get_from_screen(wm, screen);
|
||||
|
||||
ED_view3d_xr_shading_update(wm, v3d, scene);
|
||||
}
|
||||
/* Ensure no 3D View is tagged as session root. */
|
||||
else {
|
||||
v3d->runtime.flag &= ~V3D_RUNTIME_XR_SESSION_ROOT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_xr_session_update_screen_on_exit_cb(const wmXrData *xr_data)
|
||||
{
|
||||
/* Just use G_MAIN here, storing main isn't reliable enough on file read or exit. */
|
||||
wm_xr_session_update_screen(G_MAIN, xr_data);
|
||||
}
|
||||
|
||||
static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
/* Lazy-create xr context - tries to dynlink to the runtime, reading active_runtime.json. */
|
||||
if (wm_xr_init(wm) == false) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
v3d->runtime.flag |= V3D_RUNTIME_XR_SESSION_ROOT;
|
||||
wm_xr_session_toggle(wm, wm_xr_session_update_screen_on_exit_cb);
|
||||
wm_xr_session_update_screen(bmain, &wm->xr);
|
||||
|
||||
WM_event_add_notifier(C, NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void WM_OT_xr_session_toggle(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Toggle VR Session";
|
||||
ot->idname = "WM_OT_xr_session_toggle";
|
||||
ot->description =
|
||||
"Open a view for use with virtual reality headsets, or close it if already "
|
||||
"opened";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = wm_xr_session_toggle_exec;
|
||||
ot->poll = ED_operator_view3d_active;
|
||||
|
||||
/* XXX INTERNAL just to hide it from the search menu by default, an Add-on will expose it in the
|
||||
* UI instead. Not meant as a permanent solution. */
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
}
|
||||
|
||||
#endif /* WITH_XR_OPENXR */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Operator Registration & Keymaps
|
||||
* \{ */
|
||||
@@ -3686,6 +3764,9 @@ void wm_operatortypes_register(void)
|
||||
WM_operatortype_append(WM_OT_call_panel);
|
||||
WM_operatortype_append(WM_OT_radial_control);
|
||||
WM_operatortype_append(WM_OT_stereo3d_set);
|
||||
#ifdef WITH_XR_OPENXR
|
||||
WM_operatortype_append(WM_OT_xr_session_toggle);
|
||||
#endif
|
||||
#if defined(WIN32)
|
||||
WM_operatortype_append(WM_OT_console_toggle);
|
||||
#endif
|
||||
|
||||
118
source/blender/windowmanager/intern/wm_surface.c
Normal file
118
source/blender/windowmanager/intern/wm_surface.c
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*/
|
||||
|
||||
#include "BKE_context.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_threads.h"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
#include "GPU_batch_presets.h"
|
||||
#include "GPU_framebuffer.h"
|
||||
#include "GPU_immediate.h"
|
||||
#include "GPU_context.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
#include "WM_api.h"
|
||||
#include "wm.h"
|
||||
|
||||
#include "wm_surface.h"
|
||||
|
||||
static ListBase global_surface_list = {NULL, NULL};
|
||||
static wmSurface *g_drawable = NULL;
|
||||
|
||||
void wm_surfaces_iter(bContext *C, void (*cb)(bContext *C, wmSurface *))
|
||||
{
|
||||
for (wmSurface *surf = global_surface_list.first; surf; surf = surf->next) {
|
||||
cb(C, surf);
|
||||
}
|
||||
}
|
||||
|
||||
void wm_surface_clear_drawable(void)
|
||||
{
|
||||
if (g_drawable) {
|
||||
BLF_batch_reset();
|
||||
gpu_batch_presets_reset();
|
||||
immDeactivate();
|
||||
|
||||
g_drawable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void wm_surface_set_drawable(wmSurface *surface, bool activate)
|
||||
{
|
||||
BLI_assert(ELEM(g_drawable, NULL, surface));
|
||||
|
||||
g_drawable = surface;
|
||||
if (activate) {
|
||||
GHOST_ActivateOpenGLContext(surface->ghost_ctx);
|
||||
}
|
||||
|
||||
GPU_context_active_set(surface->gpu_ctx);
|
||||
immActivate();
|
||||
}
|
||||
|
||||
void wm_surface_make_drawable(wmSurface *surface)
|
||||
{
|
||||
BLI_assert(GPU_framebuffer_active_get() == NULL);
|
||||
|
||||
if (surface != g_drawable) {
|
||||
wm_surface_clear_drawable();
|
||||
wm_surface_set_drawable(surface, true);
|
||||
}
|
||||
}
|
||||
|
||||
void wm_surface_reset_drawable(void)
|
||||
{
|
||||
BLI_assert(BLI_thread_is_main());
|
||||
BLI_assert(GPU_framebuffer_active_get() == NULL);
|
||||
|
||||
if (g_drawable) {
|
||||
wm_surface_clear_drawable();
|
||||
wm_surface_set_drawable(g_drawable, true);
|
||||
}
|
||||
}
|
||||
|
||||
void wm_surface_add(wmSurface *surface)
|
||||
{
|
||||
BLI_addtail(&global_surface_list, surface);
|
||||
}
|
||||
|
||||
void wm_surface_remove(wmSurface *surface)
|
||||
{
|
||||
BLI_remlink(&global_surface_list, surface);
|
||||
surface->free_data(surface);
|
||||
MEM_freeN(surface);
|
||||
}
|
||||
|
||||
void wm_surfaces_free(void)
|
||||
{
|
||||
for (wmSurface *surf = global_surface_list.first, *surf_next; surf; surf = surf_next) {
|
||||
surf_next = surf->next;
|
||||
wm_surface_remove(surf);
|
||||
}
|
||||
|
||||
BLI_assert(BLI_listbase_is_empty(&global_surface_list));
|
||||
}
|
||||
@@ -1631,6 +1631,11 @@ void wm_window_process_events(const bContext *C)
|
||||
GHOST_DispatchEvents(g_system);
|
||||
}
|
||||
hasevent |= wm_window_timer(C);
|
||||
#ifdef WITH_XR_OPENXR
|
||||
/* XR events don't use the regular window queues. So here we don't only trigger
|
||||
* processing/dispatching but also handling. */
|
||||
hasevent |= wm_xr_events_handle(CTX_wm_manager(C));
|
||||
#endif
|
||||
|
||||
/* no event, we sleep 5 milliseconds */
|
||||
if (hasevent == 0) {
|
||||
@@ -1957,6 +1962,9 @@ void wm_window_raise(wmWindow *win)
|
||||
/** \name Window Buffers
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \brief Push rendered buffer to the screen.
|
||||
*/
|
||||
void wm_window_swap_buffers(wmWindow *win)
|
||||
{
|
||||
GHOST_SwapWindowBuffers(win->ghostwin);
|
||||
@@ -2446,3 +2454,24 @@ void WM_ghost_show_message_box(const char *title,
|
||||
GHOST_ShowMessageBox(g_system, title, message, help_label, continue_label, link, dialog_options);
|
||||
}
|
||||
/** \} */
|
||||
|
||||
#ifdef WIN32
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Direct DirectX Context Management
|
||||
* \{ */
|
||||
|
||||
void *WM_directx_context_create(void)
|
||||
{
|
||||
BLI_assert(GPU_framebuffer_active_get() == NULL);
|
||||
return GHOST_CreateDirectXContext(g_system);
|
||||
}
|
||||
|
||||
void WM_directx_context_dispose(void *context)
|
||||
{
|
||||
BLI_assert(GPU_framebuffer_active_get() == NULL);
|
||||
GHOST_DisposeDirectXContext(g_system, context);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
#endif
|
||||
|
||||
759
source/blender/windowmanager/intern/wm_xr.c
Normal file
759
source/blender/windowmanager/intern/wm_xr.c
Normal file
@@ -0,0 +1,759 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name Window-Manager XR API
|
||||
*
|
||||
* Implements Blender specific functionality for the GHOST_Xr API.
|
||||
*/
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_math_geom.h"
|
||||
#include "BLI_math_matrix.h"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
#include "DNA_xr_types.h"
|
||||
|
||||
#include "DRW_engine.h"
|
||||
|
||||
#include "ED_view3d.h"
|
||||
#include "ED_view3d_offscreen.h"
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
|
||||
#include "GPU_context.h"
|
||||
#include "GPU_draw.h"
|
||||
#include "GPU_matrix.h"
|
||||
#include "GPU_viewport.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "wm.h"
|
||||
#include "wm_surface.h"
|
||||
#include "wm_window.h"
|
||||
|
||||
struct wmXrRuntimeData *wm_xr_runtime_data_create(void);
|
||||
void wm_xr_runtime_data_free(struct wmXrRuntimeData **runtime);
|
||||
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *, void *);
|
||||
void *wm_xr_session_gpu_binding_context_create(GHOST_TXrGraphicsBinding);
|
||||
void wm_xr_session_gpu_binding_context_destroy(GHOST_TXrGraphicsBinding, GHOST_ContextHandle);
|
||||
wmSurface *wm_xr_session_surface_create(wmWindowManager *, unsigned int);
|
||||
void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4]);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
typedef struct wmXrSessionState {
|
||||
bool is_started;
|
||||
|
||||
/** Last known viewer pose (centroid of eyes, in world space) stored for queries. */
|
||||
GHOST_XrPose viewer_pose;
|
||||
/** The last known view matrix, calculated from above's viewer pose. */
|
||||
float viewer_viewmat[4][4];
|
||||
float focal_len;
|
||||
|
||||
/** Copy of XrSessionSettings.flag created on the last draw call, stored to detect changes. */
|
||||
int prev_settings_flag;
|
||||
/** Copy of wmXrDrawData.eye_position_ofs. */
|
||||
float prev_eye_position_ofs[3];
|
||||
|
||||
bool is_view_data_set;
|
||||
} wmXrSessionState;
|
||||
|
||||
typedef struct wmXrRuntimeData {
|
||||
GHOST_XrContextHandle context;
|
||||
|
||||
/* Although this struct is internal, RNA gets a handle to this for state information queries. */
|
||||
wmXrSessionState session_state;
|
||||
wmXrSessionExitFn exit_fn;
|
||||
} wmXrRuntimeData;
|
||||
|
||||
typedef struct wmXrDrawData {
|
||||
/** The pose (location + rotation) to which eye deltas will be applied to when drawing (world
|
||||
* space). With positional tracking enabled, it should be the same as the base pose, when
|
||||
* disabled it also contains a location delta from the moment the option was toggled. */
|
||||
GHOST_XrPose base_pose;
|
||||
float eye_position_ofs[3]; /* Local/view space. */
|
||||
} wmXrDrawData;
|
||||
|
||||
typedef struct {
|
||||
GHOST_TXrGraphicsBinding gpu_binding_type;
|
||||
GPUOffScreen *offscreen;
|
||||
GPUViewport *viewport;
|
||||
|
||||
GHOST_ContextHandle secondary_ghost_ctx;
|
||||
} wmXrSurfaceData;
|
||||
|
||||
typedef struct {
|
||||
wmWindowManager *wm;
|
||||
} wmXrErrorHandlerData;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
static wmSurface *g_xr_surface = NULL;
|
||||
static CLG_LogRef LOG = {"wm.xr"};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name XR-Context
|
||||
*
|
||||
* All XR functionality is accessed through a #GHOST_XrContext handle.
|
||||
* The lifetime of this context also determines the lifetime of the OpenXR instance, which is the
|
||||
* representation of the OpenXR runtime connection within the application.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
static void wm_xr_error_handler(const GHOST_XrError *error)
|
||||
{
|
||||
wmXrErrorHandlerData *handler_data = error->customdata;
|
||||
wmWindowManager *wm = handler_data->wm;
|
||||
|
||||
BKE_reports_clear(&wm->reports);
|
||||
WM_report(RPT_ERROR, error->user_message);
|
||||
WM_report_banner_show();
|
||||
|
||||
if (wm->xr.runtime->context) {
|
||||
/* Just play safe and destroy the entire runtime data, including context. */
|
||||
wm_xr_runtime_data_free(&wm->xr.runtime);
|
||||
}
|
||||
}
|
||||
|
||||
bool wm_xr_init(wmWindowManager *wm)
|
||||
{
|
||||
if (wm->xr.runtime && wm->xr.runtime->context) {
|
||||
return true;
|
||||
}
|
||||
static wmXrErrorHandlerData error_customdata;
|
||||
|
||||
/* Set up error handling */
|
||||
error_customdata.wm = wm;
|
||||
GHOST_XrErrorHandler(wm_xr_error_handler, &error_customdata);
|
||||
|
||||
{
|
||||
const GHOST_TXrGraphicsBinding gpu_bindings_candidates[] = {
|
||||
GHOST_kXrGraphicsOpenGL,
|
||||
#ifdef WIN32
|
||||
GHOST_kXrGraphicsD3D11,
|
||||
#endif
|
||||
};
|
||||
GHOST_XrContextCreateInfo create_info = {
|
||||
.gpu_binding_candidates = gpu_bindings_candidates,
|
||||
.gpu_binding_candidates_count = ARRAY_SIZE(gpu_bindings_candidates),
|
||||
};
|
||||
GHOST_XrContextHandle context;
|
||||
|
||||
if (G.debug & G_DEBUG_XR) {
|
||||
create_info.context_flag |= GHOST_kXrContextDebug;
|
||||
}
|
||||
if (G.debug & G_DEBUG_XR_TIME) {
|
||||
create_info.context_flag |= GHOST_kXrContextDebugTime;
|
||||
}
|
||||
|
||||
if (!(context = GHOST_XrContextCreate(&create_info))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set up context callbacks */
|
||||
GHOST_XrGraphicsContextBindFuncs(context,
|
||||
wm_xr_session_gpu_binding_context_create,
|
||||
wm_xr_session_gpu_binding_context_destroy);
|
||||
GHOST_XrDrawViewFunc(context, wm_xr_draw_view);
|
||||
|
||||
if (!wm->xr.runtime) {
|
||||
wm->xr.runtime = wm_xr_runtime_data_create();
|
||||
wm->xr.runtime->context = context;
|
||||
}
|
||||
}
|
||||
BLI_assert(wm->xr.runtime && wm->xr.runtime->context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wm_xr_exit(wmWindowManager *wm)
|
||||
{
|
||||
if (wm->xr.runtime != NULL) {
|
||||
wm_xr_runtime_data_free(&wm->xr.runtime);
|
||||
}
|
||||
if (wm->xr.session_settings.shading.prop) {
|
||||
IDP_FreeProperty(wm->xr.session_settings.shading.prop);
|
||||
wm->xr.session_settings.shading.prop = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool wm_xr_events_handle(wmWindowManager *wm)
|
||||
{
|
||||
if (wm->xr.runtime && wm->xr.runtime->context) {
|
||||
return GHOST_XrEventsHandle(wm->xr.runtime->context);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */ /* XR-Context */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name XR Runtime Data
|
||||
*
|
||||
* \{ */
|
||||
|
||||
wmXrRuntimeData *wm_xr_runtime_data_create(void)
|
||||
{
|
||||
wmXrRuntimeData *runtime = MEM_callocN(sizeof(*runtime), __func__);
|
||||
return runtime;
|
||||
}
|
||||
|
||||
void wm_xr_runtime_data_free(wmXrRuntimeData **runtime)
|
||||
{
|
||||
/* Note that this function may be called twice, because of an indirect recursion: If a session is
|
||||
* running while WM-XR calls this function, calling GHOST_XrContextDestroy() will call this
|
||||
* again, because it's also set as the session exit callback. So NULL-check and NULL everything
|
||||
* that is freed here. */
|
||||
|
||||
/* We free all runtime XR data here, so if the context is still alive, destroy it. */
|
||||
if ((*runtime)->context != NULL) {
|
||||
GHOST_XrContextHandle context = (*runtime)->context;
|
||||
/* Prevent recursive GHOST_XrContextDestroy() call by NULL'ing the context pointer before the
|
||||
* first call, see comment above. */
|
||||
(*runtime)->context = NULL;
|
||||
GHOST_XrContextDestroy(context);
|
||||
}
|
||||
MEM_SAFE_FREE(*runtime);
|
||||
}
|
||||
|
||||
static void wm_xr_base_pose_calc(const Scene *scene,
|
||||
const XrSessionSettings *settings,
|
||||
GHOST_XrPose *r_base_pose)
|
||||
{
|
||||
const Object *base_pose_object = ((settings->base_pose_type == XR_BASE_POSE_OBJECT) &&
|
||||
settings->base_pose_object) ?
|
||||
settings->base_pose_object :
|
||||
scene->camera;
|
||||
|
||||
if (settings->base_pose_type == XR_BASE_POSE_CUSTOM) {
|
||||
float tmp_quatx[4], tmp_quatz[4];
|
||||
|
||||
copy_v3_v3(r_base_pose->position, settings->base_pose_location);
|
||||
axis_angle_to_quat_single(tmp_quatx, 'X', M_PI_2);
|
||||
axis_angle_to_quat_single(tmp_quatz, 'Z', settings->base_pose_angle);
|
||||
mul_qt_qtqt(r_base_pose->orientation_quat, tmp_quatz, tmp_quatx);
|
||||
}
|
||||
else if (base_pose_object) {
|
||||
float tmp_quat[4];
|
||||
float tmp_eul[3];
|
||||
|
||||
mat4_to_loc_quat(r_base_pose->position, tmp_quat, base_pose_object->obmat);
|
||||
|
||||
/* Only use rotation around Z-axis to align view with floor. */
|
||||
quat_to_eul(tmp_eul, tmp_quat);
|
||||
tmp_eul[0] = M_PI_2;
|
||||
tmp_eul[1] = 0;
|
||||
eul_to_quat(r_base_pose->orientation_quat, tmp_eul);
|
||||
}
|
||||
else {
|
||||
copy_v3_fl(r_base_pose->position, 0.0f);
|
||||
axis_angle_to_quat_single(r_base_pose->orientation_quat, 'X', M_PI_2);
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_xr_draw_data_populate(const wmXrSessionState *state,
|
||||
const GHOST_XrDrawViewInfo *draw_view,
|
||||
const XrSessionSettings *settings,
|
||||
const Scene *scene,
|
||||
wmXrDrawData *r_draw_data)
|
||||
{
|
||||
const bool position_tracking_toggled = ((state->prev_settings_flag &
|
||||
XR_SESSION_USE_POSITION_TRACKING) !=
|
||||
(settings->flag & XR_SESSION_USE_POSITION_TRACKING));
|
||||
const bool use_position_tracking = settings->flag & XR_SESSION_USE_POSITION_TRACKING;
|
||||
|
||||
memset(r_draw_data, 0, sizeof(*r_draw_data));
|
||||
|
||||
wm_xr_base_pose_calc(scene, settings, &r_draw_data->base_pose);
|
||||
|
||||
if (position_tracking_toggled || !state->is_view_data_set) {
|
||||
if (use_position_tracking) {
|
||||
copy_v3_fl(r_draw_data->eye_position_ofs, 0.0f);
|
||||
}
|
||||
else {
|
||||
/* Store the current local offset (local pose) so that we can apply that to the eyes. This
|
||||
* way the eyes stay exactly where they are when disabling positional tracking. */
|
||||
copy_v3_v3(r_draw_data->eye_position_ofs, draw_view->local_pose.position);
|
||||
}
|
||||
}
|
||||
else if (!use_position_tracking) {
|
||||
/* Keep previous offset when positional tracking is disabled. */
|
||||
copy_v3_v3(r_draw_data->eye_position_ofs, state->prev_eye_position_ofs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update information that is only stored for external state queries. E.g. for Python API to
|
||||
* request the current (as in, last known) viewer pose.
|
||||
*/
|
||||
static void wm_xr_session_state_update(wmXrSessionState *state,
|
||||
const GHOST_XrDrawViewInfo *draw_view,
|
||||
const XrSessionSettings *settings,
|
||||
const wmXrDrawData *draw_data)
|
||||
{
|
||||
GHOST_XrPose viewer_pose;
|
||||
const bool use_position_tracking = settings->flag & XR_SESSION_USE_POSITION_TRACKING;
|
||||
|
||||
mul_qt_qtqt(viewer_pose.orientation_quat,
|
||||
draw_data->base_pose.orientation_quat,
|
||||
draw_view->local_pose.orientation_quat);
|
||||
copy_v3_v3(viewer_pose.position, draw_data->base_pose.position);
|
||||
/* The local pose and the eye pose (which is copied from an earlier local pose) both are view
|
||||
* space, so Y-up. In this case we need them in regular Z-up. */
|
||||
viewer_pose.position[0] += draw_data->eye_position_ofs[0];
|
||||
viewer_pose.position[1] -= draw_data->eye_position_ofs[2];
|
||||
viewer_pose.position[2] += draw_data->eye_position_ofs[1];
|
||||
if (use_position_tracking) {
|
||||
viewer_pose.position[0] += draw_view->local_pose.position[0];
|
||||
viewer_pose.position[1] -= draw_view->local_pose.position[2];
|
||||
viewer_pose.position[2] += draw_view->local_pose.position[1];
|
||||
}
|
||||
|
||||
copy_v3_v3(state->viewer_pose.position, viewer_pose.position);
|
||||
copy_qt_qt(state->viewer_pose.orientation_quat, viewer_pose.orientation_quat);
|
||||
wm_xr_pose_to_viewmat(&viewer_pose, state->viewer_viewmat);
|
||||
/* No idea why, but multiplying by two seems to make it match the VR view more. */
|
||||
state->focal_len = 2.0f *
|
||||
fov_to_focallength(draw_view->fov.angle_right - draw_view->fov.angle_left,
|
||||
DEFAULT_SENSOR_WIDTH);
|
||||
|
||||
copy_v3_v3(state->prev_eye_position_ofs, draw_data->eye_position_ofs);
|
||||
state->prev_settings_flag = settings->flag;
|
||||
state->is_view_data_set = true;
|
||||
}
|
||||
|
||||
wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr)
|
||||
{
|
||||
return xr->runtime ? &xr->runtime->session_state : NULL;
|
||||
}
|
||||
|
||||
bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3])
|
||||
{
|
||||
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
|
||||
zero_v3(r_location);
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_v3_v3(r_location, xr->runtime->session_state.viewer_pose.position);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4])
|
||||
{
|
||||
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
|
||||
unit_qt(r_rotation);
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_v4_v4(r_rotation, xr->runtime->session_state.viewer_pose.orientation_quat);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr,
|
||||
float r_viewmat[4][4],
|
||||
float *r_focal_len)
|
||||
{
|
||||
if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set) {
|
||||
unit_m4(r_viewmat);
|
||||
*r_focal_len = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
copy_m4_m4(r_viewmat, xr->runtime->session_state.viewer_viewmat);
|
||||
*r_focal_len = xr->runtime->session_state.focal_len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */ /* XR Runtime Data */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name XR-Session
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void *wm_xr_session_gpu_binding_context_create(GHOST_TXrGraphicsBinding graphics_binding)
|
||||
{
|
||||
wmSurface *surface = wm_xr_session_surface_create(G_MAIN->wm.first, graphics_binding);
|
||||
wmXrSurfaceData *data = surface->customdata;
|
||||
|
||||
wm_surface_add(surface);
|
||||
|
||||
/* Some regions may need to redraw with updated session state after the session is entirely up
|
||||
* and running. */
|
||||
WM_main_add_notifier(NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
|
||||
return data->secondary_ghost_ctx ? data->secondary_ghost_ctx : surface->ghost_ctx;
|
||||
}
|
||||
|
||||
void wm_xr_session_gpu_binding_context_destroy(GHOST_TXrGraphicsBinding UNUSED(graphics_lib),
|
||||
GHOST_ContextHandle UNUSED(context))
|
||||
{
|
||||
if (g_xr_surface) { /* Might have been freed already */
|
||||
wm_surface_remove(g_xr_surface);
|
||||
}
|
||||
|
||||
wm_window_reset_drawable();
|
||||
|
||||
/* Some regions may need to redraw with updated session state after the session is entirely
|
||||
* stopped. */
|
||||
WM_main_add_notifier(NC_WM | ND_XR_DATA_CHANGED, NULL);
|
||||
}
|
||||
|
||||
static void wm_xr_session_exit_cb(void *customdata)
|
||||
{
|
||||
wmXrData *xr_data = customdata;
|
||||
|
||||
xr_data->runtime->session_state.is_started = false;
|
||||
if (xr_data->runtime->exit_fn) {
|
||||
xr_data->runtime->exit_fn(xr_data);
|
||||
}
|
||||
|
||||
/* Free the entire runtime data (including session state and context), to play safe. */
|
||||
wm_xr_runtime_data_free(&xr_data->runtime);
|
||||
}
|
||||
|
||||
static void wm_xr_session_begin_info_create(wmXrData *xr_data,
|
||||
GHOST_XrSessionBeginInfo *r_begin_info)
|
||||
{
|
||||
/* WM-XR exit function, does some own stuff and calls callback passed to wm_xr_session_toggle(),
|
||||
* to allow external code to execute its own session-exit logic. */
|
||||
r_begin_info->exit_fn = wm_xr_session_exit_cb;
|
||||
r_begin_info->exit_customdata = xr_data;
|
||||
}
|
||||
|
||||
void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn)
|
||||
{
|
||||
wmXrData *xr_data = &wm->xr;
|
||||
|
||||
if (WM_xr_session_exists(xr_data)) {
|
||||
GHOST_XrSessionEnd(xr_data->runtime->context);
|
||||
}
|
||||
else {
|
||||
GHOST_XrSessionBeginInfo begin_info;
|
||||
|
||||
xr_data->runtime->session_state.is_started = true;
|
||||
xr_data->runtime->exit_fn = session_exit_fn;
|
||||
|
||||
wm_xr_session_begin_info_create(xr_data, &begin_info);
|
||||
GHOST_XrSessionStart(xr_data->runtime->context, &begin_info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the XR-Session was triggered.
|
||||
* If an error happened while trying to start a session, this returns false too.
|
||||
*/
|
||||
bool WM_xr_session_exists(const wmXrData *xr)
|
||||
{
|
||||
return xr->runtime && xr->runtime->context && xr->runtime->session_state.is_started;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the session is running, according to the OpenXR definition.
|
||||
*/
|
||||
bool WM_xr_session_is_ready(const wmXrData *xr)
|
||||
{
|
||||
return WM_xr_session_exists(xr) && GHOST_XrSessionIsRunning(xr->runtime->context);
|
||||
}
|
||||
|
||||
/** \} */ /* XR-Session */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name XR-Session Surface
|
||||
*
|
||||
* A wmSurface is used to manage drawing of the VR viewport. It's created and destroyed with the
|
||||
* session.
|
||||
*
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \brief Call Ghost-XR to draw a frame
|
||||
*
|
||||
* Draw callback for the XR-session surface. It's expected to be called on each main loop iteration
|
||||
* and tells Ghost-XR to submit a new frame by drawing its views. Note that for drawing each view,
|
||||
* #wm_xr_draw_view() will be called through Ghost-XR (see GHOST_XrDrawViewFunc()).
|
||||
*/
|
||||
static void wm_xr_session_surface_draw(bContext *C)
|
||||
{
|
||||
wmXrSurfaceData *surface_data = g_xr_surface->customdata;
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
|
||||
if (!GHOST_XrSessionIsRunning(wm->xr.runtime->context)) {
|
||||
return;
|
||||
}
|
||||
DRW_xr_drawing_begin();
|
||||
GHOST_XrSessionDrawViews(wm->xr.runtime->context, C);
|
||||
GPU_offscreen_unbind(surface_data->offscreen, false);
|
||||
DRW_xr_drawing_end();
|
||||
}
|
||||
|
||||
static void wm_xr_session_free_data(wmSurface *surface)
|
||||
{
|
||||
wmXrSurfaceData *data = surface->customdata;
|
||||
|
||||
if (data->secondary_ghost_ctx) {
|
||||
#ifdef WIN32
|
||||
if (data->gpu_binding_type == GHOST_kXrGraphicsD3D11) {
|
||||
WM_directx_context_dispose(data->secondary_ghost_ctx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (data->viewport) {
|
||||
GPU_viewport_free(data->viewport);
|
||||
}
|
||||
if (data->offscreen) {
|
||||
GPU_offscreen_free(data->offscreen);
|
||||
}
|
||||
|
||||
MEM_freeN(surface->customdata);
|
||||
|
||||
g_xr_surface = NULL;
|
||||
}
|
||||
|
||||
static bool wm_xr_session_surface_offscreen_ensure(const GHOST_XrDrawViewInfo *draw_view)
|
||||
{
|
||||
wmXrSurfaceData *surface_data = g_xr_surface->customdata;
|
||||
const bool size_changed = surface_data->offscreen &&
|
||||
(GPU_offscreen_width(surface_data->offscreen) != draw_view->width) &&
|
||||
(GPU_offscreen_height(surface_data->offscreen) != draw_view->height);
|
||||
char err_out[256] = "unknown";
|
||||
bool failure = false;
|
||||
|
||||
if (surface_data->offscreen) {
|
||||
BLI_assert(surface_data->viewport);
|
||||
|
||||
if (!size_changed) {
|
||||
return true;
|
||||
}
|
||||
GPU_viewport_free(surface_data->viewport);
|
||||
GPU_offscreen_free(surface_data->offscreen);
|
||||
}
|
||||
|
||||
if (!(surface_data->offscreen = GPU_offscreen_create(
|
||||
draw_view->width, draw_view->height, 0, true, false, err_out))) {
|
||||
failure = true;
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
/* Pass. */
|
||||
}
|
||||
else if (!(surface_data->viewport = GPU_viewport_create())) {
|
||||
GPU_offscreen_free(surface_data->offscreen);
|
||||
failure = true;
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
CLOG_ERROR(&LOG, "Failed to get buffer, %s\n", err_out);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
wmSurface *wm_xr_session_surface_create(wmWindowManager *UNUSED(wm), unsigned int gpu_binding_type)
|
||||
{
|
||||
if (g_xr_surface) {
|
||||
BLI_assert(false);
|
||||
return g_xr_surface;
|
||||
}
|
||||
|
||||
wmSurface *surface = MEM_callocN(sizeof(*surface), __func__);
|
||||
wmXrSurfaceData *data = MEM_callocN(sizeof(*data), "XrSurfaceData");
|
||||
|
||||
#ifndef WIN32
|
||||
BLI_assert(gpu_binding_type == GHOST_kXrGraphicsOpenGL);
|
||||
#endif
|
||||
|
||||
surface->draw = wm_xr_session_surface_draw;
|
||||
surface->free_data = wm_xr_session_free_data;
|
||||
|
||||
data->gpu_binding_type = gpu_binding_type;
|
||||
surface->customdata = data;
|
||||
|
||||
surface->ghost_ctx = DRW_xr_opengl_context_get();
|
||||
|
||||
switch (gpu_binding_type) {
|
||||
case GHOST_kXrGraphicsOpenGL:
|
||||
break;
|
||||
#ifdef WIN32
|
||||
case GHOST_kXrGraphicsD3D11:
|
||||
data->secondary_ghost_ctx = WM_directx_context_create();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
surface->gpu_ctx = DRW_xr_gpu_context_get();
|
||||
|
||||
g_xr_surface = surface;
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
/** \} */ /* XR-Session Surface */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name XR Drawing
|
||||
*
|
||||
* \{ */
|
||||
|
||||
void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4])
|
||||
{
|
||||
float iquat[4];
|
||||
invert_qt_qt_normalized(iquat, pose->orientation_quat);
|
||||
quat_to_mat4(r_viewmat, iquat);
|
||||
translate_m4(r_viewmat, -pose->position[0], -pose->position[1], -pose->position[2]);
|
||||
}
|
||||
|
||||
static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data,
|
||||
const GHOST_XrDrawViewInfo *draw_view,
|
||||
const XrSessionSettings *session_settings,
|
||||
float r_view_mat[4][4],
|
||||
float r_proj_mat[4][4])
|
||||
{
|
||||
GHOST_XrPose eye_pose;
|
||||
|
||||
copy_qt_qt(eye_pose.orientation_quat, draw_view->eye_pose.orientation_quat);
|
||||
copy_v3_v3(eye_pose.position, draw_view->eye_pose.position);
|
||||
add_v3_v3(eye_pose.position, draw_data->eye_position_ofs);
|
||||
if ((session_settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) {
|
||||
sub_v3_v3(eye_pose.position, draw_view->local_pose.position);
|
||||
}
|
||||
|
||||
perspective_m4_fov(r_proj_mat,
|
||||
draw_view->fov.angle_left,
|
||||
draw_view->fov.angle_right,
|
||||
draw_view->fov.angle_up,
|
||||
draw_view->fov.angle_down,
|
||||
session_settings->clip_start,
|
||||
session_settings->clip_end);
|
||||
|
||||
float eye_mat[4][4];
|
||||
float base_mat[4][4];
|
||||
|
||||
wm_xr_pose_to_viewmat(&eye_pose, eye_mat);
|
||||
/* Calculate the base pose matrix (in world space!). */
|
||||
wm_xr_pose_to_viewmat(&draw_data->base_pose, base_mat);
|
||||
|
||||
mul_m4_m4m4(r_view_mat, eye_mat, base_mat);
|
||||
}
|
||||
|
||||
static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
|
||||
const wmXrSurfaceData *surface_data, const GHOST_XrDrawViewInfo *draw_view)
|
||||
{
|
||||
const bool is_upside_down = surface_data->secondary_ghost_ctx &&
|
||||
GHOST_isUpsideDownContext(surface_data->secondary_ghost_ctx);
|
||||
rcti rect = {.xmin = 0, .ymin = 0, .xmax = draw_view->width - 1, .ymax = draw_view->height - 1};
|
||||
|
||||
wmViewport(&rect);
|
||||
|
||||
/* For upside down contexts, draw with inverted y-values. */
|
||||
if (is_upside_down) {
|
||||
SWAP(int, rect.ymin, rect.ymax);
|
||||
}
|
||||
GPU_viewport_draw_to_screen_ex(surface_data->viewport, &rect, draw_view->expects_srgb_buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Draw a viewport for a single eye.
|
||||
*
|
||||
* This is the main viewport drawing function for VR sessions. It's assigned to Ghost-XR as a
|
||||
* callback (see GHOST_XrDrawViewFunc()) and executed for each view (read: eye).
|
||||
*/
|
||||
void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
|
||||
{
|
||||
bContext *C = customdata;
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
wmXrSurfaceData *surface_data = g_xr_surface->customdata;
|
||||
wmXrSessionState *session_state = &wm->xr.runtime->session_state;
|
||||
XrSessionSettings *settings = &wm->xr.session_settings;
|
||||
wmXrDrawData draw_data;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
const int display_flags = V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS | settings->draw_flags;
|
||||
|
||||
float viewmat[4][4], winmat[4][4];
|
||||
|
||||
BLI_assert(WM_xr_session_is_ready(&wm->xr));
|
||||
|
||||
wm_xr_draw_data_populate(session_state, draw_view, settings, scene, &draw_data);
|
||||
wm_xr_draw_matrices_create(&draw_data, draw_view, settings, viewmat, winmat);
|
||||
wm_xr_session_state_update(session_state, draw_view, settings, &draw_data);
|
||||
|
||||
if (!wm_xr_session_surface_offscreen_ensure(draw_view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* In case a framebuffer is still bound from drawing the last eye. */
|
||||
GPU_framebuffer_restore();
|
||||
/* Some systems have drawing glitches without this. */
|
||||
GPU_clear(GPU_DEPTH_BIT);
|
||||
|
||||
/* Draws the view into the surface_data->viewport's framebuffers */
|
||||
ED_view3d_draw_offscreen_simple(CTX_data_ensure_evaluated_depsgraph(C),
|
||||
scene,
|
||||
&wm->xr.session_settings.shading,
|
||||
wm->xr.session_settings.shading.type,
|
||||
draw_view->width,
|
||||
draw_view->height,
|
||||
display_flags,
|
||||
viewmat,
|
||||
winmat,
|
||||
settings->clip_start,
|
||||
settings->clip_end,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
NULL,
|
||||
false,
|
||||
surface_data->offscreen,
|
||||
surface_data->viewport);
|
||||
|
||||
/* The draw-manager uses both GPUOffscreen and GPUViewport to manage frame and texture buffers. A
|
||||
* call to GPU_viewport_draw_to_screen() is still needed to get the final result from the
|
||||
* viewport buffers composited together and potentially color managed for display on screen.
|
||||
* It needs a bound framebuffer to draw into, for which we simply reuse the GPUOffscreen one.
|
||||
*
|
||||
* In a next step, Ghost-XR will use the the currently bound framebuffer to retrieve the image to
|
||||
* be submitted to the OpenXR swapchain. So do not un-bind the offscreen yet! */
|
||||
|
||||
GPU_offscreen_bind(surface_data->offscreen, false);
|
||||
|
||||
wm_xr_draw_viewport_buffers_to_active_framebuffer(surface_data, draw_view);
|
||||
}
|
||||
|
||||
/** \} */ /* XR Drawing */
|
||||
@@ -98,4 +98,14 @@ void wm_stereo3d_set_cancel(bContext *C, wmOperator *op);
|
||||
void wm_open_init_load_ui(wmOperator *op, bool use_prefs);
|
||||
void wm_open_init_use_scripts(wmOperator *op, bool use_prefs);
|
||||
|
||||
#ifdef WITH_XR_OPENXR
|
||||
typedef void (*wmXrSessionExitFn)(const wmXrData *xr_data);
|
||||
|
||||
/* wm_xr.c */
|
||||
bool wm_xr_init(wmWindowManager *wm);
|
||||
void wm_xr_exit(wmWindowManager *wm);
|
||||
void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn);
|
||||
bool wm_xr_events_handle(wmWindowManager *wm);
|
||||
#endif
|
||||
|
||||
#endif /* __WM_H__ */
|
||||
|
||||
57
source/blender/windowmanager/wm_surface.h
Normal file
57
source/blender/windowmanager/wm_surface.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup wm
|
||||
*
|
||||
* \name WM-Surface
|
||||
*
|
||||
* Container to manage painting in an offscreen context.
|
||||
*/
|
||||
|
||||
#ifndef __WM_SURFACE_H__
|
||||
#define __WM_SURFACE_H__
|
||||
|
||||
struct bContext;
|
||||
|
||||
typedef struct wmSurface {
|
||||
struct wmSurface *next, *prev;
|
||||
|
||||
GHOST_ContextHandle ghost_ctx;
|
||||
struct GPUContext *gpu_ctx;
|
||||
|
||||
void *customdata;
|
||||
|
||||
void (*draw)(struct bContext *);
|
||||
/** Free customdata, not the surface itself (done by wm_surface API) */
|
||||
void (*free_data)(struct wmSurface *);
|
||||
} wmSurface;
|
||||
|
||||
/* Create/Free */
|
||||
void wm_surface_add(wmSurface *surface);
|
||||
void wm_surface_remove(wmSurface *surface);
|
||||
void wm_surfaces_free(void);
|
||||
|
||||
/* Utils */
|
||||
void wm_surfaces_iter(struct bContext *C, void (*cb)(bContext *, wmSurface *));
|
||||
|
||||
/* Drawing */
|
||||
void wm_surface_make_drawable(wmSurface *surface);
|
||||
void wm_surface_clear_drawable(void);
|
||||
void wm_surface_set_drawable(wmSurface *surface, bool activate);
|
||||
void wm_surface_reset_drawable(void);
|
||||
|
||||
#endif /* __WM_SURFACE_H__ */
|
||||
@@ -111,6 +111,10 @@ if(WITH_FREESTYLE)
|
||||
add_definitions(-DWITH_FREESTYLE)
|
||||
endif()
|
||||
|
||||
if(WITH_XR_OPENXR)
|
||||
add_definitions(-DWITH_XR_OPENXR)
|
||||
endif()
|
||||
|
||||
# Setup the exe sources and buildinfo
|
||||
set(SRC
|
||||
creator.c
|
||||
@@ -856,6 +860,8 @@ elseif(WIN32)
|
||||
${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_gpu_glitchworkaround.cmd
|
||||
${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_log.cmd
|
||||
${CMAKE_SOURCE_DIR}/release/windows/batch/blender_factory_startup.cmd
|
||||
${CMAKE_SOURCE_DIR}/release/windows/batch/blender_oculus.cmd
|
||||
${CMAKE_SOURCE_DIR}/release/windows/batch/oculus.json
|
||||
DESTINATION "."
|
||||
)
|
||||
|
||||
|
||||
@@ -603,6 +603,10 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
|
||||
BLI_argsPrintArgDoc(ba, "--debug-gpu-shaders");
|
||||
BLI_argsPrintArgDoc(ba, "--debug-gpu-force-workarounds");
|
||||
BLI_argsPrintArgDoc(ba, "--debug-wm");
|
||||
# ifdef WITH_XR_OPENXR
|
||||
BLI_argsPrintArgDoc(ba, "--debug-xr");
|
||||
BLI_argsPrintArgDoc(ba, "--debug-xr-time");
|
||||
# endif
|
||||
BLI_argsPrintArgDoc(ba, "--debug-all");
|
||||
BLI_argsPrintArgDoc(ba, "--debug-io");
|
||||
|
||||
@@ -940,6 +944,16 @@ static const char arg_handle_debug_mode_generic_set_doc_wm[] =
|
||||
"\n\t"
|
||||
"Enable debug messages for the window manager, shows all operators in search, shows "
|
||||
"keymap errors.";
|
||||
# ifdef WITH_XR_OPENXR
|
||||
static const char arg_handle_debug_mode_generic_set_doc_xr[] =
|
||||
"\n\t"
|
||||
"Enable debug messages for virtual reality contexts.\n"
|
||||
"\tEnables the OpenXR API validation layer, (OpenXR) debug messages and general information "
|
||||
"prints.";
|
||||
static const char arg_handle_debug_mode_generic_set_doc_xr_time[] =
|
||||
"\n\t"
|
||||
"Enable debug messages for virtual reality frame rendering times.";
|
||||
# endif
|
||||
static const char arg_handle_debug_mode_generic_set_doc_jobs[] =
|
||||
"\n\t"
|
||||
"Enable time profiling for background jobs.";
|
||||
@@ -2091,6 +2105,16 @@ void main_args_setup(bContext *C, bArgs *ba)
|
||||
(void *)G_DEBUG_HANDLERS);
|
||||
BLI_argsAdd(
|
||||
ba, 1, NULL, "--debug-wm", CB_EX(arg_handle_debug_mode_generic_set, wm), (void *)G_DEBUG_WM);
|
||||
# ifdef WITH_XR_OPENXR
|
||||
BLI_argsAdd(
|
||||
ba, 1, NULL, "--debug-xr", CB_EX(arg_handle_debug_mode_generic_set, xr), (void *)G_DEBUG_XR);
|
||||
BLI_argsAdd(ba,
|
||||
1,
|
||||
NULL,
|
||||
"--debug-xr-time",
|
||||
CB_EX(arg_handle_debug_mode_generic_set, xr_time),
|
||||
(void *)G_DEBUG_XR_TIME);
|
||||
# endif
|
||||
BLI_argsAdd(ba,
|
||||
1,
|
||||
NULL,
|
||||
|
||||
@@ -50,6 +50,9 @@ def _init_addon_blacklist():
|
||||
# netrender has known problems re-registering
|
||||
BLACKLIST_ADDONS.add("netrender")
|
||||
|
||||
if not bpy.app.build_options.xr_openxr:
|
||||
BLACKLIST_ADDONS.add("viewport_vr_preview")
|
||||
|
||||
for mod in addon_utils.modules():
|
||||
if addon_utils.module_bl_info(mod)['blender'] < (2, 80, 0):
|
||||
BLACKLIST_ADDONS.add(mod.__name__)
|
||||
|
||||
@@ -56,6 +56,9 @@ MODULE_SYS_PATHS = {
|
||||
if not bpy.app.build_options.freestyle:
|
||||
BLACKLIST.add("render_freestyle_svg")
|
||||
|
||||
if not bpy.app.build_options.xr_openxr:
|
||||
BLACKLIST.add("viewport_vr_preview")
|
||||
|
||||
BLACKLIST_DIRS = (
|
||||
os.path.join(bpy.utils.resource_path('USER'), "scripts"),
|
||||
) + tuple(addon_utils.paths()[1:])
|
||||
|
||||
Reference in New Issue
Block a user