Fix T56657: Crash when creating a collection instance containing probes
[blender.git] / source / blender / draw / modes / pose_mode.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file blender/draw/modes/pose_mode.c
23  *  \ingroup draw
24  */
25 #include "BKE_modifier.h"
26
27 #include "DNA_modifier_types.h"
28 #include "DNA_view3d_types.h"
29
30 #include "DRW_engine.h"
31 #include "DRW_render.h"
32
33 /* If builtin shaders are needed */
34 #include "GPU_shader.h"
35
36 #include "draw_common.h"
37
38 #include "draw_mode_engines.h"
39
40 extern GlobalsUboStorage ts;
41
42 /* *********** LISTS *********** */
43 /* All lists are per viewport specific datas.
44  * They are all free when viewport changes engines
45  * or is free itself. Use POSE_engine_init() to
46  * initialize most of them and POSE_cache_init()
47  * for POSE_PassList */
48
49 typedef struct POSE_PassList {
50         struct DRWPass *bone_solid[2];
51         struct DRWPass *bone_outline[2];
52         struct DRWPass *bone_wire[2];
53         struct DRWPass *bone_envelope[2];
54         struct DRWPass *bone_axes;
55         struct DRWPass *relationship[2];
56         struct DRWPass *bone_selection;
57 } POSE_PassList;
58
59 typedef struct POSE_StorageList {
60         struct POSE_PrivateData *g_data;
61 } POSE_StorageList;
62
63 typedef struct POSE_Data {
64         void *engine_type;
65         DRWViewportEmptyList *fbl;
66         DRWViewportEmptyList *txl;
67         POSE_PassList *psl;
68         POSE_StorageList *stl;
69 } POSE_Data;
70
71 /* *********** STATIC *********** */
72
73 typedef struct POSE_PrivateData {
74         DRWShadingGroup *bone_selection_shgrp;
75         DRWShadingGroup *bone_selection_invert_shgrp;
76         float blend_color[4];
77         float blend_color_invert[4];
78         bool transparent_bones;
79 } POSE_PrivateData; /* Transient data */
80
81 static struct {
82         struct GPUShader *bone_selection_sh;
83 } e_data = {NULL};
84
85
86 /* *********** FUNCTIONS *********** */
87 static bool POSE_is_bone_selection_overlay_active(void)
88 {
89         const DRWContextState *dcs = DRW_context_state_get();
90         const View3D *v3d = dcs->v3d;
91         return v3d && (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) && OBPOSE_FROM_OBACT(dcs->obact);
92 }
93
94 static void POSE_engine_init(void *UNUSED(vedata))
95 {
96         if (!e_data.bone_selection_sh) {
97                 e_data.bone_selection_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
98         }
99 }
100
101 static void POSE_engine_free(void)
102 {
103 }
104
105 /* Here init all passes and shading groups
106  * Assume that all Passes are NULL */
107 static void POSE_cache_init(void *vedata)
108 {
109         POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
110         POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
111         const DRWContextState *draw_ctx = DRW_context_state_get();
112         View3D *v3d = draw_ctx->v3d;
113
114         if (!stl->g_data) {
115                 /* Alloc transient pointers */
116                 stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
117         }
118         POSE_PrivateData *ppd = stl->g_data;
119         ppd->transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
120
121         for (int i = 0; i < 2; ++i) {
122                 /* Solid bones */
123                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
124                 psl->bone_solid[i] = DRW_pass_create("Bone Solid Pass", state);
125
126                 /* Bones Outline */
127                 state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
128                 psl->bone_outline[i] = DRW_pass_create("Bone Outline Pass", state);
129
130                 /* Wire bones */
131                 state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND;
132                 psl->bone_wire[i] = DRW_pass_create("Bone Wire Pass", state);
133
134                 /* distance outline around envelope bones */
135                 state = DRW_STATE_ADDITIVE | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_FRONT;
136                 psl->bone_envelope[i] = DRW_pass_create("Bone Envelope Outline Pass", state);
137
138                 state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
139                         DRW_STATE_BLEND | DRW_STATE_WIRE;
140                 psl->relationship[i] = DRW_pass_create("Bone Relationship Pass", state);
141         }
142
143         {
144                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WIRE_SMOOTH | DRW_STATE_BLEND;
145                 psl->bone_axes = DRW_pass_create("Bone Axes Pass", state);
146         }
147
148         {
149                 if (POSE_is_bone_selection_overlay_active()) {
150                         copy_v4_fl4(ppd->blend_color, 0.0f, 0.0f, 0.0f, v3d->overlay.bone_select_alpha);
151                         copy_v4_fl4(ppd->blend_color_invert, 0.0f, 0.0f, 0.0f, pow(v3d->overlay.bone_select_alpha, 4));
152                         DRWShadingGroup *grp;
153                         psl->bone_selection = DRW_pass_create(
154                                 "Bone Selection",
155                                 DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND);
156                         grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection);
157                         DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color, 1);
158                         stl->g_data->bone_selection_shgrp = grp;
159                         grp = DRW_shgroup_create(e_data.bone_selection_sh, psl->bone_selection);
160                         DRW_shgroup_uniform_vec4(grp, "color", ppd->blend_color_invert, 1);
161                         stl->g_data->bone_selection_invert_shgrp = grp;
162                 }
163         }
164 }
165
166 static bool POSE_is_driven_by_active_armature(Object *ob)
167 {
168         Object *ob_arm = modifiers_isDeformedByArmature(ob);
169         if (ob_arm) {
170                 const DRWContextState *draw_ctx = DRW_context_state_get();
171                 bool is_active = DRW_pose_mode_armature(ob_arm, draw_ctx->obact);
172                 if (!is_active && ob_arm->proxy_from) {
173                         is_active = DRW_pose_mode_armature(ob_arm->proxy_from, draw_ctx->obact);
174                 }
175                 return is_active;
176         }
177         else {
178                 Object *ob_mesh_deform = modifiers_isDeformedByMeshDeform(ob);
179                 if (ob_mesh_deform) {
180                         return POSE_is_driven_by_active_armature(ob_mesh_deform);
181                 }
182         }
183         return false;
184 }
185
186 /* Add geometry to shading groups. Execute for each objects */
187 static void POSE_cache_populate(void *vedata, Object *ob)
188 {
189         POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
190         POSE_PrivateData *ppd = ((POSE_Data *)vedata)->stl->g_data;
191         const DRWContextState *draw_ctx = DRW_context_state_get();
192
193         /* In the future this will allow us to implement face gizmos,
194          * and similar functionalities. For now we handle only pose bones. */
195
196         if (ob->type == OB_ARMATURE) {
197                 if (draw_ctx->v3d->overlay.flag & V3D_OVERLAY_HIDE_BONES) {
198                         return;
199                 }
200                 if (DRW_pose_mode_armature(ob, draw_ctx->obact)) {
201                         int ghost = (ob->dtx & OB_DRAWXRAY) ? 1 : 0;
202
203                         DRWArmaturePasses passes = {
204                             .bone_solid = psl->bone_solid[ghost],
205                             .bone_outline = psl->bone_outline[ghost],
206                             .bone_wire = psl->bone_wire[ghost],
207                             .bone_envelope = psl->bone_envelope[ghost],
208                             .bone_axes = psl->bone_axes,
209                             .relationship_lines = psl->relationship[ghost],
210                         };
211                         DRW_shgroup_armature_pose(ob, passes, ppd->transparent_bones);
212                 }
213         }
214         else if (ob->type == OB_MESH &&
215                  !DRW_state_is_select() &&
216                  POSE_is_bone_selection_overlay_active())
217         {
218                 struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
219                 if (geom) {
220                         if (POSE_is_driven_by_active_armature(ob)) {
221                                 DRW_shgroup_call_object_add(ppd->bone_selection_shgrp, geom, ob);
222                         }
223                         else {
224                                 DRW_shgroup_call_object_add(ppd->bone_selection_invert_shgrp, geom, ob);
225                         }
226                 }
227         }
228 }
229
230 /**
231  * Return true if armature should be handled by the pose mode engine.
232  */
233 bool DRW_pose_mode_armature(Object *ob, Object *active_ob)
234 {
235         const DRWContextState *draw_ctx = DRW_context_state_get();
236
237         /* Pose armature is handled by pose mode engine. */
238         if (((ob == active_ob) || (ob->mode & OB_MODE_POSE)) &&
239             ((draw_ctx->object_mode & OB_MODE_POSE) != 0))
240         {
241                 return true;
242         }
243
244         /* Armature parent is also handled by pose mode engine. */
245         if ((active_ob != NULL) && ((draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) != 0)) {
246                 if (ob == draw_ctx->object_pose) {
247                         return true;
248                 }
249         }
250
251         return false;
252 }
253
254 /* Draw time ! Control rendering pipeline from here */
255 static void POSE_draw_scene(void *vedata)
256 {
257         POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
258         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
259         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
260         const DRWContextState *draw_ctx = DRW_context_state_get();
261         const bool transparent_bones = (draw_ctx->v3d->overlay.arm_flag & V3D_OVERLAY_ARM_TRANSP_BONES) != 0;
262         const bool bone_selection_overlay = POSE_is_bone_selection_overlay_active();
263
264         if (DRW_state_is_select()) {
265                 DRW_draw_pass(psl->bone_solid[0]);
266                 DRW_draw_pass(psl->bone_wire[0]);
267                 DRW_draw_pass(psl->bone_solid[1]);
268                 DRW_draw_pass(psl->bone_wire[1]);
269                 return;
270         }
271
272         if (bone_selection_overlay) {
273                 GPU_framebuffer_bind(dfbl->default_fb);
274                 DRW_draw_pass(psl->bone_selection);
275                 GPU_framebuffer_bind(dfbl->depth_only_fb);
276                 GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0);
277                 GPU_framebuffer_bind(dfbl->default_fb);
278         }
279
280         DRW_draw_pass(psl->bone_envelope[0]);
281
282         if (transparent_bones) {
283                 DRW_pass_state_add(psl->bone_solid[0], DRW_STATE_BLEND);
284                 DRW_pass_state_remove(psl->bone_solid[0], DRW_STATE_WRITE_DEPTH);
285                 DRW_draw_pass(psl->bone_solid[0]);
286         }
287
288         MULTISAMPLE_SYNC_ENABLE(dfbl, dtxl);
289
290         if (!transparent_bones) {
291                 DRW_draw_pass(psl->bone_solid[0]);
292         }
293
294         DRW_draw_pass(psl->bone_outline[0]);
295         DRW_draw_pass(psl->bone_wire[0]);
296         DRW_draw_pass(psl->relationship[0]);
297
298         MULTISAMPLE_SYNC_DISABLE(dfbl, dtxl);
299
300         if (!DRW_pass_is_empty(psl->bone_envelope[1]) ||
301             !DRW_pass_is_empty(psl->bone_solid[1]) ||
302             !DRW_pass_is_empty(psl->bone_outline[1]) ||
303             !DRW_pass_is_empty(psl->bone_wire[1]) ||
304             !DRW_pass_is_empty(psl->relationship[1]))
305         {
306                 if (DRW_state_is_fbo()) {
307                         GPU_framebuffer_bind(dfbl->default_fb);
308                         GPU_framebuffer_clear_depth(dfbl->default_fb, 1.0f);
309                 }
310
311                 if (transparent_bones) {
312                         DRW_pass_state_add(psl->bone_solid[1], DRW_STATE_BLEND);
313                         DRW_pass_state_remove(psl->bone_solid[1], DRW_STATE_WRITE_DEPTH);
314                 }
315
316                 DRW_draw_pass(psl->bone_envelope[1]);
317                 DRW_draw_pass(psl->bone_solid[1]);
318                 DRW_draw_pass(psl->bone_outline[1]);
319                 DRW_draw_pass(psl->bone_wire[1]);
320                 DRW_draw_pass(psl->relationship[1]);
321         }
322
323         /* Draw axes with linesmooth and outside of multisample buffer. */
324         DRW_draw_pass(psl->bone_axes);
325 }
326
327 static const DrawEngineDataSize POSE_data_size = DRW_VIEWPORT_DATA_SIZE(POSE_Data);
328
329 DrawEngineType draw_engine_pose_type = {
330         NULL, NULL,
331         N_("PoseMode"),
332         &POSE_data_size,
333         &POSE_engine_init,
334         &POSE_engine_free,
335         &POSE_cache_init,
336         &POSE_cache_populate,
337         NULL,
338         NULL,
339         &POSE_draw_scene,
340         NULL,
341         NULL,
342 };