2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2008-12-20 18:43:21 +00:00
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* 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
|
2018-06-01 18:19:39 +02:00
|
|
|
* of the License, or (at your option) any later version.
|
2008-12-20 18:43:21 +00:00
|
|
|
*
|
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2008-12-20 18:43:21 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
2018-06-01 18:19:39 +02:00
|
|
|
*
|
2008-12-20 18:43:21 +00:00
|
|
|
* Contributor(s): Blender Foundation
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2011-02-27 20:29:51 +00:00
|
|
|
/** \file blender/editors/space_view3d/view3d_select.c
|
|
|
|
* \ingroup spview3d
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
2010-11-03 01:56:02 +00:00
|
|
|
#include <assert.h>
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
#include "DNA_action_types.h"
|
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
|
|
#include "DNA_meta_types.h"
|
2012-02-19 22:17:30 +00:00
|
|
|
#include "DNA_mesh_types.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "DNA_tracking_types.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "DNA_gpencil_types.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
#include "BLI_array.h"
|
2009-11-10 20:43:45 +00:00
|
|
|
#include "BLI_math.h"
|
2018-02-18 21:27:33 +11:00
|
|
|
#include "BLI_lasso_2d.h"
|
2012-04-27 07:26:28 +00:00
|
|
|
#include "BLI_rect.h"
|
2009-09-16 17:43:09 +00:00
|
|
|
#include "BLI_linklist.h"
|
2012-04-27 07:26:28 +00:00
|
|
|
#include "BLI_listbase.h"
|
|
|
|
#include "BLI_string.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-04-16 08:51:41 +02:00
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
# include "BLI_endian_switch.h"
|
|
|
|
#endif
|
|
|
|
|
2011-09-18 17:10:28 +00:00
|
|
|
/* vertex box select */
|
2011-08-09 16:32:15 +00:00
|
|
|
#include "IMB_imbuf_types.h"
|
|
|
|
#include "IMB_imbuf.h"
|
|
|
|
#include "BKE_global.h"
|
|
|
|
|
2010-11-03 01:56:02 +00:00
|
|
|
#include "BKE_armature.h"
|
2012-10-06 03:02:14 +00:00
|
|
|
#include "BKE_context.h"
|
2014-01-27 15:18:40 +11:00
|
|
|
#include "BKE_curve.h"
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
#include "BKE_layer.h"
|
2012-10-06 03:02:14 +00:00
|
|
|
#include "BKE_mball.h"
|
2013-06-15 10:18:16 +00:00
|
|
|
#include "BKE_mesh.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "BKE_object.h"
|
2012-10-06 03:02:14 +00:00
|
|
|
#include "BKE_paint.h"
|
2013-04-13 20:31:52 +00:00
|
|
|
#include "BKE_editmesh.h"
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
#include "BKE_scene.h"
|
2011-11-07 12:55:18 +00:00
|
|
|
#include "BKE_tracking.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "BKE_workspace.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
2012-01-11 03:40:20 +00:00
|
|
|
#include "RNA_enum_types.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-05 15:19:31 +00:00
|
|
|
#include "ED_armature.h"
|
2009-01-14 12:26:45 +00:00
|
|
|
#include "ED_curve.h"
|
2018-03-19 14:49:59 +01:00
|
|
|
#include "ED_lattice.h"
|
2016-12-28 17:30:58 +01:00
|
|
|
#include "ED_particle.h"
|
2008-12-30 13:16:14 +00:00
|
|
|
#include "ED_mesh.h"
|
2008-12-29 12:15:42 +00:00
|
|
|
#include "ED_object.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
#include "ED_screen.h"
|
2018-08-14 10:28:41 +10:00
|
|
|
#include "ED_select_utils.h"
|
2013-10-27 03:31:19 +00:00
|
|
|
#include "ED_sculpt.h"
|
2009-07-29 12:35:09 +00:00
|
|
|
#include "ED_mball.h"
|
2018-07-31 10:22:19 +02:00
|
|
|
#include "ED_gpencil.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
#include "UI_interface.h"
|
|
|
|
|
2016-06-25 20:16:33 +10:00
|
|
|
#include "GPU_draw.h"
|
2017-08-21 01:39:03 +10:00
|
|
|
#include "GPU_glew.h"
|
2017-03-21 17:49:21 -04:00
|
|
|
#include "GPU_matrix.h"
|
2016-06-25 20:16:33 +10:00
|
|
|
|
2012-07-08 20:36:00 +00:00
|
|
|
#include "view3d_intern.h" /* own include */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2017-03-09 05:17:55 +11:00
|
|
|
// #include "PIL_time_utildefines.h"
|
|
|
|
|
2018-12-13 13:04:25 +11:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Public Utilities
|
|
|
|
* \{ */
|
|
|
|
|
2014-03-11 15:34:19 +11:00
|
|
|
float ED_view3d_select_dist_px(void)
|
|
|
|
{
|
|
|
|
return 75.0f * U.pixelsize;
|
|
|
|
}
|
|
|
|
|
2012-07-08 20:36:00 +00:00
|
|
|
/* TODO: should return whether there is valid context to continue */
|
2018-03-08 17:30:24 +11:00
|
|
|
void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
|
2009-01-02 14:11:18 +00:00
|
|
|
{
|
|
|
|
memset(vc, 0, sizeof(ViewContext));
|
2018-11-23 18:28:36 +03:00
|
|
|
vc->C = C;
|
2012-03-25 23:54:33 +00:00
|
|
|
vc->ar = CTX_wm_region(C);
|
2018-06-08 12:16:37 +02:00
|
|
|
vc->bmain = CTX_data_main(C);
|
2017-04-26 10:46:55 +02:00
|
|
|
vc->depsgraph = CTX_data_depsgraph(C);
|
2012-03-25 23:54:33 +00:00
|
|
|
vc->scene = CTX_data_scene(C);
|
2017-11-22 10:52:39 -02:00
|
|
|
vc->view_layer = CTX_data_view_layer(C);
|
2012-03-25 23:54:33 +00:00
|
|
|
vc->v3d = CTX_wm_view3d(C);
|
2016-02-04 22:26:46 +01:00
|
|
|
vc->win = CTX_wm_window(C);
|
2012-03-25 23:54:33 +00:00
|
|
|
vc->rv3d = CTX_wm_region_view3d(C);
|
|
|
|
vc->obact = CTX_data_active_object(C);
|
|
|
|
vc->obedit = CTX_data_edit_object(C);
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
|
|
|
|
{
|
|
|
|
vc->obact = obact;
|
|
|
|
if (vc->obedit) {
|
|
|
|
BLI_assert(BKE_object_is_in_editmode(obact));
|
|
|
|
vc->obedit = obact;
|
|
|
|
/* previous selections are now invalid. */
|
|
|
|
vc->v3d->flag |= V3D_INVALID_BACKBUF;
|
|
|
|
|
|
|
|
if (vc->em) {
|
|
|
|
vc->em = BKE_editmesh_from_object(vc->obedit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-13 13:04:25 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2018-12-13 19:05:11 +11:00
|
|
|
/** \name Internal Object Utilities
|
2018-12-13 13:04:25 +11:00
|
|
|
* \{ */
|
|
|
|
|
|
|
|
static void object_deselect_all_visible(ViewLayer *view_layer, View3D *v3d)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
|
|
|
|
for (base = view_layer->object_bases.first; base; base = base->next) {
|
|
|
|
if (BASE_SELECTABLE(v3d, base)) {
|
|
|
|
ED_object_base_select(base, BA_DESELECT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* deselect all except b */
|
|
|
|
static void object_deselect_all_except(ViewLayer *view_layer, Base *b)
|
2018-12-13 13:04:25 +11:00
|
|
|
{
|
|
|
|
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
|
|
|
|
if (base->flag & BASE_SELECTED) {
|
|
|
|
if (b != base) {
|
|
|
|
ED_object_base_select(base, BA_DESELECT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Internal Edit-Mesh Utilities
|
|
|
|
* \{ */
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-05-16 16:18:08 +00:00
|
|
|
BMVert *eve;
|
|
|
|
BMIter iter;
|
2013-03-09 16:19:07 +00:00
|
|
|
unsigned int index = bm_wireoffs;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2013-08-01 18:33:35 +00:00
|
|
|
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
|
2012-02-22 16:52:06 +00:00
|
|
|
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = EDBM_backbuf_check(index);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_vert_select_set(em->bm, eve, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-01 18:33:35 +00:00
|
|
|
index++;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
static void edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-05-16 16:18:08 +00:00
|
|
|
BMEdge *eed;
|
|
|
|
BMIter iter;
|
2013-10-10 22:30:16 +00:00
|
|
|
unsigned int index = bm_solidoffs;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2013-08-01 18:33:35 +00:00
|
|
|
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
|
2012-02-22 16:52:06 +00:00
|
|
|
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = EDBM_backbuf_check(index);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_edge_select_set(em->bm, eed, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-01 18:33:35 +00:00
|
|
|
index++;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-05-16 16:18:08 +00:00
|
|
|
BMFace *efa;
|
|
|
|
BMIter iter;
|
2013-03-09 16:19:07 +00:00
|
|
|
unsigned int index = 1;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2013-08-01 18:33:35 +00:00
|
|
|
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
2012-02-22 16:52:06 +00:00
|
|
|
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = EDBM_backbuf_check(index);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_face_select_set(em->bm, efa, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-01 18:33:35 +00:00
|
|
|
index++;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-04 17:38:55 +00:00
|
|
|
/* object mode, edbm_ prefix is confusing here, rename? */
|
2018-08-14 10:28:41 +10:00
|
|
|
static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op)
|
2011-07-05 18:03:31 +00:00
|
|
|
{
|
|
|
|
MVert *mv = me->mvert;
|
2013-03-09 16:19:07 +00:00
|
|
|
unsigned int index;
|
2011-07-05 18:03:31 +00:00
|
|
|
|
|
|
|
if (mv) {
|
2013-03-09 16:19:07 +00:00
|
|
|
for (index = 1; index <= me->totvert; index++, mv++) {
|
2018-08-14 10:28:41 +10:00
|
|
|
if (!(mv->flag & ME_HIDE)) {
|
|
|
|
const bool is_select = mv->flag & SELECT;
|
|
|
|
const bool is_inside = EDBM_backbuf_check(index);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
|
2011-07-05 18:03:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-09-22 16:09:27 +00:00
|
|
|
|
2012-12-04 17:38:55 +00:00
|
|
|
/* object mode, edbm_ prefix is confusing here, rename? */
|
2018-08-14 10:28:41 +10:00
|
|
|
static void edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2011-02-27 06:19:40 +00:00
|
|
|
MPoly *mpoly = me->mpoly;
|
2013-03-09 16:19:07 +00:00
|
|
|
unsigned int index;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2011-02-27 06:19:40 +00:00
|
|
|
if (mpoly) {
|
2013-03-09 16:19:07 +00:00
|
|
|
for (index = 1; index <= me->totpoly; index++, mpoly++) {
|
2018-08-14 10:28:41 +10:00
|
|
|
if (!(mpoly->flag & ME_HIDE)) {
|
|
|
|
const bool is_select = mpoly->flag & ME_FACE_SEL;
|
|
|
|
const bool is_inside = EDBM_backbuf_check(index);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-13 13:04:25 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Lasso Select
|
|
|
|
* \{ */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-01-26 08:12:12 +00:00
|
|
|
typedef struct LassoSelectUserData {
|
|
|
|
ViewContext *vc;
|
2012-10-05 15:44:11 +00:00
|
|
|
const rcti *rect;
|
2012-10-10 01:22:19 +00:00
|
|
|
const rctf *rect_fl;
|
|
|
|
rctf _rect_fl;
|
2012-10-05 15:44:11 +00:00
|
|
|
const int (*mcords)[2];
|
|
|
|
int moves;
|
2018-08-14 10:28:41 +10:00
|
|
|
eSelectOp sel_op;
|
2012-10-05 15:44:11 +00:00
|
|
|
|
|
|
|
/* runtime */
|
|
|
|
int pass;
|
2013-03-19 23:17:44 +00:00
|
|
|
bool is_done;
|
2013-11-26 06:39:14 +11:00
|
|
|
bool is_changed;
|
2012-01-26 08:12:12 +00:00
|
|
|
} LassoSelectUserData;
|
|
|
|
|
2018-03-11 15:50:07 +11:00
|
|
|
static void view3d_userdata_lassoselect_init(
|
|
|
|
LassoSelectUserData *r_data,
|
|
|
|
ViewContext *vc, const rcti *rect, const int (*mcords)[2],
|
2018-08-14 10:28:41 +10:00
|
|
|
const int moves, const eSelectOp sel_op)
|
2012-10-05 15:44:11 +00:00
|
|
|
{
|
|
|
|
r_data->vc = vc;
|
2012-10-10 01:22:19 +00:00
|
|
|
|
2012-10-05 15:44:11 +00:00
|
|
|
r_data->rect = rect;
|
2012-10-10 01:22:19 +00:00
|
|
|
r_data->rect_fl = &r_data->_rect_fl;
|
|
|
|
BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
|
|
|
|
|
2012-10-05 15:44:11 +00:00
|
|
|
r_data->mcords = mcords;
|
|
|
|
r_data->moves = moves;
|
2018-08-14 10:28:41 +10:00
|
|
|
r_data->sel_op = sel_op;
|
2012-10-05 15:44:11 +00:00
|
|
|
|
|
|
|
/* runtime */
|
|
|
|
r_data->pass = 0;
|
2013-03-19 23:17:44 +00:00
|
|
|
r_data->is_done = false;
|
2013-11-26 06:39:14 +11:00
|
|
|
r_data->is_changed = false;
|
2012-10-05 15:44:11 +00:00
|
|
|
}
|
|
|
|
|
2018-07-02 11:47:00 +02:00
|
|
|
static bool view3d_selectable_data(bContext *C)
|
2010-06-04 06:02:46 +00:00
|
|
|
{
|
|
|
|
Object *ob = CTX_data_active_object(C);
|
2011-01-17 22:37:24 +00:00
|
|
|
|
2010-09-27 10:44:46 +00:00
|
|
|
if (!ED_operator_region_view3d_active(C))
|
2010-06-04 06:02:46 +00:00
|
|
|
return 0;
|
2011-01-17 22:37:24 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ob) {
|
2018-04-05 18:20:27 +02:00
|
|
|
if (ob->mode & OB_MODE_EDIT) {
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ob->type == OB_FONT) {
|
2011-01-18 14:34:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2011-01-17 22:37:24 +00:00
|
|
|
}
|
2011-01-18 14:34:59 +00:00
|
|
|
else {
|
2018-04-05 18:20:27 +02:00
|
|
|
if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) &&
|
|
|
|
!BKE_paint_select_elem_test(ob))
|
2012-01-19 16:04:44 +00:00
|
|
|
{
|
2011-01-18 14:34:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2011-01-17 22:37:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-04 06:02:46 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
/* helper also for box_select */
|
2013-10-10 22:30:16 +00:00
|
|
|
static bool edge_fully_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-10-10 01:22:19 +00:00
|
|
|
return BLI_rctf_isect_pt_v(rect, v1) && BLI_rctf_isect_pt_v(rect, v2);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2013-10-10 22:30:16 +00:00
|
|
|
static bool edge_inside_rect(const rctf *rect, const float v1[2], const float v2[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
int d1, d2, d3, d4;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* check points in rect */
|
2012-10-10 01:22:19 +00:00
|
|
|
if (edge_fully_inside_rect(rect, v1, v2)) return 1;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* check points completely out rect */
|
2012-10-10 01:22:19 +00:00
|
|
|
if (v1[0] < rect->xmin && v2[0] < rect->xmin) return 0;
|
|
|
|
if (v1[0] > rect->xmax && v2[0] > rect->xmax) return 0;
|
|
|
|
if (v1[1] < rect->ymin && v2[1] < rect->ymin) return 0;
|
|
|
|
if (v1[1] > rect->ymax && v2[1] > rect->ymax) return 0;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* simple check lines intersecting. */
|
2012-10-10 01:22:19 +00:00
|
|
|
d1 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
|
|
|
|
d2 = (v1[1] - v2[1]) * (v1[0] - rect->xmin) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
|
|
|
|
d3 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymax);
|
|
|
|
d4 = (v1[1] - v2[1]) * (v1[0] - rect->xmax) + (v2[0] - v1[0]) * (v1[1] - rect->ymin);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (d1 < 0 && d2 < 0 && d3 < 0 && d4 < 0) return 0;
|
|
|
|
if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0) return 0;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
static void do_lasso_select_pose__do_tag(
|
2018-03-11 15:50:07 +11:00
|
|
|
void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-10-05 17:51:44 +00:00
|
|
|
LassoSelectUserData *data = userData;
|
|
|
|
bArmature *arm = data->vc->obact->data;
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
if (PBONE_SELECTABLE(arm, pchan->bone)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
bool is_point_done = false;
|
2012-10-05 17:51:44 +00:00
|
|
|
int points_proj_tot = 0;
|
2012-10-04 17:52:12 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
/* project head location to screenspace */
|
2018-08-28 16:17:37 +10:00
|
|
|
if (screen_co_a[0] != IS_CLIPPED) {
|
2012-10-05 17:51:44 +00:00
|
|
|
points_proj_tot++;
|
2018-08-28 16:17:37 +10:00
|
|
|
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX))
|
2012-10-05 10:28:36 +00:00
|
|
|
{
|
2013-03-19 23:17:44 +00:00
|
|
|
is_point_done = true;
|
2012-10-05 10:28:36 +00:00
|
|
|
}
|
2012-10-05 17:51:44 +00:00
|
|
|
}
|
2012-10-04 17:52:12 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
/* project tail location to screenspace */
|
2018-08-28 16:17:37 +10:00
|
|
|
if (screen_co_b[0] != IS_CLIPPED) {
|
2012-10-05 17:51:44 +00:00
|
|
|
points_proj_tot++;
|
2018-08-28 16:17:37 +10:00
|
|
|
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX))
|
2012-10-05 10:28:36 +00:00
|
|
|
{
|
2013-03-19 23:17:44 +00:00
|
|
|
is_point_done = true;
|
2012-10-05 10:28:36 +00:00
|
|
|
}
|
2012-10-05 17:51:44 +00:00
|
|
|
}
|
2012-10-05 10:28:36 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
/* if one of points selected, we skip the bone itself */
|
2013-03-19 23:17:44 +00:00
|
|
|
if ((is_point_done == true) ||
|
2018-08-28 16:17:37 +10:00
|
|
|
((is_point_done == false) && (points_proj_tot == 2) &&
|
|
|
|
BLI_lasso_is_edge_inside(data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)))
|
2012-10-05 17:51:44 +00:00
|
|
|
{
|
2018-08-28 16:17:37 +10:00
|
|
|
pchan->bone->flag |= BONE_DONE;
|
2009-11-09 21:03:54 +00:00
|
|
|
}
|
2013-11-26 06:39:14 +11:00
|
|
|
data->is_changed |= is_point_done;
|
2009-11-09 21:03:54 +00:00
|
|
|
}
|
2012-10-05 17:51:44 +00:00
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves)
|
2012-10-05 17:51:44 +00:00
|
|
|
{
|
2012-10-10 04:03:22 +00:00
|
|
|
ViewContext vc_tmp;
|
2012-10-05 17:51:44 +00:00
|
|
|
LassoSelectUserData data;
|
|
|
|
rcti rect;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
if ((ob->type != OB_ARMATURE) || (ob->pose == NULL)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-10 04:03:22 +00:00
|
|
|
vc_tmp = *vc;
|
|
|
|
vc_tmp.obact = ob;
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0);
|
2012-10-05 17:51:44 +00:00
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d);
|
2012-10-05 17:51:44 +00:00
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
pose_foreachScreenBone(&vc_tmp, do_lasso_select_pose__do_tag, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-02-06 17:06:20 +11:00
|
|
|
static void do_lasso_select_objects(
|
|
|
|
ViewContext *vc, const int mcords[][2], const short moves,
|
2018-08-14 10:28:41 +10:00
|
|
|
const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2018-11-23 14:41:38 -02:00
|
|
|
View3D *v3d = vc->v3d;
|
2017-02-08 12:26:41 +01:00
|
|
|
Base *base;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2018-11-23 14:41:38 -02:00
|
|
|
object_deselect_all_visible(vc->view_layer, vc->v3d);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
bool changed = false;
|
2017-11-22 10:52:39 -02:00
|
|
|
for (base = vc->view_layer->object_bases.first; base; base = base->next) {
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_SELECTABLE(v3d, base)) { /* use this to avoid un-needed lasso lookups */
|
2018-08-28 16:17:37 +10:00
|
|
|
const bool is_select = base->flag & BASE_SELECTED;
|
|
|
|
const bool is_inside = (
|
|
|
|
(ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) &&
|
|
|
|
BLI_lasso_is_point_inside(mcords, moves, base->sx, base->sy, IS_CLIPPED));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
|
2018-08-28 16:17:37 +10:00
|
|
|
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2018-10-05 10:27:04 +10:00
|
|
|
* Use for lasso & box select.
|
2018-08-28 16:17:37 +10:00
|
|
|
*/
|
|
|
|
static Base **do_pose_tag_select_op_prepare(ViewContext *vc, uint *r_bases_len)
|
|
|
|
{
|
|
|
|
Base **bases = NULL;
|
|
|
|
BLI_array_declare(bases);
|
2018-12-01 19:43:10 +03:00
|
|
|
FOREACH_BASE_IN_MODE_BEGIN (vc->view_layer, vc->v3d, OB_ARMATURE, OB_MODE_POSE, base_iter) {
|
2018-08-28 16:17:37 +10:00
|
|
|
Object *ob_iter = base_iter->object;
|
|
|
|
bArmature *arm = ob_iter->data;
|
|
|
|
for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
|
|
|
|
Bone *bone = pchan->bone;
|
|
|
|
bone->flag &= ~BONE_DONE;
|
|
|
|
}
|
|
|
|
arm->id.tag |= LIB_TAG_DOIT;
|
|
|
|
ob_iter->id.tag &= ~LIB_TAG_DOIT;
|
|
|
|
BLI_array_append(bases, base_iter);
|
|
|
|
}
|
|
|
|
FOREACH_BASE_IN_MODE_END;
|
|
|
|
*r_bases_len = BLI_array_len(bases);
|
|
|
|
return bases;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const eSelectOp sel_op)
|
|
|
|
{
|
|
|
|
bool changed_multi = false;
|
|
|
|
|
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
|
|
|
for (int i = 0; i < bases_len; i++) {
|
|
|
|
Base *base_iter = bases[i];
|
|
|
|
Object *ob_iter = base_iter->object;
|
|
|
|
if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, false)) {
|
|
|
|
ED_pose_bone_select_tag_update(ob_iter);
|
|
|
|
changed_multi = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < bases_len; i++) {
|
|
|
|
Base *base_iter = bases[i];
|
|
|
|
Object *ob_iter = base_iter->object;
|
|
|
|
bArmature *arm = ob_iter->data;
|
|
|
|
|
|
|
|
/* Don't handle twice. */
|
|
|
|
if (arm->id.tag & LIB_TAG_DOIT) {
|
|
|
|
arm->id.tag &= ~LIB_TAG_DOIT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool changed = true;
|
|
|
|
for (bPoseChannel *pchan = ob_iter->pose->chanbase.first; pchan; pchan = pchan->next) {
|
|
|
|
Bone *bone = pchan->bone;
|
|
|
|
if ((bone->flag & BONE_UNSELECTABLE) == 0) {
|
|
|
|
const bool is_select = bone->flag & BONE_SELECTED;
|
|
|
|
const bool is_inside = bone->flag & BONE_DONE;
|
2018-08-14 10:28:41 +10:00
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
2018-08-28 16:17:37 +10:00
|
|
|
SET_FLAG_FROM_TEST(bone->flag, sel_op_result, BONE_SELECTED);
|
|
|
|
if (sel_op_result == 0) {
|
|
|
|
if (arm->act_bone == bone) {
|
|
|
|
arm->act_bone = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
changed = true;
|
2016-04-26 14:33:31 +10:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
if (changed) {
|
|
|
|
ED_pose_bone_select_tag_update(ob_iter);
|
|
|
|
changed_multi = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return changed_multi;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_lasso_select_pose(
|
|
|
|
ViewContext *vc, const int mcords[][2], const short moves,
|
|
|
|
const eSelectOp sel_op)
|
|
|
|
{
|
|
|
|
uint bases_len;
|
|
|
|
Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
|
|
|
|
|
|
|
|
for (int i = 0; i < bases_len; i++) {
|
|
|
|
Base *base_iter = bases[i];
|
|
|
|
Object *ob_iter = base_iter->object;
|
|
|
|
do_lasso_tag_pose(vc, ob_iter, mcords, moves);
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
|
|
|
|
if (changed_multi) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
|
2018-08-28 16:17:37 +10:00
|
|
|
WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, vc->scene);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bases != NULL) {
|
|
|
|
MEM_freeN(bases);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_lasso_select_mesh__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = (
|
|
|
|
BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_vert_select_set(data->vc->em->bm, eve, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_mesh__doSelectEdge_pass0(
|
2018-03-11 15:50:07 +11:00
|
|
|
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = (
|
|
|
|
EDBM_backbuf_check(bm_solidoffs + index) &&
|
|
|
|
edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
|
|
|
|
data->is_done = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void do_lasso_select_mesh__doSelectEdge_pass1(
|
|
|
|
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
|
|
|
|
{
|
|
|
|
LassoSelectUserData *data = userData;
|
|
|
|
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = (
|
|
|
|
EDBM_backbuf_check(bm_solidoffs + index) &&
|
|
|
|
BLI_lasso_is_edge_inside(
|
|
|
|
data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_lasso_select_mesh__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = (
|
|
|
|
BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
|
|
|
|
BLI_lasso_is_point_inside(
|
|
|
|
data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_face_select_set(data->vc->em->bm, efa, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-16 12:45:11 +10:00
|
|
|
static void do_lasso_select_mesh(
|
2018-04-06 12:07:27 +02:00
|
|
|
ViewContext *vc,
|
2018-08-14 10:28:41 +10:00
|
|
|
const int mcords[][2], short moves, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData data;
|
2012-03-25 23:54:33 +00:00
|
|
|
ToolSettings *ts = vc->scene->toolsettings;
|
2008-12-20 18:43:21 +00:00
|
|
|
rcti rect;
|
|
|
|
int bbsel;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* set editmesh */
|
2013-04-16 05:59:48 +00:00
|
|
|
vc->em = BKE_editmesh_from_object(vc->obedit);
|
2009-01-02 14:11:18 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2012-02-12 18:43:59 +00:00
|
|
|
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
/* for non zbuf projections, don't change the GL state */
|
2011-06-09 03:56:32 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
|
2010-02-08 10:12:02 +00:00
|
|
|
|
2018-07-15 15:27:15 +02:00
|
|
|
GPU_matrix_set(vc->rv3d->viewmat);
|
2018-04-06 12:07:27 +02:00
|
|
|
bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_VERTEX) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_verts(vc->em, sel_op);
|
2011-06-09 03:56:32 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_EDGE) {
|
2011-06-09 03:56:32 +00:00
|
|
|
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
|
2018-08-14 10:28:41 +10:00
|
|
|
mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
|
2013-03-19 23:17:44 +00:00
|
|
|
if (data.is_done == false) {
|
2018-08-14 10:28:41 +10:00
|
|
|
mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_FACE) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_faces(vc->em, sel_op);
|
2011-06-09 03:56:32 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-27 04:46:52 +00:00
|
|
|
EDBM_backbuf_free();
|
2012-02-10 06:16:21 +00:00
|
|
|
EDBM_selectmode_flush(vc->em);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_curve__doSelect(
|
|
|
|
void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData *data = userData;
|
2010-04-30 04:48:40 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_inside = BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED);
|
|
|
|
if (bp) {
|
|
|
|
const bool is_select = bp->f1 & SELECT;
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
|
|
|
else {
|
2018-09-25 18:50:57 +02:00
|
|
|
if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
|
2018-08-14 10:28:41 +10:00
|
|
|
/* can only be (beztindex == 0) here since handles are hidden */
|
|
|
|
const bool is_select = bezt->f2 & SELECT;
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
bezt->f1 = bezt->f3 = bezt->f2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *flag_p = (&bezt->f1) + beztindex;
|
|
|
|
const bool is_select = *flag_p & SELECT;
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_curve(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData data;
|
2012-10-10 01:22:19 +00:00
|
|
|
rcti rect;
|
|
|
|
|
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2014-03-12 14:07:26 +06:00
|
|
|
Curve *curve = (Curve *) vc->obedit->data;
|
|
|
|
ED_curve_deselect_all(curve->editnurb);
|
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
|
2012-10-10 04:03:22 +00:00
|
|
|
nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2014-01-27 15:18:40 +11:00
|
|
|
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const float screen_co[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData *data = userData;
|
2018-10-26 18:29:42 -03:00
|
|
|
const bool is_select = bp->f1 & SELECT;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_inside = (
|
|
|
|
BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_lattice(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
LassoSelectUserData data;
|
2012-10-10 01:22:19 +00:00
|
|
|
rcti rect;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2015-11-18 12:20:28 +11:00
|
|
|
ED_lattice_flags_set(vc->obedit, 0);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
|
2012-10-10 04:03:22 +00:00
|
|
|
lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
static void do_lasso_select_armature__doSelectBone(
|
|
|
|
void *userData, EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-10-05 17:07:02 +00:00
|
|
|
LassoSelectUserData *data = userData;
|
|
|
|
bArmature *arm = data->vc->obedit->data;
|
2018-08-14 10:28:41 +10:00
|
|
|
if (EBONE_VISIBLE(arm, ebone)) {
|
2018-12-13 19:05:11 +11:00
|
|
|
int is_ignore_flag = 0;
|
|
|
|
int is_inside_flag = 0;
|
2012-10-05 10:28:36 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (screen_co_a[0] != IS_CLIPPED) {
|
2018-12-13 19:05:11 +11:00
|
|
|
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX))
|
|
|
|
{
|
|
|
|
is_inside_flag |= BONESEL_ROOT;
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
2018-12-13 19:05:11 +11:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
is_ignore_flag |= BONESEL_ROOT;
|
2012-10-05 17:07:02 +00:00
|
|
|
}
|
2012-10-05 10:28:36 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (screen_co_b[0] != IS_CLIPPED) {
|
2018-12-13 19:05:11 +11:00
|
|
|
if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) &&
|
2018-12-13 22:56:19 +11:00
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX))
|
2018-12-13 19:05:11 +11:00
|
|
|
{
|
|
|
|
is_inside_flag |= BONESEL_TIP;
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
2018-12-13 19:05:11 +11:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
is_ignore_flag |= BONESEL_TIP;
|
2012-10-05 17:07:02 +00:00
|
|
|
}
|
2012-10-05 10:28:36 +00:00
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) ||
|
|
|
|
BLI_lasso_is_edge_inside(
|
|
|
|
data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX))
|
|
|
|
{
|
|
|
|
is_inside_flag |= BONESEL_BONE;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2012-10-05 17:07:02 +00:00
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
|
|
|
|
ebone->temp.i = is_inside_flag | (is_ignore_flag >> 16);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2012-10-05 17:07:02 +00:00
|
|
|
}
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_armature(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
|
2012-10-05 17:07:02 +00:00
|
|
|
{
|
|
|
|
LassoSelectUserData data;
|
|
|
|
rcti rect;
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
|
2012-10-05 17:07:02 +00:00
|
|
|
|
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2018-04-15 11:45:51 +02:00
|
|
|
ED_armature_edit_deselect_all_visible(vc->obedit);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2012-10-05 17:07:02 +00:00
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
bArmature *arm = vc->obedit->data;
|
|
|
|
|
|
|
|
ED_armature_ebone_listbase_temp_clear(arm->edbo);
|
|
|
|
|
2012-10-10 04:03:22 +00:00
|
|
|
armature_foreachScreenBone(vc, do_lasso_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2012-10-05 17:07:02 +00:00
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
data.is_changed = ED_armature_edit_select_op_from_tagged(vc->obedit->data, sel_op);
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
if (data.is_changed) {
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
|
2010-09-15 13:22:36 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_lasso_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2])
|
2012-10-06 03:02:14 +00:00
|
|
|
{
|
|
|
|
LassoSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = ml->flag & SELECT;
|
|
|
|
const bool is_inside = (
|
|
|
|
BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT);
|
2013-11-26 06:39:14 +11:00
|
|
|
data->is_changed = true;
|
2012-10-06 03:02:14 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
|
2010-11-03 02:28:11 +00:00
|
|
|
{
|
2012-10-06 03:02:14 +00:00
|
|
|
LassoSelectUserData data;
|
|
|
|
rcti rect;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
MetaBall *mb = (MetaBall *)vc->obedit->data;
|
2010-11-03 02:28:11 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2013-03-15 10:48:48 +00:00
|
|
|
BKE_mball_deselect_all(mb);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2012-10-06 03:02:14 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
|
2010-11-03 02:28:11 +00:00
|
|
|
|
2012-10-05 10:28:36 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
|
2010-11-03 02:28:11 +00:00
|
|
|
|
2012-10-10 04:03:22 +00:00
|
|
|
mball_foreachScreenElem(vc, do_lasso_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-04-05 18:20:27 +02:00
|
|
|
static void do_lasso_select_meshobject__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
|
2012-12-23 03:04:19 +00:00
|
|
|
{
|
|
|
|
LassoSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = mv->flag & SELECT;
|
|
|
|
const bool is_inside = (
|
|
|
|
BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
|
|
|
|
BLI_lasso_is_point_inside(data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
|
|
|
|
data->is_changed = true;
|
2012-12-23 03:04:19 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
|
2011-07-14 18:04:48 +00:00
|
|
|
{
|
2018-09-21 15:44:04 +02:00
|
|
|
const bool use_zbuf = V3D_IS_ZBUF(vc->v3d);
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *ob = vc->obact;
|
2013-10-08 19:47:53 +00:00
|
|
|
Mesh *me = ob->data;
|
2011-08-09 16:32:15 +00:00
|
|
|
rcti rect;
|
2011-07-14 18:04:48 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (me == NULL || me->totvert == 0)
|
2011-07-14 18:04:48 +00:00
|
|
|
return;
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
paintvert_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2011-08-09 16:32:15 +00:00
|
|
|
|
2012-04-27 07:26:28 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
2011-08-09 16:32:15 +00:00
|
|
|
|
2012-12-23 03:04:19 +00:00
|
|
|
if (use_zbuf) {
|
|
|
|
bm_vertoffs = me->totvert + 1; /* max index array */
|
2011-08-09 16:32:15 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
|
2012-12-23 03:04:19 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
|
2012-12-23 03:04:19 +00:00
|
|
|
|
|
|
|
EDBM_backbuf_free();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
LassoSelectUserData data;
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op);
|
2012-12-23 03:04:19 +00:00
|
|
|
|
|
|
|
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
|
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
meshobject_foreachScreenVert(vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2018-04-05 18:20:27 +02:00
|
|
|
|
2012-12-23 03:04:19 +00:00
|
|
|
}
|
2011-07-14 18:04:48 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_CAN_DESELECT(sel_op)) {
|
2013-06-15 10:18:16 +00:00
|
|
|
BKE_mesh_mselect_validate(me);
|
|
|
|
}
|
2011-07-14 18:04:48 +00:00
|
|
|
paintvert_flush_flags(ob);
|
2018-11-23 18:28:36 +03:00
|
|
|
paintvert_tag_select_update(vc->C, ob);
|
2011-07-13 20:45:09 +00:00
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *ob = vc->obact;
|
2013-10-08 19:47:53 +00:00
|
|
|
Mesh *me = ob->data;
|
2008-12-20 18:43:21 +00:00
|
|
|
rcti rect;
|
2010-11-03 02:50:05 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (me == NULL || me->totpoly == 0)
|
2010-11-03 01:56:02 +00:00
|
|
|
return;
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2019-01-15 23:24:20 +11:00
|
|
|
/* flush selection at the end */
|
|
|
|
paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
bm_vertoffs = me->totpoly + 1; /* max index array */
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2012-04-27 07:26:28 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
2018-04-06 12:07:27 +02:00
|
|
|
EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_tfaces(me, sel_op);
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2012-03-27 04:46:52 +00:00
|
|
|
EDBM_backbuf_free();
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2018-12-01 15:40:48 +03:00
|
|
|
paintface_flush_flags(vc->C, ob, SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
SpaceNode *snode = sa->spacedata.first;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
bNode *node;
|
|
|
|
rcti rect;
|
2012-07-11 18:17:48 +00:00
|
|
|
int node_cent[2];
|
2008-12-20 18:43:21 +00:00
|
|
|
float node_centf[2];
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-04-27 07:26:28 +00:00
|
|
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* store selection in temp test flag */
|
2012-03-25 23:54:33 +00:00
|
|
|
for (node = snode->edittree->nodes.first; node; node = node->next) {
|
2012-08-20 15:29:02 +00:00
|
|
|
node_centf[0] = BLI_RCT_CENTER_X(&node->totr);
|
|
|
|
node_centf[1] = BLI_RCT_CENTER_Y(&node->totr);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = node->flag & SELECT;
|
|
|
|
const bool is_inside = (
|
|
|
|
BLI_rcti_isect_pt_v(&rect, node_cent) &&
|
|
|
|
BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1]));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
BIF_undo_push("Lasso select nodes");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-11 15:50:07 +11:00
|
|
|
static void view3d_lasso_select(
|
|
|
|
bContext *C, ViewContext *vc,
|
|
|
|
const int mcords[][2], short moves,
|
2018-08-14 10:28:41 +10:00
|
|
|
const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-08-15 20:36:15 +00:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (vc->obedit == NULL) { /* Object Mode */
|
2018-04-05 18:20:27 +02:00
|
|
|
if (BKE_paint_select_face_test(ob)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_paintface(vc, mcords, moves, sel_op);
|
2017-08-16 12:45:11 +10:00
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (BKE_paint_select_vert_test(ob)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_paintvert(vc, mcords, moves, sel_op);
|
2017-08-16 12:45:11 +10:00
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
|
2012-10-14 13:08:19 +00:00
|
|
|
/* pass */
|
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
PE_lasso_select(C, mcords, moves, sel_op);
|
2017-08-16 12:45:11 +10:00
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
else if (ob && (ob->mode & OB_MODE_POSE)) {
|
|
|
|
do_lasso_select_pose(vc, mcords, moves, sel_op);
|
|
|
|
}
|
2010-08-25 00:58:15 +00:00
|
|
|
else {
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_objects(vc, mcords, moves, sel_op);
|
2010-08-25 00:58:15 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-10-26 09:35:33 +00:00
|
|
|
else { /* Edit Mode */
|
2018-04-16 16:27:55 +02:00
|
|
|
|
2018-12-01 19:43:10 +03:00
|
|
|
FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) {
|
2018-04-16 17:54:33 +02:00
|
|
|
ED_view3d_viewcontext_init_object(vc, ob_iter);
|
2018-04-16 16:27:55 +02:00
|
|
|
|
2018-04-16 17:54:33 +02:00
|
|
|
switch (vc->obedit->type) {
|
|
|
|
case OB_MESH:
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_mesh(vc, mcords, moves, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
break;
|
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_curve(vc, mcords, moves, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
break;
|
|
|
|
case OB_LATTICE:
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_lattice(vc, mcords, moves, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
break;
|
|
|
|
case OB_ARMATURE:
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_armature(vc, mcords, moves, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
break;
|
|
|
|
case OB_MBALL:
|
2018-08-14 10:28:41 +10:00
|
|
|
do_lasso_select_meta(vc, mcords, moves, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(!"lasso select on incorrect object type");
|
|
|
|
break;
|
|
|
|
}
|
2010-11-03 02:28:11 +00:00
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(vc->obedit->data, ID_RECALC_SELECT);
|
2018-04-16 17:54:33 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
|
2018-04-16 16:27:55 +02:00
|
|
|
}
|
|
|
|
FOREACH_OBJECT_IN_MODE_END;
|
2009-10-26 09:35:33 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
|
|
|
|
/* lasso operator gives properties, but since old code works
|
2012-03-03 16:31:46 +00:00
|
|
|
* with short array we convert */
|
2009-01-02 14:11:18 +00:00
|
|
|
static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
ViewContext vc;
|
2012-05-14 12:41:56 +00:00
|
|
|
int mcords_tot;
|
2012-10-05 15:44:11 +00:00
|
|
|
const int (*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-14 12:41:56 +00:00
|
|
|
if (mcords) {
|
2.5
Sanitized the 'tweak' event.
Original idea was to have WM event system generating it
automatically. However, I first tested it via a handler
and operator, to check what kind of configurations would
be useful. It appeared to not work nice, also because
that inserting a tweak operator in a keymap is confusing.
Now 'tweaks' are generated automatically, and can be
catched by keymaps as any event. The current definition
of tweak is:
- if Left/Middle/Rightmouse pressed
if event wasn't handled by window queue (modal handlers)
start checking mousepositions
- while mousepositions are checked
- escape on any event other than mouse
- on mouse events:
- add tweak event if mousemove > 10 pixels
- stop checking for tweak if mousebutton released
- Tweak events have a define indicating mousebutton used
EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R
- In keymap definitions you can use _S or _A to map to
action or select mouse userdef.
- Event value in keymap should be KM_ANY for all tweaks,
or use one of the eight directions:
EVT_GESTURE_E, _SE, _S, _SW, _W, _NW, _N, _NE
- And of course you can add modifier checks in keymaps for it.
- Because tweaks are a result of mouse events, the handlers get
both to evaluate. That means that RMB-select + tweak will work
correctly.
In case you don't want both to be handled, for example the
CTRL+LMB 'extrude' and CTRL+LMB-tweak 'lasso select', you will
need to set the first acting on a EVT_RELEASE, this event only
gets passed on when tweak fails.
The current system allows all options, configurable, we had in 2.48,
and many more! A diagram of what's possible is on the todo. :)
Also in this commit: lasso select editmesh failed with 'zbuffer
occluded select'. Also circle-select failed.
2009-02-02 14:13:14 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2.5
- Edit mesh: Add ctrl+click add vertex or extrude.
I've made it not move the 3d cursor in that case.
Also found out tweak events conflicted with existing
keymap definitions; on tweak failure (= no mousemove)
it now passes on the mouse event as 'mouse down' for
the remaining keymaps to check.
These then actually respond to mouse-up instead of down...
The location in the keymaps where tweaks get generated
remains important. Examples:
1 - 'select' mouse-handler, operator return pass-through
2 - tweak handler checks, and makes tweak event
3 - grabber responds to tweak event
1 - ctrl+mouse tweak handler checks, makes tweak event,
or passes event on
2 - if tweak event, it runs lasso
3 - else when passed on, ctrl+click extrude happens
In the first case, select works on mouse-down, immediate.
In the second case, extrude happens on mouse-release, even
though the keymap defined mouse-press.
This will make designing nice balanced keymaps still not
simple; especially because you can't tell operators to
pass on the key... although we can add the convention that
select-mouse operators always pass on to enable tweaks.
Still a good reason to wait with custom keymaps
when this is fully settled!
2009-01-30 18:18:41 +00:00
|
|
|
/* setup view context for argument to callbacks */
|
2018-03-08 17:30:24 +11:00
|
|
|
ED_view3d_viewcontext_init(C, &vc);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
|
|
|
|
view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-10-14 07:40:16 +00:00
|
|
|
MEM_freeN((void *)mcords);
|
2012-05-14 12:41:56 +00:00
|
|
|
|
2.5
- Edit mesh: Add ctrl+click add vertex or extrude.
I've made it not move the 3d cursor in that case.
Also found out tweak events conflicted with existing
keymap definitions; on tweak failure (= no mousemove)
it now passes on the mouse event as 'mouse down' for
the remaining keymaps to check.
These then actually respond to mouse-up instead of down...
The location in the keymaps where tweaks get generated
remains important. Examples:
1 - 'select' mouse-handler, operator return pass-through
2 - tweak handler checks, and makes tweak event
3 - grabber responds to tweak event
1 - ctrl+mouse tweak handler checks, makes tweak event,
or passes event on
2 - if tweak event, it runs lasso
3 - else when passed on, ctrl+click extrude happens
In the first case, select works on mouse-down, immediate.
In the second case, extrude happens on mouse-release, even
though the keymap defined mouse-press.
This will make designing nice balanced keymaps still not
simple; especially because you can't tell operators to
pass on the key... although we can add the convention that
select-mouse operators always pass on to enable tweaks.
Still a good reason to wait with custom keymaps
when this is fully settled!
2009-01-30 18:18:41 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
return OPERATOR_PASS_THROUGH;
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
|
|
|
|
2009-03-29 02:15:13 +00:00
|
|
|
void VIEW3D_OT_select_lasso(wmOperatorType *ot)
|
2009-01-02 14:11:18 +00:00
|
|
|
{
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Lasso Select";
|
|
|
|
ot->description = "Select items using lasso selection";
|
|
|
|
ot->idname = "VIEW3D_OT_select_lasso";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = WM_gesture_lasso_invoke;
|
|
|
|
ot->modal = WM_gesture_lasso_modal;
|
|
|
|
ot->exec = view3d_lasso_select_exec;
|
|
|
|
ot->poll = view3d_selectable_data;
|
|
|
|
ot->cancel = WM_gesture_lasso_cancel;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->flag = OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2017-10-16 16:11:04 +11:00
|
|
|
/* properties */
|
2018-08-14 10:28:41 +10:00
|
|
|
WM_operator_properties_gesture_lasso(ot);
|
|
|
|
WM_operator_properties_select_operation(ot);
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
|
|
|
|
2018-12-13 13:04:25 +11:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Cursor Picking
|
|
|
|
* \{ */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
/* The max number of menu items in an object select menu */
|
2012-01-11 03:40:20 +00:00
|
|
|
typedef struct SelMenuItemF {
|
2012-03-25 23:54:33 +00:00
|
|
|
char idname[MAX_ID_NAME - 2];
|
2012-01-11 03:40:20 +00:00
|
|
|
int icon;
|
|
|
|
} SelMenuItemF;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
#define SEL_MENU_SIZE 22
|
2012-01-11 03:40:20 +00:00
|
|
|
static SelMenuItemF object_mouse_select_menu_data[SEL_MENU_SIZE];
|
|
|
|
|
|
|
|
/* special (crappy) operator only for menu select */
|
2018-03-11 15:50:07 +11:00
|
|
|
static const EnumPropertyItem *object_select_menu_enum_itemf(
|
|
|
|
bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
|
2012-01-11 03:40:20 +00:00
|
|
|
{
|
2012-03-25 23:54:33 +00:00
|
|
|
EnumPropertyItem *item = NULL, item_tmp = {0};
|
|
|
|
int totitem = 0;
|
|
|
|
int i = 0;
|
2012-01-11 03:40:20 +00:00
|
|
|
|
2012-03-18 07:38:51 +00:00
|
|
|
/* don't need context but avoid docgen using this */
|
2012-01-11 03:40:20 +00:00
|
|
|
if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') {
|
|
|
|
return DummyRNA_NULL_items;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (; i < SEL_MENU_SIZE && object_mouse_select_menu_data[i].idname[0] != '\0'; i++) {
|
2012-03-25 23:54:33 +00:00
|
|
|
item_tmp.name = object_mouse_select_menu_data[i].idname;
|
|
|
|
item_tmp.identifier = object_mouse_select_menu_data[i].idname;
|
|
|
|
item_tmp.value = i;
|
|
|
|
item_tmp.icon = object_mouse_select_menu_data[i].icon;
|
2012-01-11 03:40:20 +00:00
|
|
|
RNA_enum_item_add(&item, &totitem, &item_tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
RNA_enum_item_end(&item, &totitem);
|
2014-01-04 18:08:43 +11:00
|
|
|
*r_free = true;
|
2012-01-11 03:40:20 +00:00
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int object_select_menu_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2013-03-22 04:40:45 +00:00
|
|
|
const int name_index = RNA_enum_get(op->ptr, "name");
|
|
|
|
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2012-03-25 23:54:33 +00:00
|
|
|
const char *name = object_mouse_select_menu_data[name_index].idname;
|
2012-01-11 03:40:20 +00:00
|
|
|
|
2012-11-11 14:07:58 +00:00
|
|
|
if (!toggle) {
|
2012-04-30 16:22:40 +00:00
|
|
|
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
|
|
|
|
{
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
if ((base->flag & BASE_SELECTED) != 0) {
|
|
|
|
ED_object_base_select(base, BA_DESELECT);
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2012-01-11 03:40:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
}
|
|
|
|
|
2012-04-30 16:22:40 +00:00
|
|
|
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
|
|
|
|
{
|
2019-01-15 23:24:20 +11:00
|
|
|
/* this is a bit dodjy, there should only be ONE object with this name,
|
|
|
|
* but library objects can mess this up */
|
2013-03-10 06:18:03 +00:00
|
|
|
if (STREQ(name, base->object->id.name + 2)) {
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
ED_object_base_activate(C, base);
|
|
|
|
ED_object_base_select(base, BA_SELECT);
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2012-01-11 03:40:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
/* weak but ensures we activate menu again before using the enum */
|
|
|
|
memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
|
|
|
|
|
|
|
|
/* undo? */
|
2013-11-26 06:39:14 +11:00
|
|
|
if (changed) {
|
2018-06-13 15:26:59 +02:00
|
|
|
Scene *scene = CTX_data_scene(C);
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
|
2018-06-13 15:26:59 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
2012-01-11 03:40:20 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_select_menu(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Select Menu";
|
2012-01-11 03:40:20 +00:00
|
|
|
ot->description = "Menu object selection";
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->idname = "VIEW3D_OT_select_menu";
|
2012-01-11 03:40:20 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = WM_menu_invoke;
|
|
|
|
ot->exec = object_select_menu_exec;
|
2012-01-11 03:40:20 +00:00
|
|
|
|
|
|
|
/* flags */
|
2012-03-25 23:54:33 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2012-01-11 03:40:20 +00:00
|
|
|
|
|
|
|
/* keyingset to use (dynamic enum) */
|
2012-03-25 23:54:33 +00:00
|
|
|
prop = RNA_def_enum(ot->srna, "name", DummyRNA_NULL_items, 0, "Object Name", "");
|
2012-01-11 03:40:20 +00:00
|
|
|
RNA_def_enum_funcs(prop, object_select_menu_enum_itemf);
|
2014-05-05 15:22:36 +10:00
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_ENUM_NO_TRANSLATE);
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->prop = prop;
|
2012-01-11 03:40:20 +00:00
|
|
|
|
2012-11-11 14:07:58 +00:00
|
|
|
RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first");
|
2012-01-11 03:40:20 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2017-03-08 23:15:12 +11:00
|
|
|
static Base *object_mouse_select_menu(
|
|
|
|
bContext *C, ViewContext *vc, unsigned int *buffer, int hits,
|
|
|
|
const int mval[2], bool toggle)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2017-03-09 05:17:55 +11:00
|
|
|
short baseCount = 0;
|
2013-03-19 23:17:44 +00:00
|
|
|
bool ok;
|
2012-03-25 23:54:33 +00:00
|
|
|
LinkNode *linklist = NULL;
|
Render Layers and Collections (merge from render-layers)
Design Documents
----------------
* https://wiki.blender.org/index.php/Dev:2.8/Source/Layers
* https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised
User Commit Log
---------------
* New Layer and Collection system to replace render layers and viewport layers.
* A layer is a set of collections of objects (and their drawing options) required for specific tasks.
* A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers.
* All Scenes have a master collection that all other collections are children of.
* New collection "context" tab (in Properties Editor)
* New temporary viewport "collections" panel to control per-collection
visibility
Missing User Features
---------------------
* Collection "Filter"
Option to add objects based on their names
* Collection Manager operators
The existing buttons are placeholders
* Collection Manager drawing
The editor main region is empty
* Collection Override
* Per-Collection engine settings
This will come as a separate commit, as part of the clay-engine branch
Dev Commit Log
--------------
* New DNA file (DNA_layer_types.h) with the new structs
We are replacing Base by a new extended Base while keeping it backward
compatible with some legacy settings (i.e., lay, flag_legacy).
Renamed all Base to BaseLegacy to make it clear the areas of code that
still need to be converted
Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp
* Unittesting for main syncronization requirements
- read, write, add/copy/remove objects, copy scene, collection
link/unlinking, context)
* New Editor: Collection Manager
Based on patch by Julian Eisel
This is extracted from the layer-manager branch. With the following changes:
- Renamed references of layer manager to collections manager
- I doesn't include the editors/space_collections/ draw and util files
- The drawing code itself will be implemented separately by Julian
* Base / Object:
A little note about them. Original Blender code would try to keep them
in sync through the code, juggling flags back and forth. This will now
be handled by Depsgraph, keeping Object and Bases more separated
throughout the non-rendering code.
Scene.base is being cleared in doversion, and the old viewport drawing
code was poorly converted to use the new bases while the new viewport
code doesn't get merged and replace the old one.
Python API Changes
------------------
```
- scene.layers
+ # no longer exists
- scene.objects
+ scene.scene_layers.active.objects
- scene.objects.active
+ scene.render_layers.active.objects.active
- bpy.context.scene.objects.link()
+ bpy.context.scene_collection.objects.link()
- bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None)
+ bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None)
- bpy.context.object.select
+ bpy.context.object.select = True
+ bpy.context.object.select = False
+ bpy.context.object.select_get()
+ bpy.context.object.select_set(action='SELECT')
+ bpy.context.object.select_set(action='DESELECT')
-AddObjectHelper.layers
+ # no longer exists
```
2017-02-07 10:18:38 +01:00
|
|
|
|
2017-06-07 17:35:23 +02:00
|
|
|
/* handle base->object->select_color */
|
2012-04-30 16:22:40 +00:00
|
|
|
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
|
|
|
|
{
|
2013-03-19 23:17:44 +00:00
|
|
|
ok = false;
|
2009-09-16 17:43:09 +00:00
|
|
|
|
|
|
|
/* two selection methods, the CTRL select uses max dist of 15 */
|
2012-02-22 16:52:06 +00:00
|
|
|
if (buffer) {
|
2016-04-26 14:33:31 +10:00
|
|
|
for (int a = 0; a < hits; a++) {
|
2009-09-16 17:43:09 +00:00
|
|
|
/* index was converted */
|
2017-06-07 17:35:23 +02:00
|
|
|
if (base->object->select_color == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
ok = true;
|
2016-04-26 14:33:31 +10:00
|
|
|
break;
|
2016-04-26 14:24:52 +10:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-09-16 17:43:09 +00:00
|
|
|
}
|
|
|
|
else {
|
2016-04-26 14:33:31 +10:00
|
|
|
const int dist = 15 * U.pixelsize;
|
|
|
|
if (ED_view3d_project_base(vc->ar, base) == V3D_PROJ_RET_OK) {
|
|
|
|
const int delta_px[2] = {base->sx - mval[0], base->sy - mval[1]};
|
|
|
|
if (len_manhattan_v2_int(delta_px) < dist) {
|
|
|
|
ok = true;
|
|
|
|
}
|
|
|
|
}
|
2009-09-16 17:43:09 +00:00
|
|
|
}
|
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ok) {
|
2009-09-16 17:43:09 +00:00
|
|
|
baseCount++;
|
|
|
|
BLI_linklist_prepend(&linklist, base);
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (baseCount == SEL_MENU_SIZE)
|
2009-09-16 17:43:09 +00:00
|
|
|
break;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-16 17:43:09 +00:00
|
|
|
CTX_DATA_END;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (baseCount == 0) {
|
2009-09-16 17:43:09 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-02-22 16:52:06 +00:00
|
|
|
if (baseCount == 1) {
|
2012-03-25 23:54:33 +00:00
|
|
|
Base *base = (Base *)linklist->link;
|
2009-09-16 17:43:09 +00:00
|
|
|
BLI_linklist_free(linklist, NULL);
|
|
|
|
return base;
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
else {
|
2012-01-11 03:40:20 +00:00
|
|
|
/* UI, full in static array values that we later use in an enum function */
|
2009-09-16 17:43:09 +00:00
|
|
|
LinkNode *node;
|
2012-01-11 03:40:20 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
memset(object_mouse_select_menu_data, 0, sizeof(object_mouse_select_menu_data));
|
2009-09-16 17:43:09 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
for (node = linklist, i = 0; node; node = node->next, i++) {
|
|
|
|
Base *base = node->link;
|
|
|
|
Object *ob = base->object;
|
2014-04-27 00:22:49 +10:00
|
|
|
const char *name = ob->id.name + 2;
|
2009-09-16 17:43:09 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
BLI_strncpy(object_mouse_select_menu_data[i].idname, name, MAX_ID_NAME - 2);
|
2014-11-09 21:20:40 +01:00
|
|
|
object_mouse_select_menu_data[i].icon = UI_icon_from_id(&ob->id);
|
2012-01-11 03:40:20 +00:00
|
|
|
}
|
2009-09-16 17:43:09 +00:00
|
|
|
|
2012-01-11 03:40:20 +00:00
|
|
|
{
|
2014-07-11 15:07:55 +10:00
|
|
|
wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_select_menu", false);
|
2012-01-11 03:40:20 +00:00
|
|
|
PointerRNA ptr;
|
2009-09-16 17:43:09 +00:00
|
|
|
|
2014-07-11 15:07:55 +10:00
|
|
|
WM_operator_properties_create_ptr(&ptr, ot);
|
2012-11-11 14:07:58 +00:00
|
|
|
RNA_boolean_set(&ptr, "toggle", toggle);
|
2014-07-11 15:07:55 +10:00
|
|
|
WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
|
2012-01-11 03:40:20 +00:00
|
|
|
WM_operator_properties_free(&ptr);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-09-16 17:43:09 +00:00
|
|
|
|
|
|
|
BLI_linklist_free(linklist, NULL);
|
|
|
|
return NULL;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-28 11:46:02 +11:00
|
|
|
static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
|
2012-12-28 13:48:30 +00:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < hits; i++) {
|
|
|
|
if (buffer[(4 * i) + 3] & 0xFFFF0000) {
|
2013-03-19 23:17:44 +00:00
|
|
|
return true;
|
2012-12-28 13:48:30 +00:00
|
|
|
}
|
|
|
|
}
|
2013-03-19 23:17:44 +00:00
|
|
|
return false;
|
2012-12-28 13:48:30 +00:00
|
|
|
}
|
|
|
|
|
2013-06-17 06:17:19 +00:00
|
|
|
/* utility function for mixed_bones_object_selectbuffer */
|
2017-03-08 23:15:12 +11:00
|
|
|
static int selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const int hits15)
|
2013-06-17 06:17:19 +00:00
|
|
|
{
|
|
|
|
return hits15;
|
|
|
|
}
|
|
|
|
|
2017-03-08 23:15:12 +11:00
|
|
|
static int selectbuffer_ret_hits_9(unsigned int *buffer, const int hits15, const int hits9)
|
2013-06-17 06:17:19 +00:00
|
|
|
{
|
|
|
|
const int offs = 4 * hits15;
|
2014-10-21 19:02:05 +02:00
|
|
|
memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(unsigned int));
|
2013-06-17 06:17:19 +00:00
|
|
|
return hits9;
|
|
|
|
}
|
|
|
|
|
2017-03-08 23:15:12 +11:00
|
|
|
static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const int hits9, const int hits5)
|
2013-06-17 06:17:19 +00:00
|
|
|
{
|
|
|
|
const int offs = 4 * hits15 + 4 * hits9;
|
2014-10-21 19:02:05 +02:00
|
|
|
memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
|
2013-06-17 06:17:19 +00:00
|
|
|
return hits5;
|
|
|
|
}
|
|
|
|
|
2018-12-07 20:49:11 +11:00
|
|
|
/**
|
|
|
|
* Populate a select buffer with objects and bones, if there are any.
|
|
|
|
* Checks three selection levels and compare.
|
|
|
|
*/
|
2017-03-08 23:15:12 +11:00
|
|
|
static int mixed_bones_object_selectbuffer(
|
2018-12-07 20:49:11 +11:00
|
|
|
ViewContext *vc, unsigned int *buffer, const int mval[2], eV3DSelectObjectFilter select_filter,
|
|
|
|
bool do_nearest)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
rcti rect;
|
2017-03-08 23:15:12 +11:00
|
|
|
int hits15, hits9 = 0, hits5 = 0;
|
2013-03-19 23:17:44 +00:00
|
|
|
bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
|
2014-07-23 15:24:07 +02:00
|
|
|
|
2017-03-09 05:17:55 +11:00
|
|
|
const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
|
|
|
|
int hits = 0;
|
|
|
|
|
|
|
|
/* we _must_ end cache before return, use 'goto finally' */
|
2017-03-09 20:47:37 +11:00
|
|
|
view3d_opengl_select_cache_begin();
|
2017-03-09 05:17:55 +11:00
|
|
|
|
2017-03-08 23:10:31 +11:00
|
|
|
BLI_rcti_init_pt_radius(&rect, mval, 14);
|
2018-06-19 16:41:18 +02:00
|
|
|
hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
|
2013-06-17 06:17:19 +00:00
|
|
|
if (hits15 == 1) {
|
2017-03-09 05:17:55 +11:00
|
|
|
hits = selectbuffer_ret_hits_15(buffer, hits15);
|
|
|
|
goto finally;
|
2013-06-17 06:17:19 +00:00
|
|
|
}
|
|
|
|
else if (hits15 > 0) {
|
2017-03-09 09:22:56 +11:00
|
|
|
int offs;
|
2012-12-28 13:48:30 +00:00
|
|
|
has_bones15 = selectbuffer_has_bones(buffer, hits15);
|
2012-03-25 23:54:33 +00:00
|
|
|
|
|
|
|
offs = 4 * hits15;
|
2017-03-08 23:10:31 +11:00
|
|
|
BLI_rcti_init_pt_radius(&rect, mval, 9);
|
2018-06-19 16:41:18 +02:00
|
|
|
hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
|
2013-06-17 06:17:19 +00:00
|
|
|
if (hits9 == 1) {
|
2017-03-09 05:17:55 +11:00
|
|
|
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
|
|
|
|
goto finally;
|
2013-06-17 06:17:19 +00:00
|
|
|
}
|
|
|
|
else if (hits9 > 0) {
|
2012-12-28 13:48:30 +00:00
|
|
|
has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
|
2012-03-25 23:54:33 +00:00
|
|
|
|
|
|
|
offs += 4 * hits9;
|
2017-03-08 23:10:31 +11:00
|
|
|
BLI_rcti_init_pt_radius(&rect, mval, 5);
|
2018-06-19 16:41:18 +02:00
|
|
|
hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
|
2013-06-17 06:17:19 +00:00
|
|
|
if (hits5 == 1) {
|
2017-03-09 05:17:55 +11:00
|
|
|
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
|
|
|
|
goto finally;
|
2013-06-17 06:17:19 +00:00
|
|
|
}
|
|
|
|
else if (hits5 > 0) {
|
2012-12-28 13:48:30 +00:00
|
|
|
has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-17 06:17:19 +00:00
|
|
|
|
2017-03-09 05:17:55 +11:00
|
|
|
if (has_bones5) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; }
|
|
|
|
else if (has_bones9) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; }
|
|
|
|
else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
|
|
|
|
|
|
|
|
if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; }
|
|
|
|
else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; }
|
|
|
|
else { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2017-03-09 05:17:55 +11:00
|
|
|
|
|
|
|
finally:
|
2017-03-09 20:47:37 +11:00
|
|
|
view3d_opengl_select_cache_end();
|
2018-12-07 20:49:11 +11:00
|
|
|
return hits;
|
|
|
|
}
|
2017-03-09 05:17:55 +11:00
|
|
|
|
2018-12-07 20:49:11 +11:00
|
|
|
static int mixed_bones_object_selectbuffer_extended(
|
|
|
|
ViewContext *vc, unsigned int *buffer, const int mval[2], eV3DSelectObjectFilter select_filter,
|
|
|
|
bool use_cycle, bool enumerate, bool *r_do_nearest)
|
|
|
|
{
|
|
|
|
static int last_mval[2] = {-100, -100};
|
|
|
|
bool do_nearest = false;
|
|
|
|
View3D *v3d = vc->v3d;
|
|
|
|
|
|
|
|
/* define if we use solid nearest select or not */
|
|
|
|
if (use_cycle) {
|
|
|
|
if (v3d->shading.type > OB_WIRE) {
|
|
|
|
do_nearest = true;
|
|
|
|
if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
|
|
|
|
do_nearest = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
copy_v2_v2_int(last_mval, mval);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (v3d->shading.type > OB_WIRE) {
|
|
|
|
do_nearest = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r_do_nearest) {
|
|
|
|
*r_do_nearest = do_nearest;
|
|
|
|
}
|
|
|
|
|
|
|
|
do_nearest = do_nearest && !enumerate;
|
|
|
|
|
|
|
|
int hits = mixed_bones_object_selectbuffer(vc, buffer, mval, select_filter, do_nearest);
|
|
|
|
|
|
|
|
if (vc->scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
|
2018-11-23 10:00:28 +11:00
|
|
|
const bool is_pose_mode = (
|
|
|
|
(vc->obact && vc->obact->mode & OB_MODE_POSE) ||
|
|
|
|
(select_filter == VIEW3D_SELECT_FILTER_WPAINT_POSE_MODE_LOCK));
|
2018-05-29 15:16:07 +02:00
|
|
|
struct {
|
|
|
|
uint data[4];
|
|
|
|
} *buffer4 = (void *)buffer;
|
|
|
|
uint j = 0;
|
|
|
|
for (uint i = 0; i < hits; i++) {
|
|
|
|
if (((buffer4[i].data[3] & 0xFFFF0000) != 0) == is_pose_mode) {
|
|
|
|
if (i != j) {
|
2018-06-04 12:38:24 +02:00
|
|
|
buffer4[j] = buffer4[i];
|
2018-05-29 15:16:07 +02:00
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hits = j;
|
|
|
|
}
|
|
|
|
|
2017-03-09 05:17:55 +11:00
|
|
|
return hits;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
/* returns basact */
|
2018-02-28 11:46:02 +11:00
|
|
|
static Base *mouse_select_eval_buffer(
|
|
|
|
ViewContext *vc, const uint *buffer, int hits,
|
|
|
|
Base *startbase, bool has_bones, bool do_nearest)
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
{
|
2017-11-23 13:51:49 -02:00
|
|
|
ViewLayer *view_layer = vc->view_layer;
|
2018-11-23 14:41:38 -02:00
|
|
|
View3D *v3d = vc->v3d;
|
2017-02-08 12:26:41 +01:00
|
|
|
Base *base, *basact = NULL;
|
2013-03-19 23:17:44 +00:00
|
|
|
int a;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-05-19 13:28:19 +00:00
|
|
|
if (do_nearest) {
|
2012-03-25 23:54:33 +00:00
|
|
|
unsigned int min = 0xFFFFFFFF;
|
|
|
|
int selcol = 0, notcol = 0;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (has_bones) {
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
/* we skip non-bone hits */
|
2012-03-25 23:54:33 +00:00
|
|
|
for (a = 0; a < hits; a++) {
|
|
|
|
if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000) ) {
|
|
|
|
min = buffer[4 * a + 1];
|
|
|
|
selcol = buffer[4 * a + 3] & 0xFFFF;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* only exclude active object when it is selected... */
|
2017-11-23 13:51:49 -02:00
|
|
|
if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
|
|
|
|
notcol = BASACT(view_layer)->object->select_color;
|
2017-06-07 17:35:23 +02:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
for (a = 0; a < hits; a++) {
|
|
|
|
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
|
|
|
|
min = buffer[4 * a + 1];
|
|
|
|
selcol = buffer[4 * a + 3] & 0xFFFF;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2017-11-23 13:51:49 -02:00
|
|
|
base = FIRSTBASE(view_layer);
|
2012-02-22 16:52:06 +00:00
|
|
|
while (base) {
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_SELECTABLE(v3d, base)) {
|
2017-06-07 17:35:23 +02:00
|
|
|
if (base->object->select_color == selcol) break;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
base = base->next;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
if (base) basact = base;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
base = startbase;
|
2012-02-22 16:52:06 +00:00
|
|
|
while (base) {
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
/* skip objects with select restriction, to prevent prematurely ending this loop
|
2012-03-03 16:31:46 +00:00
|
|
|
* with an un-selectable choice */
|
2018-06-25 13:50:11 +02:00
|
|
|
if ((base->flag & BASE_SELECTABLE) == 0) {
|
2012-03-25 23:54:33 +00:00
|
|
|
base = base->next;
|
2017-11-23 13:51:49 -02:00
|
|
|
if (base == NULL) base = FIRSTBASE(view_layer);
|
2012-03-25 23:54:33 +00:00
|
|
|
if (base == startbase) break;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_SELECTABLE(v3d, base)) {
|
2012-03-25 23:54:33 +00:00
|
|
|
for (a = 0; a < hits; a++) {
|
2012-02-22 16:52:06 +00:00
|
|
|
if (has_bones) {
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
/* skip non-bone objects */
|
2012-03-25 23:54:33 +00:00
|
|
|
if ((buffer[4 * a + 3] & 0xFFFF0000)) {
|
2017-06-07 17:35:23 +02:00
|
|
|
if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
|
2012-03-25 23:54:33 +00:00
|
|
|
basact = base;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-06-07 17:35:23 +02:00
|
|
|
if (base->object->select_color == (buffer[(4 * a) + 3] & 0xFFFF))
|
2012-03-25 23:54:33 +00:00
|
|
|
basact = base;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (basact) break;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
base = base->next;
|
2017-11-23 13:51:49 -02:00
|
|
|
if (base == NULL) base = FIRSTBASE(view_layer);
|
2012-03-25 23:54:33 +00:00
|
|
|
if (base == startbase) break;
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
return basact;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* mval comes from event->mval, only use within region handlers */
|
2017-02-08 12:26:41 +01:00
|
|
|
Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
{
|
|
|
|
ViewContext vc;
|
2017-02-08 12:26:41 +01:00
|
|
|
Base *basact = NULL;
|
2015-02-24 17:19:07 +01:00
|
|
|
unsigned int buffer[MAXPICKBUF];
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
/* setup view context for argument to callbacks */
|
|
|
|
view3d_operator_needs_opengl(C);
|
2017-08-16 12:45:11 +10:00
|
|
|
|
2018-03-08 17:30:24 +11:00
|
|
|
ED_view3d_viewcontext_init(C, &vc);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-12-07 20:49:11 +11:00
|
|
|
const bool do_nearest = (vc.v3d->shading.type > OB_WIRE);
|
|
|
|
const int hits = mixed_bones_object_selectbuffer(
|
|
|
|
&vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (hits > 0) {
|
2013-03-19 23:17:44 +00:00
|
|
|
const bool has_bones = selectbuffer_has_bones(buffer, hits);
|
2017-11-22 10:52:39 -02:00
|
|
|
basact = mouse_select_eval_buffer(&vc, buffer, hits, vc.view_layer->object_bases.first, has_bones, do_nearest);
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
Drag and drop 2.5 integration! Finally, slashdot regulars can use
Blender too now! :)
** Drag works as follows:
- drag-able items are defined by the standard interface ui toolkit
- each button can get this feature, via uiButSetDragXXX(but, ...).
There are calls to define drag-able images, ID blocks, RNA paths,
file paths, and so on. By default you drag an icon, exceptionally
an ImBuf
- Drag items are registered centrally in the WM, it allows more drag
items simultaneous too, but not implemented
** Drop works as follows:
- On mouse release, and if drag items exist in the WM, it converts
the mouse event to an EVT_DROP type. This event then gets the full
drag info as customdata
- drop regions are defined with WM_dropbox_add(), similar to keymaps
you can make a "drop map" this way, which become 'drop map handlers'
in the queues.
- next to that the UI kit handles some common button types (like
accepting ID or names) to be catching a drop event too.
- Every "drop box" has two callbacks:
- poll() = check if the event drag data is relevant for this box
- copy() = fill in custom properties in the dropbox to initialize
an operator
- The dropbox handler then calls its standard Operator with its
dropbox properties.
** Currently implemented
Drag items:
- ID icons in browse buttons
- ID icons in context menu of properties region
- ID icons in outliner and rna viewer
- FileBrowser icons
- FileBrowser preview images
Drag-able icons are subtly visualized by making them brighter a bit
on mouse-over. In case the icon is a button or UI element too (most
cases), the drag-able feature will make the item react to
mouse-release instead of mouse-press.
Drop options:
- UI buttons: ID and text buttons (paste name)
- View3d: Object ID drop copies object
- View3d: Material ID drop assigns to object under cursor
- View3d: Image ID drop assigns to object UV texture under cursor
- Sequencer: Path drop will add either Image or Movie strip
- Image window: Path drop will open image
** Drag and drop Notes:
- Dropping into another Blender window (from same application) works
too. I've added code that passes on mousemoves and clicks to other
windows, without activating them though. This does make using multi-window
Blender a bit friendler.
- Dropping a file path to an image, is not the same as dropping an
Image ID... keep this in mind. Sequencer for example wants paths to
be dropped, textures in 3d window wants an Image ID.
- Although drop boxes could be defined via Python, I suggest they're
part of the UI and editor design (= how we want an editor to work), and
not default offered configurable like keymaps.
- At the moment only one item can be dragged at a time. This is for
several reasons.... For one, Blender doesn't have a well defined
uniform way to define "what is selected" (files, outliner items, etc).
Secondly there's potential conflicts on what todo when you drop mixed
drag sets on spots. All undefined stuff... nice for later.
- Example to bypass the above: a collection of images that form a strip,
should be represented in filewindow as a single sequence anyway.
This then will fit well and gets handled neatly by design.
- Another option to check is to allow multiple options per drop... it
could show the operator as a sort of menu, allowing arrow or scrollwheel
to choose. For time being I'd prefer to try to design a singular drop
though, just offer only one drop action per data type on given spots.
- What does work already, but a tad slow, is to use a function that
detects an object (type) under cursor, so a drag item's option can be
further refined (like drop object on object = parent). (disabled)
** More notes
- Added saving for Region layouts (like split points for toolbar)
- Label buttons now handle mouse over
- File list: added full path entry for drop feature.
- Filesel bugfix: wm_operator_exec() got called there and fully handled,
while WM event code tried same. Added new OPERATOR_HANDLED flag for this.
Maybe python needs it too?
- Cocoa: added window move event, so multi-win setups work OK (didnt save).
- Interface_handlers.c: removed win->active
- Severe area copy bug: area handlers were not set to NULL
- Filesel bugfix: next/prev folder list was not copied on area copies
** Leftover todos
- Cocoa windows seem to hang on cases still... needs check
- Cocoa 'draw overlap' swap doesn't work
- Cocoa window loses focus permanently on using Spotlight
(for these reasons, makefile building has Carbon as default atm)
- ListView templates in UI cannot become dragged yet, needs review...
it consists of two overlapping UI elements, preventing handling icon clicks.
- There's already Ghost library code to handle dropping from OS
into Blender window. I've noticed this code is unfinished for Macs, but
seems to be complete for Windows. Needs test... currently, an external
drop event will print in console when succesfully delivered to Blender's WM.
2010-01-26 18:18:21 +00:00
|
|
|
return basact;
|
|
|
|
}
|
2008-12-31 17:50:00 +00:00
|
|
|
|
2018-10-09 14:36:15 +02:00
|
|
|
Object *ED_view3d_give_object_under_cursor(bContext *C, const int mval[2])
|
|
|
|
{
|
|
|
|
Base *base = ED_view3d_give_base_under_cursor(C, mval);
|
|
|
|
if (base) return base->object;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-10-17 09:53:05 +02:00
|
|
|
bool ED_view3d_is_object_under_cursor(bContext *C, const int mval[2])
|
2018-10-16 11:17:32 +02:00
|
|
|
{
|
|
|
|
return ED_view3d_give_object_under_cursor(C, mval) != NULL;
|
|
|
|
}
|
|
|
|
|
2011-12-15 16:10:49 +00:00
|
|
|
static void deselect_all_tracks(MovieTracking *tracking)
|
|
|
|
{
|
|
|
|
MovieTrackingObject *object;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
object = tracking->objects.first;
|
2012-02-22 16:52:06 +00:00
|
|
|
while (object) {
|
2012-06-15 11:03:23 +00:00
|
|
|
ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
|
2012-03-25 23:54:33 +00:00
|
|
|
MovieTrackingTrack *track = tracksbase->first;
|
2011-12-15 16:10:49 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
while (track) {
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
|
2011-12-15 16:10:49 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
track = track->next;
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
object = object->next;
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* mval is region coords */
|
2015-11-18 12:20:28 +11:00
|
|
|
static bool ed_object_select_pick(
|
|
|
|
bContext *C, const int mval[2],
|
|
|
|
bool extend, bool deselect, bool toggle, bool obcenter, bool enumerate, bool object)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
ViewContext vc;
|
2012-03-25 23:54:33 +00:00
|
|
|
ARegion *ar = CTX_wm_region(C);
|
|
|
|
Scene *scene = CTX_data_scene(C);
|
2017-11-23 13:51:49 -02:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
2018-11-23 14:41:38 -02:00
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
2019-01-24 22:56:55 +11:00
|
|
|
const Base *oldbasact = BASACT(view_layer);
|
|
|
|
Base *base, *startbase = NULL, *basact = NULL;
|
2018-05-30 15:24:45 +02:00
|
|
|
const eObjectMode object_mode = oldbasact ? oldbasact->object->mode : OB_MODE_OBJECT;
|
2013-10-15 02:23:28 +00:00
|
|
|
bool is_obedit;
|
2014-03-11 15:34:19 +11:00
|
|
|
float dist = ED_view3d_select_dist_px() * 1.3333f;
|
2014-04-11 11:25:41 +10:00
|
|
|
bool retval = false;
|
2017-03-08 23:15:12 +11:00
|
|
|
int hits;
|
2012-10-10 01:54:02 +00:00
|
|
|
const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
/* setup view context for argument to callbacks */
|
2018-03-08 17:30:24 +11:00
|
|
|
ED_view3d_viewcontext_init(C, &vc);
|
2013-10-15 02:23:28 +00:00
|
|
|
|
|
|
|
is_obedit = (vc.obedit != NULL);
|
|
|
|
if (object) {
|
|
|
|
/* signal for view3d_opengl_select to skip editmode objects */
|
|
|
|
vc.obedit = NULL;
|
|
|
|
}
|
2018-04-16 16:27:55 +02:00
|
|
|
|
|
|
|
/* In pose mode we don't want to mess with object selection. */
|
|
|
|
const bool is_pose_mode = (vc.obact && vc.obact->mode & OB_MODE_POSE);
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* always start list from basact in wire mode */
|
2017-11-23 13:51:49 -02:00
|
|
|
startbase = FIRSTBASE(view_layer);
|
2019-01-24 22:59:55 +11:00
|
|
|
if (oldbasact && oldbasact->next) {
|
|
|
|
startbase = oldbasact->next;
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* This block uses the control key to make the object selected
|
|
|
|
* by its center point rather than its contents */
|
|
|
|
|
2011-08-23 09:05:12 +00:00
|
|
|
/* in editmode do not activate */
|
2012-02-22 16:52:06 +00:00
|
|
|
if (obcenter) {
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* note; shift+alt goes to group-flush-selecting */
|
2012-02-22 16:52:06 +00:00
|
|
|
if (enumerate) {
|
2012-11-11 14:07:58 +00:00
|
|
|
basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:54:33 +00:00
|
|
|
base = startbase;
|
2012-02-22 16:52:06 +00:00
|
|
|
while (base) {
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_SELECTABLE(v3d, base)) {
|
2012-10-10 01:54:02 +00:00
|
|
|
float screen_co[2];
|
2018-03-11 15:50:07 +11:00
|
|
|
if (ED_view3d_project_float_global(
|
|
|
|
ar, base->object->obmat[3], screen_co,
|
|
|
|
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
|
2012-10-10 01:54:02 +00:00
|
|
|
{
|
|
|
|
float dist_temp = len_manhattan_v2v2(mval_fl, screen_co);
|
2019-01-24 22:59:55 +11:00
|
|
|
if (base == oldbasact) {
|
|
|
|
dist_temp += 10.0f;
|
|
|
|
}
|
2012-10-10 01:54:02 +00:00
|
|
|
if (dist_temp < dist) {
|
|
|
|
dist = dist_temp;
|
|
|
|
basact = base;
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
base = base->next;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2019-01-24 22:59:55 +11:00
|
|
|
if (base == NULL) {
|
|
|
|
base = FIRSTBASE(view_layer);
|
|
|
|
}
|
|
|
|
if (base == startbase) {
|
|
|
|
break;
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-18 20:40:41 +02:00
|
|
|
if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
|
|
|
|
if (is_obedit == false) {
|
|
|
|
if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
|
|
|
|
if (object_mode == OB_MODE_OBJECT) {
|
|
|
|
struct Main *bmain = CTX_data_main(C);
|
|
|
|
ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
|
|
|
|
}
|
|
|
|
if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
|
|
|
|
basact = NULL;
|
|
|
|
}
|
2018-05-30 15:24:45 +02:00
|
|
|
}
|
2018-05-29 15:43:53 +02:00
|
|
|
}
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-02-24 17:19:07 +01:00
|
|
|
unsigned int buffer[MAXPICKBUF];
|
2014-07-23 15:24:07 +02:00
|
|
|
bool do_nearest;
|
2009-09-16 17:43:09 +00:00
|
|
|
|
2017-03-09 05:17:55 +11:00
|
|
|
// TIMEIT_START(select_time);
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* if objects have posemode set, the bones are in the same selection buffer */
|
2018-11-26 15:28:59 +11:00
|
|
|
const eV3DSelectObjectFilter select_filter = (
|
|
|
|
(object == false) ? ED_view3d_select_filter_from_mode(scene, vc.obact) : VIEW3D_SELECT_FILTER_NOP);
|
2018-12-07 20:49:11 +11:00
|
|
|
hits = mixed_bones_object_selectbuffer_extended(
|
|
|
|
&vc, buffer, mval, select_filter,
|
|
|
|
true, enumerate,
|
2018-06-19 16:41:18 +02:00
|
|
|
&do_nearest);
|
2017-03-09 05:17:55 +11:00
|
|
|
|
|
|
|
// TIMEIT_END(select_time);
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
if (hits > 0) {
|
2011-11-07 12:55:18 +00:00
|
|
|
/* note: bundles are handling in the same way as bones */
|
2013-03-19 23:17:44 +00:00
|
|
|
const bool has_bones = selectbuffer_has_bones(buffer, hits);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
/* note; shift+alt goes to group-flush-selecting */
|
2016-04-26 14:24:52 +10:00
|
|
|
if (enumerate) {
|
2012-11-11 14:07:58 +00:00
|
|
|
basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-07-23 15:24:07 +02:00
|
|
|
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, has_bones, do_nearest);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2018-05-29 15:16:07 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (has_bones && basact) {
|
2012-03-25 23:54:33 +00:00
|
|
|
if (basact->object->type == OB_CAMERA) {
|
2019-01-24 22:56:55 +11:00
|
|
|
if (oldbasact == basact) {
|
2011-11-07 12:55:18 +00:00
|
|
|
int i, hitresult;
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
for (i = 0; i < hits; i++) {
|
|
|
|
hitresult = buffer[3 + (i * 4)];
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* if there's bundles in buffer select bundles first,
|
2012-03-03 16:31:46 +00:00
|
|
|
* so non-camera elements should be ignored in buffer */
|
2017-06-07 17:35:23 +02:00
|
|
|
if (basact->object->select_color != (hitresult & 0xFFFF)) {
|
2011-11-07 12:55:18 +00:00
|
|
|
continue;
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
/* index of bundle is 1<<16-based. if there's no "bone" index
|
2019-01-15 23:24:20 +11:00
|
|
|
* in height word, this buffer value belongs to camera. not to bundle
|
|
|
|
*/
|
2012-03-25 23:54:33 +00:00
|
|
|
if (buffer[4 * i + 3] & 0xFFFF0000) {
|
2013-09-09 11:37:37 +00:00
|
|
|
MovieClip *clip = BKE_object_movieclip_get(scene, basact->object, false);
|
2012-03-25 23:54:33 +00:00
|
|
|
MovieTracking *tracking = &clip->tracking;
|
2011-12-15 16:10:49 +00:00
|
|
|
ListBase *tracksbase;
|
|
|
|
MovieTrackingTrack *track;
|
2011-12-05 18:57:17 +00:00
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
track = BKE_tracking_track_get_indexed(&clip->tracking, hitresult >> 16, &tracksbase);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (TRACK_SELECTED(track) && extend) {
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = false;
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_track_deselect(track, TRACK_AREA_ALL);
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:54:33 +00:00
|
|
|
int oldsel = TRACK_SELECTED(track) ? 1 : 0;
|
2019-01-24 22:59:55 +11:00
|
|
|
if (!extend) {
|
2011-12-15 16:10:49 +00:00
|
|
|
deselect_all_tracks(tracking);
|
2019-01-24 22:59:55 +11:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2012-06-15 11:03:23 +00:00
|
|
|
BKE_tracking_track_select(tracksbase, track, TRACK_AREA_ALL, extend);
|
2011-12-15 16:10:49 +00:00
|
|
|
|
2019-01-24 22:59:55 +11:00
|
|
|
if (oldsel != (TRACK_SELECTED(track) ? 1 : 0)) {
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2019-01-24 22:59:55 +11:00
|
|
|
}
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2017-02-07 19:11:17 +01:00
|
|
|
basact->flag |= BASE_SELECTED;
|
2017-02-08 12:26:41 +01:00
|
|
|
BKE_scene_object_base_flag_sync_from_base(basact);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2013-03-19 23:17:44 +00:00
|
|
|
retval = true;
|
2011-11-07 12:55:18 +00:00
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
|
|
|
|
DEG_id_tag_update(&clip->id, ID_RECALC_SELECT);
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_MOVIECLIP | ND_SELECT, track);
|
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
2011-11-07 12:55:18 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-12-15 16:10:49 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (!changed) {
|
2011-12-15 16:10:49 +00:00
|
|
|
/* fallback to regular object selection if no new bundles were selected,
|
2012-03-03 16:31:46 +00:00
|
|
|
* allows to select object parented to reconstruction object */
|
2014-07-23 15:24:07 +02:00
|
|
|
basact = mouse_select_eval_buffer(&vc, buffer, hits, startbase, 0, do_nearest);
|
2011-12-15 16:10:49 +00:00
|
|
|
}
|
2011-11-07 12:55:18 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-16 16:27:55 +02:00
|
|
|
else if (ED_armature_pose_select_pick_with_buffer(
|
2018-11-25 09:50:34 -02:00
|
|
|
view_layer, v3d, basact, buffer, hits, extend, deselect, toggle, do_nearest))
|
2018-04-16 16:27:55 +02:00
|
|
|
{
|
2012-10-07 14:00:18 +00:00
|
|
|
/* then bone is found */
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
/* we make the armature selected:
|
2012-03-03 16:31:46 +00:00
|
|
|
* not-selected active object in posemode won't work well for tools */
|
2017-02-07 19:11:17 +01:00
|
|
|
basact->flag |= BASE_SELECTED;
|
2017-11-09 13:11:20 -02:00
|
|
|
BKE_scene_object_base_flag_sync_from_base(basact);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2013-03-19 23:17:44 +00:00
|
|
|
retval = true;
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, basact->object);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2019-01-15 23:24:20 +11:00
|
|
|
/* in weightpaint, we use selected bone to select vertexgroup,
|
|
|
|
* so no switch to new active object */
|
2019-01-24 22:56:55 +11:00
|
|
|
if (oldbasact && (oldbasact->object->mode & OB_MODE_WEIGHT_PAINT)) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* prevent activating */
|
2012-03-25 23:54:33 +00:00
|
|
|
basact = NULL;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2008-12-29 12:15:42 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
/* prevent bone selecting to pass on to object selecting */
|
2019-01-24 22:59:55 +11:00
|
|
|
if (basact == oldbasact) {
|
2012-03-25 23:54:33 +00:00
|
|
|
basact = NULL;
|
2019-01-24 22:59:55 +11:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2018-11-23 10:00:28 +11:00
|
|
|
|
|
|
|
if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
|
|
|
|
if (is_obedit == false) {
|
|
|
|
if (basact && !BKE_object_is_mode_compat(basact->object, object_mode)) {
|
|
|
|
if (object_mode == OB_MODE_OBJECT) {
|
|
|
|
struct Main *bmain = CTX_data_main(C);
|
|
|
|
ED_object_mode_generic_exit(bmain, vc.depsgraph, scene, basact->object);
|
|
|
|
}
|
|
|
|
if (!BKE_object_is_mode_compat(basact->object, object_mode)) {
|
|
|
|
basact = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-29 15:16:07 +02:00
|
|
|
|
2018-06-18 20:40:41 +02:00
|
|
|
if (scene->toolsettings->object_flag & SCE_OBJECT_MODE_LOCK) {
|
|
|
|
/* Disallow switching modes,
|
|
|
|
* special exception for edit-mode - vertex-parent operator. */
|
|
|
|
if (is_obedit == false) {
|
|
|
|
if (oldbasact && basact) {
|
|
|
|
if ((oldbasact->object->mode != basact->object->mode) &&
|
|
|
|
(oldbasact->object->mode & basact->object->mode) == 0)
|
|
|
|
{
|
|
|
|
basact = NULL;
|
|
|
|
}
|
2018-05-29 15:16:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-24 22:56:55 +11:00
|
|
|
/* Ensure code above doesn't change the active base. */
|
|
|
|
BLI_assert(oldbasact == BASACT(view_layer));
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* so, do we have something selected? */
|
2012-02-22 16:52:06 +00:00
|
|
|
if (basact) {
|
2013-03-19 23:17:44 +00:00
|
|
|
retval = true;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (vc.obedit) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* only do select */
|
2018-12-13 13:04:25 +11:00
|
|
|
object_deselect_all_except(view_layer, basact);
|
2017-02-07 19:11:17 +01:00
|
|
|
ED_object_base_select(basact, BA_SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
/* also prevent making it active on mouse selection */
|
2018-11-23 14:41:38 -02:00
|
|
|
else if (BASE_SELECTABLE(v3d, basact)) {
|
2012-05-24 21:05:27 +00:00
|
|
|
if (extend) {
|
2017-02-07 19:11:17 +01:00
|
|
|
ED_object_base_select(basact, BA_SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2012-05-25 09:51:53 +00:00
|
|
|
else if (deselect) {
|
2017-02-07 19:11:17 +01:00
|
|
|
ED_object_base_select(basact, BA_DESELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2012-05-25 09:51:53 +00:00
|
|
|
else if (toggle) {
|
2017-02-07 19:11:17 +01:00
|
|
|
if (basact->flag & BASE_SELECTED) {
|
2012-05-25 09:51:53 +00:00
|
|
|
if (basact == oldbasact) {
|
2017-02-07 19:11:17 +01:00
|
|
|
ED_object_base_select(basact, BA_DESELECT);
|
2012-05-25 09:51:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2017-02-07 19:11:17 +01:00
|
|
|
ED_object_base_select(basact, BA_SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2012-05-24 21:05:27 +00:00
|
|
|
else {
|
2018-04-16 16:27:55 +02:00
|
|
|
/* When enabled, this puts other objects out of multi pose-mode. */
|
|
|
|
if (is_pose_mode == false) {
|
2018-12-13 13:04:25 +11:00
|
|
|
object_deselect_all_except(view_layer, basact);
|
2018-04-16 16:27:55 +02:00
|
|
|
ED_object_base_select(basact, BA_SELECT);
|
|
|
|
}
|
2012-05-24 21:05:27 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2013-10-15 02:23:28 +00:00
|
|
|
if ((oldbasact != basact) && (is_obedit == false)) {
|
2017-02-07 19:11:17 +01:00
|
|
|
ED_object_base_activate(C, basact); /* adds notifier */
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2018-07-31 10:22:19 +02:00
|
|
|
|
|
|
|
/* Set special modes for grease pencil
|
|
|
|
The grease pencil modes are not real modes, but a hack to make the interface
|
|
|
|
consistent, so need some tricks to keep UI synchronized */
|
2018-09-27 15:49:59 +02:00
|
|
|
// XXX: This stuff needs reviewing (Aligorith)
|
2018-07-31 20:11:55 +10:00
|
|
|
if (false &&
|
|
|
|
(((oldbasact) && oldbasact->object->type == OB_GPENCIL) ||
|
|
|
|
(basact->object->type == OB_GPENCIL)))
|
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
/* set cursor */
|
2018-07-31 20:11:55 +10:00
|
|
|
if (ELEM(basact->object->mode,
|
2018-12-14 16:45:57 +01:00
|
|
|
OB_MODE_PAINT_GPENCIL,
|
|
|
|
OB_MODE_SCULPT_GPENCIL,
|
|
|
|
OB_MODE_WEIGHT_GPENCIL))
|
2018-07-31 20:11:55 +10:00
|
|
|
{
|
2018-07-31 10:22:19 +02:00
|
|
|
ED_gpencil_toggle_brush_cursor(C, true, NULL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* TODO: maybe is better use restore */
|
|
|
|
ED_gpencil_toggle_brush_cursor(C, false, NULL);
|
|
|
|
}
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2011-08-16 22:44:12 +00:00
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-11-24 04:59:52 +00:00
|
|
|
|
|
|
|
return retval;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-12-13 13:04:25 +11:00
|
|
|
/* mouse selection in weight paint */
|
|
|
|
/* gets called via generic mouse select operator */
|
|
|
|
static bool ed_wpaint_vertex_select_pick(
|
|
|
|
bContext *C, const int mval[2],
|
|
|
|
bool extend, bool deselect, bool toggle, Object *obact)
|
|
|
|
{
|
|
|
|
View3D *v3d = CTX_wm_view3d(C);
|
|
|
|
const bool use_zbuf = V3D_IS_ZBUF(v3d);
|
|
|
|
|
|
|
|
Mesh *me = obact->data; /* already checked for NULL */
|
|
|
|
unsigned int index = 0;
|
|
|
|
MVert *mv;
|
|
|
|
|
|
|
|
if (ED_mesh_pick_vert(C, obact, mval, &index, ED_MESH_PICK_DEFAULT_VERT_SIZE, use_zbuf)) {
|
|
|
|
mv = &me->mvert[index];
|
|
|
|
if (extend) {
|
|
|
|
mv->flag |= SELECT;
|
|
|
|
}
|
|
|
|
else if (deselect) {
|
|
|
|
mv->flag &= ~SELECT;
|
|
|
|
}
|
|
|
|
else if (toggle) {
|
|
|
|
mv->flag ^= SELECT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
|
|
|
|
mv->flag |= SELECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* update mselect */
|
|
|
|
if (mv->flag & SELECT) {
|
|
|
|
BKE_mesh_mselect_active_set(me, index, ME_VSEL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BKE_mesh_mselect_validate(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
paintvert_flush_flags(obact);
|
|
|
|
paintvert_tag_select_update(C, obact);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int view3d_select_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
Object *obedit = CTX_data_edit_object(C);
|
|
|
|
Object *obact = CTX_data_active_object(C);
|
|
|
|
bool extend = RNA_boolean_get(op->ptr, "extend");
|
|
|
|
bool deselect = RNA_boolean_get(op->ptr, "deselect");
|
|
|
|
bool toggle = RNA_boolean_get(op->ptr, "toggle");
|
|
|
|
bool center = RNA_boolean_get(op->ptr, "center");
|
|
|
|
bool enumerate = RNA_boolean_get(op->ptr, "enumerate");
|
|
|
|
/* only force object select for editmode to support vertex parenting,
|
|
|
|
* or paint-select to allow pose bone select with vert/face select */
|
|
|
|
bool object = (RNA_boolean_get(op->ptr, "object") &&
|
|
|
|
(obedit ||
|
|
|
|
BKE_paint_select_elem_test(obact) ||
|
|
|
|
/* so its possible to select bones in weightpaint mode (LMB select) */
|
|
|
|
(obact && (obact->mode & OB_MODE_WEIGHT_PAINT) && BKE_object_pose_armature_get(obact))));
|
|
|
|
|
|
|
|
bool retval = false;
|
|
|
|
int location[2];
|
|
|
|
|
|
|
|
RNA_int_get_array(op->ptr, "location", location);
|
|
|
|
|
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
|
|
|
if (object) {
|
|
|
|
obedit = NULL;
|
|
|
|
obact = NULL;
|
|
|
|
|
|
|
|
/* ack, this is incorrect but to do this correctly we would need an
|
|
|
|
* alternative editmode/objectmode keymap, this copies the functionality
|
|
|
|
* from 2.4x where Ctrl+Select in editmode does object select only */
|
|
|
|
center = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obedit && object == false) {
|
|
|
|
if (obedit->type == OB_MESH)
|
|
|
|
retval = EDBM_select_pick(C, location, extend, deselect, toggle);
|
|
|
|
else if (obedit->type == OB_ARMATURE)
|
|
|
|
retval = ED_armature_edit_select_pick(C, location, extend, deselect, toggle);
|
|
|
|
else if (obedit->type == OB_LATTICE)
|
|
|
|
retval = ED_lattice_select_pick(C, location, extend, deselect, toggle);
|
|
|
|
else if (ELEM(obedit->type, OB_CURVE, OB_SURF))
|
|
|
|
retval = ED_curve_editnurb_select_pick(C, location, extend, deselect, toggle);
|
|
|
|
else if (obedit->type == OB_MBALL)
|
|
|
|
retval = ED_mball_select_pick(C, location, extend, deselect, toggle);
|
|
|
|
else if (obedit->type == OB_FONT)
|
|
|
|
retval = ED_curve_editfont_select_pick(C, location, extend, deselect, toggle);
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT)
|
|
|
|
return PE_mouse_particles(C, location, extend, deselect, toggle);
|
|
|
|
else if (obact && BKE_paint_select_face_test(obact))
|
|
|
|
retval = paintface_mouse_select(C, obact, location, extend, deselect, toggle);
|
|
|
|
else if (BKE_paint_select_vert_test(obact))
|
|
|
|
retval = ed_wpaint_vertex_select_pick(C, location, extend, deselect, toggle, obact);
|
|
|
|
else
|
|
|
|
retval = ed_object_select_pick(C, location, extend, deselect, toggle, center, enumerate, object);
|
|
|
|
|
|
|
|
/* passthrough allows tweaks
|
|
|
|
* FINISHED to signal one operator worked
|
|
|
|
* */
|
|
|
|
if (retval)
|
|
|
|
return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED;
|
|
|
|
else
|
|
|
|
return OPERATOR_PASS_THROUGH; /* nothing selected, just passthrough */
|
|
|
|
}
|
|
|
|
|
|
|
|
static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
|
|
|
{
|
|
|
|
RNA_int_set_array(op->ptr, "location", event->mval);
|
|
|
|
|
|
|
|
return view3d_select_exec(C, op);
|
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_select(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
PropertyRNA *prop;
|
|
|
|
|
|
|
|
/* identifiers */
|
|
|
|
ot->name = "Select";
|
|
|
|
ot->description = "Select and activate item(s)";
|
|
|
|
ot->idname = "VIEW3D_OT_select";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke = view3d_select_invoke;
|
|
|
|
ot->exec = view3d_select_exec;
|
|
|
|
ot->poll = ED_operator_view3d_active;
|
|
|
|
|
|
|
|
/* flags */
|
|
|
|
ot->flag = OPTYPE_UNDO;
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
WM_operator_properties_mouse_select(ot);
|
|
|
|
|
|
|
|
prop = RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting, in editmode used to extend object selection");
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
prop = RNA_def_boolean(ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only)");
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
prop = RNA_def_boolean(ot->srna, "object", 0, "Object", "Use object selection (editmode only)");
|
|
|
|
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
|
|
|
|
|
|
|
prop = RNA_def_int_vector(ot->srna, "location", 2, NULL, INT_MIN, INT_MAX, "Location", "Mouse location", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_property_flag(prop, PROP_HIDDEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Box Select
|
|
|
|
* \{ */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-01-26 08:12:12 +00:00
|
|
|
typedef struct BoxSelectUserData {
|
|
|
|
ViewContext *vc;
|
2012-10-05 15:44:11 +00:00
|
|
|
const rcti *rect;
|
2012-10-10 01:22:19 +00:00
|
|
|
const rctf *rect_fl;
|
|
|
|
rctf _rect_fl;
|
2018-08-14 10:28:41 +10:00
|
|
|
eSelectOp sel_op;
|
2012-10-05 15:44:11 +00:00
|
|
|
|
|
|
|
/* runtime */
|
2013-03-19 23:17:44 +00:00
|
|
|
bool is_done;
|
2013-11-26 06:39:14 +11:00
|
|
|
bool is_changed;
|
2012-01-26 08:12:12 +00:00
|
|
|
} BoxSelectUserData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-03-11 15:50:07 +11:00
|
|
|
static void view3d_userdata_boxselect_init(
|
|
|
|
BoxSelectUserData *r_data,
|
2018-08-14 10:28:41 +10:00
|
|
|
ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
|
2012-10-05 15:44:11 +00:00
|
|
|
{
|
|
|
|
r_data->vc = vc;
|
2012-10-10 01:22:19 +00:00
|
|
|
|
2012-10-05 15:44:11 +00:00
|
|
|
r_data->rect = rect;
|
2012-10-10 01:22:19 +00:00
|
|
|
r_data->rect_fl = &r_data->_rect_fl;
|
|
|
|
BLI_rctf_rcti_copy(&r_data->_rect_fl, rect);
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
r_data->sel_op = sel_op;
|
2012-10-05 15:44:11 +00:00
|
|
|
|
|
|
|
/* runtime */
|
2013-03-19 23:17:44 +00:00
|
|
|
r_data->is_done = false;
|
2013-11-26 06:39:14 +11:00
|
|
|
r_data->is_changed = false;
|
2012-10-05 15:44:11 +00:00
|
|
|
}
|
|
|
|
|
2013-03-19 23:17:44 +00:00
|
|
|
bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2013-05-01 17:27:14 +00:00
|
|
|
const float radius_squared = radius * radius;
|
|
|
|
return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-04-05 18:20:27 +02:00
|
|
|
static void do_paintvert_box_select__doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
|
2012-12-23 07:30:48 +00:00
|
|
|
{
|
|
|
|
BoxSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = mv->flag & SELECT;
|
|
|
|
const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
|
2012-12-23 07:30:48 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-16 12:45:11 +10:00
|
|
|
static int do_paintvert_box_select(
|
2018-08-14 10:28:41 +10:00
|
|
|
ViewContext *vc, rcti *rect, const eSelectOp sel_op)
|
2012-12-23 07:30:48 +00:00
|
|
|
{
|
2018-09-21 15:44:04 +02:00
|
|
|
const bool use_zbuf = V3D_IS_ZBUF(vc->v3d);
|
2012-12-23 07:30:48 +00:00
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
struct ImBuf *ibuf;
|
|
|
|
unsigned int *rt;
|
|
|
|
int a, index;
|
|
|
|
char *selar;
|
2015-07-11 21:09:22 +10:00
|
|
|
const int size[2] = {
|
|
|
|
BLI_rcti_size_x(rect) + 1,
|
|
|
|
BLI_rcti_size_y(rect) + 1};
|
2012-12-23 07:30:48 +00:00
|
|
|
|
|
|
|
me = vc->obact->data;
|
|
|
|
|
2015-07-11 21:09:22 +10:00
|
|
|
if ((me == NULL) || (me->totvert == 0) || (size[0] * size[1] <= 0)) {
|
2012-12-23 07:30:48 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
2015-07-11 21:09:22 +10:00
|
|
|
}
|
2012-12-23 07:30:48 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
paintvert_deselect_all_visible(vc->obact, SEL_DESELECT, false);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2012-12-23 07:30:48 +00:00
|
|
|
|
|
|
|
if (use_zbuf) {
|
|
|
|
selar = MEM_callocN(me->totvert + 1, "selar");
|
2018-04-06 12:07:27 +02:00
|
|
|
ED_view3d_backbuf_validate(vc);
|
2012-12-23 07:30:48 +00:00
|
|
|
|
2015-07-11 21:09:22 +10:00
|
|
|
ibuf = IMB_allocImBuf(size[0], size[1], 32, IB_rect);
|
2012-12-23 07:30:48 +00:00
|
|
|
rt = ibuf->rect;
|
2015-07-11 21:09:22 +10:00
|
|
|
glReadPixels(
|
|
|
|
rect->xmin + vc->ar->winrct.xmin,
|
|
|
|
rect->ymin + vc->ar->winrct.ymin,
|
|
|
|
size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
|
|
|
|
if (ENDIAN_ORDER == B_ENDIAN) {
|
|
|
|
IMB_convert_rgba_to_abgr(ibuf);
|
|
|
|
}
|
2016-06-25 20:16:33 +10:00
|
|
|
GPU_select_to_index_array(ibuf->rect, size[0] * size[1]);
|
2012-12-23 07:30:48 +00:00
|
|
|
|
2015-07-11 21:09:22 +10:00
|
|
|
a = size[0] * size[1];
|
2012-12-23 07:30:48 +00:00
|
|
|
while (a--) {
|
|
|
|
if (*rt) {
|
2015-07-11 21:09:22 +10:00
|
|
|
index = *rt;
|
|
|
|
if (index <= me->totvert) {
|
|
|
|
selar[index] = 1;
|
|
|
|
}
|
2012-12-23 07:30:48 +00:00
|
|
|
}
|
|
|
|
rt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
mvert = me->mvert;
|
|
|
|
for (a = 1; a <= me->totvert; a++, mvert++) {
|
2018-08-14 10:28:41 +10:00
|
|
|
if ((mvert->flag & ME_HIDE) == 0) {
|
|
|
|
const bool is_select = mvert->flag & SELECT;
|
|
|
|
const bool is_inside = (selar[a] != 0);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT);
|
2012-12-23 07:30:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
IMB_freeImBuf(ibuf);
|
|
|
|
MEM_freeN(selar);
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
glReadBuffer(GL_BACK);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BoxSelectUserData data;
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
|
2012-12-23 07:30:48 +00:00
|
|
|
|
|
|
|
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
|
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
meshobject_foreachScreenVert(vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2012-12-23 07:30:48 +00:00
|
|
|
}
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_CAN_DESELECT(sel_op)) {
|
2013-06-15 10:18:16 +00:00
|
|
|
BKE_mesh_mselect_validate(me);
|
|
|
|
}
|
2012-12-23 07:30:48 +00:00
|
|
|
paintvert_flush_flags(vc->obact);
|
2018-11-23 18:28:36 +03:00
|
|
|
paintvert_tag_select_update(vc->C, vc->obact);
|
2012-12-23 07:30:48 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2018-03-11 15:50:07 +11:00
|
|
|
static void do_nurbs_box_select__doSelect(
|
|
|
|
void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
|
|
|
|
if (bp) {
|
|
|
|
const bool is_select = bp->f1 & SELECT;
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
|
|
|
else {
|
2018-09-25 18:50:57 +02:00
|
|
|
if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
|
2018-08-14 10:28:41 +10:00
|
|
|
/* can only be (beztindex == 0) here since handles are hidden */
|
|
|
|
const bool is_select = bezt->f2 & SELECT;
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(bezt->f2, sel_op_result, SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
bezt->f1 = bezt->f3 = bezt->f2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
char *flag_p = (&bezt->f1) + beztindex;
|
|
|
|
const bool is_select = *flag_p & SELECT;
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(*flag_p, sel_op_result, SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static int do_nurbs_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData data;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2014-03-12 14:07:26 +06:00
|
|
|
Curve *curve = (Curve *) vc->obedit->data;
|
|
|
|
ED_curve_deselect_all(curve->editnurb);
|
|
|
|
}
|
2009-11-29 22:16:29 +00:00
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
|
2012-10-10 04:03:22 +00:00
|
|
|
nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2014-01-27 15:18:40 +11:00
|
|
|
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
|
2010-11-03 01:56:02 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, const float screen_co[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = bp->f1 & SELECT;
|
|
|
|
const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static int do_lattice_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData data;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2015-11-18 12:20:28 +11:00
|
|
|
ED_lattice_flags_set(vc->obedit, 0);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2009-11-29 22:16:29 +00:00
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
|
2012-10-10 04:03:22 +00:00
|
|
|
lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-11-03 01:56:02 +00:00
|
|
|
return OPERATOR_FINISHED;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_mesh_box_select__doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_vert_select_set(data->vc->em->bm, eve, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-14 10:28:41 +10:00
|
|
|
static void do_mesh_box_select__doSelectEdge_pass0(
|
2018-03-11 15:50:07 +11:00
|
|
|
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = (
|
|
|
|
EDBM_backbuf_check(bm_solidoffs + index) &&
|
|
|
|
edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
|
2018-11-25 02:12:48 +01:00
|
|
|
data->is_done = true;
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
static void do_mesh_box_select__doSelectEdge_pass1(
|
|
|
|
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
|
|
|
|
{
|
|
|
|
BoxSelectUserData *data = userData;
|
|
|
|
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = (
|
|
|
|
EDBM_backbuf_check(bm_solidoffs + index) &&
|
|
|
|
edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_mesh_box_select__doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData *data = userData;
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
|
|
|
|
const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
BM_face_select_set(data->vc->em->bm, efa, sel_op_result);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-16 12:45:11 +10:00
|
|
|
static int do_mesh_box_select(
|
2018-08-14 10:28:41 +10:00
|
|
|
ViewContext *vc, rcti *rect, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
BoxSelectUserData data;
|
2012-03-25 23:54:33 +00:00
|
|
|
ToolSettings *ts = vc->scene->toolsettings;
|
2008-12-20 18:43:21 +00:00
|
|
|
int bbsel;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2012-02-12 18:43:59 +00:00
|
|
|
EDBM_flag_disable_all(vc->em, BM_ELEM_SELECT);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2009-11-29 22:16:29 +00:00
|
|
|
|
2012-03-18 07:38:51 +00:00
|
|
|
/* for non zbuf projections, don't change the GL state */
|
2011-06-09 03:56:32 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
|
2010-02-08 10:12:02 +00:00
|
|
|
|
2018-07-15 15:27:15 +02:00
|
|
|
GPU_matrix_set(vc->rv3d->viewmat);
|
2018-04-06 12:07:27 +02:00
|
|
|
bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_VERTEX) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_verts(vc->em, sel_op);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_EDGE) {
|
2012-03-25 23:54:33 +00:00
|
|
|
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
|
2018-08-14 10:28:41 +10:00
|
|
|
mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
|
|
|
|
if (data.is_done == false) {
|
|
|
|
mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_FACE) {
|
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_faces(vc->em, sel_op);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-27 04:46:52 +00:00
|
|
|
EDBM_backbuf_free();
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-10 06:16:21 +00:00
|
|
|
EDBM_selectmode_flush(vc->em);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-11-03 01:56:02 +00:00
|
|
|
return OPERATOR_FINISHED;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2017-08-16 12:45:11 +10:00
|
|
|
static int do_meta_box_select(
|
2018-04-06 12:07:27 +02:00
|
|
|
ViewContext *vc,
|
2018-08-14 10:28:41 +10:00
|
|
|
const rcti *rect, const eSelectOp sel_op)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2018-11-09 14:26:58 -02:00
|
|
|
Object *ob = vc->obedit;
|
|
|
|
MetaBall *mb = (MetaBall *)ob->data;
|
2008-12-20 18:43:21 +00:00
|
|
|
MetaElem *ml;
|
2010-11-03 01:56:02 +00:00
|
|
|
int a;
|
|
|
|
|
2015-02-24 17:19:07 +01:00
|
|
|
unsigned int buffer[MAXPICKBUF];
|
2017-03-08 23:15:12 +11:00
|
|
|
int hits;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-06-19 16:41:18 +02:00
|
|
|
hits = view3d_opengl_select(
|
|
|
|
vc, buffer, MAXPICKBUF, rect,
|
|
|
|
VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
2010-01-11 19:52:03 +00:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2012-10-06 03:02:14 +00:00
|
|
|
BKE_mball_deselect_all(mb);
|
2018-08-14 10:28:41 +10:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-11-09 14:26:58 -02:00
|
|
|
int metaelem_id = 0;
|
|
|
|
for (ml = mb->editelems->first; ml; ml = ml->next, metaelem_id += 0x10000) {
|
|
|
|
bool is_inside_radius = false;
|
|
|
|
bool is_inside_stiff = false;
|
|
|
|
|
2012-03-25 23:54:33 +00:00
|
|
|
for (a = 0; a < hits; a++) {
|
2018-11-09 14:26:58 -02:00
|
|
|
int hitresult = buffer[(4 * a) + 3];
|
|
|
|
|
|
|
|
if (hitresult == -1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (hitresult & MBALL_NOSEL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const uint hit_object = hitresult & 0xFFFF;
|
|
|
|
if (vc->obedit->select_color != hit_object) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (metaelem_id != (hitresult & 0xFFFF0000 & ~(MBALLSEL_ANY))) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hitresult & MBALLSEL_RADIUS) {
|
|
|
|
is_inside_radius = true;
|
2010-11-03 01:56:02 +00:00
|
|
|
break;
|
2009-11-29 22:16:29 +00:00
|
|
|
}
|
2018-11-09 14:26:58 -02:00
|
|
|
|
|
|
|
if (hitresult & MBALLSEL_STIFF) {
|
|
|
|
is_inside_stiff = true;
|
2010-11-03 01:56:02 +00:00
|
|
|
break;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-09 14:26:58 -02:00
|
|
|
if (is_inside_radius) {
|
2018-08-14 10:28:41 +10:00
|
|
|
ml->flag |= MB_SCALE_RAD;
|
|
|
|
}
|
2018-11-09 14:26:58 -02:00
|
|
|
if (is_inside_stiff) {
|
2018-08-14 10:28:41 +10:00
|
|
|
ml->flag &= ~MB_SCALE_RAD;
|
|
|
|
}
|
2018-11-09 14:26:58 -02:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
const bool is_select = (ml->flag & SELECT);
|
2018-11-09 14:26:58 -02:00
|
|
|
const bool is_inside = is_inside_radius || is_inside_stiff;
|
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT);
|
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
2009-11-29 22:16:29 +00:00
|
|
|
|
2010-11-03 01:56:02 +00:00
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
2017-08-16 12:45:11 +10:00
|
|
|
static int do_armature_box_select(
|
2018-04-06 12:07:27 +02:00
|
|
|
ViewContext *vc,
|
2018-08-14 10:28:41 +10:00
|
|
|
const rcti *rect, const eSelectOp sel_op)
|
2010-11-03 01:56:02 +00:00
|
|
|
{
|
2018-12-13 19:05:11 +11:00
|
|
|
bool changed = false;
|
2010-11-03 01:56:02 +00:00
|
|
|
int a;
|
|
|
|
|
2015-02-24 17:19:07 +01:00
|
|
|
unsigned int buffer[MAXPICKBUF];
|
2017-03-08 23:15:12 +11:00
|
|
|
int hits;
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2018-06-19 16:41:18 +02:00
|
|
|
hits = view3d_opengl_select(
|
|
|
|
vc, buffer, MAXPICKBUF, rect,
|
|
|
|
VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
2018-04-16 16:27:55 +02:00
|
|
|
|
|
|
|
uint objects_len = 0;
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc->view_layer, vc->v3d, &objects_len);
|
2018-04-16 16:27:55 +02:00
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
|
|
|
ED_armature_edit_deselect_all_visible_multi(objects, objects_len);
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
Object *obedit = objects[ob_index];
|
2018-12-13 19:05:11 +11:00
|
|
|
obedit->id.tag &= ~LIB_TAG_DOIT;
|
2018-04-16 16:27:55 +02:00
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
bArmature *arm = obedit->data;
|
|
|
|
ED_armature_ebone_listbase_temp_clear(arm->edbo);
|
2018-04-16 16:27:55 +02:00
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
|
|
|
|
/* first we only check points inside the border */
|
2012-03-25 23:54:33 +00:00
|
|
|
for (a = 0; a < hits; a++) {
|
2018-12-13 19:05:11 +11:00
|
|
|
int select_id = buffer[(4 * a) + 3];
|
|
|
|
if (select_id != -1) {
|
|
|
|
if ((select_id & 0xFFFF0000) == 0) {
|
2016-08-24 14:17:26 +02:00
|
|
|
continue;
|
|
|
|
}
|
2018-04-16 16:27:55 +02:00
|
|
|
|
|
|
|
EditBone *ebone;
|
2018-12-13 19:05:11 +11:00
|
|
|
Object *obedit = ED_armature_object_and_ebone_from_select_buffer(objects, objects_len, select_id, &ebone);
|
|
|
|
ebone->temp.i |= select_id & BONESEL_ANY;
|
|
|
|
obedit->id.tag |= LIB_TAG_DOIT;
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-15 21:45:19 +02:00
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
Object *obedit = objects[ob_index];
|
2018-12-13 19:05:11 +11:00
|
|
|
if (obedit->id.tag & LIB_TAG_DOIT) {
|
|
|
|
obedit->id.tag &= ~LIB_TAG_DOIT;
|
|
|
|
changed |= ED_armature_edit_select_op_from_tagged(obedit->data, sel_op);
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-15 21:45:19 +02:00
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
MEM_freeN(objects);
|
|
|
|
|
2018-12-13 19:05:11 +11:00
|
|
|
return (hits > 0 || changed) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
2009-11-29 22:16:29 +00:00
|
|
|
|
2017-06-02 16:35:58 +10:00
|
|
|
/**
|
|
|
|
* Compare result of 'GPU_select': 'uint[4]',
|
|
|
|
* needed for when we need to align with object draw-order.
|
|
|
|
*/
|
2018-04-16 08:51:41 +02:00
|
|
|
static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
|
2017-06-02 16:35:58 +10:00
|
|
|
{
|
|
|
|
/* 4th element is select id */
|
2018-04-16 08:51:41 +02:00
|
|
|
uint sel_a = ((uint *)sel_a_p)[3];
|
|
|
|
uint sel_b = ((uint *)sel_b_p)[3];
|
|
|
|
|
|
|
|
#ifdef __BIG_ENDIAN__
|
|
|
|
BLI_endian_switch_uint32(&sel_a);
|
|
|
|
BLI_endian_switch_uint32(&sel_b);
|
|
|
|
#endif
|
2017-06-02 16:35:58 +10:00
|
|
|
|
|
|
|
if (sel_a < sel_b) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (sel_a > sel_b) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-28 14:04:37 +10:00
|
|
|
static int do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
|
|
|
|
{
|
2018-11-23 14:41:38 -02:00
|
|
|
View3D *v3d = vc->v3d;
|
2018-11-19 07:21:14 +11:00
|
|
|
bool changed = false;
|
2018-08-28 14:04:37 +10:00
|
|
|
int totobj = MAXPICKBUF; /* XXX solve later */
|
|
|
|
|
|
|
|
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
|
2018-08-28 16:17:37 +10:00
|
|
|
uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
|
2018-11-23 10:00:28 +11:00
|
|
|
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact);
|
2018-08-28 16:17:37 +10:00
|
|
|
const int hits = view3d_opengl_select(
|
2018-08-28 14:04:37 +10:00
|
|
|
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
|
|
|
|
VIEW3D_SELECT_ALL, select_filter);
|
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
|
|
|
|
base->object->id.tag &= ~LIB_TAG_DOIT;
|
2018-08-28 14:04:37 +10:00
|
|
|
}
|
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
Base **bases = NULL;
|
|
|
|
BLI_array_declare(bases);
|
2018-08-28 14:04:37 +10:00
|
|
|
|
2018-11-19 07:21:14 +11:00
|
|
|
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
2018-11-23 14:41:38 -02:00
|
|
|
object_deselect_all_visible(vc->view_layer, vc->v3d);
|
2018-11-19 07:21:14 +11:00
|
|
|
changed = true;
|
|
|
|
}
|
2018-08-28 14:04:37 +10:00
|
|
|
|
2018-11-19 07:21:14 +11:00
|
|
|
if ((hits == -1) && !SEL_OP_USE_OUTSIDE(sel_op)) {
|
|
|
|
goto finally;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_SELECTABLE(v3d, base)) {
|
2018-11-19 07:21:14 +11:00
|
|
|
if ((base->object->select_color & 0x0000FFFF) != 0) {
|
|
|
|
BLI_array_append(bases, base);
|
2018-08-28 14:04:37 +10:00
|
|
|
}
|
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
}
|
2018-08-28 14:04:37 +10:00
|
|
|
|
2018-11-19 07:21:14 +11:00
|
|
|
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
|
|
|
|
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
|
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
|
|
|
|
Bone *bone;
|
|
|
|
Base *base = ED_armature_base_and_bone_from_select_buffer(bases, BLI_array_len(bases), *col, &bone);
|
|
|
|
base->object->id.tag |= LIB_TAG_DOIT;
|
|
|
|
}
|
2018-08-28 14:04:37 +10:00
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
for (Base *base = vc->view_layer->object_bases.first; base && hits; base = base->next) {
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_SELECTABLE(v3d, base)) {
|
2018-08-28 16:17:37 +10:00
|
|
|
const bool is_select = base->flag & BASE_SELECTED;
|
|
|
|
const bool is_inside = base->object->id.tag & LIB_TAG_DOIT;
|
|
|
|
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
|
|
|
|
if (sel_op_result != -1) {
|
|
|
|
ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT);
|
2018-11-19 07:21:14 +11:00
|
|
|
changed = true;
|
2018-08-28 14:04:37 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
|
2018-11-19 07:21:14 +11:00
|
|
|
finally:
|
2018-08-28 16:17:37 +10:00
|
|
|
if (bases != NULL) {
|
|
|
|
MEM_freeN(bases);
|
|
|
|
}
|
2018-11-19 07:21:14 +11:00
|
|
|
|
2018-08-28 14:04:37 +10:00
|
|
|
MEM_freeN(vbuffer);
|
|
|
|
|
2018-11-19 07:21:14 +11:00
|
|
|
if (changed) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
|
2018-11-19 07:21:14 +11:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2018-08-28 14:04:37 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
static int do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
|
2010-11-03 01:56:02 +00:00
|
|
|
{
|
2018-08-28 16:17:37 +10:00
|
|
|
uint bases_len;
|
|
|
|
Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
int totobj = MAXPICKBUF; /* XXX solve later */
|
2009-11-29 22:16:29 +00:00
|
|
|
|
2010-11-03 01:56:02 +00:00
|
|
|
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
|
2018-08-28 16:17:37 +10:00
|
|
|
uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
|
2018-11-23 10:00:28 +11:00
|
|
|
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene, vc->obact);
|
2018-08-28 16:17:37 +10:00
|
|
|
const int hits = view3d_opengl_select(
|
2018-06-19 16:41:18 +02:00
|
|
|
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect,
|
|
|
|
VIEW3D_SELECT_ALL, select_filter);
|
2010-11-03 01:56:02 +00:00
|
|
|
/*
|
2012-03-03 16:31:46 +00:00
|
|
|
* LOGIC NOTES (theeth):
|
|
|
|
* The buffer and ListBase have the same relative order, which makes the selection
|
|
|
|
* very simple. Loop through both data sets at the same time, if the color
|
|
|
|
* is the same as the object, we have a hit and can move to the next color
|
|
|
|
* and object pair, if not, just move to the next object,
|
|
|
|
* keeping the same color until we have a hit.
|
|
|
|
*/
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
if (hits > 0) {
|
2018-08-14 10:28:41 +10:00
|
|
|
/* no need to loop if there's no hit */
|
2017-06-02 16:35:58 +10:00
|
|
|
|
|
|
|
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
|
2018-04-16 08:51:41 +02:00
|
|
|
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
|
2017-06-02 16:35:58 +10:00
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
|
|
|
|
Bone *bone;
|
2018-08-28 16:17:37 +10:00
|
|
|
Base *base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, *col, &bone);
|
2018-04-16 16:27:55 +02:00
|
|
|
|
|
|
|
if (base == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
/* Loop over contiguous bone hits for 'base'. */
|
|
|
|
for (; col != col_end; col += 4) {
|
|
|
|
/* should never fail */
|
|
|
|
if (bone != NULL) {
|
2018-08-28 16:17:37 +10:00
|
|
|
base->object->id.tag |= LIB_TAG_DOIT;
|
|
|
|
bone->flag |= BONE_DONE;
|
2018-04-16 16:27:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Select the next bone if we're not switching bases. */
|
|
|
|
if (col + 4 != col_end) {
|
|
|
|
if ((base->object->select_color & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
|
|
|
|
break;
|
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
if (base->object->pose != NULL) {
|
2018-04-16 19:40:57 +02:00
|
|
|
const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
|
2018-05-24 13:47:33 +02:00
|
|
|
bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
|
2018-04-16 19:40:57 +02:00
|
|
|
bone = pchan ? pchan->bone : NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bone = NULL;
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-15 22:17:03 +10:00
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
}
|
2018-08-15 22:17:03 +10:00
|
|
|
|
2018-08-28 16:17:37 +10:00
|
|
|
const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op);
|
|
|
|
if (changed_multi) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
2018-08-28 16:17:37 +10:00
|
|
|
|
|
|
|
if (bases != NULL) {
|
|
|
|
MEM_freeN(bases);
|
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
MEM_freeN(vbuffer);
|
|
|
|
|
|
|
|
return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
static int view3d_box_select_exec(bContext *C, wmOperator *op)
|
2010-11-03 01:56:02 +00:00
|
|
|
{
|
|
|
|
ViewContext vc;
|
|
|
|
rcti rect;
|
2012-03-25 23:54:33 +00:00
|
|
|
int ret = OPERATOR_CANCELLED;
|
2008-12-29 12:15:42 +00:00
|
|
|
|
2010-11-03 01:56:02 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
|
|
|
/* setup view context for argument to callbacks */
|
2018-03-08 17:30:24 +11:00
|
|
|
ED_view3d_viewcontext_init(C, &vc);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-08-14 10:28:41 +10:00
|
|
|
eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
|
2017-10-16 21:58:51 +11:00
|
|
|
WM_operator_properties_border_to_rcti(op, &rect);
|
2010-11-03 01:56:02 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (vc.obedit) {
|
2018-04-16 16:27:55 +02:00
|
|
|
|
2018-12-01 19:43:10 +03:00
|
|
|
FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) {
|
2018-04-16 17:54:33 +02:00
|
|
|
ED_view3d_viewcontext_init_object(&vc, ob_iter);
|
|
|
|
|
|
|
|
switch (vc.obedit->type) {
|
|
|
|
case OB_MESH:
|
|
|
|
vc.em = BKE_editmesh_from_object(vc.obedit);
|
2018-08-14 10:28:41 +10:00
|
|
|
ret |= do_mesh_box_select(&vc, &rect, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
if (ret & OPERATOR_FINISHED) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
|
2018-04-16 17:54:33 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
2018-08-14 10:28:41 +10:00
|
|
|
ret |= do_nurbs_box_select(&vc, &rect, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
if (ret & OPERATOR_FINISHED) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
|
2018-04-16 17:54:33 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_MBALL:
|
2018-08-14 10:28:41 +10:00
|
|
|
ret |= do_meta_box_select(&vc, &rect, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
if (ret & OPERATOR_FINISHED) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
|
2018-04-16 17:54:33 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_ARMATURE:
|
2018-08-14 10:28:41 +10:00
|
|
|
ret |= do_armature_box_select(&vc, &rect, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
if (ret & OPERATOR_FINISHED) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT);
|
2018-04-16 17:54:33 +02:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OB_LATTICE:
|
2018-08-14 10:28:41 +10:00
|
|
|
ret |= do_lattice_box_select(&vc, &rect, sel_op);
|
2018-04-16 17:54:33 +02:00
|
|
|
if (ret & OPERATOR_FINISHED) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
|
2018-04-16 17:54:33 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2018-10-05 10:27:04 +10:00
|
|
|
assert(!"box select on incorrect object type");
|
2018-04-16 17:54:33 +02:00
|
|
|
break;
|
|
|
|
}
|
2018-04-16 16:27:55 +02:00
|
|
|
}
|
|
|
|
FOREACH_OBJECT_IN_MODE_END;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
else { /* no editmode, unified for bones and objects */
|
2018-04-05 18:20:27 +02:00
|
|
|
if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) {
|
2018-08-14 10:28:41 +10:00
|
|
|
/* XXX, this is not selection, could be it's own operator. */
|
|
|
|
ret |= ED_sculpt_mask_box_select(C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false);
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
ret |= do_paintface_box_select(&vc, &rect, sel_op);
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
|
2018-08-14 10:28:41 +10:00
|
|
|
ret |= do_paintvert_box_select(&vc, &rect, sel_op);
|
2011-07-14 18:04:48 +00:00
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
|
2018-10-05 10:27:04 +10:00
|
|
|
ret |= PE_box_select(C, &rect, sel_op);
|
2016-12-28 17:30:58 +01:00
|
|
|
}
|
2018-08-28 14:04:37 +10:00
|
|
|
else if (vc.obact && vc.obact->mode & OB_MODE_POSE) {
|
|
|
|
ret |= do_pose_box_select(C, &vc, &rect, sel_op);
|
|
|
|
}
|
2010-11-03 01:56:02 +00:00
|
|
|
else { /* object mode with none active */
|
2018-08-28 14:04:37 +10:00
|
|
|
ret |= do_object_box_select(C, &vc, &rect, sel_op);
|
2010-11-03 01:56:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
if (ret & OPERATOR_FINISHED) {
|
|
|
|
ret = OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ret = OPERATOR_CANCELLED;
|
|
|
|
}
|
|
|
|
|
2010-11-03 01:56:02 +00:00
|
|
|
return ret;
|
2018-06-04 09:31:30 +02:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-10-05 10:27:04 +10:00
|
|
|
void VIEW3D_OT_select_box(wmOperatorType *ot)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
2018-10-05 10:27:04 +10:00
|
|
|
ot->name = "Box Select";
|
|
|
|
ot->description = "Select items using box selection";
|
|
|
|
ot->idname = "VIEW3D_OT_select_box";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* api callbacks */
|
2018-10-05 10:27:04 +10:00
|
|
|
ot->invoke = WM_gesture_box_invoke;
|
|
|
|
ot->exec = view3d_box_select_exec;
|
|
|
|
ot->modal = WM_gesture_box_modal;
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->poll = view3d_selectable_data;
|
2018-10-05 10:27:04 +10:00
|
|
|
ot->cancel = WM_gesture_box_cancel;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->flag = OPTYPE_UNDO;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* rna */
|
2018-10-05 10:27:04 +10:00
|
|
|
WM_operator_properties_gesture_box(ot);
|
2018-08-14 10:28:41 +10:00
|
|
|
WM_operator_properties_select_operation(ot);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-12-13 13:04:25 +11:00
|
|
|
/** \} */
|
2013-06-15 10:18:16 +00:00
|
|
|
|
2018-12-13 13:04:25 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Circle Select
|
|
|
|
* \{ */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-01-26 08:12:12 +00:00
|
|
|
typedef struct CircleSelectUserData {
|
|
|
|
ViewContext *vc;
|
2013-06-15 06:03:15 +00:00
|
|
|
bool select;
|
2012-10-10 01:22:19 +00:00
|
|
|
int mval[2];
|
|
|
|
float mval_fl[2];
|
2012-01-26 08:12:12 +00:00
|
|
|
float radius;
|
2012-10-05 15:44:11 +00:00
|
|
|
float radius_squared;
|
|
|
|
|
|
|
|
/* runtime */
|
2013-11-26 06:39:14 +11:00
|
|
|
bool is_changed;
|
2012-01-26 08:12:12 +00:00
|
|
|
} CircleSelectUserData;
|
|
|
|
|
2018-03-11 15:50:07 +11:00
|
|
|
static void view3d_userdata_circleselect_init(
|
|
|
|
CircleSelectUserData *r_data,
|
|
|
|
ViewContext *vc, const bool select, const int mval[2], const float rad)
|
2012-10-05 15:44:11 +00:00
|
|
|
{
|
|
|
|
r_data->vc = vc;
|
|
|
|
r_data->select = select;
|
|
|
|
copy_v2_v2_int(r_data->mval, mval);
|
2012-10-10 01:22:19 +00:00
|
|
|
r_data->mval_fl[0] = mval[0];
|
|
|
|
r_data->mval_fl[1] = mval[1];
|
|
|
|
|
2012-10-05 15:44:11 +00:00
|
|
|
r_data->radius = rad;
|
|
|
|
r_data->radius_squared = rad * rad;
|
|
|
|
|
|
|
|
/* runtime */
|
2013-11-26 06:39:14 +11:00
|
|
|
r_data->is_changed = false;
|
2012-10-05 15:44:11 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void mesh_circle_doSelectVert(void *userData, BMVert *eve, const float screen_co[2], int UNUSED(index))
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2012-04-20 16:55:47 +00:00
|
|
|
BM_vert_select_set(data->vc->em->bm, eve, data->select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2018-03-11 15:50:07 +11:00
|
|
|
static void mesh_circle_doSelectEdge(
|
|
|
|
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int UNUSED(index))
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2013-05-01 17:27:14 +00:00
|
|
|
if (edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b)) {
|
2012-04-20 16:55:47 +00:00
|
|
|
BM_edge_select_set(data->vc->em->bm, eed, data->select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2012-10-10 01:22:19 +00:00
|
|
|
static void mesh_circle_doSelectFace(void *userData, BMFace *efa, const float screen_co[2], int UNUSED(index))
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
2012-10-05 15:44:11 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2012-04-20 16:55:47 +00:00
|
|
|
BM_face_select_set(data->vc->em->bm, efa, data->select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
static void mesh_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-03-25 23:54:33 +00:00
|
|
|
ToolSettings *ts = vc->scene->toolsettings;
|
2008-12-20 18:43:21 +00:00
|
|
|
int bbsel;
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData data;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
|
2010-09-23 21:01:12 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2013-04-16 05:59:48 +00:00
|
|
|
vc->em = BKE_editmesh_from_object(vc->obedit);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-10-05 15:44:11 +00:00
|
|
|
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_VERTEX) {
|
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_EDGE) {
|
2010-09-23 21:01:12 +00:00
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2010-09-23 21:01:12 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-02-22 16:52:06 +00:00
|
|
|
if (ts->selectmode & SCE_SELECT_FACE) {
|
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2010-09-23 21:01:12 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-03-27 04:46:52 +00:00
|
|
|
EDBM_backbuf_free();
|
2012-02-10 06:16:21 +00:00
|
|
|
EDBM_selectmode_flush(vc->em);
|
2010-09-23 21:01:12 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
static void paint_facesel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2010-09-23 21:01:12 +00:00
|
|
|
{
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *ob = vc->obact;
|
2013-10-08 19:47:53 +00:00
|
|
|
Mesh *me = ob->data;
|
2013-09-30 07:58:38 +00:00
|
|
|
bool bbsel;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2013-09-30 07:58:38 +00:00
|
|
|
bm_vertoffs = me->totpoly + 1; /* max index array */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
|
2013-09-30 07:58:38 +00:00
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_tfaces(me, select ? SEL_OP_ADD : SEL_OP_SUB);
|
2012-03-27 04:46:52 +00:00
|
|
|
EDBM_backbuf_free();
|
2018-12-01 15:40:48 +03:00
|
|
|
paintface_flush_flags(vc->C, ob, SELECT);
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2018-04-05 18:20:27 +02:00
|
|
|
static void paint_vertsel_circle_select_doSelectVert(void *userData, MVert *mv, const float screen_co[2], int UNUSED(index))
|
2012-12-23 07:30:48 +00:00
|
|
|
{
|
|
|
|
CircleSelectUserData *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-12-23 07:30:48 +00:00
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2017-11-20 01:35:49 +11:00
|
|
|
SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
|
2012-12-23 07:30:48 +00:00
|
|
|
}
|
|
|
|
}
|
2018-04-06 12:07:27 +02:00
|
|
|
static void paint_vertsel_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2011-07-05 18:03:31 +00:00
|
|
|
{
|
2018-09-21 15:44:04 +02:00
|
|
|
const bool use_zbuf = V3D_IS_ZBUF(vc->v3d);
|
2012-03-25 23:54:33 +00:00
|
|
|
Object *ob = vc->obact;
|
2012-12-23 07:30:48 +00:00
|
|
|
Mesh *me = ob->data;
|
2013-09-30 07:58:38 +00:00
|
|
|
bool bbsel;
|
2012-01-26 08:12:12 +00:00
|
|
|
/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
|
2012-12-23 07:30:48 +00:00
|
|
|
|
|
|
|
if (use_zbuf) {
|
2012-03-25 23:54:33 +00:00
|
|
|
bm_vertoffs = me->totvert + 1; /* max index array */
|
2011-08-09 16:32:15 +00:00
|
|
|
|
2018-04-06 12:07:27 +02:00
|
|
|
bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
|
2013-09-30 07:58:38 +00:00
|
|
|
if (bbsel) {
|
2018-08-14 10:28:41 +10:00
|
|
|
edbm_backbuf_check_and_select_verts_obmode(me, select ? SEL_OP_ADD : SEL_OP_SET);
|
2013-09-30 07:58:38 +00:00
|
|
|
EDBM_backbuf_free();
|
|
|
|
}
|
2012-12-23 07:30:48 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
CircleSelectUserData data;
|
2011-07-12 19:06:06 +00:00
|
|
|
|
2012-12-23 07:30:48 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
|
|
|
|
|
|
|
|
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
|
2018-04-06 12:07:27 +02:00
|
|
|
meshobject_foreachScreenVert(vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2011-07-05 18:03:31 +00:00
|
|
|
}
|
2012-12-23 07:30:48 +00:00
|
|
|
|
2018-08-14 17:01:31 +10:00
|
|
|
if (select == false) {
|
2013-06-15 10:18:16 +00:00
|
|
|
BKE_mesh_mselect_validate(me);
|
|
|
|
}
|
2012-12-23 07:30:48 +00:00
|
|
|
paintvert_flush_flags(ob);
|
2018-11-23 18:28:36 +03:00
|
|
|
paintvert_tag_select_update(vc->C, ob);
|
2011-07-05 18:03:31 +00:00
|
|
|
}
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2018-03-11 15:50:07 +11:00
|
|
|
static void nurbscurve_circle_doSelect(
|
|
|
|
void *userData, Nurb *UNUSED(nu), BPoint *bp, BezTriple *bezt, int beztindex, const float screen_co[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if (bp) {
|
2012-03-25 23:54:33 +00:00
|
|
|
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-09-25 18:50:57 +02:00
|
|
|
if ((data->vc->v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CU_HANDLES) == 0) {
|
2012-05-25 09:51:53 +00:00
|
|
|
/* can only be (beztindex == 0) here since handles are hidden */
|
2012-03-25 23:54:33 +00:00
|
|
|
bezt->f1 = bezt->f2 = bezt->f3 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:54:33 +00:00
|
|
|
if (beztindex == 0) {
|
|
|
|
bezt->f1 = data->select ? (bezt->f1 | SELECT) : (bezt->f1 & ~SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
2012-03-25 23:54:33 +00:00
|
|
|
else if (beztindex == 1) {
|
|
|
|
bezt->f2 = data->select ? (bezt->f2 | SELECT) : (bezt->f2 & ~SELECT);
|
2012-02-22 16:52:06 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-03-25 23:54:33 +00:00
|
|
|
bezt->f3 = data->select ? (bezt->f3 | SELECT) : (bezt->f3 & ~SELECT);
|
2010-04-30 04:48:40 +00:00
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-06-15 06:03:15 +00:00
|
|
|
static void nurbscurve_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData data;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-10-06 01:30:49 +00:00
|
|
|
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
|
2012-10-10 04:03:22 +00:00
|
|
|
nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2014-01-27 15:18:40 +11:00
|
|
|
BKE_curve_nurb_vert_active_validate(vc->obedit->data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void latticecurve_circle_doSelect(void *userData, BPoint *bp, const float screen_co[2])
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2012-03-25 23:54:33 +00:00
|
|
|
bp->f1 = data->select ? (bp->f1 | SELECT) : (bp->f1 & ~SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-15 06:03:15 +00:00
|
|
|
static void lattice_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData data;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2012-10-05 15:44:11 +00:00
|
|
|
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-10-22 23:22:05 +00:00
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
|
2012-10-10 04:03:22 +00:00
|
|
|
lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2009-11-05 08:54:33 +00:00
|
|
|
|
2012-07-08 20:36:00 +00:00
|
|
|
/* NOTE: pose-bone case is copied from editbone case... */
|
2017-03-08 23:15:12 +11:00
|
|
|
static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2])
|
2010-12-31 03:35:34 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
2012-10-05 15:44:11 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2010-12-31 03:35:34 +00:00
|
|
|
if (data->select)
|
|
|
|
pchan->bone->flag |= BONE_SELECTED;
|
|
|
|
else
|
|
|
|
pchan->bone->flag &= ~BONE_SELECTED;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2018-03-11 15:50:07 +11:00
|
|
|
static void do_circle_select_pose__doSelectBone(
|
|
|
|
void *userData, struct bPoseChannel *pchan, const float screen_co_a[2], const float screen_co_b[2])
|
2010-12-31 03:35:34 +00:00
|
|
|
{
|
2012-10-05 17:51:44 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
|
|
|
bArmature *arm = data->vc->obact->data;
|
2010-12-31 03:35:34 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
if (PBONE_SELECTABLE(arm, pchan->bone)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
bool is_point_done = false;
|
2012-10-05 17:51:44 +00:00
|
|
|
int points_proj_tot = 0;
|
2012-10-05 05:27:51 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
/* project head location to screenspace */
|
2012-10-10 01:22:19 +00:00
|
|
|
if (screen_co_a[0] != IS_CLIPPED) {
|
2012-10-05 17:51:44 +00:00
|
|
|
points_proj_tot++;
|
2012-10-10 01:22:19 +00:00
|
|
|
if (pchan_circle_doSelectJoint(data, pchan, screen_co_a)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
is_point_done = true;
|
2012-10-05 05:59:15 +00:00
|
|
|
}
|
2012-10-05 17:51:44 +00:00
|
|
|
}
|
2012-10-05 05:27:51 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
/* project tail location to screenspace */
|
2012-10-10 01:22:19 +00:00
|
|
|
if (screen_co_b[0] != IS_CLIPPED) {
|
2012-10-05 17:51:44 +00:00
|
|
|
points_proj_tot++;
|
2013-08-03 17:10:00 +00:00
|
|
|
if (pchan_circle_doSelectJoint(data, pchan, screen_co_b)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
is_point_done = true;
|
2012-10-05 05:59:15 +00:00
|
|
|
}
|
2012-10-05 17:51:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* check if the head and/or tail is in the circle
|
|
|
|
* - the call to check also does the selection already
|
|
|
|
*/
|
2012-10-05 05:27:51 +00:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
/* only if the endpoints didn't get selected, deal with the middle of the bone too
|
|
|
|
* It works nicer to only do this if the head or tail are not in the circle,
|
|
|
|
* otherwise there is no way to circle select joints alone */
|
2013-03-19 23:17:44 +00:00
|
|
|
if ((is_point_done == false) && (points_proj_tot == 2) &&
|
2012-10-10 01:22:19 +00:00
|
|
|
edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
|
2012-10-05 17:51:44 +00:00
|
|
|
{
|
|
|
|
if (data->select) pchan->bone->flag |= BONE_SELECTED;
|
|
|
|
else pchan->bone->flag &= ~BONE_SELECTED;
|
2013-11-26 06:39:14 +11:00
|
|
|
data->is_changed = true;
|
2012-10-05 05:27:51 +00:00
|
|
|
}
|
2012-10-05 17:51:44 +00:00
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
data->is_changed |= is_point_done;
|
2010-12-31 03:35:34 +00:00
|
|
|
}
|
2012-10-05 17:51:44 +00:00
|
|
|
}
|
2013-06-15 06:03:15 +00:00
|
|
|
static void pose_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2012-10-05 17:51:44 +00:00
|
|
|
{
|
|
|
|
CircleSelectUserData data;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-10-05 17:51:44 +00:00
|
|
|
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
|
|
|
|
|
|
|
|
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-10-10 04:03:22 +00:00
|
|
|
pose_foreachScreenBone(vc, do_circle_select_pose__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2010-12-31 03:35:34 +00:00
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
if (data.is_changed) {
|
2018-08-28 16:17:37 +10:00
|
|
|
ED_pose_bone_select_tag_update(vc->obact);
|
2010-12-31 03:35:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-08 23:15:12 +11:00
|
|
|
static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], bool head)
|
2009-11-05 08:54:33 +00:00
|
|
|
{
|
2012-01-26 08:12:12 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
2012-10-10 01:22:19 +00:00
|
|
|
|
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2009-11-05 08:54:33 +00:00
|
|
|
if (head) {
|
2013-07-16 03:41:09 +00:00
|
|
|
if (data->select)
|
|
|
|
ebone->flag |= BONE_ROOTSEL;
|
2018-06-04 09:31:30 +02:00
|
|
|
else
|
2013-07-16 03:41:09 +00:00
|
|
|
ebone->flag &= ~BONE_ROOTSEL;
|
2009-11-05 08:54:33 +00:00
|
|
|
}
|
|
|
|
else {
|
2013-07-16 03:41:09 +00:00
|
|
|
if (data->select)
|
|
|
|
ebone->flag |= BONE_TIPSEL;
|
2018-06-04 09:31:30 +02:00
|
|
|
else
|
2013-07-16 03:41:09 +00:00
|
|
|
ebone->flag &= ~BONE_TIPSEL;
|
2009-11-05 08:54:33 +00:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2018-03-11 15:50:07 +11:00
|
|
|
static void do_circle_select_armature__doSelectBone(
|
|
|
|
void *userData, struct EditBone *ebone, const float screen_co_a[2], const float screen_co_b[2])
|
2009-11-05 08:54:33 +00:00
|
|
|
{
|
2012-10-05 17:07:02 +00:00
|
|
|
CircleSelectUserData *data = userData;
|
|
|
|
bArmature *arm = data->vc->obedit->data;
|
2009-11-05 08:54:33 +00:00
|
|
|
|
2013-07-15 02:03:31 +00:00
|
|
|
if (data->select ? EBONE_SELECTABLE(arm, ebone) : EBONE_VISIBLE(arm, ebone)) {
|
2013-03-19 23:17:44 +00:00
|
|
|
bool is_point_done = false;
|
2012-10-05 17:07:02 +00:00
|
|
|
int points_proj_tot = 0;
|
2012-10-05 05:27:51 +00:00
|
|
|
|
2012-10-05 17:07:02 +00:00
|
|
|
/* project head location to screenspace */
|
2012-10-10 01:22:19 +00:00
|
|
|
if (screen_co_a[0] != IS_CLIPPED) {
|
2012-10-05 17:07:02 +00:00
|
|
|
points_proj_tot++;
|
2013-03-19 23:17:44 +00:00
|
|
|
if (armature_circle_doSelectJoint(data, ebone, screen_co_a, true)) {
|
|
|
|
is_point_done = true;
|
2012-10-05 05:59:15 +00:00
|
|
|
}
|
2012-10-05 17:07:02 +00:00
|
|
|
}
|
2012-10-05 05:27:51 +00:00
|
|
|
|
2012-10-05 17:07:02 +00:00
|
|
|
/* project tail location to screenspace */
|
2012-10-10 01:22:19 +00:00
|
|
|
if (screen_co_b[0] != IS_CLIPPED) {
|
2012-10-05 17:07:02 +00:00
|
|
|
points_proj_tot++;
|
2013-03-19 23:17:44 +00:00
|
|
|
if (armature_circle_doSelectJoint(data, ebone, screen_co_b, false)) {
|
|
|
|
is_point_done = true;
|
2012-10-05 05:59:15 +00:00
|
|
|
}
|
2012-10-05 17:07:02 +00:00
|
|
|
}
|
2012-10-05 05:27:51 +00:00
|
|
|
|
2012-10-05 17:07:02 +00:00
|
|
|
/* check if the head and/or tail is in the circle
|
|
|
|
* - the call to check also does the selection already
|
|
|
|
*/
|
2012-10-05 05:27:51 +00:00
|
|
|
|
2012-10-05 17:07:02 +00:00
|
|
|
/* only if the endpoints didn't get selected, deal with the middle of the bone too
|
|
|
|
* It works nicer to only do this if the head or tail are not in the circle,
|
|
|
|
* otherwise there is no way to circle select joints alone */
|
2013-03-19 23:17:44 +00:00
|
|
|
if ((is_point_done == false) && (points_proj_tot == 2) &&
|
2012-10-10 01:22:19 +00:00
|
|
|
edge_inside_circle(data->mval_fl, data->radius, screen_co_a, screen_co_b))
|
2012-10-05 17:07:02 +00:00
|
|
|
{
|
2013-07-16 03:41:09 +00:00
|
|
|
if (data->select) ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
|
|
|
else ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
|
2013-11-26 06:39:14 +11:00
|
|
|
data->is_changed = true;
|
2009-11-05 08:54:33 +00:00
|
|
|
}
|
2012-10-05 17:07:02 +00:00
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
data->is_changed |= is_point_done;
|
2009-11-05 08:54:33 +00:00
|
|
|
}
|
2012-10-05 17:07:02 +00:00
|
|
|
}
|
2013-06-15 06:03:15 +00:00
|
|
|
static void armature_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2012-10-05 17:07:02 +00:00
|
|
|
{
|
|
|
|
CircleSelectUserData data;
|
|
|
|
bArmature *arm = vc->obedit->data;
|
|
|
|
|
|
|
|
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
|
|
|
|
|
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
|
|
|
|
|
2012-10-10 04:03:22 +00:00
|
|
|
armature_foreachScreenBone(vc, do_circle_select_armature__doSelectBone, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2009-11-09 21:03:54 +00:00
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
if (data.is_changed) {
|
2018-04-15 11:45:51 +02:00
|
|
|
ED_armature_edit_sync_selection(arm->edbo);
|
|
|
|
ED_armature_edit_validate_active(arm);
|
2012-03-25 23:54:33 +00:00
|
|
|
WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, vc->obedit);
|
2010-09-15 13:22:36 +00:00
|
|
|
}
|
2009-11-05 08:54:33 +00:00
|
|
|
}
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void do_circle_select_mball__doSelectElem(void *userData, struct MetaElem *ml, const float screen_co[2])
|
2012-10-06 03:02:14 +00:00
|
|
|
{
|
|
|
|
CircleSelectUserData *data = userData;
|
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
|
2012-10-06 03:02:14 +00:00
|
|
|
if (data->select) ml->flag |= SELECT;
|
|
|
|
else ml->flag &= ~SELECT;
|
2013-11-26 06:39:14 +11:00
|
|
|
data->is_changed = true;
|
2012-10-06 03:02:14 +00:00
|
|
|
}
|
|
|
|
}
|
2013-06-15 06:03:15 +00:00
|
|
|
static void mball_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2012-10-06 01:30:49 +00:00
|
|
|
{
|
2012-10-06 03:02:14 +00:00
|
|
|
CircleSelectUserData data;
|
2012-10-06 01:30:49 +00:00
|
|
|
|
2012-10-06 03:02:14 +00:00
|
|
|
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
|
2012-10-06 01:30:49 +00:00
|
|
|
|
|
|
|
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
|
|
|
|
|
2012-10-10 04:03:22 +00:00
|
|
|
mball_foreachScreenElem(vc, do_circle_select_mball__doSelectElem, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
2012-10-06 01:30:49 +00:00
|
|
|
}
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/** Callbacks for circle selection in Editmode */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2017-08-16 12:45:11 +10:00
|
|
|
static void obedit_circle_select(
|
2018-04-06 12:07:27 +02:00
|
|
|
ViewContext *vc, const bool select, const int mval[2], float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2012-03-25 23:54:33 +00:00
|
|
|
switch (vc->obedit->type) {
|
|
|
|
case OB_MESH:
|
2018-04-06 12:07:27 +02:00
|
|
|
mesh_circle_select(vc, select, mval, rad);
|
2012-03-25 23:54:33 +00:00
|
|
|
break;
|
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
|
|
|
nurbscurve_circle_select(vc, select, mval, rad);
|
|
|
|
break;
|
|
|
|
case OB_LATTICE:
|
|
|
|
lattice_circle_select(vc, select, mval, rad);
|
|
|
|
break;
|
|
|
|
case OB_ARMATURE:
|
|
|
|
armature_circle_select(vc, select, mval, rad);
|
|
|
|
break;
|
2012-10-06 01:30:49 +00:00
|
|
|
case OB_MBALL:
|
|
|
|
mball_circle_select(vc, select, mval, rad);
|
|
|
|
break;
|
2012-03-25 23:54:33 +00:00
|
|
|
default:
|
|
|
|
return;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-15 06:03:15 +00:00
|
|
|
static bool object_circle_select(ViewContext *vc, const bool select, const int mval[2], float rad)
|
2012-10-06 01:30:49 +00:00
|
|
|
{
|
2017-11-23 13:51:49 -02:00
|
|
|
ViewLayer *view_layer = vc->view_layer;
|
2018-11-23 14:41:38 -02:00
|
|
|
View3D *v3d = vc->v3d;
|
|
|
|
|
2012-10-06 01:30:49 +00:00
|
|
|
const float radius_squared = rad * rad;
|
|
|
|
const float mval_fl[2] = {mval[0], mval[1]};
|
2013-11-26 06:39:14 +11:00
|
|
|
bool changed = false;
|
2017-02-08 12:26:41 +01:00
|
|
|
const int select_flag = select ? BASE_SELECTED : 0;
|
2013-06-15 06:03:15 +00:00
|
|
|
|
2012-10-06 01:30:49 +00:00
|
|
|
|
2017-02-08 12:26:41 +01:00
|
|
|
Base *base;
|
2017-11-23 13:51:49 -02:00
|
|
|
for (base = FIRSTBASE(view_layer); base; base = base->next) {
|
2018-11-23 14:41:38 -02:00
|
|
|
if (BASE_SELECTABLE(v3d, base) && ((base->flag & BASE_SELECTED) != select_flag)) {
|
2012-10-06 01:30:49 +00:00
|
|
|
float screen_co[2];
|
2018-03-11 15:50:07 +11:00
|
|
|
if (ED_view3d_project_float_global(
|
|
|
|
vc->ar, base->object->obmat[3], screen_co,
|
|
|
|
V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_WIN | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK)
|
2012-10-06 01:30:49 +00:00
|
|
|
{
|
|
|
|
if (len_squared_v2v2(mval_fl, screen_co) <= radius_squared) {
|
2017-02-08 12:26:41 +01:00
|
|
|
ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
|
2013-11-26 06:39:14 +11:00
|
|
|
changed = true;
|
2012-10-06 01:30:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-26 06:39:14 +11:00
|
|
|
return changed;
|
2012-10-06 01:30:49 +00:00
|
|
|
}
|
|
|
|
|
2008-12-29 12:15:42 +00:00
|
|
|
/* not a real operator, only for circle test */
|
2009-01-02 14:11:18 +00:00
|
|
|
static int view3d_circle_select_exec(bContext *C, wmOperator *op)
|
2008-12-21 16:24:19 +00:00
|
|
|
{
|
2018-04-16 16:27:55 +02:00
|
|
|
ViewContext vc;
|
2013-03-22 04:40:45 +00:00
|
|
|
const int radius = RNA_int_get(op->ptr, "radius");
|
2017-10-16 21:58:51 +11:00
|
|
|
const bool select = !RNA_boolean_get(op->ptr, "deselect");
|
2012-10-06 01:30:49 +00:00
|
|
|
const int mval[2] = {RNA_int_get(op->ptr, "x"),
|
|
|
|
RNA_int_get(op->ptr, "y")};
|
2011-05-11 09:31:00 +00:00
|
|
|
|
2018-04-16 16:27:55 +02:00
|
|
|
|
|
|
|
ED_view3d_viewcontext_init(C, &vc);
|
|
|
|
|
|
|
|
Object *obact = vc.obact;
|
|
|
|
Object *obedit = vc.obedit;
|
|
|
|
|
|
|
|
if (obedit || BKE_paint_select_elem_test(obact) ||
|
2018-04-05 18:20:27 +02:00
|
|
|
(obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
|
2010-12-31 03:35:34 +00:00
|
|
|
{
|
2.5
Sanitized the 'tweak' event.
Original idea was to have WM event system generating it
automatically. However, I first tested it via a handler
and operator, to check what kind of configurations would
be useful. It appeared to not work nice, also because
that inserting a tweak operator in a keymap is confusing.
Now 'tweaks' are generated automatically, and can be
catched by keymaps as any event. The current definition
of tweak is:
- if Left/Middle/Rightmouse pressed
if event wasn't handled by window queue (modal handlers)
start checking mousepositions
- while mousepositions are checked
- escape on any event other than mouse
- on mouse events:
- add tweak event if mousemove > 10 pixels
- stop checking for tweak if mousebutton released
- Tweak events have a define indicating mousebutton used
EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R
- In keymap definitions you can use _S or _A to map to
action or select mouse userdef.
- Event value in keymap should be KM_ANY for all tweaks,
or use one of the eight directions:
EVT_GESTURE_E, _SE, _S, _SW, _W, _NW, _N, _NE
- And of course you can add modifier checks in keymaps for it.
- Because tweaks are a result of mouse events, the handlers get
both to evaluate. That means that RMB-select + tweak will work
correctly.
In case you don't want both to be handled, for example the
CTRL+LMB 'extrude' and CTRL+LMB-tweak 'lasso select', you will
need to set the first acting on a EVT_RELEASE, this event only
gets passed on when tweak fails.
The current system allows all options, configurable, we had in 2.48,
and many more! A diagram of what's possible is on the todo. :)
Also in this commit: lasso select editmesh failed with 'zbuffer
occluded select'. Also circle-select failed.
2009-02-02 14:13:14 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
2018-04-16 16:27:55 +02:00
|
|
|
|
2018-12-01 19:43:10 +03:00
|
|
|
FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) {
|
2018-04-16 17:54:33 +02:00
|
|
|
ED_view3d_viewcontext_init_object(&vc, ob_iter);
|
2018-04-16 16:27:55 +02:00
|
|
|
|
2018-04-16 17:54:33 +02:00
|
|
|
obact = vc.obact;
|
|
|
|
obedit = vc.obedit;
|
2018-02-06 17:06:20 +11:00
|
|
|
|
2018-04-16 17:54:33 +02:00
|
|
|
if (CTX_data_edit_object(C)) {
|
2018-04-06 12:07:27 +02:00
|
|
|
obedit_circle_select(&vc, select, mval, (float)radius);
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(obact->data, ID_RECALC_SELECT);
|
2018-04-16 17:54:33 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
|
|
|
|
}
|
|
|
|
else if (BKE_paint_select_face_test(obact)) {
|
2018-04-06 12:07:27 +02:00
|
|
|
paint_facesel_circle_select(&vc, select, mval, (float)radius);
|
2018-04-16 17:54:33 +02:00
|
|
|
}
|
|
|
|
else if (BKE_paint_select_vert_test(obact)) {
|
2018-04-06 12:07:27 +02:00
|
|
|
paint_vertsel_circle_select(&vc, select, mval, (float)radius);
|
2018-04-16 17:54:33 +02:00
|
|
|
}
|
|
|
|
else if (obact->mode & OB_MODE_POSE) {
|
|
|
|
pose_circle_select(&vc, select, mval, (float)radius);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return PE_circle_select(C, select, mval, (float)radius);
|
|
|
|
}
|
2018-04-16 16:27:55 +02:00
|
|
|
}
|
|
|
|
FOREACH_OBJECT_IN_MODE_END;
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
2018-04-05 18:20:27 +02:00
|
|
|
else if (obact && obact->mode & OB_MODE_SCULPT) {
|
2010-01-04 17:03:44 +00:00
|
|
|
return OPERATOR_CANCELLED;
|
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
else {
|
2012-10-06 01:30:49 +00:00
|
|
|
if (object_circle_select(&vc, select, mval, (float)radius)) {
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT);
|
2018-04-16 16:27:55 +02:00
|
|
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
|
2008-12-21 16:24:19 +00:00
|
|
|
}
|
|
|
|
}
|
2018-03-08 17:21:39 +11:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
return OPERATOR_FINISHED;
|
2008-12-21 16:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-29 02:15:13 +00:00
|
|
|
void VIEW3D_OT_select_circle(wmOperatorType *ot)
|
2008-12-21 16:24:19 +00:00
|
|
|
{
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "Circle Select";
|
|
|
|
ot->description = "Select items using circle selection";
|
|
|
|
ot->idname = "VIEW3D_OT_select_circle";
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->invoke = WM_gesture_circle_invoke;
|
|
|
|
ot->modal = WM_gesture_circle_modal;
|
|
|
|
ot->exec = view3d_circle_select_exec;
|
|
|
|
ot->poll = view3d_selectable_data;
|
|
|
|
ot->cancel = WM_gesture_circle_cancel;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->flag = OPTYPE_UNDO;
|
2017-10-16 15:32:09 +11:00
|
|
|
|
|
|
|
/* properties */
|
2017-10-16 21:58:51 +11:00
|
|
|
WM_operator_properties_gesture_circle_select(ot);
|
2008-12-21 16:24:19 +00:00
|
|
|
}
|
2018-12-13 13:04:25 +11:00
|
|
|
|
|
|
|
/** \} */
|