| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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) 2015 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup edgizmolib | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  |  * \name Gizmo Library Utilities | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  |  * \brief This file contains functions for common behaviors of gizmos. | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | #include "DNA_view3d_types.h"
 | 
					
						
							|  |  |  | #include "DNA_screen_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 14:11:45 +11:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-08 07:16:47 +10:00
										 |  |  | #include "WM_types.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 14:11:45 +11:00
										 |  |  | #include "ED_view3d.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | /* own includes */ | 
					
						
							| 
									
										
										
										
											2018-07-14 23:16:34 +02:00
										 |  |  | #include "gizmo_library_intern.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* factor for precision tweaking */ | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | #define GIZMO_PRECISION_FAC 0.05f
 | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | BLI_INLINE float gizmo_offset_from_value_constr( | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |         const float range_fac, const float min, const float range, const float value, | 
					
						
							|  |  |  |         const bool inverted) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return inverted ? (range_fac * (min + range - value) / range) : (range_fac * (value / range)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | BLI_INLINE float gizmo_value_from_offset_constr( | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |         const float range_fac, const float min, const float range, const float value, | 
					
						
							|  |  |  |         const bool inverted) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return inverted ? (min + range - (value * range / range_fac)) : (value * range / range_fac); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | float gizmo_offset_from_value( | 
					
						
							|  |  |  |         GizmoCommonData *data, const float value, const bool constrained, const bool inverted) | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (constrained) | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | 		return gizmo_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | float gizmo_value_from_offset( | 
					
						
							|  |  |  |         GizmoCommonData *data, GizmoInteraction *inter, const float offset, | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |         const bool constrained, const bool inverted, const bool use_precision) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const float max = data->min + data->range; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (use_precision) { | 
					
						
							|  |  |  | 		/* add delta offset of this step to total precision_offset */ | 
					
						
							|  |  |  | 		inter->precision_offset += offset - inter->prev_offset; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	inter->prev_offset = offset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | 	float ofs_new = inter->init_offset + offset - inter->precision_offset * (1.0f - GIZMO_PRECISION_FAC); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 	float value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (constrained) { | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | 		value = gizmo_value_from_offset_constr(data->range_fac, data->min, data->range, ofs_new, inverted); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		value = ofs_new; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* clamp to custom range */ | 
					
						
							| 
									
										
										
										
											2018-12-03 13:01:04 +11:00
										 |  |  | 	if (data->is_custom_range_set) { | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 		CLAMP(value, data->min, max); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | void gizmo_property_data_update( | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  |         wmGizmo *gz, GizmoCommonData *data, wmGizmoProperty *gz_prop, | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |         const bool constrained, const bool inverted) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 	if (gz_prop->custom_func.value_get_fn != NULL) { | 
					
						
							| 
									
										
										
										
											2017-06-15 20:48:24 +10:00
										 |  |  | 		/* pass  */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 	else if (gz_prop->prop != NULL) { | 
					
						
							| 
									
										
										
										
											2017-06-15 20:48:24 +10:00
										 |  |  | 		/* pass  */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 		data->offset = 0.0f; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-21 16:42:12 +10:00
										 |  |  | 	float value = WM_gizmo_target_property_float_get(gz, gz_prop); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (constrained) { | 
					
						
							| 
									
										
										
										
											2018-12-03 13:01:04 +11:00
										 |  |  | 		if (data->is_custom_range_set == false) { | 
					
						
							| 
									
										
										
										
											2017-06-15 20:48:24 +10:00
										 |  |  | 			float range[2]; | 
					
						
							| 
									
										
										
										
											2018-09-13 08:17:16 +10:00
										 |  |  | 			if (WM_gizmo_target_property_float_range_get(gz, gz_prop, range)) { | 
					
						
							| 
									
										
										
										
											2017-08-03 17:55:16 +10:00
										 |  |  | 				data->range = range[1] - range[0]; | 
					
						
							|  |  |  | 				data->min = range[0]; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				BLI_assert(0); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | 		data->offset = gizmo_offset_from_value_constr(data->range_fac, data->min, data->range, value, inverted); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		data->offset = value; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | void gizmo_property_value_reset( | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  |         bContext *C, const wmGizmo *gz, GizmoInteraction *inter, | 
					
						
							|  |  |  |         wmGizmoProperty *gz_prop) | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-21 16:42:12 +10:00
										 |  |  | 	WM_gizmo_target_property_float_set(C, gz, gz_prop, inter->init_value); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | void gizmo_color_get( | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  |         const wmGizmo *gz, const bool highlight, | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  |         float r_col[4]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 	if (highlight && !(gz->flag & WM_GIZMO_DRAW_HOVER)) { | 
					
						
							|  |  |  | 		copy_v4_v4(r_col, gz->color_hi); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 		copy_v4_v4(r_col, gz->color); | 
					
						
							| 
									
										
										
										
											2016-10-07 16:34:55 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  |  * Takes mouse coordinates and returns them in relation to the gizmo. | 
					
						
							|  |  |  |  * Both 2D & 3D supported, use so we can use 2D gizmos in the 3D view. | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | bool gizmo_window_project_2d( | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  |         bContext *C, const struct wmGizmo *gz, const float mval[2], int axis, bool use_offset, | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  |         float r_co[2]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-03 19:45:56 +10:00
										 |  |  | 	float mat[4][4]; | 
					
						
							| 
									
										
										
										
											2017-08-15 17:13:32 +10:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2017-08-30 18:13:25 +10:00
										 |  |  | 		float mat_identity[4][4]; | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | 		struct WM_GizmoMatrixParams params = {NULL}; | 
					
						
							| 
									
										
										
										
											2017-08-30 18:13:25 +10:00
										 |  |  | 		if (use_offset == false) { | 
					
						
							|  |  |  | 			unit_m4(mat_identity); | 
					
						
							|  |  |  | 			params.matrix_offset = mat_identity; | 
					
						
							| 
									
										
										
										
											2017-08-15 17:13:32 +10:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 		WM_gizmo_calc_matrix_final_params(gz, ¶ms, mat); | 
					
						
							| 
									
										
										
										
											2017-08-03 19:45:56 +10:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 	/* rotate mouse in relation to the center and relocate it */ | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 	if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) { | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 		/* For 3d views, transform 2D mouse pos onto plane. */ | 
					
						
							|  |  |  | 		ARegion *ar = CTX_wm_region(C); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 12:53:39 +10:00
										 |  |  | 		float plane[4], co[3]; | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 		plane_from_point_normal_v3(plane, mat[3], mat[2]); | 
					
						
							| 
									
										
										
										
											2018-10-09 14:36:15 +02:00
										 |  |  | 		bool clip_ray = ((RegionView3D *)ar->regiondata)->is_persp; | 
					
						
							|  |  |  | 		if (ED_view3d_win_to_3d_on_plane(ar, plane, mval, clip_ray, co)) { | 
					
						
							| 
									
										
										
										
											2018-09-20 12:13:11 +10:00
										 |  |  | 			float imat[4][4]; | 
					
						
							|  |  |  | 			invert_m4_m4(imat, mat); | 
					
						
							|  |  |  | 			mul_m4_v3(imat, co); | 
					
						
							|  |  |  | 			r_co[0] = co[(axis + 1) % 3]; | 
					
						
							|  |  |  | 			r_co[1] = co[(axis + 2) % 3]; | 
					
						
							|  |  |  | 			return true; | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-09 22:37:09 +02:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		float co[3] = {mval[0], mval[1], 0.0f}; | 
					
						
							|  |  |  | 		float imat[4][4]; | 
					
						
							|  |  |  | 		invert_m4_m4(imat, mat); | 
					
						
							| 
									
										
										
										
											2018-08-29 14:39:58 +10:00
										 |  |  | 		mul_m4_v3(imat, co); | 
					
						
							| 
									
										
										
										
											2018-05-09 22:37:09 +02:00
										 |  |  | 		copy_v2_v2(r_co, co); | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | bool gizmo_window_project_3d( | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  |         bContext *C, const struct wmGizmo *gz, const float mval[2], bool use_offset, | 
					
						
							| 
									
										
										
										
											2018-05-09 22:37:09 +02:00
										 |  |  |         float r_co[3]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	float mat[4][4]; | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		float mat_identity[4][4]; | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | 		struct WM_GizmoMatrixParams params = {NULL}; | 
					
						
							| 
									
										
										
										
											2018-05-09 22:37:09 +02:00
										 |  |  | 		if (use_offset == false) { | 
					
						
							|  |  |  | 			unit_m4(mat_identity); | 
					
						
							|  |  |  | 			params.matrix_offset = mat_identity; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 		WM_gizmo_calc_matrix_final_params(gz, ¶ms, mat); | 
					
						
							| 
									
										
										
										
											2018-05-09 22:37:09 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-15 14:24:10 +02:00
										 |  |  | 	if (gz->parent_gzgroup->type->flag & WM_GIZMOGROUPTYPE_3D) { | 
					
						
							| 
									
										
										
										
											2018-05-09 22:37:09 +02:00
										 |  |  | 		View3D *v3d = CTX_wm_view3d(C); | 
					
						
							|  |  |  | 		ARegion *ar = CTX_wm_region(C); | 
					
						
							|  |  |  | 		/* Note: we might want a custom reference point passed in,
 | 
					
						
							| 
									
										
										
										
											2018-07-14 23:49:00 +02:00
										 |  |  | 		 * instead of the gizmo center. */ | 
					
						
							| 
									
										
										
										
											2018-05-09 22:37:09 +02:00
										 |  |  | 		ED_view3d_win_to_3d(v3d, ar, mat[3], mval, r_co); | 
					
						
							|  |  |  | 		invert_m4(mat); | 
					
						
							|  |  |  | 		mul_m4_v3(mat, r_co); | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2017-08-03 19:45:56 +10:00
										 |  |  | 		float co[3] = {mval[0], mval[1], 0.0f}; | 
					
						
							|  |  |  | 		float imat[4][4]; | 
					
						
							|  |  |  | 		invert_m4_m4(imat, mat); | 
					
						
							|  |  |  | 		mul_m4_v3(imat, co); | 
					
						
							|  |  |  | 		copy_v2_v2(r_co, co); | 
					
						
							| 
									
										
										
										
											2017-08-02 19:15:15 +10:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |