#include "externals.hh" #include "ui.hh" #include "ui-app.hh" #include "ui-imgui-sdl.hh" #include "ui-texture.hh" #include /*= T_UIApp =================================================================*/ namespace { #include "font-awesome.inl" static const ImWchar IconsRanges_[] = { ICON_MIN_FA , ICON_MAX_FA , 0 }; } // namespace T_UIApp::T_UIApp( ) { SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER , 1 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE , 24 ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE , 8 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION , 2 ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION , 2 ); SDL_DisplayMode current; SDL_GetCurrentDisplayMode( 0 , ¤t ); window_ = SDL_CreateWindow( "DEMO", SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED , 1280 , 720 , SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE ); gl_ = SDL_GL_CreateContext( window_ ); glewInit( ); if ( !GLEW_VERSION_4_5 ) { fprintf( stderr , "OpenGL 4.5 required\n" ); exit( 1 ); } ImGui_ImplSdl_Init( window_ ); using namespace ImGui; StyleColorsDark( ); ImGuiIO& io{ GetIO( ) }; io.IniFilename = nullptr; { ImFontConfig cfg; cfg.SizePixels = 13.0f; defaultFont_ = io.Fonts->AddFontDefault( &cfg ); ImFontConfig icons; icons.MergeMode = true; icons.PixelSnapH = true; io.Fonts->AddFontFromMemoryCompressedBase85TTF( FontAwesome__compressed_data_base85 , 13.f , &icons , IconsRanges_ ); } { ImFontConfig cfg; cfg.SizePixels = 9.0f; smallFont_ = io.Fonts->AddFontDefault( &cfg ); ImFontConfig icons; icons.MergeMode = true; icons.PixelSnapH = true; icons.DstFont = smallFont_; io.Fonts->AddFontFromMemoryCompressedBase85TTF( FontAwesome__compressed_data_base85 , 9.f , &icons , IconsRanges_ ); } } T_UIApp::~T_UIApp( ) { ImGui_ImplSdl_Shutdown( ); SDL_GL_DeleteContext( gl_ ); SDL_DestroyWindow( window_ ); SDL_Quit( ); } void T_UIApp::addAction( T_UIAction action ) noexcept { actions_.set( std::move( action ) ); } void T_UIApp::actionMenu( T_String const& id ) const noexcept { auto const* const a{ actions_.get( id ) }; if ( a ) { a->menuItem( ); } } void T_UIApp::actionButton( T_String const& id ) const noexcept { auto const* const a{ actions_.get( id ) }; if ( a ) { a->tbButton( ); } } void T_UIApp::handleEvents( ) noexcept { SDL_Event event; mMove_ = ImVec2( ); while ( SDL_PollEvent( &event ) ) { ImGui_ImplSdl_ProcessEvent( &event ); if ( event.type == SDL_QUIT ) { #warning FIXME request confirmation exiting_ = true; return; } if ( mCapture_ && event.type == SDL_MOUSEMOTION ) { mMove_.x += event.motion.xrel; mMove_.y += event.motion.yrel; } } ImGui_ImplSdl_NewFrame( window_ , mCapture_ , mInitial_ ); ImGui::GetIO( ).MouseDrawCursor = true; handleMouseCapture( ); } void T_UIApp::handleMouseCapture( ) noexcept { using namespace ImGui; auto const& io( GetIO( ) ); const T_MouseButtons mb( ([]() {; T_MouseButtons mb; if ( IsMouseDown( 0 ) ) { mb |= E_MouseButton::LEFT; } if ( IsMouseDown( 1 ) ) { mb |= E_MouseButton::RIGHT; } if ( IsMouseDown( 2 ) ) { mb |= E_MouseButton::MIDDLE; } return mb; })() ); const T_KeyboardModifiers kb( ([&io]() { T_KeyboardModifiers kb; if ( io.KeyCtrl ) { kb |= E_KeyboardModifier::CTRL; } if ( io.KeyShift ) { kb |= E_KeyboardModifier::SHIFT; } if ( io.KeyAlt ) { kb |= E_KeyboardModifier::ALT; } return kb; })() ); const bool appCanGrab( !( ImGui::IsMouseHoveringAnyWindow( ) || io.WantCaptureMouse || io.WantCaptureKeyboard ) ); if ( mCapture_ && !( mb && mDelegate_ ) ) { mCapture_ = false; CaptureMouseFromApp( false ); SDL_SetRelativeMouseMode( SDL_FALSE ); SDL_WarpMouseInWindow( window_ , mInitial_.x , mInitial_.y ); SetMouseCursor( ImGuiMouseCursor_Arrow ); } else if ( mCapture_ && mDelegate_ ) { SetMouseCursor( ImGuiMouseCursor_Move ); mDelegate_->handleDragAndDrop( mMove_ , kb , mb ); } else if ( appCanGrab && mb && mDelegate_ ) { mCapture_ = true; mInitial_ = GetMousePos( ); CaptureMouseFromApp( true ); SDL_SetRelativeMouseMode( SDL_TRUE ); SetMouseCursor( ImGuiMouseCursor_Move ); } if ( ( appCanGrab || mCapture_ ) && io.MouseWheel && mDelegate_ ) { mDelegate_->handleWheel( io.MouseWheel , kb , mb ); } } void T_UIApp::render( ) noexcept { handleDialogs( ); glUseProgram( 0 ); glBindProgramPipeline( 0 ); UI::Textures( ).reset( ); glClearColor( 0 , 0 , 0 , 1 ); ImGui::Render( ); } void T_UIApp::swap( ) const noexcept { SDL_GL_SwapWindow( window_ ); } void T_UIApp::handleDialogs( ) noexcept { const auto nDialogs{ modals_.size( ) }; for ( auto i = 0u ; i < nDialogs ; i ++ ) { const bool keep{ modals_[ i ]->draw( ) }; assert( keep || i + 1 == nDialogs ); if ( !keep ) { modals_.removeLast( ); } } }