Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/gpencil/gpencil_uv.c
| Context not available. | |||||
| float initial_length; | float initial_length; | ||||
| float pixel_size; /* use when mouse input is interpreted as spatial distance */ | float pixel_size; /* use when mouse input is interpreted as spatial distance */ | ||||
| bool is_modal; | |||||
| /* Arrays of original loc/rot/scale by stroke. */ | /* Arrays of original loc/rot/scale by stroke. */ | ||||
| float (*array_loc)[2]; | float (*array_loc)[2]; | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| static bool gpencil_uv_transform_init(bContext *C, wmOperator *op, const bool is_modal) | static bool gpencil_uv_transform_init(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| GpUvData *opdata; | GpUvData *opdata; | ||||
| if (is_modal) { | |||||
| float zero[2] = {0.0f}; | |||||
| RNA_float_set_array(op->ptr, "location", zero); | |||||
| RNA_float_set(op->ptr, "rotation", 0.0f); | |||||
| RNA_float_set(op->ptr, "scale", 1.0f); | |||||
| } | |||||
| op->customdata = opdata = MEM_mallocN(sizeof(GpUvData), __func__); | op->customdata = opdata = MEM_mallocN(sizeof(GpUvData), __func__); | ||||
| opdata->is_modal = is_modal; | |||||
| opdata->ob = CTX_data_active_object(C); | opdata->ob = CTX_data_active_object(C); | ||||
| opdata->gpd = (bGPdata *)opdata->ob->data; | opdata->gpd = (bGPdata *)opdata->ob->data; | ||||
| gp_point_conversion_init(C, &opdata->gsc); | gp_point_conversion_init(C, &opdata->gsc); | ||||
| Context not available. | |||||
| opdata->vinit_rotation[0] = 1.0f; | opdata->vinit_rotation[0] = 1.0f; | ||||
| opdata->vinit_rotation[1] = 0.0f; | opdata->vinit_rotation[1] = 0.0f; | ||||
| if (is_modal) { | ARegion *region = CTX_wm_region(C); | ||||
| ARegion *region = CTX_wm_region(C); | |||||
| opdata->draw_handle_pixel = ED_region_draw_cb_activate( | opdata->draw_handle_pixel = ED_region_draw_cb_activate( | ||||
| region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); | region->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); | ||||
| } | |||||
| /* Calc selected strokes center. */ | /* Calc selected strokes center. */ | ||||
| zero_v2(opdata->mcenter); | zero_v2(opdata->mcenter); | ||||
| Context not available. | |||||
| } | } | ||||
| GP_EDITABLE_STROKES_END(gpstroke_iter); | GP_EDITABLE_STROKES_END(gpstroke_iter); | ||||
| } | } | ||||
| /* convert to 2D */ | /* Convert to 2D. */ | ||||
| gp_point_3d_to_xy(&opdata->gsc, GP_STROKE_3DSPACE, center, opdata->mcenter); | gp_point_3d_to_xy(&opdata->gsc, GP_STROKE_3DSPACE, center, opdata->mcenter); | ||||
| return true; | return true; | ||||
| Context not available. | |||||
| opdata = op->customdata; | opdata = op->customdata; | ||||
| if (opdata->is_modal) { | ARegion *region = CTX_wm_region(C); | ||||
| ARegion *region = CTX_wm_region(C); | |||||
| ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); | ED_region_draw_cb_exit(region->type, opdata->draw_handle_pixel); | ||||
| } | |||||
| WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT); | WM_cursor_set(CTX_wm_window(C), WM_CURSOR_DEFAULT); | ||||
| Context not available. | |||||
| const int mode = RNA_enum_get(op->ptr, "mode"); | const int mode = RNA_enum_get(op->ptr, "mode"); | ||||
| GpUvData *opdata = op->customdata; | GpUvData *opdata = op->customdata; | ||||
| bGPdata *gpd = opdata->gpd; | bGPdata *gpd = opdata->gpd; | ||||
| bool changed = false; | bool changed = false; | ||||
| /* Get actual vector. */ | /* Get actual vector. */ | ||||
| float vr[2]; | float vr[2]; | ||||
| float mdiff[2]; | |||||
| sub_v2_v2v2(vr, opdata->mouse, opdata->mcenter); | sub_v2_v2v2(vr, opdata->mouse, opdata->mcenter); | ||||
| normalize_v2(vr); | normalize_v2(vr); | ||||
| float location[2]; | float uv_rotation = angle_signed_v2v2(opdata->vinit_rotation, vr); | ||||
| RNA_float_get_array(op->ptr, "location", location); | |||||
| float uv_rotation = (opdata->is_modal) ? angle_signed_v2v2(opdata->vinit_rotation, vr) : | |||||
| RNA_float_get(op->ptr, "rotation"); | |||||
| uv_rotation *= SMOOTH_FACTOR; | |||||
| if (opdata->is_modal) { | |||||
| RNA_float_set(op->ptr, "rotation", uv_rotation); | |||||
| } | |||||
| int i = 0; | int i = 0; | ||||
| float offset[2]; | |||||
| offset[0] = cos(uv_rotation) - sin(uv_rotation); | |||||
| offset[1] = cos(uv_rotation) + sin(uv_rotation); | |||||
| /* Apply transformations to all strokes. */ | /* Translate. */ | ||||
| if ((mode == GP_UV_TRANSLATE) || (!opdata->is_modal)) { | if (mode == GP_UV_TRANSLATE) { | ||||
| float mdiff[2]; | mdiff[0] = fabs(opdata->mcenter[0] - opdata->mouse[0]); | ||||
| mdiff[0] = opdata->mcenter[0] - opdata->mouse[0]; | mdiff[1] = fabs(opdata->mcenter[1] - opdata->mouse[1]); | ||||
| mdiff[1] = opdata->mcenter[1] - opdata->mouse[1]; | |||||
| /* Apply a big amount of smooth always for translate to get smooth result. */ | /* Apply a big amount of smooth always for translate to get smooth result. */ | ||||
| mul_v2_fl(mdiff, 0.006f); | mul_v2_fl(mdiff, 0.002f); | ||||
| /* Apply angle in translation. */ | /* Apply angle in translation. */ | ||||
| mdiff[0] *= cos(uv_rotation); | mul_v2_v2(mdiff, offset); | ||||
| mdiff[1] *= sin(uv_rotation); | RNA_float_set_array(op->ptr, "location", mdiff); | ||||
| if (opdata->is_modal) { | |||||
| RNA_float_set_array(op->ptr, "location", mdiff); | |||||
| } | |||||
| changed = (bool)((mdiff[0] != 0.0f) || (mdiff[1] != 0.0f)); | GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { | ||||
| if (changed) { | if (gps->flag & GP_STROKE_SELECT) { | ||||
| GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { | |||||
| if (gps->flag & GP_STROKE_SELECT) { | sub_v2_v2v2(gps->uv_translation, opdata->array_loc[i], mdiff); | ||||
| if (opdata->is_modal) { | changed = true; | ||||
| add_v2_v2v2(gps->uv_translation, opdata->array_loc[i], mdiff); | |||||
| } | /* Calc geometry data. */ | ||||
| else { | BKE_gpencil_stroke_geometry_update(gps); | ||||
| copy_v2_v2(gps->uv_translation, location); | i++; | ||||
| } | |||||
| /* Calc geometry data. */ | |||||
| BKE_gpencil_stroke_geometry_update(gps); | |||||
| i++; | |||||
| } | |||||
| } | } | ||||
| GP_EDITABLE_STROKES_END(gpstroke_iter); | |||||
| } | } | ||||
| GP_EDITABLE_STROKES_END(gpstroke_iter); | |||||
| } | } | ||||
| if ((mode == GP_UV_ROTATE) || (!opdata->is_modal)) { | /* Rotate. */ | ||||
| changed = (bool)(uv_rotation != 0.0f); | if (mode == GP_UV_ROTATE) { | ||||
| changed |= (bool)(uv_rotation != 0.0f); | |||||
| RNA_float_set(op->ptr, "rotation", uv_rotation); | |||||
| if (changed) { | if (changed) { | ||||
| GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { | GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { | ||||
| if (gps->flag & GP_STROKE_SELECT) { | if (gps->flag & GP_STROKE_SELECT) { | ||||
| gps->uv_rotation = (opdata->is_modal) ? opdata->array_rot[i] + uv_rotation : uv_rotation; | gps->uv_rotation = opdata->array_rot[i] - uv_rotation; | ||||
| /* Calc geometry data. */ | /* Calc geometry data. */ | ||||
| BKE_gpencil_stroke_geometry_update(gps); | BKE_gpencil_stroke_geometry_update(gps); | ||||
| i++; | i++; | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| if ((mode == GP_UV_SCALE) || (!opdata->is_modal)) { | /* Scale. */ | ||||
| float mdiff[2]; | if (mode == GP_UV_SCALE) { | ||||
| mdiff[0] = opdata->mcenter[0] - opdata->mouse[0]; | mdiff[0] = opdata->mcenter[0] - opdata->mouse[0]; | ||||
| mdiff[1] = opdata->mcenter[1] - opdata->mouse[1]; | mdiff[1] = opdata->mcenter[1] - opdata->mouse[1]; | ||||
| float scale = (opdata->is_modal) ? | float scale = ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) / | ||||
| ((len_v2(mdiff) - opdata->initial_length) * opdata->pixel_size) / | opdata->ob_scale; | ||||
| opdata->ob_scale : | |||||
| RNA_float_get(op->ptr, "scale"); | |||||
| scale *= SMOOTH_FACTOR; | scale *= SMOOTH_FACTOR; | ||||
| RNA_float_set(op->ptr, "scale", scale); | |||||
| if (opdata->is_modal) { | changed |= (bool)(scale != 0.0f); | ||||
| RNA_float_set(op->ptr, "scale", scale); | |||||
| } | |||||
| changed = (bool)(scale != 0.0f); | |||||
| if (changed) { | if (changed) { | ||||
| GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { | GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { | ||||
| if (gps->flag & GP_STROKE_SELECT) { | if (gps->flag & GP_STROKE_SELECT) { | ||||
| gps->uv_scale = (opdata->is_modal) ? opdata->array_scale[i] + scale : scale; | gps->uv_scale = opdata->array_scale[i] + scale; | ||||
| /* Calc geometry data. */ | /* Calc geometry data. */ | ||||
| BKE_gpencil_stroke_geometry_update(gps); | BKE_gpencil_stroke_geometry_update(gps); | ||||
| i++; | i++; | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| if ((!opdata->is_modal) || (changed)) { | if (changed) { | ||||
| /* Update cursor line. */ | /* Update cursor line. */ | ||||
| DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); | DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY); | ||||
| WM_main_add_notifier(NC_GEOM | ND_DATA, NULL); | WM_main_add_notifier(NC_GEOM | ND_DATA, NULL); | ||||
| Context not available. | |||||
| return changed; | return changed; | ||||
| } | } | ||||
| static int gpencil_transform_fill_exec(bContext *C, wmOperator *op) | |||||
| { | |||||
| if (!gpencil_uv_transform_init(C, op, false)) { | |||||
| return OPERATOR_CANCELLED; | |||||
| } | |||||
| if (!gpencil_uv_transform_calc(C, op)) { | |||||
| gpencil_uv_transform_exit(C, op); | |||||
| return OPERATOR_CANCELLED; | |||||
| } | |||||
| gpencil_uv_transform_exit(C, op); | |||||
| return OPERATOR_FINISHED; | |||||
| } | |||||
| static bool gpencil_transform_fill_poll(bContext *C) | static bool gpencil_transform_fill_poll(bContext *C) | ||||
| { | { | ||||
| if (!ED_operator_view3d_active(C)) { | if (!ED_operator_view3d_active(C)) { | ||||
| Context not available. | |||||
| float mlen[2]; | float mlen[2]; | ||||
| float center_3d[3]; | float center_3d[3]; | ||||
| if (!gpencil_uv_transform_init(C, op, true)) { | if (!gpencil_uv_transform_init(C, op)) { | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| Context not available. | |||||
| opdata->mouse[1] = event->mval[1]; | opdata->mouse[1] = event->mval[1]; | ||||
| copy_v3_v3(center_3d, opdata->ob->loc); | copy_v3_v3(center_3d, opdata->ob->loc); | ||||
| mlen[0] = opdata->mcenter[0] - event->mval[0]; | mlen[0] = event->mval[0] - opdata->mcenter[0]; | ||||
| mlen[1] = opdata->mcenter[1] - event->mval[1]; | mlen[1] = event->mval[1] - opdata->mcenter[1]; | ||||
| opdata->initial_length = len_v2(mlen); | opdata->initial_length = len_v2(mlen); | ||||
| opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f; | /* Consider initial position as the orientation vector. */ | ||||
| const int mode = RNA_enum_get(op->ptr, "mode"); | |||||
| if (mode == GP_UV_ROTATE) { | |||||
| opdata->vinit_rotation[0] = mlen[0]; | |||||
| opdata->vinit_rotation[1] = mlen[1]; | |||||
| normalize_v2(opdata->vinit_rotation); | |||||
| } | |||||
| /* Calc init rotation vector. */ | opdata->pixel_size = rv3d ? ED_view3d_pixel_size(rv3d, center_3d) : 1.0f; | ||||
| float mouse[2] = {event->mval[0], event->mval[1]}; | |||||
| sub_v2_v2v2(opdata->vinit_rotation, mouse, opdata->mcenter); | |||||
| normalize_v2(opdata->vinit_rotation); | |||||
| gpencil_uv_transform_calc(C, op); | gpencil_uv_transform_calc(C, op); | ||||
| Context not available. | |||||
| /* api callbacks */ | /* api callbacks */ | ||||
| ot->invoke = gpencil_transform_fill_invoke; | ot->invoke = gpencil_transform_fill_invoke; | ||||
| ot->modal = gpencil_transform_fill_modal; | ot->modal = gpencil_transform_fill_modal; | ||||
| ot->exec = gpencil_transform_fill_exec; | |||||
| ot->cancel = gpencil_transform_fill_cancel; | ot->cancel = gpencil_transform_fill_cancel; | ||||
| ot->poll = gpencil_transform_fill_poll; | ot->poll = gpencil_transform_fill_poll; | ||||
| Context not available. | |||||