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:
authorHans Goudey <h.goudey@me.com>2019-11-21 00:12:32 +0300
committerHans Goudey <h.goudey@me.com>2019-11-21 00:25:28 +0300
commitba1e9ae4733ae956331c7e8899f6939997205298 (patch)
tree007362ed2c9ee4564b67404f552906d6e66848db /source/blender/editors/interface/interface_templates.c
parent8c6ce742391b2b8798143a4a2c2224ebbeb7f1ec (diff)
Bevel: Custom Profile and CurveProfile Widget
Custom profiles in bevel allows the profile curve to be controlled by manually placed control points. Orientation is regularized along groups of edges, and the 'pipe case' is updated. This commit includes many updates to comments and changed variable names as well. A 'cutoff' vertex mesh method is added to bevel in addition to the existing grid fill option for replacing vertices. The UI of the bevel modifier and tool are updated and unified. Also, a 'CurveProfile' widget is added to BKE for defining the profile in the interface, which may be useful in other situations. Many thanks to Howard, my mentor for this GSoC project. Reviewers: howardt, campbellbarton Differential Revision: https://developer.blender.org/D5516
Diffstat (limited to 'source/blender/editors/interface/interface_templates.c')
-rw-r--r--source/blender/editors/interface/interface_templates.c608
1 files changed, 608 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 021d7733fae..b205572ba06 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -35,6 +35,7 @@
#include "DNA_texture_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_shader_fx_types.h"
+#include "DNA_curveprofile_types.h"
#include "BLI_utildefines.h"
#include "BLI_alloca.h"
@@ -69,6 +70,7 @@
#include "BKE_packedFile.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
+#include "BKE_curveprofile.h"
#include "BKE_report.h"
#include "BKE_screen.h"
#include "BKE_shader_fx.h"
@@ -4505,6 +4507,612 @@ void uiTemplateCurveMapping(uiLayout *layout,
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Curve Profile Template
+ * \{ */
+
+static void CurveProfile_presets_dofunc(bContext *C, void *profile_v, int event)
+{
+ CurveProfile *profile = profile_v;
+
+ profile->preset = event;
+ BKE_curveprofile_reset(profile);
+ BKE_curveprofile_update(profile, false);
+
+ ED_undo_push(C, "CurveProfile tools");
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static uiBlock *CurveProfile_presets_func(bContext *C, ARegion *ar, CurveProfile *profile)
+{
+ uiBlock *block;
+ short yco = 0;
+ short menuwidth = 12 * UI_UNIT_X;
+ menuwidth = 0;
+
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_func_butmenu_set(block, CurveProfile_presets_dofunc, profile);
+
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Default"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ PROF_PRESET_LINE,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Support Loops"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ PROF_PRESET_SUPPORTS,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Cornice Moulding"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ PROF_PRESET_CORNICE,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Crown Moulding"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ PROF_PRESET_CROWN,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Steps"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ PROF_PRESET_STEPS,
+ "");
+
+ UI_block_direction_set(block, UI_DIR_DOWN);
+ UI_block_bounds_set_text(block, (int)(3.0f * UI_UNIT_X));
+
+ return block;
+}
+
+static uiBlock *CurveProfile_buttons_presets(bContext *C, ARegion *ar, void *profile_v)
+{
+ return CurveProfile_presets_func(C, ar, (CurveProfile *)profile_v);
+}
+
+/* Only for CurveProfile tools block */
+enum {
+ UIPROFILE_FUNC_RESET,
+ UIPROFILE_FUNC_RESET_VIEW,
+};
+
+static void CurveProfile_tools_dofunc(bContext *C, void *profile_v, int event)
+{
+ CurveProfile *profile = profile_v;
+
+ switch (event) {
+ case UIPROFILE_FUNC_RESET: /* reset */
+ BKE_curveprofile_reset(profile);
+ BKE_curveprofile_update(profile, false);
+ break;
+ case UIPROFILE_FUNC_RESET_VIEW: /* reset view to clipping rect */
+ profile->view_rect = profile->clip_rect;
+ break;
+ }
+ ED_undo_push(C, "CurveProfile tools");
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static uiBlock *CurveProfile_tools_func(bContext *C, ARegion *ar, CurveProfile *profile)
+{
+ uiBlock *block;
+ short yco = 0;
+ short menuwidth = 10 * UI_UNIT_X;
+
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_func_butmenu_set(block, CurveProfile_tools_dofunc, profile);
+
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Reset View"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UIPROFILE_FUNC_RESET_VIEW,
+ "");
+ uiDefIconTextBut(block,
+ UI_BTYPE_BUT_MENU,
+ 1,
+ ICON_BLANK1,
+ IFACE_("Reset Curve"),
+ 0,
+ yco -= UI_UNIT_Y,
+ menuwidth,
+ UI_UNIT_Y,
+ NULL,
+ 0.0,
+ 0.0,
+ 0,
+ UIPROFILE_FUNC_RESET,
+ "");
+
+ UI_block_direction_set(block, UI_DIR_DOWN);
+ UI_block_bounds_set_text(block, (int)(3.0f * UI_UNIT_X));
+
+ return block;
+}
+
+static uiBlock *CurveProfile_buttons_tools(bContext *C, ARegion *ar, void *profile_v)
+{
+ return CurveProfile_tools_func(C, ar, (CurveProfile *)profile_v);
+}
+
+static void CurveProfile_buttons_zoom_in(bContext *C, void *profile_v, void *UNUSED(arg))
+{
+ CurveProfile *profile = profile_v;
+ float d;
+
+ /* we allow 20 times zoom */
+ if (BLI_rctf_size_x(&profile->view_rect) > 0.04f * BLI_rctf_size_x(&profile->clip_rect)) {
+ d = 0.1154f * BLI_rctf_size_x(&profile->view_rect);
+ profile->view_rect.xmin += d;
+ profile->view_rect.xmax -= d;
+ d = 0.1154f * BLI_rctf_size_y(&profile->view_rect);
+ profile->view_rect.ymin += d;
+ profile->view_rect.ymax -= d;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static void CurveProfile_buttons_zoom_out(bContext *C, void *profile_v, void *UNUSED(arg))
+{
+ CurveProfile *profile = profile_v;
+ float d, d1;
+
+ /* Allow 20 times zoom, but don't view outside clip */
+ if (BLI_rctf_size_x(&profile->view_rect) < 20.0f * BLI_rctf_size_x(&profile->clip_rect)) {
+ d = d1 = 0.15f * BLI_rctf_size_x(&profile->view_rect);
+
+ if (profile->flag & PROF_USE_CLIP) {
+ if (profile->view_rect.xmin - d < profile->clip_rect.xmin) {
+ d1 = profile->view_rect.xmin - profile->clip_rect.xmin;
+ }
+ }
+ profile->view_rect.xmin -= d1;
+
+ d1 = d;
+ if (profile->flag & PROF_USE_CLIP) {
+ if (profile->view_rect.xmax + d > profile->clip_rect.xmax) {
+ d1 = -profile->view_rect.xmax + profile->clip_rect.xmax;
+ }
+ }
+ profile->view_rect.xmax += d1;
+
+ d = d1 = 0.15f * BLI_rctf_size_y(&profile->view_rect);
+
+ if (profile->flag & PROF_USE_CLIP) {
+ if (profile->view_rect.ymin - d < profile->clip_rect.ymin) {
+ d1 = profile->view_rect.ymin - profile->clip_rect.ymin;
+ }
+ }
+ profile->view_rect.ymin -= d1;
+
+ d1 = d;
+ if (profile->flag & PROF_USE_CLIP) {
+ if (profile->view_rect.ymax + d > profile->clip_rect.ymax) {
+ d1 = -profile->view_rect.ymax + profile->clip_rect.ymax;
+ }
+ }
+ profile->view_rect.ymax += d1;
+ }
+
+ ED_region_tag_redraw(CTX_wm_region(C));
+}
+
+static void CurveProfile_clipping_toggle(bContext *C, void *cb_v, void *profile_v)
+{
+ CurveProfile *profile = profile_v;
+
+ profile->flag ^= PROF_USE_CLIP;
+
+ BKE_curveprofile_update(profile, false);
+ rna_update_cb(C, cb_v, NULL);
+}
+
+static void CurveProfile_buttons_reverse(bContext *C, void *cb_v, void *profile_v)
+{
+ CurveProfile *profile = profile_v;
+
+ BKE_curveprofile_reverse(profile);
+ BKE_curveprofile_update(profile, false);
+ rna_update_cb(C, cb_v, NULL);
+}
+
+static void CurveProfile_buttons_delete(bContext *C, void *cb_v, void *profile_v)
+{
+ CurveProfile *profile = profile_v;
+
+ BKE_curveprofile_remove_by_flag(profile, SELECT);
+ BKE_curveprofile_update(profile, false);
+
+ rna_update_cb(C, cb_v, NULL);
+}
+
+static void CurveProfile_buttons_setsharp(bContext *C, void *cb_v, void *profile_v)
+{
+ CurveProfile *profile = profile_v;
+
+ BKE_curveprofile_selected_handle_set(profile, HD_VECT, HD_VECT);
+ BKE_curveprofile_update(profile, false);
+
+ rna_update_cb(C, cb_v, NULL);
+}
+
+static void CurveProfile_buttons_setcurved(bContext *C, void *cb_v, void *profile_v)
+{
+ CurveProfile *profile = profile_v;
+
+ BKE_curveprofile_selected_handle_set(profile, HD_AUTO, HD_AUTO);
+ BKE_curveprofile_update(profile, false);
+
+ rna_update_cb(C, cb_v, NULL);
+}
+
+static void CurveProfile_buttons_update(bContext *C, void *arg1_v, void *profile_v)
+{
+ CurveProfile *profile = profile_v;
+ BKE_curveprofile_update(profile, true);
+ rna_update_cb(C, arg1_v, NULL);
+}
+
+static void CurveProfile_buttons_layout(uiLayout *layout, PointerRNA *ptr, RNAUpdateCb *cb)
+{
+ CurveProfile *profile = ptr->data;
+ CurveProfilePoint *point = NULL;
+ uiLayout *row, *sub;
+ uiBlock *block;
+ uiBut *bt;
+ int i, icon, path_width, path_height;
+ bool point_last_or_first = false;
+ rctf bounds;
+
+ block = uiLayoutGetBlock(layout);
+
+ UI_block_emboss_set(block, UI_EMBOSS);
+
+ uiLayoutRow(layout, false);
+
+ /* Preset selector */
+ /* There is probably potential to use simpler "uiItemR" functions here, but automatic updating
+ * after a preset is selected would be more complicated. */
+ bt = uiDefBlockBut(
+ block, CurveProfile_buttons_presets, profile, "Preset", 0, 0, UI_UNIT_X, UI_UNIT_X, "");
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ row = uiLayoutRow(layout, false);
+
+ /* (Left aligned) */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
+
+ /* Zoom in */
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_ZOOM_IN,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Zoom in"));
+ UI_but_func_set(bt, CurveProfile_buttons_zoom_in, profile, NULL);
+
+ /* Zoom out */
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_ZOOM_OUT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Zoom out"));
+ UI_but_func_set(bt, CurveProfile_buttons_zoom_out, profile, NULL);
+
+ /* (Right aligned) */
+ sub = uiLayoutRow(row, true);
+ uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT);
+
+ /* Reset view, reset curve */
+ bt = uiDefIconBlockBut(
+ block, CurveProfile_buttons_tools, profile, 0, 0, 0, 0, UI_UNIT_X, UI_UNIT_X, TIP_("Tools"));
+ UI_but_funcN_set(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ /* Flip path */
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_ARROW_LEFTRIGHT,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Reverse Path"));
+ UI_but_funcN_set(bt, CurveProfile_buttons_reverse, MEM_dupallocN(cb), profile);
+
+ /* Clipping toggle */
+ icon = (profile->flag & PROF_USE_CLIP) ? ICON_CLIPUV_HLT : ICON_CLIPUV_DEHLT;
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ icon,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Toggle Profile Clipping"));
+ UI_but_funcN_set(bt, CurveProfile_clipping_toggle, MEM_dupallocN(cb), profile);
+
+ UI_block_funcN_set(block, rna_update_cb, MEM_dupallocN(cb), NULL);
+
+ /* The path itself */
+ path_width = max_ii(uiLayoutGetWidth(layout), UI_UNIT_X);
+ path_width = min_ii(path_width, (int)(16.0f * UI_UNIT_X));
+ path_height = path_width;
+ uiLayoutRow(layout, false);
+ uiDefBut(block,
+ UI_BTYPE_CURVEPROFILE,
+ 0,
+ "",
+ 0,
+ 0,
+ (short)path_width,
+ (short)path_height,
+ profile,
+ 0.0f,
+ 1.0f,
+ -1,
+ 0,
+ "");
+
+ /* Position sliders for (first) selected point */
+ for (i = 0; i < profile->path_len; i++) {
+ if (profile->path[i].flag & PROF_SELECT) {
+ point = &profile->path[i];
+ break;
+ }
+ }
+ if (i == 0 || i == profile->path_len - 1) {
+ point_last_or_first = true;
+ }
+
+ /* Selected point data */
+ if (point) {
+ if (profile->flag & PROF_USE_CLIP) {
+ bounds = profile->clip_rect;
+ }
+ else {
+ bounds.xmin = bounds.ymin = -1000.0;
+ bounds.xmax = bounds.ymax = 1000.0;
+ }
+
+ uiLayoutRow(layout, true);
+ UI_block_funcN_set(block, CurveProfile_buttons_update, MEM_dupallocN(cb), profile);
+
+ /* Sharp / Smooth */
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_LINCURVE,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Set the point's handle type to sharp."));
+ if (point_last_or_first) {
+ UI_but_flag_enable(bt, UI_BUT_DISABLED);
+ }
+ UI_but_funcN_set(bt, CurveProfile_buttons_setsharp, MEM_dupallocN(cb), profile);
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_SMOOTHCURVE,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Set the point's handle type to sharp."));
+ UI_but_funcN_set(bt, CurveProfile_buttons_setcurved, MEM_dupallocN(cb), profile);
+ if (point_last_or_first) {
+ UI_but_flag_enable(bt, UI_BUT_DISABLED);
+ }
+
+ /* Position */
+ bt = uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ "X:",
+ 0,
+ 2 * UI_UNIT_Y,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ &point->x,
+ bounds.xmin,
+ bounds.xmax,
+ 1,
+ 5,
+ "");
+ if (point_last_or_first) {
+ UI_but_flag_enable(bt, UI_BUT_DISABLED);
+ }
+
+ bt = uiDefButF(block,
+ UI_BTYPE_NUM,
+ 0,
+ "Y:",
+ 0,
+ 1 * UI_UNIT_Y,
+ UI_UNIT_X * 10,
+ UI_UNIT_Y,
+ &point->y,
+ bounds.ymin,
+ bounds.ymax,
+ 1,
+ 5,
+ "");
+ if (point_last_or_first) {
+ UI_but_flag_enable(bt, UI_BUT_DISABLED);
+ }
+
+ /* Delete points */
+ bt = uiDefIconBut(block,
+ UI_BTYPE_BUT,
+ 0,
+ ICON_X,
+ 0,
+ 0,
+ UI_UNIT_X,
+ UI_UNIT_X,
+ NULL,
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.0,
+ TIP_("Delete points"));
+ UI_but_funcN_set(bt, CurveProfile_buttons_delete, MEM_dupallocN(cb), profile);
+ if (point_last_or_first) {
+ UI_but_flag_enable(bt, UI_BUT_DISABLED);
+ }
+ }
+
+ uiItemR(layout, ptr, "use_sample_straight_edges", 0, NULL, ICON_NONE);
+ uiItemR(layout, ptr, "use_sample_even_lengths", 0, NULL, ICON_NONE);
+
+ UI_block_funcN_set(block, NULL, NULL, NULL);
+}
+
+/** Template for a path creation widget intended for custom bevel profiles.
+ * This section is quite similar to uiTemplateCurveMapping, but with reduced complexity */
+void uiTemplateCurveProfile(uiLayout *layout, PointerRNA *ptr, const char *propname)
+{
+ RNAUpdateCb *cb;
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ PointerRNA cptr;
+ ID *id;
+ uiBlock *block = uiLayoutGetBlock(layout);
+
+ if (!prop) {
+ RNA_warning(
+ "Curve Profile property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ RNA_warning(
+ "Curve Profile is not a pointer: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ cptr = RNA_property_pointer_get(ptr, prop);
+ if (!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveProfile)) {
+ return;
+ }
+
+ /* Share update functionality with the CurveMapping widget template. */
+ cb = MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
+ cb->ptr = *ptr;
+ cb->prop = prop;
+
+ id = cptr.owner_id;
+ UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE);
+
+ CurveProfile_buttons_layout(layout, &cptr, cb);
+
+ UI_block_lock_clear(block);
+
+ MEM_freeN(cb);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name ColorPicker Template
* \{ */