#pragma once #include "AftrConfig.h" #ifdef AFTR_CONFIG_USE_IMGUI #include #include "SelectionQueryResult.h" #include "Mat4.h" namespace Aftr { class WorldContainer; /// Written by Scott Nykl. /// Let's a user manipulate the pose of any WO, view the coordinate frames of any two WOs in /// in each other's frame, and easily adjust pose via keyboard or mouse input. See /// modules/TestIMGUI for examples. class AftrImGui_WO_Editor { struct BiModal_WO_Selection_State; public: struct Mouse_MutatePose_State; AftrImGui_WO_Editor( const std::string& editor_window_name = "WO Editor" ); void draw( SelectionQueryResult const& q, WorldContainer const& cont, std::function cam_functor = nullptr ) const; void onResizeWindow( int newWidthPix, int newHeightPix ) { this->onLayoutChange = true; } void draw_global_pose( WO* wo ) const noexcept; void draw_alternative_pose_input( WO* wo ) const noexcept; void draw_local_pose( WO* wo ) const noexcept; void draw_relative_pose( WO const* wo, WorldContainer const& cont, Camera* cam = nullptr ) const noexcept; bool draw_Mouse_MutatePose_State( Mouse_MutatePose_State* state, std::string const& text = "Mutate Pose" ) const noexcept; void draw_wo_info( WO const* wo ) const noexcept; template static std::string to_string_xyz_ypr_deg( Mat4T const& pose, unsigned int const numDecimals = 3 ); static std::string to_string_WOid_label_or_nullptr( WO const* wo ); struct Select_WO_from_container { WO* selected_wo{ nullptr }; bool isCam{ false }; }; /// Example usage to ensure this draws each frame: /// if( WO* sel = this->draw_Popup_Select_WO_from_container( cont ); sel != nullptr ) /// std::cout << "Selected WO: " << sel->getID() << "\n"; /// If cam is non-null, that cam will also appear in the popup of selectable objects since /// the camera typically isn't in the default WorldContainer. /// If the camera *is* the WO* returned, the second return param will be true Select_WO_from_container draw_Popup_Select_WO_from_container( WorldContainer const& cont, Camera* cam = nullptr, std::string const& but_text = "Select WO" ) const; struct Mouse_MutatePose_State { enum class TRANSFORM_STATE { PENDING, CANCELLED, APPLIED }; WO* w = nullptr; Mat4 orig_pose; //stores orientation and position of WO immediately before mouse mutations began Mat4 pending_xform; //stores the final xform applied to WO over course of mutation. std::string cmd; //start_pixel and delta_pixel are non-nullopt when an active mouse pose mutation is occurring std::optional< VectorI > start_pixel; //.x and .y store the pixel location reported by ImGui::GetMousePos() std::optional< VectorI > delta_pixel; //.x and .y store the pixel location reported by ImGui::GetMousePos() TRANSFORM_STATE xform_status = TRANSFORM_STATE::PENDING; }; private: /// Optionally, append the Camera* to the end of the list as a selection option. Select_WO_from_container getMostRecentlySelectedWO_either_LeftClicked_or_SelectedFromMenu( BiModal_WO_Selection_State& inout_selectionState, SelectionQueryResult const& q, WorldContainer const& cont, Camera* cam = nullptr, std::string const& but_text = "Select WO") const; SelectionQueryResult query; ///< Stores most recent successful query (non-nullptr WO and coordinate) const std::string editor_window_name; mutable bool onLayoutChange{ true }; //This stores the ungly state needed to handle selecting a WO via a Left-CRTL click OR by selecting //a specific WO from a menu list of WOs. This stateful struct is only used by the //getMostRecentlySelectedWO_either_LeftClicked_or_SelectedFromMenu() method. struct BiModal_WO_Selection_State { Select_WO_from_container old_leftClicked_wo; //used by getMostRecentlySelectedWO_either_LeftClicked_or_SelectedFromMenu Select_WO_from_container old_popupSel_wo; //used by getMostRecentlySelectedWO_either_LeftClicked_or_SelectedFromMenu SelectionQueryResult::clock_type::time_point popupSel_time; }; mutable BiModal_WO_Selection_State recent_selection_state_for_WO; //stores state that is mutated by used by getMostRecentlySelectedWO_either_LeftClicked_or_SelectedFromMenu mutable Mouse_MutatePose_State mutate_pose_state; mutable Select_WO_from_container rel_obj; //used by draw_relative_pose mutable bool expand_Global_Pose_TreeNode{ true }; mutable bool expand_Alternative_Pose_Input_TreeNode{ true }; mutable bool expand_Local_Pose_TreeNode{ true }; mutable bool expand_Relative_Pose_TreeNode{ true }; mutable bool expand_WO_info_TreeNode{ true }; mutable std::string draw_alternative_pose_input__input_buffer = "Copy/Paste or Type your desired inputs here...\n"; //stores the string passed into fromString_opt(...) mutable std::string draw_alternative_pose_input__result_buffer; //stores the feedback on the parsing of the orientation. }; } //namespace Aftr #endif