mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +00:00 
			
		
		
		
	ColorEdit: Fix multiple issues. (#4014)
* Change g.ColorEditLastColor type to ImU32 and store RGB color value. - Fixes inability to change hue when saturation is 0. (#4014) - Fixes edgecases where lossy color conversion prevent restoration of hue/saturation. - Fixes hue value jitter when modifying color using SV square. * Fix hue resetting to 0 when it is set to 255 by explicitly restoring hue if it is 0 and previous value was 1. * Further reduce hue jitter by restoring hue when color is modified using SV square.
This commit is contained in:
		| @@ -63,6 +63,10 @@ Other Changes: | ||||
|   The only situation where that change would make a meaningful difference is TreePush((const char*)NULL) | ||||
|   (_explicitely_ casting a null pointer to const char*), which is unlikely and will now crash. | ||||
|   You may replace it with anything else. | ||||
| - ColorEdit4: Fixed not being able to change hue when saturation is 0. (#4014) [@rokups] | ||||
| - ColorEdit4: Fixed hue resetting to 0 when it is set to 255. [@rokups] | ||||
| - ColorEdit4: Fixed hue value jitter when source color is stored as RGB in 32-bit integer and perform | ||||
|   RGB<>HSV round trips every frames. [@rokups] | ||||
| - Menus: Fixed vertical alignments of MenuItem() calls within a menu bar. (broken in 1.84). (#4538) | ||||
| - Menus: Adjust closing logic to accomodate for varying font size and dpi. | ||||
| - Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510). | ||||
|   | ||||
							
								
								
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							| @@ -64,7 +64,7 @@ Index of this file: | ||||
| // Version | ||||
| // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) | ||||
| #define IMGUI_VERSION               "1.85 WIP" | ||||
| #define IMGUI_VERSION_NUM           18416 | ||||
| #define IMGUI_VERSION_NUM           18417 | ||||
| #define IMGUI_CHECKVERSION()        ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) | ||||
| #define IMGUI_HAS_TABLE | ||||
|  | ||||
|   | ||||
| @@ -1606,9 +1606,9 @@ struct ImGuiContext | ||||
|     ImFont                  InputTextPasswordFont; | ||||
|     ImGuiID                 TempInputId;                        // Temporary text input when CTRL+clicking on a slider, etc. | ||||
|     ImGuiColorEditFlags     ColorEditOptions;                   // Store user options for color edit widgets | ||||
|     float                   ColorEditLastHue;                   // Backup of last Hue associated to LastColor[3], so we can restore Hue in lossy RGB<>HSV round trips | ||||
|     float                   ColorEditLastSat;                   // Backup of last Saturation associated to LastColor[3], so we can restore Saturation in lossy RGB<>HSV round trips | ||||
|     float                   ColorEditLastColor[3]; | ||||
|     float                   ColorEditLastHue;                   // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips | ||||
|     float                   ColorEditLastSat;                   // Backup of last Saturation associated to LastColor, so we can restore Saturation in lossy RGB<>HSV round trips | ||||
|     ImU32                   ColorEditLastColor;                 // RGB value with alpha set to 0. | ||||
|     ImVec4                  ColorPickerRef;                     // Initial/reference color at the time of opening the color picker. | ||||
|     ImGuiComboPreviewData   ComboPreviewData; | ||||
|     float                   SliderCurrentAccum;                 // Accumulated slider delta when using navigation controls. | ||||
| @@ -1777,7 +1777,7 @@ struct ImGuiContext | ||||
|         TempInputId = 0; | ||||
|         ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_; | ||||
|         ColorEditLastHue = ColorEditLastSat = 0.0f; | ||||
|         ColorEditLastColor[0] = ColorEditLastColor[1] = ColorEditLastColor[2] = FLT_MAX; | ||||
|         ColorEditLastColor = 0; | ||||
|         SliderCurrentAccum = 0.0f; | ||||
|         SliderCurrentAccumDirty = false; | ||||
|         DragCurrentAccumDirty = false; | ||||
|   | ||||
| @@ -4781,6 +4781,30 @@ bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flag | ||||
|     return ColorEdit4(label, col, flags | ImGuiColorEditFlags_NoAlpha); | ||||
| } | ||||
|  | ||||
| // ColorEdit supports RGB and HSV inputs. In case of RGB input resulting color may have undefined hue and/or saturation. | ||||
| // Since widget displays both RGB and HSV values we must preserve hue and saturation to prevent these values resetting. | ||||
| static void ColorEditRestoreHS(const float* col, float* H, float* S, float* V) | ||||
| { | ||||
|     // This check is optional. Suppose we have two color widgets side by side, both widgets display different colors, but both colors have hue and/or saturation undefined. | ||||
|     // With color check: hue/saturation is preserved in one widget. Editing color in one widget would reset hue/saturation in another one. | ||||
|     // Without color check: common hue/saturation would be displayed in all widgets that have hue/saturation undefined. | ||||
|     // g.ColorEditLastColor is stored as ImU32 RGB value: this essentially gives us color equality check with reduced precision. | ||||
|     // Tiny external color changes would not be detected and this check would still pass. This is OK, since we only restore hue/saturation _only_ if they are undefined, | ||||
|     // therefore this change flipping hue/saturation from undefined to a very tiny value would still be represented in color picker. | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     if (g.ColorEditLastColor != ImGui::ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0))) | ||||
|         return; | ||||
|  | ||||
|     // When S == 0, H is undefined. | ||||
|     // When H == 1 it wraps around to 0. | ||||
|     if (*S == 0.0f || (*H == 0.0f && g.ColorEditLastHue == 1)) | ||||
|         *H = g.ColorEditLastHue; | ||||
|  | ||||
|     // When V == 0, S is undefined. | ||||
|     if (*V == 0.0f) | ||||
|         *S = g.ColorEditLastSat; | ||||
| } | ||||
|  | ||||
| // Edit colors components (each component in 0.0f..1.0f range). | ||||
| // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. | ||||
| // With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. | ||||
| @@ -4836,13 +4860,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag | ||||
|     { | ||||
|         // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. | ||||
|         ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); | ||||
|         if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) | ||||
|         { | ||||
|             if (f[1] == 0) | ||||
|                 f[0] = g.ColorEditLastHue; | ||||
|             if (f[2] == 0) | ||||
|                 f[1] = g.ColorEditLastSat; | ||||
|         } | ||||
|         ColorEditRestoreHS(col, &f[0], &f[1], &f[2]); | ||||
|     } | ||||
|     int i[4] = { IM_F32_TO_INT8_UNBOUND(f[0]), IM_F32_TO_INT8_UNBOUND(f[1]), IM_F32_TO_INT8_UNBOUND(f[2]), IM_F32_TO_INT8_UNBOUND(f[3]) }; | ||||
|  | ||||
| @@ -4977,7 +4995,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag | ||||
|             g.ColorEditLastHue = f[0]; | ||||
|             g.ColorEditLastSat = f[1]; | ||||
|             ColorConvertHSVtoRGB(f[0], f[1], f[2], f[0], f[1], f[2]); | ||||
|             memcpy(g.ColorEditLastColor, f, sizeof(float) * 3); | ||||
|             g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(f[0], f[1], f[2], 0)); | ||||
|         } | ||||
|         if ((flags & ImGuiColorEditFlags_DisplayRGB) && (flags & ImGuiColorEditFlags_InputHSV)) | ||||
|             ColorConvertRGBtoHSV(f[0], f[1], f[2], f[0], f[1], f[2]); | ||||
| @@ -5112,13 +5130,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | ||||
|     { | ||||
|         // Hue is lost when converting from greyscale rgb (saturation=0). Restore it. | ||||
|         ColorConvertRGBtoHSV(R, G, B, H, S, V); | ||||
|         if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) | ||||
|         { | ||||
|             if (S == 0) | ||||
|                 H = g.ColorEditLastHue; | ||||
|             if (V == 0) | ||||
|                 S = g.ColorEditLastSat; | ||||
|         } | ||||
|         ColorEditRestoreHS(col, &H, &S, &V); | ||||
|     } | ||||
|     else if (flags & ImGuiColorEditFlags_InputHSV) | ||||
|     { | ||||
| @@ -5171,6 +5183,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | ||||
|         { | ||||
|             S = ImSaturate((io.MousePos.x - picker_pos.x) / (sv_picker_size - 1)); | ||||
|             V = 1.0f - ImSaturate((io.MousePos.y - picker_pos.y) / (sv_picker_size - 1)); | ||||
|  | ||||
|             // Greatly reduces hue jitter and reset to 0 when hue == 255 and color is rapidly modified using SV square. | ||||
|             if (g.ColorEditLastColor == ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0))) | ||||
|                 H = g.ColorEditLastHue; | ||||
|             value_changed = value_changed_sv = true; | ||||
|         } | ||||
|         if (!(flags & ImGuiColorEditFlags_NoOptions)) | ||||
| @@ -5247,7 +5263,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | ||||
|             ColorConvertHSVtoRGB(H >= 1.0f ? H - 10 * 1e-6f : H, S > 0.0f ? S : 10 * 1e-6f, V > 0.0f ? V : 1e-6f, col[0], col[1], col[2]); | ||||
|             g.ColorEditLastHue = H; | ||||
|             g.ColorEditLastSat = S; | ||||
|             memcpy(g.ColorEditLastColor, col, sizeof(float) * 3); | ||||
|             g.ColorEditLastColor = ColorConvertFloat4ToU32(ImVec4(col[0], col[1], col[2], 0)); | ||||
|         } | ||||
|         else if (flags & ImGuiColorEditFlags_InputHSV) | ||||
|         { | ||||
| @@ -5301,13 +5317,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl | ||||
|             G = col[1]; | ||||
|             B = col[2]; | ||||
|             ColorConvertRGBtoHSV(R, G, B, H, S, V); | ||||
|             if (memcmp(g.ColorEditLastColor, col, sizeof(float) * 3) == 0) // Fix local Hue as display below will use it immediately. | ||||
|             { | ||||
|                 if (S == 0) | ||||
|                     H = g.ColorEditLastHue; | ||||
|                 if (V == 0) | ||||
|                     S = g.ColorEditLastSat; | ||||
|             } | ||||
|             ColorEditRestoreHS(col, &H, &S, &V);   // Fix local Hue as display below will use it immediately. | ||||
|         } | ||||
|         else if (flags & ImGuiColorEditFlags_InputHSV) | ||||
|         { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Rokas Kupstys
					Rokas Kupstys