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:
Diffstat (limited to 'source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.c')
-rw-r--r--source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.c373
1 files changed, 373 insertions, 0 deletions
diff --git a/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.c b/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.c
new file mode 100644
index 00000000000..c3879fe8bbd
--- /dev/null
+++ b/source/blender/editors/interface/eyedroppers/eyedropper_gpencil_color.c
@@ -0,0 +1,373 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2009 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * Eyedropper (RGB Color)
+ *
+ * Defines:
+ * - #UI_OT_eyedropper_gpencil_color
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_material_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_gpencil.h"
+#include "BKE_lib_id.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_paint.h"
+#include "BKE_report.h"
+
+#include "UI_interface.h"
+
+#include "IMB_colormanagement.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "ED_gpencil.h"
+#include "ED_screen.h"
+#include "ED_undo.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
+#include "eyedropper_intern.h"
+#include "interface_intern.h"
+
+typedef struct EyedropperGPencil {
+ struct ColorManagedDisplay *display;
+ /** color under cursor RGB */
+ float color[3];
+ /** Mode */
+ int mode;
+} EyedropperGPencil;
+
+/* Helper: Draw status message while the user is running the operator */
+static void eyedropper_gpencil_status_indicators(bContext *C)
+{
+ char msg_str[UI_MAX_DRAW_STR];
+ BLI_strncpy(
+ msg_str, TIP_("LMB: Stroke - Shift: Fill - Shift+Ctrl: Stroke + Fill"), UI_MAX_DRAW_STR);
+
+ ED_workspace_status_text(C, msg_str);
+}
+
+/* Initialize. */
+static bool eyedropper_gpencil_init(bContext *C, wmOperator *op)
+{
+ EyedropperGPencil *eye = MEM_callocN(sizeof(EyedropperGPencil), __func__);
+
+ op->customdata = eye;
+ Scene *scene = CTX_data_scene(C);
+
+ const char *display_device;
+ display_device = scene->display_settings.display_device;
+ eye->display = IMB_colormanagement_display_get_named(display_device);
+
+ eye->mode = RNA_enum_get(op->ptr, "mode");
+ return true;
+}
+
+/* Exit and free memory. */
+static void eyedropper_gpencil_exit(bContext *C, wmOperator *op)
+{
+ /* Clear status message area. */
+ ED_workspace_status_text(C, NULL);
+
+ MEM_SAFE_FREE(op->customdata);
+}
+
+static void eyedropper_add_material(bContext *C,
+ const float col_conv[4],
+ const bool only_stroke,
+ const bool only_fill,
+ const bool both)
+{
+ Main *bmain = CTX_data_main(C);
+ Object *ob = CTX_data_active_object(C);
+ Material *ma = NULL;
+
+ bool found = false;
+
+ /* Look for a similar material in grease pencil slots. */
+ short *totcol = BKE_object_material_len_p(ob);
+ for (short i = 0; i < *totcol; i++) {
+ ma = BKE_object_material_get(ob, i + 1);
+ if (ma == NULL) {
+ continue;
+ }
+
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ if (gp_style != NULL) {
+ /* Check stroke color. */
+ bool found_stroke = compare_v3v3(gp_style->stroke_rgba, col_conv, 0.01f) &&
+ (gp_style->flag & GP_MATERIAL_STROKE_SHOW);
+ /* Check fill color. */
+ bool found_fill = compare_v3v3(gp_style->fill_rgba, col_conv, 0.01f) &&
+ (gp_style->flag & GP_MATERIAL_FILL_SHOW);
+
+ if ((only_stroke) && (found_stroke) && ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) {
+ found = true;
+ }
+ else if ((only_fill) && (found_fill) && ((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0)) {
+ found = true;
+ }
+ else if ((both) && (found_stroke) && (found_fill)) {
+ found = true;
+ }
+
+ /* Found existing material. */
+ if (found) {
+ ob->actcol = i + 1;
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ return;
+ }
+ }
+ }
+
+ /* If material was not found add a new material with stroke and/or fill color
+ * depending of the secondary key (LMB: Stroke, Shift: Fill, Shift+Ctrl: Stroke/Fill)
+ */
+ int idx;
+ Material *ma_new = BKE_gpencil_object_material_new(bmain, ob, "Material", &idx);
+ WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, &ob->id);
+ WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
+ DEG_relations_tag_update(bmain);
+
+ BLI_assert(ma_new != NULL);
+
+ MaterialGPencilStyle *gp_style_new = ma_new->gp_style;
+ BLI_assert(gp_style_new != NULL);
+
+ /* Only create Stroke (default option). */
+ if (only_stroke) {
+ /* Stroke color. */
+ gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW;
+ gp_style_new->flag &= ~GP_MATERIAL_FILL_SHOW;
+ copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
+ zero_v4(gp_style_new->fill_rgba);
+ }
+ /* Fill Only. */
+ else if (only_fill) {
+ /* Fill color. */
+ gp_style_new->flag &= ~GP_MATERIAL_STROKE_SHOW;
+ gp_style_new->flag |= GP_MATERIAL_FILL_SHOW;
+ zero_v4(gp_style_new->stroke_rgba);
+ copy_v3_v3(gp_style_new->fill_rgba, col_conv);
+ }
+ /* Stroke and Fill. */
+ else if (both) {
+ gp_style_new->flag |= GP_MATERIAL_STROKE_SHOW | GP_MATERIAL_FILL_SHOW;
+ copy_v3_v3(gp_style_new->stroke_rgba, col_conv);
+ copy_v3_v3(gp_style_new->fill_rgba, col_conv);
+ }
+ /* Push undo for new created material. */
+ ED_undo_push(C, "Add Grease Pencil Material");
+}
+
+/* Create a new palette color and palette if needed. */
+static void eyedropper_add_palette_color(bContext *C, const float col_conv[4])
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *ts = scene->toolsettings;
+ GpPaint *gp_paint = ts->gp_paint;
+ GpVertexPaint *gp_vertexpaint = ts->gp_vertexpaint;
+ Paint *paint = &gp_paint->paint;
+ Paint *vertexpaint = &gp_vertexpaint->paint;
+
+ /* Check for Palette in Draw and Vertex Paint Mode. */
+ if (paint->palette == NULL) {
+ Palette *palette = BKE_palette_add(bmain, "Grease Pencil");
+ id_us_min(&palette->id);
+
+ BKE_paint_palette_set(paint, palette);
+
+ if (vertexpaint->palette == NULL) {
+ BKE_paint_palette_set(vertexpaint, palette);
+ }
+ }
+ /* Check if the color exist already. */
+ Palette *palette = paint->palette;
+ LISTBASE_FOREACH (PaletteColor *, palcolor, &palette->colors) {
+ if (compare_v3v3(palcolor->rgb, col_conv, 0.01f)) {
+ return;
+ }
+ }
+
+ /* Create Colors. */
+ PaletteColor *palcol = BKE_palette_color_add(palette);
+ if (palcol) {
+ copy_v3_v3(palcol->rgb, col_conv);
+ }
+}
+
+/* Set the material or the palette color. */
+static void eyedropper_gpencil_color_set(bContext *C, const wmEvent *event, EyedropperGPencil *eye)
+{
+
+ const bool only_stroke = (event->modifier & (KM_CTRL | KM_SHIFT)) == 0;
+ const bool only_fill = ((event->modifier & KM_CTRL) == 0 && (event->modifier & KM_SHIFT));
+ const bool both = ((event->modifier & KM_CTRL) && (event->modifier & KM_SHIFT));
+
+ float col_conv[4];
+
+ /* Convert from linear rgb space to display space because grease pencil colors are in display
+ * space, and this conversion is needed to undo the conversion to linear performed by
+ * eyedropper_color_sample_fl. */
+ if (eye->display) {
+ copy_v3_v3(col_conv, eye->color);
+ IMB_colormanagement_scene_linear_to_display_v3(col_conv, eye->display);
+ }
+ else {
+ copy_v3_v3(col_conv, eye->color);
+ }
+
+ /* Add material or Palette color. */
+ if (eye->mode == 0) {
+ eyedropper_add_material(C, col_conv, only_stroke, only_fill, both);
+ }
+ else {
+ eyedropper_add_palette_color(C, col_conv);
+ }
+}
+
+/* Sample the color below cursor. */
+static void eyedropper_gpencil_color_sample(bContext *C, EyedropperGPencil *eye, const int m_xy[2])
+{
+ eyedropper_color_sample_fl(C, m_xy, eye->color);
+}
+
+/* Cancel operator. */
+static void eyedropper_gpencil_cancel(bContext *C, wmOperator *op)
+{
+ eyedropper_gpencil_exit(C, op);
+}
+
+/* Main modal status check. */
+static int eyedropper_gpencil_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ EyedropperGPencil *eye = (EyedropperGPencil *)op->customdata;
+ /* Handle modal keymap */
+ switch (event->type) {
+ case EVT_MODAL_MAP: {
+ switch (event->val) {
+ case EYE_MODAL_SAMPLE_BEGIN: {
+ return OPERATOR_RUNNING_MODAL;
+ }
+ case EYE_MODAL_CANCEL: {
+ eyedropper_gpencil_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ case EYE_MODAL_SAMPLE_CONFIRM: {
+ eyedropper_gpencil_color_sample(C, eye, event->xy);
+
+ /* Create material. */
+ eyedropper_gpencil_color_set(C, event, eye);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+ eyedropper_gpencil_exit(C, op);
+ return OPERATOR_FINISHED;
+ }
+ default: {
+ break;
+ }
+ }
+ break;
+ }
+ case MOUSEMOVE:
+ case INBETWEEN_MOUSEMOVE: {
+ eyedropper_gpencil_color_sample(C, eye, event->xy);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int eyedropper_gpencil_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ /* Init. */
+ if (eyedropper_gpencil_init(C, op)) {
+ /* Add modal temp handler. */
+ WM_event_add_modal_handler(C, op);
+ /* Status message. */
+ eyedropper_gpencil_status_indicators(C);
+
+ return OPERATOR_RUNNING_MODAL;
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+/* Repeat operator */
+static int eyedropper_gpencil_exec(bContext *C, wmOperator *op)
+{
+ /* init */
+ if (eyedropper_gpencil_init(C, op)) {
+
+ /* cleanup */
+ eyedropper_gpencil_exit(C, op);
+
+ return OPERATOR_FINISHED;
+ }
+ return OPERATOR_PASS_THROUGH;
+}
+
+static bool eyedropper_gpencil_poll(bContext *C)
+{
+ /* Only valid if the current active object is grease pencil. */
+ Object *obact = CTX_data_active_object(C);
+ if ((obact == NULL) || (obact->type != OB_GPENCIL)) {
+ return false;
+ }
+
+ /* Test we have a window below. */
+ return (CTX_wm_window(C) != NULL);
+}
+
+void UI_OT_eyedropper_gpencil_color(wmOperatorType *ot)
+{
+ static const EnumPropertyItem items_mode[] = {
+ {0, "MATERIAL", 0, "Material", ""},
+ {1, "PALETTE", 0, "Palette", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Grease Pencil Eyedropper";
+ ot->idname = "UI_OT_eyedropper_gpencil_color";
+ ot->description = "Sample a color from the Blender Window and create Grease Pencil material";
+
+ /* api callbacks */
+ ot->invoke = eyedropper_gpencil_invoke;
+ ot->modal = eyedropper_gpencil_modal;
+ ot->cancel = eyedropper_gpencil_cancel;
+ ot->exec = eyedropper_gpencil_exec;
+ ot->poll = eyedropper_gpencil_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
+
+ /* properties */
+ ot->prop = RNA_def_enum(ot->srna, "mode", items_mode, 0, "Mode", "");
+}