647 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			647 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * This program is free software; you can redistribute it and/or
 | 
						|
 * modify it under the terms of the GNU General Public License
 | 
						|
 * as published by the Free Software Foundation; either version 2
 | 
						|
 * of the License, or (at your option) any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful,
 | 
						|
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
 * GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program; if not, write to the Free Software Foundation,
 | 
						|
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
						|
 */
 | 
						|
 | 
						|
/** \file
 | 
						|
 * \ingroup spnode
 | 
						|
 */
 | 
						|
 | 
						|
#include <math.h>
 | 
						|
 | 
						|
#include "BLI_math_matrix.h"
 | 
						|
#include "BLI_math_vector.h"
 | 
						|
#include "BLI_rect.h"
 | 
						|
#include "BLI_utildefines.h"
 | 
						|
 | 
						|
#include "BKE_context.h"
 | 
						|
#include "BKE_image.h"
 | 
						|
#include "BKE_main.h"
 | 
						|
 | 
						|
#include "ED_gizmo_library.h"
 | 
						|
#include "ED_screen.h"
 | 
						|
 | 
						|
#include "IMB_imbuf_types.h"
 | 
						|
 | 
						|
#include "MEM_guardedalloc.h"
 | 
						|
 | 
						|
#include "RNA_access.h"
 | 
						|
 | 
						|
#include "WM_api.h"
 | 
						|
#include "WM_types.h"
 | 
						|
 | 
						|
#include "node_intern.h"
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/** \name Local Utilities
 | 
						|
 * \{ */
 | 
						|
 | 
						|
static void node_gizmo_calc_matrix_space(const SpaceNode *snode,
 | 
						|
                                         const ARegion *region,
 | 
						|
                                         float matrix_space[4][4])
 | 
						|
{
 | 
						|
  unit_m4(matrix_space);
 | 
						|
  mul_v3_fl(matrix_space[0], snode->zoom);
 | 
						|
  mul_v3_fl(matrix_space[1], snode->zoom);
 | 
						|
  matrix_space[3][0] = (region->winx / 2) + snode->xof;
 | 
						|
  matrix_space[3][1] = (region->winy / 2) + snode->yof;
 | 
						|
}
 | 
						|
 | 
						|
static void node_gizmo_calc_matrix_space_with_image_dims(const SpaceNode *snode,
 | 
						|
                                                         const ARegion *region,
 | 
						|
                                                         const float image_dims[2],
 | 
						|
                                                         float matrix_space[4][4])
 | 
						|
{
 | 
						|
  unit_m4(matrix_space);
 | 
						|
  mul_v3_fl(matrix_space[0], snode->zoom * image_dims[0]);
 | 
						|
  mul_v3_fl(matrix_space[1], snode->zoom * image_dims[1]);
 | 
						|
  matrix_space[3][0] = ((region->winx / 2) + snode->xof) - ((image_dims[0] / 2.0f) * snode->zoom);
 | 
						|
  matrix_space[3][1] = ((region->winy / 2) + snode->yof) - ((image_dims[1] / 2.0f) * snode->zoom);
 | 
						|
}
 | 
						|
 | 
						|
/** \} */
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/** \name Backdrop Gizmo
 | 
						|
 * \{ */
 | 
						|
 | 
						|
static void gizmo_node_backdrop_prop_matrix_get(const wmGizmo *UNUSED(gz),
 | 
						|
                                                wmGizmoProperty *gz_prop,
 | 
						|
                                                void *value_p)
 | 
						|
{
 | 
						|
  float(*matrix)[4] = value_p;
 | 
						|
  BLI_assert(gz_prop->type->array_length == 16);
 | 
						|
  const SpaceNode *snode = gz_prop->custom_func.user_data;
 | 
						|
  matrix[0][0] = snode->zoom;
 | 
						|
  matrix[1][1] = snode->zoom;
 | 
						|
  matrix[3][0] = snode->xof;
 | 
						|
  matrix[3][1] = snode->yof;
 | 
						|
}
 | 
						|
 | 
						|
static void gizmo_node_backdrop_prop_matrix_set(const wmGizmo *UNUSED(gz),
 | 
						|
                                                wmGizmoProperty *gz_prop,
 | 
						|
                                                const void *value_p)
 | 
						|
{
 | 
						|
  const float(*matrix)[4] = value_p;
 | 
						|
  BLI_assert(gz_prop->type->array_length == 16);
 | 
						|
  SpaceNode *snode = gz_prop->custom_func.user_data;
 | 
						|
  snode->zoom = matrix[0][0];
 | 
						|
  snode->zoom = matrix[1][1];
 | 
						|
  snode->xof = matrix[3][0];
 | 
						|
  snode->yof = matrix[3][1];
 | 
						|
}
 | 
						|
 | 
						|
static bool WIDGETGROUP_node_transform_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
 | 
						|
{
 | 
						|
  SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
 | 
						|
  if ((snode->flag & SNODE_BACKDRAW) == 0) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
 | 
						|
    bNode *node = nodeGetActive(snode->edittree);
 | 
						|
 | 
						|
    if (node && ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_transform_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  wmGizmoWrapper *wwrapper = MEM_mallocN(sizeof(wmGizmoWrapper), __func__);
 | 
						|
 | 
						|
  wwrapper->gizmo = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
 | 
						|
 | 
						|
  RNA_enum_set(wwrapper->gizmo->ptr,
 | 
						|
               "transform",
 | 
						|
               ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE_UNIFORM);
 | 
						|
 | 
						|
  gzgroup->customdata = wwrapper;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_transform_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  Main *bmain = CTX_data_main(C);
 | 
						|
  wmGizmo *cage = ((wmGizmoWrapper *)gzgroup->customdata)->gizmo;
 | 
						|
  const ARegion *region = CTX_wm_region(C);
 | 
						|
  /* center is always at the origin */
 | 
						|
  const float origin[3] = {region->winx / 2, region->winy / 2};
 | 
						|
 | 
						|
  void *lock;
 | 
						|
  Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
 | 
						|
  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
 | 
						|
 | 
						|
  if (ibuf) {
 | 
						|
    const float dims[2] = {
 | 
						|
        (ibuf->x > 0) ? ibuf->x : 64.0f,
 | 
						|
        (ibuf->y > 0) ? ibuf->y : 64.0f,
 | 
						|
    };
 | 
						|
 | 
						|
    RNA_float_set_array(cage->ptr, "dimensions", dims);
 | 
						|
    WM_gizmo_set_matrix_location(cage, origin);
 | 
						|
    WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, false);
 | 
						|
 | 
						|
    /* need to set property here for undo. TODO would prefer to do this in _init */
 | 
						|
    SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
#if 0
 | 
						|
    PointerRNA nodeptr;
 | 
						|
    RNA_pointer_create(snode->id, &RNA_SpaceNodeEditor, snode, &nodeptr);
 | 
						|
    WM_gizmo_target_property_def_rna(cage, "offset", &nodeptr, "backdrop_offset", -1);
 | 
						|
    WM_gizmo_target_property_def_rna(cage, "scale", &nodeptr, "backdrop_zoom", -1);
 | 
						|
#endif
 | 
						|
 | 
						|
    WM_gizmo_target_property_def_func(cage,
 | 
						|
                                      "matrix",
 | 
						|
                                      &(const struct wmGizmoPropertyFnParams){
 | 
						|
                                          .value_get_fn = gizmo_node_backdrop_prop_matrix_get,
 | 
						|
                                          .value_set_fn = gizmo_node_backdrop_prop_matrix_set,
 | 
						|
                                          .range_get_fn = NULL,
 | 
						|
                                          .user_data = snode,
 | 
						|
                                      });
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    WM_gizmo_set_flag(cage, WM_GIZMO_HIDDEN, true);
 | 
						|
  }
 | 
						|
 | 
						|
  BKE_image_release_ibuf(ima, ibuf, lock);
 | 
						|
}
 | 
						|
 | 
						|
void NODE_GGT_backdrop_transform(wmGizmoGroupType *gzgt)
 | 
						|
{
 | 
						|
  gzgt->name = "Backdrop Transform Widget";
 | 
						|
  gzgt->idname = "NODE_GGT_backdrop_transform";
 | 
						|
 | 
						|
  gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
 | 
						|
 | 
						|
  gzgt->poll = WIDGETGROUP_node_transform_poll;
 | 
						|
  gzgt->setup = WIDGETGROUP_node_transform_setup;
 | 
						|
  gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
 | 
						|
  gzgt->refresh = WIDGETGROUP_node_transform_refresh;
 | 
						|
}
 | 
						|
 | 
						|
/** \} */
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/** \name Crop Gizmo
 | 
						|
 * \{ */
 | 
						|
 | 
						|
struct NodeCropWidgetGroup {
 | 
						|
  wmGizmo *border;
 | 
						|
 | 
						|
  struct {
 | 
						|
    float dims[2];
 | 
						|
  } state;
 | 
						|
 | 
						|
  struct {
 | 
						|
    PointerRNA ptr;
 | 
						|
    PropertyRNA *prop;
 | 
						|
    bContext *context;
 | 
						|
  } update_data;
 | 
						|
};
 | 
						|
 | 
						|
static void gizmo_node_crop_update(struct NodeCropWidgetGroup *crop_group)
 | 
						|
{
 | 
						|
  RNA_property_update(
 | 
						|
      crop_group->update_data.context, &crop_group->update_data.ptr, crop_group->update_data.prop);
 | 
						|
}
 | 
						|
 | 
						|
static void two_xy_to_rect(const NodeTwoXYs *nxy,
 | 
						|
                           rctf *rect,
 | 
						|
                           const float dims[2],
 | 
						|
                           bool is_relative)
 | 
						|
{
 | 
						|
  if (is_relative) {
 | 
						|
    rect->xmin = nxy->fac_x1;
 | 
						|
    rect->xmax = nxy->fac_x2;
 | 
						|
    rect->ymin = nxy->fac_y1;
 | 
						|
    rect->ymax = nxy->fac_y2;
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    rect->xmin = nxy->x1 / dims[0];
 | 
						|
    rect->xmax = nxy->x2 / dims[0];
 | 
						|
    rect->ymin = nxy->y1 / dims[1];
 | 
						|
    rect->ymax = nxy->y2 / dims[1];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static void two_xy_from_rect(NodeTwoXYs *nxy,
 | 
						|
                             const rctf *rect,
 | 
						|
                             const float dims[2],
 | 
						|
                             bool is_relative)
 | 
						|
{
 | 
						|
  if (is_relative) {
 | 
						|
    nxy->fac_x1 = rect->xmin;
 | 
						|
    nxy->fac_x2 = rect->xmax;
 | 
						|
    nxy->fac_y1 = rect->ymin;
 | 
						|
    nxy->fac_y2 = rect->ymax;
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    nxy->x1 = rect->xmin * dims[0];
 | 
						|
    nxy->x2 = rect->xmax * dims[0];
 | 
						|
    nxy->y1 = rect->ymin * dims[1];
 | 
						|
    nxy->y2 = rect->ymax * dims[1];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/* scale callbacks */
 | 
						|
static void gizmo_node_crop_prop_matrix_get(const wmGizmo *gz,
 | 
						|
                                            wmGizmoProperty *gz_prop,
 | 
						|
                                            void *value_p)
 | 
						|
{
 | 
						|
  float(*matrix)[4] = value_p;
 | 
						|
  BLI_assert(gz_prop->type->array_length == 16);
 | 
						|
  struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
 | 
						|
  const float *dims = crop_group->state.dims;
 | 
						|
  const bNode *node = gz_prop->custom_func.user_data;
 | 
						|
  const NodeTwoXYs *nxy = node->storage;
 | 
						|
  bool is_relative = (bool)node->custom2;
 | 
						|
  rctf rct;
 | 
						|
  two_xy_to_rect(nxy, &rct, dims, is_relative);
 | 
						|
  matrix[0][0] = fabsf(BLI_rctf_size_x(&rct));
 | 
						|
  matrix[1][1] = fabsf(BLI_rctf_size_y(&rct));
 | 
						|
  matrix[3][0] = (BLI_rctf_cent_x(&rct) - 0.5f) * dims[0];
 | 
						|
  matrix[3][1] = (BLI_rctf_cent_y(&rct) - 0.5f) * dims[1];
 | 
						|
}
 | 
						|
 | 
						|
static void gizmo_node_crop_prop_matrix_set(const wmGizmo *gz,
 | 
						|
                                            wmGizmoProperty *gz_prop,
 | 
						|
                                            const void *value_p)
 | 
						|
{
 | 
						|
  const float(*matrix)[4] = value_p;
 | 
						|
  BLI_assert(gz_prop->type->array_length == 16);
 | 
						|
  struct NodeCropWidgetGroup *crop_group = gz->parent_gzgroup->customdata;
 | 
						|
  const float *dims = crop_group->state.dims;
 | 
						|
  bNode *node = gz_prop->custom_func.user_data;
 | 
						|
  NodeTwoXYs *nxy = node->storage;
 | 
						|
  bool is_relative = (bool)node->custom2;
 | 
						|
  rctf rct;
 | 
						|
  two_xy_to_rect(nxy, &rct, dims, is_relative);
 | 
						|
  const bool nx = rct.xmin > rct.xmax;
 | 
						|
  const bool ny = rct.ymin > rct.ymax;
 | 
						|
  BLI_rctf_resize(&rct, fabsf(matrix[0][0]), fabsf(matrix[1][1]));
 | 
						|
  BLI_rctf_recenter(&rct, (matrix[3][0] / dims[0]) + 0.5f, (matrix[3][1] / dims[1]) + 0.5f);
 | 
						|
  BLI_rctf_isect(
 | 
						|
      &(rctf){
 | 
						|
          .xmin = 0,
 | 
						|
          .ymin = 0,
 | 
						|
          .xmax = 1,
 | 
						|
          .ymax = 1,
 | 
						|
      },
 | 
						|
      &rct,
 | 
						|
      &rct);
 | 
						|
  if (nx) {
 | 
						|
    SWAP(float, rct.xmin, rct.xmax);
 | 
						|
  }
 | 
						|
  if (ny) {
 | 
						|
    SWAP(float, rct.ymin, rct.ymax);
 | 
						|
  }
 | 
						|
  two_xy_from_rect(nxy, &rct, dims, is_relative);
 | 
						|
  gizmo_node_crop_update(crop_group);
 | 
						|
}
 | 
						|
 | 
						|
static bool WIDGETGROUP_node_crop_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
 | 
						|
{
 | 
						|
  SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
 | 
						|
  if ((snode->flag & SNODE_BACKDRAW) == 0) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
 | 
						|
    bNode *node = nodeGetActive(snode->edittree);
 | 
						|
 | 
						|
    if (node && ELEM(node->type, CMP_NODE_CROP)) {
 | 
						|
      /* ignore 'use_crop_size', we can't usefully edit the crop in this case. */
 | 
						|
      if ((node->custom1 & (1 << 0)) == 0) {
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_crop_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  struct NodeCropWidgetGroup *crop_group = MEM_mallocN(sizeof(struct NodeCropWidgetGroup),
 | 
						|
                                                       __func__);
 | 
						|
 | 
						|
  crop_group->border = WM_gizmo_new("GIZMO_GT_cage_2d", gzgroup, NULL);
 | 
						|
 | 
						|
  RNA_enum_set(crop_group->border->ptr,
 | 
						|
               "transform",
 | 
						|
               ED_GIZMO_CAGE2D_XFORM_FLAG_TRANSLATE | ED_GIZMO_CAGE2D_XFORM_FLAG_SCALE);
 | 
						|
 | 
						|
  gzgroup->customdata = crop_group;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_crop_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  ARegion *region = CTX_wm_region(C);
 | 
						|
  wmGizmo *gz = gzgroup->gizmos.first;
 | 
						|
 | 
						|
  SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
 | 
						|
  node_gizmo_calc_matrix_space(snode, region, gz->matrix_space);
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_crop_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  Main *bmain = CTX_data_main(C);
 | 
						|
  struct NodeCropWidgetGroup *crop_group = gzgroup->customdata;
 | 
						|
  wmGizmo *gz = crop_group->border;
 | 
						|
 | 
						|
  void *lock;
 | 
						|
  Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
 | 
						|
  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
 | 
						|
 | 
						|
  if (ibuf) {
 | 
						|
    crop_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
 | 
						|
    crop_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
 | 
						|
 | 
						|
    RNA_float_set_array(gz->ptr, "dimensions", crop_group->state.dims);
 | 
						|
    WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, false);
 | 
						|
 | 
						|
    SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
    bNode *node = nodeGetActive(snode->edittree);
 | 
						|
 | 
						|
    crop_group->update_data.context = (bContext *)C;
 | 
						|
    RNA_pointer_create(
 | 
						|
        (ID *)snode->edittree, &RNA_CompositorNodeCrop, node, &crop_group->update_data.ptr);
 | 
						|
    crop_group->update_data.prop = RNA_struct_find_property(&crop_group->update_data.ptr,
 | 
						|
                                                            "relative");
 | 
						|
 | 
						|
    WM_gizmo_target_property_def_func(gz,
 | 
						|
                                      "matrix",
 | 
						|
                                      &(const struct wmGizmoPropertyFnParams){
 | 
						|
                                          .value_get_fn = gizmo_node_crop_prop_matrix_get,
 | 
						|
                                          .value_set_fn = gizmo_node_crop_prop_matrix_set,
 | 
						|
                                          .range_get_fn = NULL,
 | 
						|
                                          .user_data = node,
 | 
						|
                                      });
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
 | 
						|
  }
 | 
						|
 | 
						|
  BKE_image_release_ibuf(ima, ibuf, lock);
 | 
						|
}
 | 
						|
 | 
						|
void NODE_GGT_backdrop_crop(wmGizmoGroupType *gzgt)
 | 
						|
{
 | 
						|
  gzgt->name = "Backdrop Crop Widget";
 | 
						|
  gzgt->idname = "NODE_GGT_backdrop_crop";
 | 
						|
 | 
						|
  gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
 | 
						|
 | 
						|
  gzgt->poll = WIDGETGROUP_node_crop_poll;
 | 
						|
  gzgt->setup = WIDGETGROUP_node_crop_setup;
 | 
						|
  gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
 | 
						|
  gzgt->draw_prepare = WIDGETGROUP_node_crop_draw_prepare;
 | 
						|
  gzgt->refresh = WIDGETGROUP_node_crop_refresh;
 | 
						|
}
 | 
						|
 | 
						|
/** \} */
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/** \name Sun Beams
 | 
						|
 * \{ */
 | 
						|
 | 
						|
struct NodeSunBeamsWidgetGroup {
 | 
						|
  wmGizmo *gizmo;
 | 
						|
 | 
						|
  struct {
 | 
						|
    float dims[2];
 | 
						|
  } state;
 | 
						|
};
 | 
						|
 | 
						|
static bool WIDGETGROUP_node_sbeam_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
 | 
						|
{
 | 
						|
  SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
 | 
						|
  if ((snode->flag & SNODE_BACKDRAW) == 0) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
 | 
						|
    bNode *node = nodeGetActive(snode->edittree);
 | 
						|
 | 
						|
    if (node && ELEM(node->type, CMP_NODE_SUNBEAMS)) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_sbeam_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  struct NodeSunBeamsWidgetGroup *sbeam_group = MEM_mallocN(sizeof(struct NodeSunBeamsWidgetGroup),
 | 
						|
                                                            __func__);
 | 
						|
 | 
						|
  sbeam_group->gizmo = WM_gizmo_new("GIZMO_GT_move_3d", gzgroup, NULL);
 | 
						|
  wmGizmo *gz = sbeam_group->gizmo;
 | 
						|
 | 
						|
  RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
 | 
						|
 | 
						|
  gz->scale_basis = 0.05f / 75.0f;
 | 
						|
 | 
						|
  gzgroup->customdata = sbeam_group;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_sbeam_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
 | 
						|
  ARegion *region = CTX_wm_region(C);
 | 
						|
  wmGizmo *gz = gzgroup->gizmos.first;
 | 
						|
 | 
						|
  SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
 | 
						|
  node_gizmo_calc_matrix_space_with_image_dims(
 | 
						|
      snode, region, sbeam_group->state.dims, gz->matrix_space);
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_sbeam_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  Main *bmain = CTX_data_main(C);
 | 
						|
  struct NodeSunBeamsWidgetGroup *sbeam_group = gzgroup->customdata;
 | 
						|
  wmGizmo *gz = sbeam_group->gizmo;
 | 
						|
 | 
						|
  void *lock;
 | 
						|
  Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
 | 
						|
  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
 | 
						|
 | 
						|
  if (ibuf) {
 | 
						|
    sbeam_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
 | 
						|
    sbeam_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
 | 
						|
 | 
						|
    SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
    bNode *node = nodeGetActive(snode->edittree);
 | 
						|
 | 
						|
    /* need to set property here for undo. TODO would prefer to do this in _init */
 | 
						|
    PointerRNA nodeptr;
 | 
						|
    RNA_pointer_create((ID *)snode->edittree, &RNA_CompositorNodeSunBeams, node, &nodeptr);
 | 
						|
    WM_gizmo_target_property_def_rna(gz, "offset", &nodeptr, "source", -1);
 | 
						|
 | 
						|
    WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
 | 
						|
  }
 | 
						|
 | 
						|
  BKE_image_release_ibuf(ima, ibuf, lock);
 | 
						|
}
 | 
						|
 | 
						|
void NODE_GGT_backdrop_sun_beams(wmGizmoGroupType *gzgt)
 | 
						|
{
 | 
						|
  gzgt->name = "Sun Beams Widget";
 | 
						|
  gzgt->idname = "NODE_GGT_sbeam";
 | 
						|
 | 
						|
  gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
 | 
						|
 | 
						|
  gzgt->poll = WIDGETGROUP_node_sbeam_poll;
 | 
						|
  gzgt->setup = WIDGETGROUP_node_sbeam_setup;
 | 
						|
  gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
 | 
						|
  gzgt->draw_prepare = WIDGETGROUP_node_sbeam_draw_prepare;
 | 
						|
  gzgt->refresh = WIDGETGROUP_node_sbeam_refresh;
 | 
						|
}
 | 
						|
 | 
						|
/** \} */
 | 
						|
 | 
						|
/* -------------------------------------------------------------------- */
 | 
						|
/** \name Corner Pin
 | 
						|
 * \{ */
 | 
						|
 | 
						|
struct NodeCornerPinWidgetGroup {
 | 
						|
  wmGizmo *gizmos[4];
 | 
						|
 | 
						|
  struct {
 | 
						|
    float dims[2];
 | 
						|
  } state;
 | 
						|
};
 | 
						|
 | 
						|
static bool WIDGETGROUP_node_corner_pin_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
 | 
						|
{
 | 
						|
  SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
 | 
						|
  if ((snode->flag & SNODE_BACKDRAW) == 0) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (snode && snode->edittree && snode->edittree->type == NTREE_COMPOSIT) {
 | 
						|
    bNode *node = nodeGetActive(snode->edittree);
 | 
						|
 | 
						|
    if (node && ELEM(node->type, CMP_NODE_CORNERPIN)) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_corner_pin_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  struct NodeCornerPinWidgetGroup *cpin_group = MEM_mallocN(
 | 
						|
      sizeof(struct NodeCornerPinWidgetGroup), __func__);
 | 
						|
  const wmGizmoType *gzt_move_3d = WM_gizmotype_find("GIZMO_GT_move_3d", false);
 | 
						|
 | 
						|
  for (int i = 0; i < 4; i++) {
 | 
						|
    cpin_group->gizmos[i] = WM_gizmo_new_ptr(gzt_move_3d, gzgroup, NULL);
 | 
						|
    wmGizmo *gz = cpin_group->gizmos[i];
 | 
						|
 | 
						|
    RNA_enum_set(gz->ptr, "draw_style", ED_GIZMO_MOVE_STYLE_CROSS_2D);
 | 
						|
 | 
						|
    gz->scale_basis = 0.01f / 75.0;
 | 
						|
  }
 | 
						|
 | 
						|
  gzgroup->customdata = cpin_group;
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_corner_pin_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
 | 
						|
  ARegion *region = CTX_wm_region(C);
 | 
						|
 | 
						|
  SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
 | 
						|
  float matrix_space[4][4];
 | 
						|
  node_gizmo_calc_matrix_space_with_image_dims(
 | 
						|
      snode, region, cpin_group->state.dims, matrix_space);
 | 
						|
 | 
						|
  for (int i = 0; i < 4; i++) {
 | 
						|
    wmGizmo *gz = cpin_group->gizmos[i];
 | 
						|
    copy_m4_m4(gz->matrix_space, matrix_space);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static void WIDGETGROUP_node_corner_pin_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 | 
						|
{
 | 
						|
  Main *bmain = CTX_data_main(C);
 | 
						|
  struct NodeCornerPinWidgetGroup *cpin_group = gzgroup->customdata;
 | 
						|
 | 
						|
  void *lock;
 | 
						|
  Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
 | 
						|
  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
 | 
						|
 | 
						|
  if (ibuf) {
 | 
						|
    cpin_group->state.dims[0] = (ibuf->x > 0) ? ibuf->x : 64.0f;
 | 
						|
    cpin_group->state.dims[1] = (ibuf->y > 0) ? ibuf->y : 64.0f;
 | 
						|
 | 
						|
    SpaceNode *snode = CTX_wm_space_node(C);
 | 
						|
    bNode *node = nodeGetActive(snode->edittree);
 | 
						|
 | 
						|
    /* need to set property here for undo. TODO would prefer to do this in _init */
 | 
						|
    int i = 0;
 | 
						|
    for (bNodeSocket *sock = node->inputs.first; sock && i < 4; sock = sock->next) {
 | 
						|
      if (sock->type == SOCK_VECTOR) {
 | 
						|
        wmGizmo *gz = cpin_group->gizmos[i++];
 | 
						|
 | 
						|
        PointerRNA sockptr;
 | 
						|
        RNA_pointer_create((ID *)snode->edittree, &RNA_NodeSocket, sock, &sockptr);
 | 
						|
        WM_gizmo_target_property_def_rna(gz, "offset", &sockptr, "default_value", -1);
 | 
						|
 | 
						|
        WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_MODAL, true);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    for (int i = 0; i < 4; i++) {
 | 
						|
      wmGizmo *gz = cpin_group->gizmos[i];
 | 
						|
      WM_gizmo_set_flag(gz, WM_GIZMO_HIDDEN, true);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  BKE_image_release_ibuf(ima, ibuf, lock);
 | 
						|
}
 | 
						|
 | 
						|
void NODE_GGT_backdrop_corner_pin(wmGizmoGroupType *gzgt)
 | 
						|
{
 | 
						|
  gzgt->name = "Corner Pin Widget";
 | 
						|
  gzgt->idname = "NODE_GGT_backdrop_corner_pin";
 | 
						|
 | 
						|
  gzgt->flag |= WM_GIZMOGROUPTYPE_PERSISTENT;
 | 
						|
 | 
						|
  gzgt->poll = WIDGETGROUP_node_corner_pin_poll;
 | 
						|
  gzgt->setup = WIDGETGROUP_node_corner_pin_setup;
 | 
						|
  gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
 | 
						|
  gzgt->draw_prepare = WIDGETGROUP_node_corner_pin_draw_prepare;
 | 
						|
  gzgt->refresh = WIDGETGROUP_node_corner_pin_refresh;
 | 
						|
}
 | 
						|
 | 
						|
/** \} */
 |