Skip to content

Commit

Permalink
ImGui::CustomDragFloatN
Browse files Browse the repository at this point in the history
A custom version of ImGui::DragFloatN that do not return 'true' if value is modified using keyboard while editing until 'Enter' is pressed.
  • Loading branch information
Benualdo committed Nov 14, 2024
1 parent 1c67faf commit c961a9e
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 45 deletions.
64 changes: 64 additions & 0 deletions src/editor/ImGui/Extensions/ImGuiExtensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ namespace ImGui

g_disabledStack.push_back(_disabled);
}

//--------------------------------------------------------------------------------------
void PopDisabledStyle()
{
Expand All @@ -521,4 +522,67 @@ namespace ImGui
ApplyDisabledStyle(disabled);
}
}

//--------------------------------------------------------------------------------------
// A custom version of ImGui::DragScalarN that do not return 'true" when value is entered using keyboard
//--------------------------------------------------------------------------------------
bool CustomDragScalarN(InteractionType & _interactionType, const char * label, ImGuiDataType data_type, void * p_data, int components, float v_speed, const void * p_min, const void * p_max, const char * format, ImGuiSliderFlags flags)
{
auto * window = GetCurrentWindow();
if (window->SkipItems)
return false;

_interactionType = InteractionType::Continuous;

ImGuiContext & g = *GImGui;
bool value_changed = false;
BeginGroup();
PushID(label);
PushMultiItemsWidths(components, CalcItemWidth());
size_t type_size = DataTypeGetInfo(data_type)->Size;
for (int i = 0; i < components; i++)
{
PushID(i);
if (i > 0)
SameLine(0, g.Style.ItemInnerSpacing.x);
value_changed |= DragScalar("", data_type, p_data, v_speed, p_min, p_max, format, flags);

const ImGuiID id = ImGui::GetCurrentWindow()->GetID("");
if (ImGui::TempInputIsActive(id))
value_changed = false;

if (ImGui::IsItemDeactivatedAfterEdit())
{
value_changed = true;
_interactionType = InteractionType::Single;
}

PopID();
PopItemWidth();
p_data = (void *)((char *)p_data + type_size);
}
PopID();

const char * label_end = FindRenderedTextEnd(label);
if (label != label_end)
{
SameLine(0, g.Style.ItemInnerSpacing.x);
TextEx(label, label_end);
}

EndGroup();
return value_changed;
}

//--------------------------------------------------------------------------------------
bool CustomDragFloat3(InteractionType & _interactionType, const char * label, float v[3], float v_speed, float v_min, float v_max, const char * format, ImGuiSliderFlags flags)
{
return CustomDragScalarN(_interactionType, label, ImGuiDataType_Float, v, 3, v_speed, &v_min, &v_max, format, flags);
}

//--------------------------------------------------------------------------------------
bool CustomDragFloat4(InteractionType & _interactionType, const char * label, float v[4], float v_speed, float v_min, float v_max, const char * format, ImGuiSliderFlags flags)
{
return CustomDragScalarN(_interactionType, label, ImGuiDataType_Float, v, 4, v_speed, &v_min, &v_max, format, flags);
}
}
9 changes: 9 additions & 0 deletions src/editor/ImGui/Extensions/imGuiExtensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ namespace vg::renderer

namespace ImGui
{
vg_enum_class(InteractionType, vg::core::u8,
Single = 0,
Continuous
);

ImVec4 getDisabledButtonColor();
ImVec4 getDisabledTextColor();

Expand Down Expand Up @@ -61,4 +66,8 @@ namespace ImGui

void PushDisabledStyle(bool _disabled);
void PopDisabledStyle();

bool CustomDragScalarN(InteractionType & _interactionType, const char * label, ImGuiDataType data_type, void * p_data, int components, float v_speed = 1.0f, const void * p_min = NULL, const void * p_max = NULL, const char * format = NULL, ImGuiSliderFlags flags = 0);
bool CustomDragFloat3(InteractionType & _interactionType, const char * label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char * format = "%.3f", ImGuiSliderFlags flags = 0);
bool CustomDragFloat4(InteractionType & _interactionType, const char * label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char * format = "%.3f", ImGuiSliderFlags flags = 0);
}
88 changes: 44 additions & 44 deletions src/editor/ImGui/Window/ImGuiWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "editor/imgui/Extensions/FileDialog/ImGuiFileDialog.h"
#include "ImGuiWindow.h"

#include "D:\GitHub\vimontgames\vgframework\extern\imgui\imgui_internal.h"

#if !VG_ENABLE_INLINE
#include "ImGuiWindow.inl"
#endif
Expand Down Expand Up @@ -332,11 +334,6 @@ namespace vg::editor

template <> struct ImGuiDataTypeInfo<float> { static const ImGuiDataType_ type = ImGuiDataType_Float; };

vg_enum_class(InteractionType, core::u8,
Single = 0,
Continuous
);

template <typename T> EditingState undoRedoBeforeEdit(bool & edited, PropertyContext & _propContext, IObject * _object, const IProperty * _prop, typename vectorTraits<T>::type * temp, typename vectorTraits<T>::type * _ptr, InteractionType _interactionType, bool _itemActive = false, bool _itemAfterEdit = false)
{
constexpr auto count = vectorTraits<T>::count;
Expand Down Expand Up @@ -460,6 +457,8 @@ namespace vg::editor
if (_propContext.m_readOnly)
ImGui::BeginDisabled(true);

InteractionType interactionType = InteractionType::Continuous;

if (asBool(PropertyFlags::Color & flags) && (count == 3 || count == 4))
{
ImGuiColorEditFlags colorEditFlags = 0;
Expand All @@ -481,15 +480,15 @@ namespace vg::editor
else
{
if (asBool(PropertyFlags::HasRange & flags))
edited = ImGui::DragScalarN(ImGuiWindow::getPropertyLabel(_label).c_str(), ImGuiDataTypeInfo<S>::type, &temp, count, dragSpeed, &minRange, &maxRange, editFormat);
edited = CustomDragScalarN(interactionType, ImGuiWindow::getPropertyLabel(_label).c_str(), ImGuiDataTypeInfo<S>::type, &temp, count, dragSpeed, &minRange, &maxRange, editFormat, ImGuiSliderFlags_NoRoundToFormat);
else
edited = ImGui::DragScalarN(ImGuiWindow::getPropertyLabel(_label).c_str(), ImGuiDataTypeInfo<S>::type, &temp, count, dragSpeed, nullptr, nullptr, editFormat);
edited = CustomDragScalarN(interactionType, ImGuiWindow::getPropertyLabel(_label).c_str(), ImGuiDataTypeInfo<S>::type, &temp, count, dragSpeed, nullptr, nullptr, editFormat, ImGuiSliderFlags_NoRoundToFormat);
}

if (_propContext.m_readOnly)
edited = false;

EditingState editingState = undoRedoBeforeEdit<T>(edited, _propContext, _object, _prop, (S*)&temp[0], _ptr, InteractionType::Continuous);
EditingState editingState = undoRedoBeforeEdit<T>(edited, _propContext, _object, _prop, (S*)&temp[0], _ptr, interactionType);

if (_propContext.m_readOnly)
ImGui::EndDisabled();
Expand Down Expand Up @@ -2713,6 +2712,7 @@ namespace vg::editor
ImGui::BeginDisabled();

bool itemActive = false, itemAfterEdit = false;
InteractionType interactionType = InteractionType::Continuous;

//if (useTRS)
{
Expand All @@ -2731,19 +2731,19 @@ namespace vg::editor
float prevRot[3] = { rotation[0], rotation[1], rotation[2] };
float prevScale[3] = { scale[0], scale[1], scale[2] };

edited |= ImGui::DragFloat3(getPropertyLabel("T").c_str(), (float *)&translation, getDragSpeedFloat(_prop) * 90.0f/8.0f, -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
itemActive = ImGui::IsItemActive();
itemAfterEdit = ImGui::IsItemDeactivatedAfterEdit();
edited |= CustomDragFloat3(interactionType, getPropertyLabel("T").c_str(), (float *)&translation, getDragSpeedFloat(_prop) * 90.0f/8.0f, -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
itemActive = ImGui::IsItemActive() || InteractionType::Single == interactionType;
itemAfterEdit = ImGui::IsItemDeactivatedAfterEdit() || InteractionType::Single == interactionType;
drawPropertyLabel(_propContext, TLabel.c_str(), "Represents the translation part of the matrix");

edited |= ImGui::DragFloat3(getPropertyLabel("R").c_str(), (float *)&rotation, getDragSpeedFloat(_prop) * 90.0f / 8.0f, -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
itemActive |= ImGui::IsItemActive();
itemAfterEdit |= ImGui::IsItemDeactivatedAfterEdit();
edited |= CustomDragFloat3(interactionType, getPropertyLabel("R").c_str(), (float *)&rotation, getDragSpeedFloat(_prop) * 90.0f / 8.0f, -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
itemActive |= ImGui::IsItemActive() || InteractionType::Single == interactionType;
itemAfterEdit |= ImGui::IsItemDeactivatedAfterEdit() || InteractionType::Single == interactionType;
drawPropertyLabel(_propContext, RLabel.c_str(), "Represents the rotation part of the matrix");

edited |= ImGui::DragFloat3(getPropertyLabel("S").c_str(), (float *)&scale, getDragSpeedFloat(_prop) * 90.0f / 8.0f, 0.01f, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
itemActive |= ImGui::IsItemActive();
itemAfterEdit |= ImGui::IsItemDeactivatedAfterEdit();
edited |= CustomDragFloat3(interactionType, getPropertyLabel("S").c_str(), (float *)&scale, getDragSpeedFloat(_prop) * 90.0f / 8.0f, 0.01f, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
itemActive |= ImGui::IsItemActive() || InteractionType::Single == interactionType;
itemAfterEdit |= ImGui::IsItemDeactivatedAfterEdit() || InteractionType::Single == interactionType;
drawPropertyLabel(_propContext, SLabel.c_str(), "Represents the scale part of the matrix");

if (edited)
Expand Down Expand Up @@ -2817,35 +2817,35 @@ namespace vg::editor
}

if (EditingState::Unknown == editingState)
editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, InteractionType::Continuous, itemActive, itemAfterEdit);
editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, interactionType, itemActive, itemAfterEdit);

//else
if (false && ImGui::TreeNode(getObjectLabel("(float4x4) " + (string)displayName, _propContext.m_originalProp).c_str()))
{
ImGui::Spacing();

edited |= ImGui::DragFloat4(getPropertyLabel("I").c_str(), (float *)&temp[0], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
if (EditingState::Unknown == editingState)
editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, InteractionType::Continuous);
drawPropertyLabel(_propContext, LabelI.c_str(), "Represents the x-axis in the transformed space");

edited |= ImGui::DragFloat4(getPropertyLabel("J").c_str(), (float *)&temp[4], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
if (EditingState::Unknown == editingState)
editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, InteractionType::Continuous);
drawPropertyLabel(_propContext, LabelJ.c_str(), "Represents the y-axis in the transformed space");

edited |= ImGui::DragFloat4(getPropertyLabel("K").c_str(), (float *)&temp[8], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
if (EditingState::Unknown == editingState)
editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, InteractionType::Continuous);
drawPropertyLabel(_propContext, LabelK.c_str(), "Represents the z-axis in the transformed space");

edited |= ImGui::DragFloat4(getPropertyLabel("T").c_str(), (float *)&temp[12], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
if (EditingState::Unknown == editingState)
editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, InteractionType::Continuous);
drawPropertyLabel(_propContext, LabelT.c_str(), "Represents the translation component");

ImGui::TreePop();
}
//if (false && ImGui::TreeNode(getObjectLabel("(float4x4) " + (string)displayName, _propContext.m_originalProp).c_str()))
//{
// ImGui::Spacing();
//
// edited |= ImGui::CustomDragFloat4(interactionType, getPropertyLabel("I").c_str(), (float *)&temp[0], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
// if (EditingState::Unknown == editingState || InteractionType::Single == interactionType)
// editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, interactionType);
// drawPropertyLabel(_propContext, LabelI.c_str(), "Represents the x-axis in the transformed space");
//
// edited |= ImGui::CustomDragFloat4(interactionType, getPropertyLabel("J").c_str(), (float *)&temp[4], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
// if (EditingState::Unknown == editingState || InteractionType::Single == interactionType)
// editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, interactionType);
// drawPropertyLabel(_propContext, LabelJ.c_str(), "Represents the y-axis in the transformed space");
//
// edited |= ImGui::CustomDragFloat4(interactionType, getPropertyLabel("K").c_str(), (float *)&temp[8], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
// if (EditingState::Unknown == editingState || InteractionType::Single == interactionType)
// editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, interactionType);
// drawPropertyLabel(_propContext, LabelK.c_str(), "Represents the z-axis in the transformed space");
//
// edited |= ImGui::CustomDragFloat4(interactionType, getPropertyLabel("T").c_str(), (float *)&temp[12], getDragSpeedFloat(_prop), -style::range::maxFloat, style::range::maxFloat, g_editFloatFormat) && !_propContext.m_readOnly;
// if (EditingState::Unknown == editingState || InteractionType::Single == interactionType)
// editingState = undoRedoBeforeEdit<float4x4>(edited, _propContext, _object, _prop, (float *)&temp[0], pFloat, interactionType);
// drawPropertyLabel(_propContext, LabelT.c_str(), "Represents the translation component");
//
// ImGui::TreePop();
//}

if (_propContext.m_readOnly)
ImGui::EndDisabled();
Expand Down
2 changes: 1 addition & 1 deletion src/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

#define VG_FRAMEWORK_VERSION_MAJOR 0
#define VG_FRAMEWORK_VERSION_MINOR 42
#define VG_FRAMEWORK_VERSION_PATCH 1
#define VG_FRAMEWORK_VERSION_PATCH 2

0 comments on commit c961a9e

Please sign in to comment.