diff --git a/dearpygui/_dearpygui.pyi b/dearpygui/_dearpygui.pyi index 3768e3f25..692b7264e 100644 --- a/dearpygui/_dearpygui.pyi +++ b/dearpygui/_dearpygui.pyi @@ -327,7 +327,7 @@ def add_item_edited_handler(*, label: str ='', user_data: Any ='', use_internal_ """Adds an edited handler.""" ... -def add_item_focus_handler(*, label: str ='', user_data: Any ='', use_internal_label: bool ='', tag: Union[int, str] ='', parent: Union[int, str] ='', callback: Callable ='', show: bool ='') -> Union[int, str]: +def add_item_focus_handler(*, label: str ='', user_data: Any ='', use_internal_label: bool ='', tag: Union[int, str] ='', parent: Union[int, str] ='', callback: Callable ='', show: bool ='', event_type: int ='') -> Union[int, str]: """Adds a focus handler.""" ... @@ -335,7 +335,7 @@ def add_item_handler_registry(*, label: str ='', user_data: Any ='', use_interna """Adds an item handler registry.""" ... -def add_item_hover_handler(*, label: str ='', user_data: Any ='', use_internal_label: bool ='', tag: Union[int, str] ='', parent: Union[int, str] ='', callback: Callable ='', show: bool ='') -> Union[int, str]: +def add_item_hover_handler(*, label: str ='', user_data: Any ='', use_internal_label: bool ='', tag: Union[int, str] ='', parent: Union[int, str] ='', callback: Callable ='', show: bool ='', event_type: int ='') -> Union[int, str]: """Adds a hover handler.""" ... @@ -1430,6 +1430,10 @@ mvComboHeight_Small=0 mvComboHeight_Regular=0 mvComboHeight_Large=0 mvComboHeight_Largest=0 +mvEventType_Off=0 +mvEventType_Enter=0 +mvEventType_On=0 +mvEventType_Leave=0 mvPlatform_Windows=0 mvPlatform_Apple=0 mvPlatform_Linux=0 diff --git a/dearpygui/_dearpygui_RTD.py b/dearpygui/_dearpygui_RTD.py index 65f4f23e9..b796cdc3a 100644 --- a/dearpygui/_dearpygui_RTD.py +++ b/dearpygui/_dearpygui_RTD.py @@ -4940,6 +4940,7 @@ def add_item_focus_handler(**kwargs): parent (Union[int, str], optional): Parent to add this item to. (runtime adding) callback (Callable, optional): Registers a callback. show (bool, optional): Attempt to render widget. + event_type (int, optional): What kind of events to track: just got focus (mvEventType_Enter), currently having focus (mvEventType_On), lost focus (mvEventType_Leave). Can be a combination of these flags. Defaults to mvEventType_On. id (Union[int, str], optional): (deprecated) Returns: Union[int, str] @@ -4974,6 +4975,7 @@ def add_item_hover_handler(**kwargs): parent (Union[int, str], optional): Parent to add this item to. (runtime adding) callback (Callable, optional): Registers a callback. show (bool, optional): Attempt to render widget. + event_type (int, optional): What kind of events to track: mouse-in (mvEventType_Enter), mouse-over (mvEventType_On), mouse-out (mvEventType_Leave). Can be a combination of these flags. Defaults to mouse-over. id (Union[int, str], optional): (deprecated) Returns: Union[int, str] @@ -8983,6 +8985,10 @@ def unstage(item): mvComboHeight_Regular=internal_dpg.mvComboHeight_Regular mvComboHeight_Large=internal_dpg.mvComboHeight_Large mvComboHeight_Largest=internal_dpg.mvComboHeight_Largest +mvEventType_Off=internal_dpg.mvEventType_Off +mvEventType_Enter=internal_dpg.mvEventType_Enter +mvEventType_On=internal_dpg.mvEventType_On +mvEventType_Leave=internal_dpg.mvEventType_Leave mvPlatform_Windows=internal_dpg.mvPlatform_Windows mvPlatform_Apple=internal_dpg.mvPlatform_Apple mvPlatform_Linux=internal_dpg.mvPlatform_Linux diff --git a/dearpygui/dearpygui.py b/dearpygui/dearpygui.py index 6c69a5027..70768c754 100644 --- a/dearpygui/dearpygui.py +++ b/dearpygui/dearpygui.py @@ -5464,7 +5464,7 @@ def add_item_edited_handler(*, label: str =None, user_data: Any =None, use_inter return internal_dpg.add_item_edited_handler(label=label, user_data=user_data, use_internal_label=use_internal_label, tag=tag, parent=parent, callback=callback, show=show, **kwargs) -def add_item_focus_handler(*, label: str =None, user_data: Any =None, use_internal_label: bool =True, tag: Union[int, str] =0, parent: Union[int, str] =0, callback: Callable =None, show: bool =True, **kwargs) -> Union[int, str]: +def add_item_focus_handler(*, label: str =None, user_data: Any =None, use_internal_label: bool =True, tag: Union[int, str] =0, parent: Union[int, str] =0, callback: Callable =None, show: bool =True, event_type: int =None, **kwargs) -> Union[int, str]: """ Adds a focus handler. Args: @@ -5475,6 +5475,7 @@ def add_item_focus_handler(*, label: str =None, user_data: Any =None, use_intern parent (Union[int, str], optional): Parent to add this item to. (runtime adding) callback (Callable, optional): Registers a callback. show (bool, optional): Attempt to render widget. + event_type (int, optional): What kind of events to track: just got focus (mvEventType_Enter), currently having focus (mvEventType_On), lost focus (mvEventType_Leave). Can be a combination of these flags. Defaults to mvEventType_On. id (Union[int, str], optional): (deprecated) Returns: Union[int, str] @@ -5484,7 +5485,7 @@ def add_item_focus_handler(*, label: str =None, user_data: Any =None, use_intern warnings.warn('id keyword renamed to tag', DeprecationWarning, 2) tag=kwargs['id'] - return internal_dpg.add_item_focus_handler(label=label, user_data=user_data, use_internal_label=use_internal_label, tag=tag, parent=parent, callback=callback, show=show, **kwargs) + return internal_dpg.add_item_focus_handler(label=label, user_data=user_data, use_internal_label=use_internal_label, tag=tag, parent=parent, callback=callback, show=show, event_type=event_type, **kwargs) def add_item_handler_registry(*, label: str =None, user_data: Any =None, use_internal_label: bool =True, tag: Union[int, str] =0, show: bool =True, **kwargs) -> Union[int, str]: """ Adds an item handler registry. @@ -5506,7 +5507,7 @@ def add_item_handler_registry(*, label: str =None, user_data: Any =None, use_int return internal_dpg.add_item_handler_registry(label=label, user_data=user_data, use_internal_label=use_internal_label, tag=tag, show=show, **kwargs) -def add_item_hover_handler(*, label: str =None, user_data: Any =None, use_internal_label: bool =True, tag: Union[int, str] =0, parent: Union[int, str] =0, callback: Callable =None, show: bool =True, **kwargs) -> Union[int, str]: +def add_item_hover_handler(*, label: str =None, user_data: Any =None, use_internal_label: bool =True, tag: Union[int, str] =0, parent: Union[int, str] =0, callback: Callable =None, show: bool =True, event_type: int =None, **kwargs) -> Union[int, str]: """ Adds a hover handler. Args: @@ -5517,6 +5518,7 @@ def add_item_hover_handler(*, label: str =None, user_data: Any =None, use_intern parent (Union[int, str], optional): Parent to add this item to. (runtime adding) callback (Callable, optional): Registers a callback. show (bool, optional): Attempt to render widget. + event_type (int, optional): What kind of events to track: mouse-in (mvEventType_Enter), mouse-over (mvEventType_On), mouse-out (mvEventType_Leave). Can be a combination of these flags. Defaults to mouse-over. id (Union[int, str], optional): (deprecated) Returns: Union[int, str] @@ -5526,7 +5528,7 @@ def add_item_hover_handler(*, label: str =None, user_data: Any =None, use_intern warnings.warn('id keyword renamed to tag', DeprecationWarning, 2) tag=kwargs['id'] - return internal_dpg.add_item_hover_handler(label=label, user_data=user_data, use_internal_label=use_internal_label, tag=tag, parent=parent, callback=callback, show=show, **kwargs) + return internal_dpg.add_item_hover_handler(label=label, user_data=user_data, use_internal_label=use_internal_label, tag=tag, parent=parent, callback=callback, show=show, event_type=event_type, **kwargs) def add_item_resize_handler(*, label: str =None, user_data: Any =None, use_internal_label: bool =True, tag: Union[int, str] =0, parent: Union[int, str] =0, callback: Callable =None, show: bool =True, **kwargs) -> Union[int, str]: """ Adds a resize handler. @@ -9956,6 +9958,10 @@ def unstage(item : Union[int, str], **kwargs) -> None: mvComboHeight_Regular=internal_dpg.mvComboHeight_Regular mvComboHeight_Large=internal_dpg.mvComboHeight_Large mvComboHeight_Largest=internal_dpg.mvComboHeight_Largest +mvEventType_Off=internal_dpg.mvEventType_Off +mvEventType_Enter=internal_dpg.mvEventType_Enter +mvEventType_On=internal_dpg.mvEventType_On +mvEventType_Leave=internal_dpg.mvEventType_Leave mvPlatform_Windows=internal_dpg.mvPlatform_Windows mvPlatform_Apple=internal_dpg.mvPlatform_Apple mvPlatform_Linux=internal_dpg.mvPlatform_Linux diff --git a/src/dearpygui.cpp b/src/dearpygui.cpp index 867d382cb..27145a651 100644 --- a/src/dearpygui.cpp +++ b/src/dearpygui.cpp @@ -69,6 +69,11 @@ GetModuleConstants() ModuleConstants.push_back({"mvComboHeight_Large", 2L }); ModuleConstants.push_back({"mvComboHeight_Largest", 3L }); + ModuleConstants.push_back({"mvEventType_Off", mvEventType_Off }); + ModuleConstants.push_back({"mvEventType_Enter", mvEventType_Enter }); + ModuleConstants.push_back({"mvEventType_On", mvEventType_On }); + ModuleConstants.push_back({"mvEventType_Leave", mvEventType_Leave }); + ModuleConstants.push_back({"mvPlatform_Windows", 0L }); ModuleConstants.push_back({"mvPlatform_Apple", 1L }); ModuleConstants.push_back({"mvPlatform_Linux", 2L }); diff --git a/src/mvAppItem.cpp b/src/mvAppItem.cpp index b5fdffbf6..bae62efd6 100644 --- a/src/mvAppItem.cpp +++ b/src/mvAppItem.cpp @@ -4855,6 +4855,8 @@ DearPyGui::GetEntityParser(mvAppItemType type) MV_PARSER_ARG_CALLBACK) ); + args.push_back({ mvPyDataType::Integer, "event_type", mvArgType::KEYWORD_ARG, "None", "What kind of events to track: mouse-in (mvEventType_Enter), mouse-over (mvEventType_On), mouse-out (mvEventType_Leave). Can be a combination of these flags. Defaults to mouse-over." }); + setup.about = "Adds a hover handler."; setup.category = { "Widgets", "Events" }; break; @@ -4881,6 +4883,8 @@ DearPyGui::GetEntityParser(mvAppItemType type) MV_PARSER_ARG_CALLBACK) ); + args.push_back({ mvPyDataType::Integer, "event_type", mvArgType::KEYWORD_ARG, "None", "What kind of events to track: just got focus (mvEventType_Enter), currently having focus (mvEventType_On), lost focus (mvEventType_Leave). Can be a combination of these flags. Defaults to mvEventType_On." }); + setup.about = "Adds a focus handler."; setup.category = { "Widgets", "Events" }; break; diff --git a/src/mvAppItemState.cpp b/src/mvAppItemState.cpp index da166671b..33a0d5b0b 100644 --- a/src/mvAppItemState.cpp +++ b/src/mvAppItemState.cpp @@ -8,8 +8,10 @@ void ResetAppItemState(mvAppItemState& state) { state.hovered = false; + state.prevHovered = false; state.active = false; state.focused = false; + state.prevFocused = false; state.leftclicked = false; state.rightclicked = false; state.middleclicked = false; @@ -27,8 +29,10 @@ void UpdateAppItemState(mvAppItemState& state) { state.lastFrameUpdate = GContext->frame; + state.prevHovered = state.hovered; state.hovered = ImGui::IsItemHovered(); state.active = ImGui::IsItemActive(); + state.prevFocused = state.focused; state.focused = ImGui::IsItemFocused(); if (state.focused) { diff --git a/src/mvAppItemState.h b/src/mvAppItemState.h index b635645a7..691326387 100644 --- a/src/mvAppItemState.h +++ b/src/mvAppItemState.h @@ -66,8 +66,10 @@ inline b8 IsItemDoubleClicked(ImGuiMouseButton mouse_button) struct mvAppItemState { b8 hovered = false; + b8 prevHovered = false; b8 active = false; b8 focused = false; + b8 prevFocused = false; b8 leftclicked = false; b8 rightclicked = false; b8 middleclicked = false; diff --git a/src/mvBasicWidgets.cpp b/src/mvBasicWidgets.cpp index 7c009d96e..b7b66aae3 100644 --- a/src/mvBasicWidgets.cpp +++ b/src/mvBasicWidgets.cpp @@ -2642,6 +2642,7 @@ DearPyGui::draw_simple_plot(ImDrawList* drawlist, mvAppItem& item, const mvSimpl // * only update if applicable //----------------------------------------------------------------------------- item.state.lastFrameUpdate = GContext->frame; + item.state.prevHovered = item.state.hovered; item.state.hovered = ImGui::IsItemHovered(); item.state.leftclicked = ImGui::IsItemClicked(); item.state.rightclicked = ImGui::IsItemClicked(1); @@ -4388,26 +4389,7 @@ DearPyGui::draw_radio_button(ImDrawList* drawlist, mvAppItem& item, mvRadioButto //----------------------------------------------------------------------------- // update state //----------------------------------------------------------------------------- - item.state.lastFrameUpdate = GContext->frame; - item.state.hovered = ImGui::IsItemHovered(); - item.state.active = ImGui::IsItemActive(); - item.state.focused = ImGui::IsItemFocused(); - item.state.leftclicked = ImGui::IsItemClicked(); - item.state.rightclicked = ImGui::IsItemClicked(1); - item.state.middleclicked = ImGui::IsItemClicked(2); - for (int i = 0; i < item.state.doubleclicked.size(); i++) - { - item.state.doubleclicked[i] = IsItemDoubleClicked(i); - } - item.state.visible = ImGui::IsItemVisible(); - item.state.activated = ImGui::IsItemActivated(); - item.state.deactivated = ImGui::IsItemDeactivated(); - item.state.deactivatedAfterEdit = ImGui::IsItemDeactivatedAfterEdit(); - item.state.toggledOpen = ImGui::IsItemToggledOpen(); - item.state.rectMin = { ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y }; - item.state.rectMax = { ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y }; - item.state.rectSize = { ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y }; - item.state.contextRegionAvail = { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }; + UpdateAppItemState(item.state); //----------------------------------------------------------------------------- // post draw diff --git a/src/mvContainers.cpp b/src/mvContainers.cpp index 93969a59a..9b097909b 100644 --- a/src/mvContainers.cpp +++ b/src/mvContainers.cpp @@ -639,7 +639,9 @@ DearPyGui::draw_menu(ImDrawList* drawlist, mvAppItem& item, mvMenuConfig& config item.state.active = ImGui::IsItemActive(); item.state.activated = ImGui::IsItemActivated(); item.state.deactivated = ImGui::IsItemDeactivated(); + item.state.prevFocused = item.state.focused; item.state.focused = ImGui::IsWindowFocused(); + item.state.prevHovered = item.state.hovered; item.state.hovered = ImGui::IsWindowHovered(); item.state.rectSize = { ImGui::GetWindowWidth(), ImGui::GetWindowHeight() }; item.state.contextRegionAvail = { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }; @@ -682,7 +684,9 @@ DearPyGui::draw_menu(ImDrawList* drawlist, mvAppItem& item, mvMenuConfig& config item.state.active = ImGui::IsItemActive(); item.state.activated = ImGui::IsItemActivated(); item.state.deactivated = ImGui::IsItemDeactivated(); + item.state.prevFocused = item.state.focused; item.state.focused = false; + item.state.prevHovered = item.state.hovered; item.state.hovered = false; item.state.rectSize = { 0.0f, 0.0f }; item.state.contextRegionAvail = { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }; @@ -779,6 +783,7 @@ DearPyGui::draw_tab(ImDrawList* drawlist, mvAppItem& item, mvTabConfig& config) } item.state.lastFrameUpdate = GContext->frame; + item.state.prevHovered = item.state.hovered; // create tab item and see if it is selected if (ImGui::BeginTabItem(item.info.internalLabel.c_str(), config.closable ? &item.config.show : nullptr, config._flags)) { @@ -927,7 +932,9 @@ DearPyGui::draw_child_window(ImDrawList* drawlist, mvAppItem& item, mvChildWindo item.state.lastFrameUpdate = GContext->frame; item.state.active = ImGui::IsItemActive(); item.state.deactivated = ImGui::IsItemDeactivated(); + item.state.prevFocused = item.state.focused; item.state.focused = ImGui::IsWindowFocused(); + item.state.prevHovered = item.state.hovered; item.state.hovered = ImGui::IsWindowHovered(); item.state.rectSize = { ImGui::GetWindowWidth(), ImGui::GetWindowHeight() }; item.state.contextRegionAvail = { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }; @@ -1511,7 +1518,9 @@ DearPyGui::draw_window(ImDrawList* drawlist, mvAppItem& item, mvWindowAppItemCon // shouldn't have to do this but do. Fix later item.config.show = false; item.state.lastFrameUpdate = GContext->frame; + item.state.prevHovered = item.state.hovered; item.state.hovered = false; + item.state.prevFocused = item.state.focused; item.state.focused = false; item.state.toggledOpen = false; item.state.visible = false; @@ -1550,7 +1559,9 @@ DearPyGui::draw_window(ImDrawList* drawlist, mvAppItem& item, mvWindowAppItemCon item.config.show = false; // Update item state so that get_item_state is valid item.state.lastFrameUpdate = GContext->frame; + item.state.prevHovered = item.state.hovered; item.state.hovered = false; + item.state.prevFocused = item.state.focused; item.state.focused = false; item.state.toggledOpen = false; item.state.visible = false; @@ -1658,7 +1669,9 @@ DearPyGui::draw_window(ImDrawList* drawlist, mvAppItem& item, mvWindowAppItemCon item.state.lastFrameUpdate = GContext->frame; item.state.visible = true; + item.state.prevHovered = item.state.hovered; item.state.hovered = ImGui::IsWindowHovered(); + item.state.prevFocused = item.state.focused; item.state.focused = ImGui::IsWindowFocused(); item.state.rectSize = { ImGui::GetWindowSize().x, ImGui::GetWindowSize().y }; item.state.toggledOpen = ImGui::IsWindowCollapsed(); @@ -1705,7 +1718,9 @@ DearPyGui::draw_window(ImDrawList* drawlist, mvAppItem& item, mvWindowAppItemCon if (!item.config.show) { item.state.lastFrameUpdate = GContext->frame; + item.state.prevHovered = item.state.hovered; item.state.hovered = false; + item.state.prevFocused = item.state.focused; item.state.focused = false; item.state.toggledOpen = false; item.state.visible = false; diff --git a/src/mvItemHandlers.cpp b/src/mvItemHandlers.cpp index 01dca1844..f8491a475 100644 --- a/src/mvItemHandlers.cpp +++ b/src/mvItemHandlers.cpp @@ -131,6 +131,40 @@ void mvItemHandler::submitHandler(mvAppItem* parent) }); } +void mvBoolStateHandler::checkEvent(bool curState, bool prevState, mvAppItem* parent) +{ + mvEventType eventType = curState? + (prevState? mvEventType_On : mvEventType_EnterAndOn) : + (prevState? mvEventType_LeaveAndOff : mvEventType_Off); + + if (trackedEventType & eventType) + { + // We do not pass eventType to callback yet in order to keep it compatible + // with the old version. + submitHandler(parent); + } +} + +void mvBoolStateHandler::handleSpecificKeywordArgs(PyObject* dict) +{ + if (dict == nullptr) + return; + + if (PyObject* item = PyDict_GetItemString(dict, "event_type")) + { + if (item != Py_None) + trackedEventType = static_cast(ToInt(item)); + } +} + +void mvBoolStateHandler::getSpecificConfiguration(PyObject* dict) +{ + if (dict == nullptr) + return; + + PyDict_SetItemString(dict, "event_type", mvPyObject(ToPyInt(trackedEventType))); +} + void mvActivatedHandler::customAction(void* data) { @@ -277,21 +311,14 @@ void mvEditedHandler::customAction(void* data) void mvFocusHandler::customAction(void* data) { - mvAppItemState* state = static_cast(data); - if (state->focused) - { - submitHandler(state->parent); - } + checkEvent(state->focused, state->prevFocused, state->parent); } void mvHoverHandler::customAction(void* data) { mvAppItemState* state = static_cast(data); - if (state->hovered) - { - submitHandler(state->parent); - } + checkEvent(state->hovered, state->prevHovered, state->parent); } void mvResizeHandler::customAction(void* data) diff --git a/src/mvItemHandlers.h b/src/mvItemHandlers.h index f49aa92eb..d32a91d06 100644 --- a/src/mvItemHandlers.h +++ b/src/mvItemHandlers.h @@ -23,6 +23,39 @@ class mvItemHandler : public mvAppItem void submitHandler(mvAppItem* parent); }; +enum mvEventType +{ + // These constants can be used as a combination of flags + mvEventType_None = 0, + mvEventType_Off = 1 << 1, + mvEventType_Enter = 1 << 2, + mvEventType_On = 1 << 3, + mvEventType_Leave = 1 << 4, + // When the state changes, we observe two events in a single frame: + // both "enter" and "on" or both "leave" and "off". We need to define + // these flags here so that they can be used as a mask later on. + mvEventType_EnterAndOn = mvEventType_Enter | mvEventType_On, + mvEventType_LeaveAndOff = mvEventType_Leave | mvEventType_Off, + // This is the state the handler will react to by default + mvEventType_Default = mvEventType_On +}; + +// This is a base class for handlers that monitor a single bool variable +// that can switch on or off and reflects the item state, like "focused" +// or "hovered". +class mvBoolStateHandler : public mvItemHandler +{ +public: + explicit mvBoolStateHandler(mvUUID uuid) : mvItemHandler(uuid) {} + void draw(ImDrawList* drawlist, float x, float y) override {} + void checkEvent(bool curState, bool prevState, mvAppItem* parent); + void handleSpecificKeywordArgs(PyObject* dict) override; + void getSpecificConfiguration(PyObject* dict) override; + +protected: + mvEventType trackedEventType = mvEventType_Default; +}; + class mvActivatedHandler : public mvItemHandler { public: @@ -89,19 +122,17 @@ class mvEditedHandler : public mvItemHandler void customAction(void* data = nullptr) override; }; -class mvFocusHandler : public mvItemHandler +class mvFocusHandler : public mvBoolStateHandler { public: - explicit mvFocusHandler(mvUUID uuid) : mvItemHandler(uuid) {} - void draw(ImDrawList* drawlist, float x, float y) override {} + explicit mvFocusHandler(mvUUID uuid) : mvBoolStateHandler(uuid) {} void customAction(void* data = nullptr) override; }; -class mvHoverHandler : public mvItemHandler +class mvHoverHandler : public mvBoolStateHandler { public: - explicit mvHoverHandler(mvUUID uuid) : mvItemHandler(uuid) {} - void draw(ImDrawList* drawlist, float x, float y) override {} + explicit mvHoverHandler(mvUUID uuid) : mvBoolStateHandler(uuid) {} void customAction(void* data = nullptr) override; }; diff --git a/src/mvNodes.cpp b/src/mvNodes.cpp index 71635ddfd..6f81f1bd2 100644 --- a/src/mvNodes.cpp +++ b/src/mvNodes.cpp @@ -213,6 +213,7 @@ void mvNodeEditor::draw(ImDrawList* drawlist, float x, float y) } state.lastFrameUpdate = GContext->frame; + state.prevHovered = state.hovered; state.hovered = ImNodes::IsEditorHovered(); state.visible = ret; state.rectSize = { ImNodes::mvEditorGetSize().Max.x - ImNodes::mvEditorGetSize().Min.x, ImNodes::mvEditorGetSize().Max.y - ImNodes::mvEditorGetSize().Min.y }; @@ -240,6 +241,7 @@ void mvNodeEditor::draw(ImDrawList* drawlist, float x, float y) for (auto& child : childslots[0]) { child->state.lastFrameUpdate = GContext->frame; + child->state.prevHovered = child->state.hovered; child->state.hovered = false; if (anyLinkHovered && linkHovered == static_cast(child.get())->getId()) @@ -250,6 +252,7 @@ void mvNodeEditor::draw(ImDrawList* drawlist, float x, float y) for (auto& child : childslots[1]) { child->state.lastFrameUpdate = GContext->frame; + child->state.prevHovered = child->state.hovered; child->state.hovered = false; if (child->config.show) @@ -267,6 +270,7 @@ void mvNodeEditor::draw(ImDrawList* drawlist, float x, float y) for (auto& grandchild : child->childslots[1]) { grandchild->state.lastFrameUpdate = GContext->frame; + grandchild->state.prevHovered = grandchild->state.hovered; grandchild->state.hovered = false; if (anyPinHovered && pinHovered == static_cast(grandchild.get())->getId()) diff --git a/src/mvTables.cpp b/src/mvTables.cpp index b02b8ec20..4bcd43809 100644 --- a/src/mvTables.cpp +++ b/src/mvTables.cpp @@ -360,6 +360,7 @@ void mvTable::draw(ImDrawList* drawlist, float x, float y) ImGuiTableColumnFlags flags = ImGui::TableGetColumnFlags(columnnum); item->state.lastFrameUpdate = GContext->frame; item->state.visible = flags & ImGuiTableColumnFlags_IsVisible; + item->state.prevHovered = item->state.hovered; item->state.hovered = flags & ImGuiTableColumnFlags_IsHovered; // Note: when the table is empty, TableGetColumnFlags will incorrectly return // zero status flags for all columns. While this is fine for `visible` and `hovered`,