Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2012-03-14 10:32:43 +0400
committerNicholas Bishop <nicholasbishop@gmail.com>2012-03-14 10:32:43 +0400
commit7454d939c5ac94b114b1754e899e1395d2473dc9 (patch)
tree599830486f2f2d46afdb894e9e0826547463de8f /source/blender/editors/sculpt_paint/paint_hide.c
parent68b8f3b0a84d79ca75e3c4708836be6c83985abe (diff)
Add partial visibility operator including keymaps and menu items.
Uses HKEY for border hide, CTRL+HKEY for border show, and ALT+HKEY for show all. Documentation: http://wiki.blender.org/index.php/User:Nicholasbishop/PartialVisibility Code review: http://codereview.appspot.com/5695043
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_hide.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
new file mode 100644
index 00000000000..9008458cafa
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -0,0 +1,392 @@
+/*
+ * $Id$
+ *
+ * ***** 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
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2010 by Nicholas Bishop
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s):
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Implements the PBVH node hiding operator
+ *
+ */
+
+/** \file blender/editors/sculpt_paint/paint_hide.c
+ * \ingroup edsculpt
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_listbase.h"
+#include "BLI_math_vector.h"
+#include "BLI_pbvh.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_context.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_mesh.h"
+#include "BKE_multires.h"
+#include "BKE_paint.h"
+#include "BKE_subsurf.h"
+
+#include "BIF_glutil.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "paint_intern.h"
+#include "sculpt_intern.h" /* for undo push */
+
+#include <assert.h>
+
+static int planes_contain_v3(float (*planes)[4], int totplane, const float p[3])
+{
+ int i;
+
+ for(i = 0; i < totplane; i++) {
+ if(dot_v3v3(planes[i], p) + planes[i][3] > 0)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* return true if the element should be hidden/shown */
+static int is_effected(PartialVisArea area,
+ float planes[4][4],
+ const float co[3])
+{
+ if(area == PARTIALVIS_ALL)
+ return 1;
+ else {
+ int inside = planes_contain_v3(planes, 4, co);
+ return ((inside && area == PARTIALVIS_INSIDE) ||
+ (!inside && area == PARTIALVIS_OUTSIDE));
+ }
+}
+
+static void partialvis_update_mesh(Object *ob,
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
+{
+ MVert *mvert;
+ int *vert_indices;
+ int any_changed = 0, any_visible = 0, totvert, i;
+
+ BLI_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
+ BLI_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
+
+ sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+
+ for(i = 0; i < totvert; i++) {
+ MVert *v = &mvert[vert_indices[i]];
+
+ /* hide vertex if in the hide volume */
+ if(is_effected(area, planes, v->co)) {
+ if(action == PARTIALVIS_HIDE)
+ v->flag |= ME_HIDE;
+ else
+ v->flag &= ~ME_HIDE;
+ any_changed = 1;
+ }
+
+ if(!(v->flag & ME_HIDE))
+ any_visible = 1;
+ }
+
+ if(any_changed) {
+ BLI_pbvh_node_mark_rebuild_draw(node);
+ BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+ }
+}
+
+/* Hide or show elements in multires grids with a special GridFlags
+ customdata layer. */
+static void partialvis_update_grids(Object *ob,
+ PBVH *pbvh,
+ PBVHNode *node,
+ PartialVisAction action,
+ PartialVisArea area,
+ float planes[4][4])
+{
+ DMGridData **grids;
+ BLI_bitmap *grid_hidden;
+ int any_visible = 0;
+ int *grid_indices, gridsize, totgrid, any_changed, i;
+
+ /* get PBVH data */
+ BLI_pbvh_node_get_grids(pbvh, node,
+ &grid_indices, &totgrid, NULL, &gridsize,
+ &grids, NULL);
+ grid_hidden = BLI_pbvh_grid_hidden(pbvh);
+
+ sculpt_undo_push_node(ob, node, SCULPT_UNDO_HIDDEN);
+
+ any_changed = 0;
+ for(i = 0; i < totgrid; i++) {
+ int any_hidden = 0;
+ int g = grid_indices[i], x, y;
+ BLI_bitmap gh = grid_hidden[g];
+
+ if(!gh) {
+ switch(action) {
+ case PARTIALVIS_HIDE:
+ /* create grid flags data */
+ gh = grid_hidden[g] = BLI_BITMAP_NEW(gridsize * gridsize,
+ "partialvis_update_grids");
+ break;
+ case PARTIALVIS_SHOW:
+ /* entire grid is visible, nothing to show */
+ continue;
+ }
+ }
+ else if(action == PARTIALVIS_SHOW && area == PARTIALVIS_ALL) {
+ /* special case if we're showing all, just free the
+ grid */
+ MEM_freeN(gh);
+ grid_hidden[g] = NULL;
+ any_changed = 1;
+ any_visible = 1;
+ continue;
+ }
+
+ for(y = 0; y < gridsize; y++) {
+ for(x = 0; x < gridsize; x++) {
+ const float *co = grids[g][y * gridsize + x].co;
+
+ /* skip grid element if not in the effected area */
+ if(is_effected(area, planes, co)) {
+ /* set or clear the hide flag */
+ BLI_BITMAP_MODIFY(gh, y * gridsize + x,
+ action == PARTIALVIS_HIDE);
+
+ any_changed = 1;
+ }
+
+ /* keep track of whether any elements are still hidden */
+ if(BLI_BITMAP_GET(gh, y * gridsize + x))
+ any_hidden = 1;
+ else
+ any_visible = 1;
+ }
+ }
+
+ /* if everything in the grid is now visible, free the grid
+ flags */
+ if(!any_hidden) {
+ MEM_freeN(gh);
+ grid_hidden[g] = NULL;
+ }
+ }
+
+ /* mark updates if anything was hidden/shown */
+ if(any_changed) {
+ BLI_pbvh_node_mark_rebuild_draw(node);
+ BLI_pbvh_node_fully_hidden_set(node, !any_visible);
+ multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED);
+ }
+}
+
+static void rect_from_props(rcti *rect, PointerRNA *ptr)
+{
+ rect->xmin= RNA_int_get(ptr, "xmin");
+ rect->ymin= RNA_int_get(ptr, "ymin");
+ rect->xmax= RNA_int_get(ptr, "xmax");
+ rect->ymax= RNA_int_get(ptr, "ymax");
+}
+
+static void clip_planes_from_rect(bContext *C,
+ float clip_planes[4][4],
+ const rcti *rect)
+{
+ ViewContext vc;
+ BoundBox bb;
+ bglMats mats= {{0}};
+
+ view3d_operator_needs_opengl(C);
+ view3d_set_viewcontext(C, &vc);
+ view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
+ ED_view3d_calc_clipping(&bb, clip_planes, &mats, rect);
+ mul_m4_fl(clip_planes, -1.0f);
+}
+
+/* If mode is inside, get all PBVH nodes that lie at least partially
+ inside the clip_planes volume. If mode is outside, get all nodes
+ that lie at least partially outside the volume. If showing all, get
+ all nodes. */
+static void get_pbvh_nodes(PBVH *pbvh,
+ PBVHNode ***nodes,
+ int *totnode,
+ float clip_planes[4][4],
+ PartialVisArea mode)
+{
+ BLI_pbvh_SearchCallback cb;
+
+ /* select search callback */
+ switch(mode) {
+ case PARTIALVIS_INSIDE:
+ cb = BLI_pbvh_node_planes_contain_AABB;
+ break;
+ case PARTIALVIS_OUTSIDE:
+ cb = BLI_pbvh_node_planes_exclude_AABB;
+ break;
+ case PARTIALVIS_ALL:
+ cb = NULL;
+ }
+
+ BLI_pbvh_search_gather(pbvh, cb, clip_planes, nodes, totnode);
+}
+
+static int hide_show_exec(bContext *C, wmOperator *op)
+{
+ ARegion *ar = CTX_wm_region(C);
+ Object *ob = CTX_data_active_object(C);
+ Mesh *me = ob->data;
+ PartialVisAction action;
+ PartialVisArea area;
+ PBVH *pbvh;
+ PBVHNode **nodes;
+ DerivedMesh *dm;
+ PBVHType pbvh_type;
+ float clip_planes[4][4];
+ rcti rect;
+ int totnode, i;
+
+ /* read operator properties */
+ action = RNA_enum_get(op->ptr, "action");
+ area = RNA_enum_get(op->ptr, "area");
+ rect_from_props(&rect, op->ptr);
+
+ clip_planes_from_rect(C, clip_planes, &rect);
+
+ dm = mesh_get_derived_final(CTX_data_scene(C), ob, CD_MASK_BAREMESH);
+ pbvh = dm->getPBVH(ob, dm);
+ ob->sculpt->pbvh = pbvh;
+
+ get_pbvh_nodes(pbvh, &nodes, &totnode, clip_planes, area);
+ pbvh_type = BLI_pbvh_type(pbvh);
+
+ /* start undo */
+ switch(action) {
+ case PARTIALVIS_HIDE:
+ sculpt_undo_push_begin("Hide area");
+ break;
+ case PARTIALVIS_SHOW:
+ sculpt_undo_push_begin("Show area");
+ break;
+ }
+
+ for(i = 0; i < totnode; i++) {
+ switch(pbvh_type) {
+ case PBVH_FACES:
+ partialvis_update_mesh(ob, pbvh, nodes[i], action, area, clip_planes);
+ break;
+ case PBVH_GRIDS:
+ partialvis_update_grids(ob, pbvh, nodes[i], action, area, clip_planes);
+ break;
+ }
+ }
+
+ if(nodes)
+ MEM_freeN(nodes);
+
+ /* end undo */
+ sculpt_undo_push_end();
+
+ /* ensure that edges and faces get hidden as well (not used by
+ sculpt but it looks wrong when entering editmode otherwise) */
+ if(pbvh_type == PBVH_FACES) {
+ mesh_flush_hidden_from_verts(me->mvert, me->mloop,
+ me->medge, me->totedge,
+ me->mpoly, me->totpoly);
+ }
+
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+static int hide_show_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+ PartialVisArea area = RNA_enum_get(op->ptr, "area");
+
+ if(area != PARTIALVIS_ALL)
+ return WM_border_select_invoke(C, op, event);
+ else
+ return op->type->exec(C, op);
+}
+
+void PAINT_OT_hide_show(struct wmOperatorType *ot)
+{
+ static EnumPropertyItem action_items[] = {
+ {PARTIALVIS_HIDE, "HIDE", 0, "Hide", "Hide vertices"},
+ {PARTIALVIS_SHOW, "SHOW", 0, "Show", "Show vertices"},
+ {0}};
+
+ static EnumPropertyItem area_items[] = {
+ {PARTIALVIS_OUTSIDE, "OUTSIDE", 0, "Outside",
+ "Hide or show vertices outside the selection"},
+ {PARTIALVIS_INSIDE, "INSIDE", 0, "Inside",
+ "Hide or show vertices inside the selection"},
+ {PARTIALVIS_ALL, "ALL", 0, "All",
+ "Hide or show all vertices"},
+ {0}};
+
+ /* identifiers */
+ ot->name = "Hide/Show";
+ ot->idname = "PAINT_OT_hide_show";
+
+ /* api callbacks */
+ ot->invoke = hide_show_invoke;
+ ot->modal = WM_border_select_modal;
+ ot->exec = hide_show_exec;
+ /* sculpt-only for now */
+ ot->poll = sculpt_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER;
+
+ /* rna */
+ RNA_def_enum(ot->srna, "action", action_items, PARTIALVIS_HIDE,
+ "Action", "Whether to hide or show vertices");
+ RNA_def_enum(ot->srna, "area", area_items, PARTIALVIS_INSIDE,
+ "Area", "Which vertices to hide or show");
+
+ RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+ RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
+}