From 6101dee3c972866fe58a3806494be510c3ee5142 Mon Sep 17 00:00:00 2001 From: milkdropper <59471060+milkdropper@users.noreply.github.com> Date: Mon, 31 Aug 2020 20:58:56 +0400 Subject: [PATCH 01/19] Revert "Fix blank preset bug (#412)" This reverts commit f8cea68105a858186c9ef0cd3c510505fbd7c753. --- src/libprojectM/PipelineMerger.cpp | 8 -------- src/libprojectM/PipelineMerger.hpp | 1 - src/libprojectM/projectM.cpp | 4 ---- 3 files changed, 13 deletions(-) diff --git a/src/libprojectM/PipelineMerger.cpp b/src/libprojectM/PipelineMerger.cpp index 6ac408e42d..f899f659ce 100644 --- a/src/libprojectM/PipelineMerger.cpp +++ b/src/libprojectM/PipelineMerger.cpp @@ -5,14 +5,6 @@ const double PipelineMerger::e(2.71828182845904523536); const double PipelineMerger::s(0.5); -void PipelineMerger::ensureAlphaIsNotBlended(const Pipeline & a) -{ - for ( std::vector::const_iterator pos = a.drawables.begin(); pos != a.drawables.end(); ++pos ) - { - ( *pos )->masterAlpha = 1.0; - } -} - void PipelineMerger::mergePipelines(const Pipeline & a, const Pipeline & b, Pipeline & out, RenderItemMatcher::MatchResults & results, RenderItemMergeFunction & mergeFunction, float ratio) { diff --git a/src/libprojectM/PipelineMerger.hpp b/src/libprojectM/PipelineMerger.hpp index f9f9ce7c6d..a0bba9120c 100644 --- a/src/libprojectM/PipelineMerger.hpp +++ b/src/libprojectM/PipelineMerger.hpp @@ -16,7 +16,6 @@ class PipelineMerger static void mergePipelines(const Pipeline &a, const Pipeline &b, Pipeline &out, RenderItemMatcher::MatchResults & matching, RenderItemMergeFunction & merger, float ratio); - static void ensureAlphaIsNotBlended(const Pipeline & a); private : diff --git a/src/libprojectM/projectM.cpp b/src/libprojectM/projectM.cpp index f1b0ed9032..31f1cb1769 100755 --- a/src/libprojectM/projectM.cpp +++ b/src/libprojectM/projectM.cpp @@ -385,10 +385,6 @@ Pipeline * projectM::renderFrameOnlyPass1(Pipeline *pPipeline) /*pPipeline is a } } - if ( !timeKeeper->IsSmoothing() ) - { - PipelineMerger::ensureAlphaIsNotBlended(m_activePreset->pipeline()); - } if ( timeKeeper->IsSmoothing() && timeKeeper->SmoothRatio() <= 1.0 && !m_presetChooser->empty() ) { From ef6800cfcd2092bf16482401606760c0108257b8 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:12:16 +0400 Subject: [PATCH 02/19] Disable most keybinds if search menu is up. Return enters search menu. Return/Escape exits search menu. --- src/libprojectM/KeyHandler.cpp | 150 +++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 53 deletions(-) diff --git a/src/libprojectM/KeyHandler.cpp b/src/libprojectM/KeyHandler.cpp index 7613cb07ae..8a03d99d89 100755 --- a/src/libprojectM/KeyHandler.cpp +++ b/src/libprojectM/KeyHandler.cpp @@ -120,17 +120,27 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode switch (keycode) { case PROJECTM_K_HOME: - if (renderer->showmenu) { // pageup only does something when the preset menu is active. + if (renderer->showmenu && !isTextInputActive()) { // pageup only does something when the preset menu is active. selectPreset(0); // jump to top of presets. } + else if (renderer->showmenu && isTextInputActive()) + { + renderer->m_activePresetID = 1; + selectPresetByName(renderer->m_presetList[0].name,true); + } break; case PROJECTM_K_END: - if (renderer->showmenu) { // pageup only does something when the preset menu is active. + if (renderer->showmenu && !isTextInputActive()) { // pageup only does something when the preset menu is active. selectPreset(m_presetLoader->size() - 1); // jump to bottom of presets. } + else if (renderer->showmenu && isTextInputActive()) + { + renderer->m_activePresetID = renderer->m_presetList.size(); + selectPresetByName(renderer->m_presetList[renderer->m_activePresetID - 1].name,true); + } break; case PROJECTM_K_PAGEUP: - if (renderer->showmenu) { // pageup only does something when the preset menu is active. + if (renderer->showmenu && !isTextInputActive()) { // pageup only does something when the preset menu is active. int upPreset = m_presetPos->lastIndex() - (renderer->textMenuPageSize / 2.0f); // jump up by page size / 2 if (upPreset < 0) // handle lower boundary upPreset = m_presetLoader->size() - 1; @@ -138,7 +148,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_PAGEDOWN: - if (renderer->showmenu) { // pagedown only does something when the preset menu is active. + if (renderer->showmenu && !isTextInputActive()) { // pagedown only does something when the preset menu is active. int downPreset = m_presetPos->lastIndex() + (renderer->textMenuPageSize / 2.0f); // jump down by page size / 2 if (downPreset >= (m_presetLoader->size() - 1)) // handle upper boundary downPreset = 0; @@ -166,49 +176,60 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_h: - renderer->showhelp = !renderer->showhelp; - renderer->showstats = false; - renderer->showmenu = false; + if (!isTextInputActive(true)) { + renderer->showhelp = !renderer->showhelp; + renderer->showstats = false; + renderer->showmenu = false; + } case PROJECTM_K_F1: - renderer->showhelp = !renderer->showhelp; - renderer->showstats = false; - renderer->showmenu = false; + if (!isTextInputActive(true)) { + renderer->showhelp = !renderer->showhelp; + renderer->showstats = false; + renderer->showmenu = false; + } break; case PROJECTM_K_y: - this->setShuffleEnabled(!this->isShuffleEnabled()); - if (this->isShuffleEnabled()) { - renderer->setToastMessage("Shuffle Enabled"); - } - else { - renderer->setToastMessage("Shuffle Disabled"); + if (!isTextInputActive(true)) { + this->setShuffleEnabled(!this->isShuffleEnabled()); + if (this->isShuffleEnabled()) { + renderer->setToastMessage("Shuffle Enabled"); + } + else { + renderer->setToastMessage("Shuffle Disabled"); + } } break; - case PROJECTM_K_F5: - renderer->showfps = !renderer->showfps; - // Initialize counters and reset frame count. - renderer->lastTimeFPS = duration_cast(system_clock::now().time_since_epoch()); - renderer->currentTimeFPS = duration_cast(system_clock::now().time_since_epoch()); - renderer->totalframes = 0; - // Hide preset name from screen and replace it with FPS counter. - if (renderer->showfps) - { - renderer->showpreset = false; + if (!isTextInputActive(true)) { + renderer->showfps = !renderer->showfps; + // Initialize counters and reset frame count. + renderer->lastTimeFPS = duration_cast(system_clock::now().time_since_epoch()); + renderer->currentTimeFPS = duration_cast(system_clock::now().time_since_epoch()); + renderer->totalframes = 0; + // Hide preset name from screen and replace it with FPS counter. + if (renderer->showfps) + { + renderer->showpreset = false; + } } break; case PROJECTM_K_F4: - renderer->showstats = !renderer->showstats; - if (renderer->showstats) { - renderer->showhelp = false; - renderer->showmenu = false; + if (!isTextInputActive(true)) { + renderer->showstats = !renderer->showstats; + if (renderer->showstats) { + renderer->showhelp = false; + renderer->showmenu = false; + } } break; case PROJECTM_K_F3: { - renderer->showpreset = !renderer->showpreset; - // Hide FPS from screen and replace it with preset name. - if (renderer->showpreset) - { - renderer->showfps = false; + if (!isTextInputActive(true)) { + renderer->showpreset = !renderer->showpreset; + // Hide FPS from screen and replace it with preset name. + if (renderer->showpreset) + { + renderer->showfps = false; + } } break; } @@ -225,7 +246,9 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode break; case PROJECTM_K_ESCAPE: { - // exit( 1 ); + renderer->showinput = false; // hide input menu + setShuffleEnabled(renderer->shuffletrack); // restore shuffle + renderer->showmenu = false; // hide input break; } case PROJECTM_K_f: @@ -238,33 +261,41 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode break; case PROJECTM_K_H: case PROJECTM_K_m: - renderer->showmenu = !renderer->showmenu; - if (renderer->showmenu) { - renderer->showhelp = false; - renderer->showstats = false; - populatePresetMenu(); + if (!isTextInputActive(true)) { + renderer->showmenu = !renderer->showmenu; + if (renderer->showmenu) { + renderer->showhelp = false; + renderer->showstats = false; + populatePresetMenu(); + } } break; case PROJECTM_K_M: - renderer->showmenu = !renderer->showmenu; - if (renderer->showmenu) - { - renderer->showhelp=false; - renderer->showstats=false; - populatePresetMenu(); + if (!isTextInputActive(true)) { + renderer->showmenu = !renderer->showmenu; + if (renderer->showmenu) + { + renderer->showhelp = false; + renderer->showstats = false; + populatePresetMenu(); + } } break; case PROJECTM_K_n: + if (!isTextInputActive(true)) selectNext(true); break; case PROJECTM_K_N: + if (!isTextInputActive(true)) selectNext(false); break; case PROJECTM_K_r: - selectRandom(true); - break; + if (!isTextInputActive(true)) + selectRandom(true); + break; case PROJECTM_K_R: - selectRandom(false); + if (!isTextInputActive(true)) + selectRandom(false); break; case PROJECTM_K_p: selectPrevious(true); @@ -274,14 +305,27 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode selectPrevious(false); break; case PROJECTM_K_l: - setPresetLock(!isPresetLocked()); + if (!isTextInputActive(true)) + setPresetLock(!isPresetLocked()); break; case PROJECTM_K_s: renderer->studio = !renderer->studio; case PROJECTM_K_i: break; - case PROJECTM_K_z: - break; + case PROJECTM_K_RETURN: + renderer->toggleInput(); + if (renderer->showinput) { + renderer->shuffletrack = this->isShuffleEnabled(); // track previous shuffle state. + setShuffleEnabled(false); // disable shuffle + renderer->showhelp = false; + renderer->showstats = false; + renderer->showmenu = true; + populatePresetMenu(); + } else { + setShuffleEnabled(renderer->shuffletrack); // restore shuffle + renderer->showmenu = false; + } + break; case PROJECTM_K_0: // nWaveMode=0; break; From 9a052b3e47a1dc7887acb24103ea7a8e82c8e82b Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:13:19 +0400 Subject: [PATCH 03/19] SDL handles text input properly. --- src/projectM-sdl/pmSDL.cpp | 209 ++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 107 deletions(-) diff --git a/src/projectM-sdl/pmSDL.cpp b/src/projectM-sdl/pmSDL.cpp index 39d09e3b2e..d45b3763fe 100644 --- a/src/projectM-sdl/pmSDL.cpp +++ b/src/projectM-sdl/pmSDL.cpp @@ -297,121 +297,109 @@ void projectMSDL::keyHandler(SDL_Event *sdl_evt) { // handle keyboard input (for our app first, then projectM) switch (sdl_keycode) { - case SDLK_q: - if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) { - // cmd/ctrl-q = quit - done = 1; - return; - } - break; - case SDLK_i: - if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) - { - toggleAudioInput(); - return; // handled - } - break; - case SDLK_s: - if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) - { - // command-s: [s]tretch monitors - // Stereo requires fullscreen + + case SDLK_q: + if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) { + // cmd/ctrl-q = quit + done = 1; + return; + } + break; + case SDLK_BACKSPACE: + projectM::deleteSearchText(); + break; + case SDLK_RETURN: + if (!projectM::isTextInputActive()) { + SDL_StartTextInput(); + } + break; + case SDLK_ESCAPE: + if (projectM::isTextInputActive()) + SDL_StopTextInput(); + break; + case SDLK_i: + if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) + { + toggleAudioInput(); + return; // handled + } + break; + case SDLK_s: + if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) + { + // command-s: [s]tretch monitors + // Stereo requires fullscreen #if !STEREOSCOPIC_SBS - if (!this->stretch) { // if stretching is not already enabled, enable it. - stretchMonitors(); - this->stretch = true; - } else { - toggleFullScreen(); // else, just toggle full screen so we leave stretch mode. - this->stretch = false; - } + if (!this->stretch) { // if stretching is not already enabled, enable it. + stretchMonitors(); + this->stretch = true; + } else { + toggleFullScreen(); // else, just toggle full screen so we leave stretch mode. + this->stretch = false; + } #endif - return; // handled - } - case SDLK_m: - if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) - { - // command-m: change [m]onitor - // Stereo requires fullscreen + return; // handled + } + case SDLK_m: + if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) + { + // command-m: change [m]onitor + // Stereo requires fullscreen #if !STEREOSCOPIC_SBS - nextMonitor(); + nextMonitor(); #endif - this->stretch = false; // if we are switching monitors, ensure we disable monitor stretching. - return; // handled - } - case SDLK_f: - if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) { - // command-f: fullscreen - // Stereo requires fullscreen + this->stretch = false; // if we are switching monitors, ensure we disable monitor stretching. + return; // handled + } + case SDLK_f: + if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) { + // command-f: fullscreen + // Stereo requires fullscreen #if !STEREOSCOPIC_SBS - toggleFullScreen(); + toggleFullScreen(); #endif - this->stretch = false; // if we are toggling fullscreen, ensure we disable monitor stretching. - return; // handled + this->stretch = false; // if we are toggling fullscreen, ensure we disable monitor stretching. + return; // handled + } + break; + case SDLK_LEFT: + // selectPrevious(true); + break; + case SDLK_RIGHT: + // selectNext(true); + break; + case SDLK_UP: + break; + case SDLK_DOWN: + break; + + case SDLK_F3: + break; + + + case SDLK_SPACE: + if (!projectM::isTextInputActive(true)) + setPresetLock(!isPresetLocked()); + break; + case SDLK_F1: + break; + case SDLK_DELETE: + /* + try { + if (selectedPresetIndex(index)) { + DeleteFile( + LPCSTR( + getPresetURL(index).c_str() + ) + ); } - break; - case SDLK_LEFT: - // selectPrevious(true); - break; - case SDLK_RIGHT: - // selectNext(true); - break; - case SDLK_UP: - break; - case SDLK_DOWN: - break; - - case SDLK_F3: - break; - - - case SDLK_SPACE: - setPresetLock( - !isPresetLocked() - ); - break; - case SDLK_F1: - case SDLK_ESCAPE: - - // exit(1); - // show help with other keys - sdl_keycode = SDLK_F1; - break; - case SDLK_DELETE: - /* - try { - if (selectedPresetIndex(index)) { - DeleteFile( - LPCSTR( - getPresetURL(index).c_str() - ) - ); - } - } - catch (const std::exception & e) { - printf("Delete failed"); - } - */ - break; - case SDLK_RETURN: - /* - try { - if (selectedPresetIndex(index)) { - CopyFile( - LPCSTR( - app->getPresetURL(index).c_str() - ), - LPCTSTR(L"C:\\"), - false - ); - } - } - catch (const std::exception & e) { - printf("Delete failed"); - } - */ - break; + } + catch (const std::exception & e) { + printf("Delete failed"); + } + */ + break; } - // translate into projectM codes and perform default projectM handler evt = sdl2pmEvent(sdl_evt); mod = sdl2pmModifier(sdl_mod); @@ -514,6 +502,13 @@ void projectMSDL::pollEvent() { case SDL_MOUSEBUTTONUP: mouseDown = false; break; + case SDL_TEXTINPUT: + if (projectM::isTextInputActive(true)) + { + projectM::setSearchText(evt.text.text); + projectM::populatePresetMenu(); + } + break; case SDL_QUIT: done = true; break; From f7e0743625eec5aa2beb3c6fc66932a21258632f Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:14:50 +0400 Subject: [PATCH 04/19] toggleSearchText --- src/libprojectM/projectM.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libprojectM/projectM.hpp b/src/libprojectM/projectM.hpp index 8477346222..42dc713d5c 100644 --- a/src/libprojectM/projectM.hpp +++ b/src/libprojectM/projectM.hpp @@ -188,6 +188,7 @@ class DLLEXPORT projectM void touchDestroy(float x, float y); void touchDestroyAll(); void setHelpText(const std::string & helpText); + void toggleSearchText(); // turn search text input on / off void setToastMessage(const std::string & toastMessage); const Settings & settings() const { return _settings; @@ -229,6 +230,18 @@ class DLLEXPORT projectM /// Returns true if the active preset is locked bool isPresetLocked() const; + /// Returns true if the text based search menu is up. + bool isTextInputActive(bool nomin = false) const; + + unsigned int getPresetIndex(std::string &url) const; + + /// Plays a preset immediately when given preset name + void selectPresetByName(std::string name, bool hardCut = true); + + void setSearchText(const std::string & searchKey); + void deleteSearchText(); + + /// Returns index of currently active preset. In the case where the active /// preset was removed from the playlist, this function will return the element /// before active preset (thus the next in order preset is invariant with respect @@ -298,6 +311,8 @@ class DLLEXPORT projectM std::vector presetHistory; std::vector presetFuture; + /// Get the preset index given a name + const unsigned int getSearchIndex(std::string &name) const; void selectPrevious(const bool); void selectNext(const bool); From 45adbba0ada79d69b4f1f61d781ae52389ca9563 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:15:07 +0400 Subject: [PATCH 05/19] toggleSearchText --- src/libprojectM/KeyHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libprojectM/KeyHandler.cpp b/src/libprojectM/KeyHandler.cpp index 8a03d99d89..3251163c15 100755 --- a/src/libprojectM/KeyHandler.cpp +++ b/src/libprojectM/KeyHandler.cpp @@ -313,7 +313,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode case PROJECTM_K_i: break; case PROJECTM_K_RETURN: - renderer->toggleInput(); + renderer->toggleSearchText(); if (renderer->showinput) { renderer->shuffletrack = this->isShuffleEnabled(); // track previous shuffle state. setShuffleEnabled(false); // disable shuffle From 9f37e97b2f2623761d4afbc64764407954f251a4 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:16:18 +0400 Subject: [PATCH 06/19] showsearch --- src/libprojectM/KeyHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libprojectM/KeyHandler.cpp b/src/libprojectM/KeyHandler.cpp index 3251163c15..000cc7392b 100755 --- a/src/libprojectM/KeyHandler.cpp +++ b/src/libprojectM/KeyHandler.cpp @@ -246,7 +246,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode break; case PROJECTM_K_ESCAPE: { - renderer->showinput = false; // hide input menu + renderer->showsearch = false; // hide input menu setShuffleEnabled(renderer->shuffletrack); // restore shuffle renderer->showmenu = false; // hide input break; @@ -314,7 +314,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode break; case PROJECTM_K_RETURN: renderer->toggleSearchText(); - if (renderer->showinput) { + if (renderer->showsearch) { renderer->shuffletrack = this->isShuffleEnabled(); // track previous shuffle state. setShuffleEnabled(false); // disable shuffle renderer->showhelp = false; From 4752761b0f688dc63ec52e61020265f8596fe021 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:17:07 +0400 Subject: [PATCH 07/19] draw_search & more --- src/libprojectM/Renderer/Renderer.hpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/libprojectM/Renderer/Renderer.hpp b/src/libprojectM/Renderer/Renderer.hpp index e3d1a25389..1c90fc946f 100644 --- a/src/libprojectM/Renderer/Renderer.hpp +++ b/src/libprojectM/Renderer/Renderer.hpp @@ -75,9 +75,12 @@ class Renderer bool showtitle; bool showpreset; bool showhelp; + bool showsearch; bool showmenu; bool showstats; + bool shuffletrack; + bool studio; bool correction; @@ -161,6 +164,7 @@ class Renderer return duration_cast(system_clock::now().time_since_epoch());; } + void toggleInput(); void touch(float x, float y, int pressure, int type); void touchDrag(float x, float y, int pressure); void touchDestroy(float x, float y); @@ -168,11 +172,18 @@ class Renderer bool touchedWaveform(float x, float y, int i); void setToastMessage(const std::string& theValue); + void setSearchText(const std::string& theValue); + void deleteSearchText(); + void resetSearchText(); std::string toastMessage() const { return m_toastMessage; } - + + std::string searchText() const { + return m_searchText; + } + private: PerPixelMesh mesh; @@ -185,9 +196,9 @@ class Renderer #ifdef USE_TEXT_MENU void drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment, - int verticalAlignment, float r, float b, float g, float a); + int verticalAlignment, float r, float b, float g, float a, bool highlightable); void drawText(const char* string, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment, - int verticalAlignment, float r, float b, float g, float a); + int verticalAlignment, float r, float b, float g, float a, bool highlightable); #endif /** USE_TEXT_MENU */ RenderContext renderContext; @@ -197,6 +208,7 @@ class Renderer std::string m_datadir; std::string m_fps; std::string m_toastMessage; + std::string m_searchText; float* p; @@ -252,6 +264,7 @@ class Renderer void draw_help(); void draw_menu(); void draw_preset(); + void draw_search(); void draw_title(); void draw_title_to_screen(bool flip); void draw_title_to_texture(); From 34bc6746a3c3f2c186f9caa20f8741f19455bbee Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:17:42 +0400 Subject: [PATCH 08/19] draw search & highlight search text. --- src/libprojectM/Renderer/Renderer.cpp | 151 ++++++++++++++++++++------ 1 file changed, 116 insertions(+), 35 deletions(-) diff --git a/src/libprojectM/Renderer/Renderer.cpp b/src/libprojectM/Renderer/Renderer.cpp index 785563bf3a..8c8a091b26 100644 --- a/src/libprojectM/Renderer/Renderer.cpp +++ b/src/libprojectM/Renderer/Renderer.cpp @@ -27,13 +27,13 @@ class Preset; void Renderer::drawText(const char* string, GLfloat x, GLfloat y, GLfloat scale, - int horizontalAlignment = GLT_LEFT, int verticalAlignment = GLT_TOP, float r = 1.0f, float b = 1.0f, float g = 1.0f, float a = 1.0f) + int horizontalAlignment = GLT_LEFT, int verticalAlignment = GLT_TOP, float r = 1.0f, float b = 1.0f, float g = 1.0f, float a = 1.0f, bool highlightable = false) { - drawText(this->title_font, string, x, y, scale, horizontalAlignment, verticalAlignment, r, g, b, a); + drawText(this->title_font, string, x, y, scale, horizontalAlignment, verticalAlignment, r, g, b, a, highlightable); } void Renderer::drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, GLfloat scale, - int horizontalAlignment = GLT_LEFT, int verticalAlignment = GLT_TOP, float r = 1.0f, float b = 1.0f, float g = 1.0f, float a = 1.0f) + int horizontalAlignment = GLT_LEFT, int verticalAlignment = GLT_TOP, float r = 1.0f, float b = 1.0f, float g = 1.0f, float a = 1.0f, bool highlightable = false) { // Initialize glText gltInit(); @@ -69,24 +69,41 @@ void Renderer::drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, if (windowWidth > textWidth) { // redraw without transparency - gltColor(r, g, b, a); - gltSetText(text, string); - gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); - } - else { + if (highlightable && showsearch && searchText().length() > 1) + { + int offset = x; + std::string str_find = string; + for( size_t pos = 0; ; pos += str_find.length() ) { + // find search term + pos = str_find.find(searchText()); + + // draw everything normal, up to search term. + gltColor(r, g, b, a); + gltSetText(text, str_find.substr(0,pos).c_str()); + gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); + + // highlight search term + GLfloat textWidth = gltGetTextWidth(text, scale); + offset = offset + textWidth; + gltColor(1.0f, 0.0f, 1.0f, 1.0f); + gltSetText(text, searchText().c_str()); + gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); + + // draw rest of name, normally + textWidth = gltGetTextWidth(text, scale); + offset = offset + textWidth; + gltColor(r, g, b, a); + gltSetText(text, str_find.substr(pos+searchText().length(),str_find.length()).c_str()); + gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); + break; // first search hit is useful enough. + } + } else { + gltColor(r, g, b, a); + gltSetText(text, string); + gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); + } + } else { // if the text is greater than the window width, we have a problem. - - // Option 1: Reduce text length until it fits. - // If it's a single line of text then reduce the text and add a "..." to the end. - // Before: Geiss & Sperl - Feedback (projectM idle HDR mix) - // After: Geiss & Sperl - Feed... - // - // If it's multiline then just cut the text off. - // Before: F1: This help menu - // UP: Increase Beat Sensitivity - // After : F1: This help menu - // UP: Increase Beat Sensi - std::string substring(string); while (textWidth > windowWidth) { substring.pop_back(); @@ -103,21 +120,42 @@ void Renderer::drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, substring.pop_back(); substring += "..."; } - string = substring.c_str(); - // Option 2: Reduce the scale (size) of the text until it fits. - /* - while (textWidth > windowWidth) { - scale = scale - 0.1; + if (highlightable && showsearch && searchText().length() > 1) + { + int offset = x; + std::string str_find = substring; + for (size_t pos = 0; ; pos += str_find.length()) { + // find search term + pos = str_find.find(string); + + // draw everything normal, up to search term. + gltColor(r, g, b, a); + gltSetText(text, str_find.substr(0, pos).c_str()); + gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); + + // highlight search term + GLfloat textWidth = gltGetTextWidth(text, scale); + offset = offset + textWidth; + gltColor(1.0f, 0.0f, 1.0f, 1.0f); + gltSetText(text, searchText().c_str()); + gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); + + // draw rest of name, normally + textWidth = gltGetTextWidth(text, scale); + offset = offset + textWidth; + gltColor(r, g, b, a); + gltSetText(text, str_find.substr(pos + searchText().length(), str_find.length()).c_str()); + gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); + break; // first search hit is useful enough. + } + } else { + string = substring.c_str(); + // Redraw now that the text fits. + gltColor(r, g, b, a); + gltSetText(text, string); gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); - textWidth = gltGetTextWidth(text, scale); } - */ - - // Redraw now that the text fits. - gltColor(r, g, b, a); - gltSetText(text, string); - gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); } // Finish drawing text @@ -149,9 +187,11 @@ Renderer::Renderer(int width, int height, int gx, int gy, BeatDetect* _beatDetec this->showtitle = false; this->showpreset = false; this->showhelp = false; + this->showsearch = false; this->showmenu = false; this->showstats = false; this->studio = false; + this->m_activePresetID = 0; this->realfps = 0; /* Set up the v xoffset and vy offset to 0 which is normal Only used for VR */ this->vstartx = 0; @@ -421,6 +461,8 @@ void Renderer::Pass2(const Pipeline& pipeline, const PipelineContext& pipelineCo if (this->showfps == true) draw_fps(); // this->realfps + if (this->showsearch == true) + draw_search(); if (this->showmenu == true) draw_menu(); if (this->showpreset == true) @@ -769,6 +811,32 @@ void Renderer::touchDestroyAll() waveformList.clear(); } +void Renderer::toggleSearchText() { + this->showsearch = !this->showsearch; + if (this->showsearch) + { + this->showfps = false; + this->showtitle = false; + } +} + +void Renderer::setSearchText(const std::string& theValue) +{ + m_searchText = m_searchText + theValue; +} + +void Renderer::resetSearchText() +{ + m_searchText = ""; +} + +void Renderer::deleteSearchText() +{ + if (m_searchText.length() >= 1) { + m_searchText = m_searchText.substr(0, m_searchText.size() - 1); + } +} + void Renderer::setToastMessage(const std::string& theValue) { // Initialize counters @@ -788,6 +856,16 @@ void Renderer::draw_title_to_screen(bool flip) #endif /** USE_TEXT_MENU */ } +void Renderer::draw_search() +{ +#ifdef USE_TEXT_MENU + std::string search = "Search: "; + search = search + searchText(); + + drawText(search.c_str(), 30, 20, 2.5); +#endif /** USE_TEXT_MENU */ +} + void Renderer::draw_title() { #ifdef USE_TEXT_MENU @@ -802,13 +880,16 @@ void Renderer::draw_menu() int menu_xOffset = 30; // x axis static point. int menu_yOffset = 60; // y axis start point. float windowHeight = vh; + float alpha = 1.0; + if (this->showsearch) // if search input is up, slightly dim preset menu + alpha = 0.82f; for (auto& it : m_presetList) { // loop over preset buffer - if (menu_yOffset < windowHeight - textMenuLineHeight) { // if we are not at the bottom of the scree, display preset name. + if (menu_yOffset < windowHeight - textMenuLineHeight) { // if we are not at the bottom of the screen, display preset name. if (it.id == m_activePresetID) { // if this is the active preset, add some color. - drawText(it.name.c_str(), menu_xOffset, menu_yOffset , 1.5, GLT_LEFT, 0, 1.0, 0.1, 0.1, 1.0); + drawText(it.name.c_str(), menu_xOffset, menu_yOffset , 1.5, GLT_LEFT, 0, 1.0, 0.1, 0.1, 1.0, true); } else { - drawText(it.name.c_str(), menu_xOffset, menu_yOffset , 1.5, GLT_LEFT, 0, 1.0, 1.0, 1.0, 1.0); + drawText(it.name.c_str(), menu_xOffset, menu_yOffset , 1.5, GLT_LEFT, 0, 1.0, 1.0, 1.0, alpha, true); } } menu_yOffset = menu_yOffset + textMenuLineHeight; // increase line y offset so we can track if we reached the bottom of the screen. From e3ca0ccec65bd0eb620c41207ddbddb105562737 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:18:52 +0400 Subject: [PATCH 09/19] populate menu with search results if searching search based on text update next / previous based on search results. --- src/libprojectM/projectM.cpp | 142 ++++++++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 20 deletions(-) diff --git a/src/libprojectM/projectM.cpp b/src/libprojectM/projectM.cpp index 228bc57c5f..6508f9142b 100755 --- a/src/libprojectM/projectM.cpp +++ b/src/libprojectM/projectM.cpp @@ -787,25 +787,47 @@ void projectM::populatePresetMenu() { if (renderer->showmenu) { // only track a preset list buffer if the preset menu is up. renderer->m_presetList.clear(); // clear preset list buffer from renderer. - renderer->m_activePresetID = m_presetPos->lastIndex(); // tell renderer about the active preset ID (so it can be highlighted) - - int page_start = 0; - if (m_presetPos->lastIndex() != m_presetLoader->size()) - { - page_start = renderer->m_activePresetID; // if it's not the idle preset, then set it to the true value - } - if (page_start < renderer->textMenuPageSize) { - page_start = 0; // if we are on page 1, start at the first preset. - } - if (page_start % renderer->textMenuPageSize == 0) { - // if it's a perfect division of the page size, we are good. - } else { - page_start = page_start - (page_start % renderer->textMenuPageSize); // if not, find closest divisable number for page start + + if(isTextInputActive()) { + // if a searchTerm is active, we will populate the preset menu with search terms instead of the page we are on. + int h = 0; + for(unsigned int i = 0; i < getPlaylistSize(); i++) { + if (getPresetName(i).find(renderer->searchText()) != std::string::npos) { + if (h < renderer->textMenuPageSize) + { + h++; + renderer->m_presetList.push_back({ h, getPresetName(i), "" }); // populate the renders preset list. + int id = getSearchIndex(renderer->presetName()); + if (h == getSearchIndex(getPresetName(id))) + { + renderer->m_activePresetID = h; + } + } + } + } } - int page_end = page_start + renderer->textMenuPageSize; // page end is page start + page size - while (page_start < page_end) { - renderer->m_presetList.push_back({page_start, getPresetName(page_start), ""}); // populate the renders preset list. - page_start++; + else { + // normal preset menu, based on pagination. + renderer->m_activePresetID = m_presetPos->lastIndex(); // tell renderer about the active preset ID (so it can be highlighted) + int page_start = 0; + if (m_presetPos->lastIndex() != m_presetLoader->size()) + { + page_start = renderer->m_activePresetID; // if it's not the idle preset, then set it to the true value + } + if (page_start < renderer->textMenuPageSize) { + page_start = 0; // if we are on page 1, start at the first preset. + } + if (page_start % renderer->textMenuPageSize == 0) { + // if it's a perfect division of the page size, we are good. + } + else { + page_start = page_start - (page_start % renderer->textMenuPageSize); // if not, find closest divisable number for page start + } + int page_end = page_start + renderer->textMenuPageSize; // page end is page start + page size + while (page_start < page_end) { + renderer->m_presetList.push_back({ page_start, getPresetName(page_start), "" }); // populate the renders preset list. + page_start++; + } } } } @@ -854,7 +876,17 @@ void projectM::selectPrevious(const bool hardCut) { if (m_presetChooser->empty()) return; - if (settings().shuffleEnabled && presetHistory.size() >= 1 && presetHistory.back() != m_presetLoader->size() && !renderer->showmenu) { // if randomly browsing presets, "previous" should return to last random preset not the index--. Avoid returning to size() because that's the idle:// preset. + if (isTextInputActive(true) && renderer->m_presetList.size() >= 1) + { + if (renderer->m_activePresetID <= 1) { + renderer->m_activePresetID = renderer->m_presetList.size(); + selectPresetByName(renderer->m_presetList[renderer->m_activePresetID - 1].name,true); + } + else { + renderer->m_activePresetID--; + selectPresetByName(renderer->m_presetList[renderer->m_activePresetID-1].name,true); + } + } else if (settings().shuffleEnabled && presetHistory.size() >= 1 && presetHistory.back() != m_presetLoader->size() && !renderer->showmenu) { // if randomly browsing presets, "previous" should return to last random preset not the index--. Avoid returning to size() because that's the idle:// preset. presetFuture.push_back(m_presetPos->lastIndex()); selectPreset(presetHistory.back()); presetHistory.pop_back(); @@ -871,7 +903,17 @@ void projectM::selectPrevious(const bool hardCut) { void projectM::selectNext(const bool hardCut) { if (m_presetChooser->empty()) return; - if (settings().shuffleEnabled && presetFuture.size() >= 1 && presetFuture.front() != m_presetLoader->size() && !renderer->showmenu) { // if shuffling and we have future presets already stashed then let's go forward rather than truely move randomly. + if (isTextInputActive() && renderer->m_presetList.size() >= 1) // if search is active and there are search results + { + if (renderer->m_activePresetID >= renderer->m_presetList.size()) { + renderer->m_activePresetID = 1; + selectPresetByName(renderer->m_presetList[0].name,true); + } + else { + selectPresetByName(renderer->m_presetList[renderer->m_activePresetID].name,true); + renderer->m_activePresetID++; + } + } else if (settings().shuffleEnabled && presetFuture.size() >= 1 && presetFuture.front() != m_presetLoader->size() && !renderer->showmenu) { // if shuffling and we have future presets already stashed then let's go forward rather than truely move randomly. presetHistory.push_back(m_presetPos->lastIndex()); selectPreset(presetFuture.back()); presetFuture.pop_back(); @@ -928,6 +970,17 @@ void projectM::setPresetLock ( bool isLocked ) } } +bool projectM::isTextInputActive( bool nomin ) const +{ + if (renderer->showsearch && (renderer->searchText().length() >= 2 || nomin)) + { + return true; + } + else { + return false; + } +} + bool projectM::isPresetLocked() const { return renderer->noSwitch; @@ -1046,6 +1099,55 @@ void projectM::getMeshSize(int *w, int *h) { *h = _settings.meshY; } +void projectM::toggleSearchText() +{ + if ( renderer ) + renderer->toggleSearchText(); +} + +const unsigned int projectM::getSearchIndex(std::string &name) const +{ + for (auto& it : renderer->m_presetList) { + if (it.name == name) return it.id; + } + return 0; +} + +unsigned int projectM::getPresetIndex(std::string& name) const +{ + return m_presetLoader->getPresetIndex(name); +} + +void projectM::selectPresetByName(std::string name, bool hardCut) { + unsigned int index = getPresetIndex(name); + if (m_presetChooser->empty()) return; + selectPreset(index); +} + +void projectM::setSearchText(const std::string & searchKey) +{ + if ( renderer ) + renderer->setSearchText(searchKey); + populatePresetMenu(); + if (renderer->m_presetList.size() >= 1) { + std::string topPreset = renderer->m_presetList.front().name; + renderer->m_activePresetID = 1; + selectPresetByName(topPreset); + } +} + +void projectM::deleteSearchText() +{ + if ( renderer ) + renderer->deleteSearchText(); + populatePresetMenu(); + if (renderer->m_presetList.size() >= 1) { + renderer->m_activePresetID = 1; + std::string topPreset = renderer->m_presetList.front().name; + selectPresetByName(topPreset); + } +} + void projectM::setToastMessage(const std::string & toastMessage) { if ( renderer ) From 49947258051030991737be1f2ce47a3024e51952 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:19:50 +0400 Subject: [PATCH 10/19] preset loader updates care of @khoaxtru20 --- src/libprojectM/PresetLoader.cpp | 15 +++++++++++++++ src/libprojectM/PresetLoader.hpp | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/src/libprojectM/PresetLoader.cpp b/src/libprojectM/PresetLoader.cpp index 2b4ef100f5..b661c03e49 100644 --- a/src/libprojectM/PresetLoader.cpp +++ b/src/libprojectM/PresetLoader.cpp @@ -149,6 +149,21 @@ const std::string & PresetLoader::getPresetName ( PresetIndex index ) const return _presetNames[index]; } +const std::vector &PresetLoader::getPresetNames() const +{ + return _presetNames; +} + +const unsigned int PresetLoader::getPresetIndex(std::string &name) const +{ + //Need a better structure than a vector for reverse lookup + for (int index = 0; index < _presetNames.size(); index++) + { + if (_presetNames[index] == name) return index; + } + return 0; +} + int PresetLoader::getPresetRating ( PresetIndex index, const PresetRatingType ratingType ) const { return _ratings[ratingType][index]; diff --git a/src/libprojectM/PresetLoader.hpp b/src/libprojectM/PresetLoader.hpp index df314387c4..6de901b702 100644 --- a/src/libprojectM/PresetLoader.hpp +++ b/src/libprojectM/PresetLoader.hpp @@ -70,6 +70,12 @@ class PresetLoader { /// Get a preset name given an index const std::string & getPresetName ( PresetIndex index) const; + /// Get vector of preset names + const std::vector & getPresetNames() const; + + /// Get the preset index given a name + const unsigned int getPresetIndex(std::string &name) const; + /// Returns the number of presets in the active directory inline std::size_t size() const { return _entries.size(); From ffdb4806a7fd1662a3dddcf5303dfb962acea692 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:21:29 +0400 Subject: [PATCH 11/19] toggleSearchText --- src/libprojectM/Renderer/Renderer.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libprojectM/Renderer/Renderer.hpp b/src/libprojectM/Renderer/Renderer.hpp index 1c90fc946f..a9be0f76b3 100644 --- a/src/libprojectM/Renderer/Renderer.hpp +++ b/src/libprojectM/Renderer/Renderer.hpp @@ -164,6 +164,7 @@ class Renderer return duration_cast(system_clock::now().time_since_epoch());; } + void toggleSearchText(); void toggleInput(); void touch(float x, float y, int pressure, int type); void touchDrag(float x, float y, int pressure); From 15230781e162cf5d161c2d5d4295e9d6110aa1e9 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:36:45 +0400 Subject: [PATCH 12/19] comments --- src/libprojectM/KeyHandler.cpp | 26 +++++++++++++------------- src/libprojectM/PresetLoader.cpp | 3 +++ src/libprojectM/Renderer/Renderer.cpp | 9 ++++----- src/libprojectM/Renderer/Renderer.hpp | 1 - src/libprojectM/projectM.cpp | 19 ++++++++++++++++--- src/libprojectM/projectM.hpp | 2 ++ 6 files changed, 38 insertions(+), 22 deletions(-) diff --git a/src/libprojectM/KeyHandler.cpp b/src/libprojectM/KeyHandler.cpp index 000cc7392b..c956daaf35 100755 --- a/src/libprojectM/KeyHandler.cpp +++ b/src/libprojectM/KeyHandler.cpp @@ -176,20 +176,20 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_h: - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable help when searching. renderer->showhelp = !renderer->showhelp; renderer->showstats = false; renderer->showmenu = false; } case PROJECTM_K_F1: - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable F1 when searching. renderer->showhelp = !renderer->showhelp; renderer->showstats = false; renderer->showmenu = false; } break; case PROJECTM_K_y: - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable shuffle toggle when searching. this->setShuffleEnabled(!this->isShuffleEnabled()); if (this->isShuffleEnabled()) { renderer->setToastMessage("Shuffle Enabled"); @@ -200,7 +200,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_F5: - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable fps when searching. renderer->showfps = !renderer->showfps; // Initialize counters and reset frame count. renderer->lastTimeFPS = duration_cast(system_clock::now().time_since_epoch()); @@ -214,7 +214,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_F4: - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable states when searching. renderer->showstats = !renderer->showstats; if (renderer->showstats) { renderer->showhelp = false; @@ -223,7 +223,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_F3: { - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable current preset name when searching. renderer->showpreset = !renderer->showpreset; // Hide FPS from screen and replace it with preset name. if (renderer->showpreset) @@ -261,7 +261,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode break; case PROJECTM_K_H: case PROJECTM_K_m: - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable menu when searching (hint: it's already up). renderer->showmenu = !renderer->showmenu; if (renderer->showmenu) { renderer->showhelp = false; @@ -271,7 +271,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_M: - if (!isTextInputActive(true)) { + if (!isTextInputActive(true)) { // disable menu when searching (hint: it's already up). renderer->showmenu = !renderer->showmenu; if (renderer->showmenu) { @@ -282,19 +282,19 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_n: - if (!isTextInputActive(true)) + if (!isTextInputActive(true)) // disable next key when searching (down arrow is more natural) selectNext(true); break; case PROJECTM_K_N: - if (!isTextInputActive(true)) + if (!isTextInputActive(true)) // disable next key when searching (down arrow is more natural) selectNext(false); break; case PROJECTM_K_r: - if (!isTextInputActive(true)) + if (!isTextInputActive(true)) // disable random key when searching selectRandom(true); break; case PROJECTM_K_R: - if (!isTextInputActive(true)) + if (!isTextInputActive(true)) // disable random key when searching selectRandom(false); break; case PROJECTM_K_p: @@ -305,7 +305,7 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode selectPrevious(false); break; case PROJECTM_K_l: - if (!isTextInputActive(true)) + if (!isTextInputActive(true)) // disable lock key when searching setPresetLock(!isPresetLocked()); break; case PROJECTM_K_s: diff --git a/src/libprojectM/PresetLoader.cpp b/src/libprojectM/PresetLoader.cpp index b661c03e49..dc71d5e8c1 100644 --- a/src/libprojectM/PresetLoader.cpp +++ b/src/libprojectM/PresetLoader.cpp @@ -149,11 +149,14 @@ const std::string & PresetLoader::getPresetName ( PresetIndex index ) const return _presetNames[index]; } + +// Get vector of preset names const std::vector &PresetLoader::getPresetNames() const { return _presetNames; } +// Get the preset index given a name const unsigned int PresetLoader::getPresetIndex(std::string &name) const { //Need a better structure than a vector for reverse lookup diff --git a/src/libprojectM/Renderer/Renderer.cpp b/src/libprojectM/Renderer/Renderer.cpp index 8c8a091b26..493587903f 100644 --- a/src/libprojectM/Renderer/Renderer.cpp +++ b/src/libprojectM/Renderer/Renderer.cpp @@ -811,6 +811,7 @@ void Renderer::touchDestroyAll() waveformList.clear(); } +// turn search menu on / off void Renderer::toggleSearchText() { this->showsearch = !this->showsearch; if (this->showsearch) @@ -820,16 +821,13 @@ void Renderer::toggleSearchText() { } } +// search based on new key input void Renderer::setSearchText(const std::string& theValue) { m_searchText = m_searchText + theValue; } -void Renderer::resetSearchText() -{ - m_searchText = ""; -} - +// search text backspace (delete a key) void Renderer::deleteSearchText() { if (m_searchText.length() >= 1) { @@ -856,6 +854,7 @@ void Renderer::draw_title_to_screen(bool flip) #endif /** USE_TEXT_MENU */ } +// render search text menu void Renderer::draw_search() { #ifdef USE_TEXT_MENU diff --git a/src/libprojectM/Renderer/Renderer.hpp b/src/libprojectM/Renderer/Renderer.hpp index a9be0f76b3..5ace4c2093 100644 --- a/src/libprojectM/Renderer/Renderer.hpp +++ b/src/libprojectM/Renderer/Renderer.hpp @@ -175,7 +175,6 @@ class Renderer void setToastMessage(const std::string& theValue); void setSearchText(const std::string& theValue); void deleteSearchText(); - void resetSearchText(); std::string toastMessage() const { return m_toastMessage; diff --git a/src/libprojectM/projectM.cpp b/src/libprojectM/projectM.cpp index 6508f9142b..030b5534d2 100755 --- a/src/libprojectM/projectM.cpp +++ b/src/libprojectM/projectM.cpp @@ -791,9 +791,9 @@ void projectM::populatePresetMenu() if(isTextInputActive()) { // if a searchTerm is active, we will populate the preset menu with search terms instead of the page we are on. int h = 0; - for(unsigned int i = 0; i < getPlaylistSize(); i++) { - if (getPresetName(i).find(renderer->searchText()) != std::string::npos) { - if (h < renderer->textMenuPageSize) + for(unsigned int i = 0; i < getPlaylistSize(); i++) { // loop over all presets + if (getPresetName(i).find(renderer->searchText()) != std::string::npos) { // if term matches + if (h < renderer->textMenuPageSize) // limit to just one page, pagination is not needed. { h++; renderer->m_presetList.push_back({ h, getPresetName(i), "" }); // populate the renders preset list. @@ -878,11 +878,14 @@ void projectM::selectPrevious(const bool hardCut) { if (isTextInputActive(true) && renderer->m_presetList.size() >= 1) { + // if search menu is up, previous is based on search terms. if (renderer->m_activePresetID <= 1) { + // loop to bottom of page is at top renderer->m_activePresetID = renderer->m_presetList.size(); selectPresetByName(renderer->m_presetList[renderer->m_activePresetID - 1].name,true); } else { + // otherwise move back renderer->m_activePresetID--; selectPresetByName(renderer->m_presetList[renderer->m_activePresetID-1].name,true); } @@ -905,11 +908,14 @@ void projectM::selectNext(const bool hardCut) { return; if (isTextInputActive() && renderer->m_presetList.size() >= 1) // if search is active and there are search results { + // if search menu is down, previous is based on search terms. if (renderer->m_activePresetID >= renderer->m_presetList.size()) { + // loop to top of page is at bottom renderer->m_activePresetID = 1; selectPresetByName(renderer->m_presetList[0].name,true); } else { + // otherwise move forward selectPresetByName(renderer->m_presetList[renderer->m_activePresetID].name,true); renderer->m_activePresetID++; } @@ -970,6 +976,7 @@ void projectM::setPresetLock ( bool isLocked ) } } +// check if search menu is up and you have search terms (2 chars). nomin means you don't care about search terms. bool projectM::isTextInputActive( bool nomin ) const { if (renderer->showsearch && (renderer->searchText().length() >= 2 || nomin)) @@ -1099,12 +1106,14 @@ void projectM::getMeshSize(int *w, int *h) { *h = _settings.meshY; } +// toggleSearchText void projectM::toggleSearchText() { if ( renderer ) renderer->toggleSearchText(); } +// get index from search results based on preset name const unsigned int projectM::getSearchIndex(std::string &name) const { for (auto& it : renderer->m_presetList) { @@ -1113,17 +1122,20 @@ const unsigned int projectM::getSearchIndex(std::string &name) const return 0; } +// get preset index based on preset name unsigned int projectM::getPresetIndex(std::string& name) const { return m_presetLoader->getPresetIndex(name); } +// load preset based on name void projectM::selectPresetByName(std::string name, bool hardCut) { unsigned int index = getPresetIndex(name); if (m_presetChooser->empty()) return; selectPreset(index); } +// update search text based on new keystroke void projectM::setSearchText(const std::string & searchKey) { if ( renderer ) @@ -1136,6 +1148,7 @@ void projectM::setSearchText(const std::string & searchKey) } } +// update search text based on new backspace void projectM::deleteSearchText() { if ( renderer ) diff --git a/src/libprojectM/projectM.hpp b/src/libprojectM/projectM.hpp index 42dc713d5c..ef28356e58 100644 --- a/src/libprojectM/projectM.hpp +++ b/src/libprojectM/projectM.hpp @@ -238,7 +238,9 @@ class DLLEXPORT projectM /// Plays a preset immediately when given preset name void selectPresetByName(std::string name, bool hardCut = true); + // search based on keystroke void setSearchText(const std::string & searchKey); + // delete part of search term (backspace) void deleteSearchText(); From f509b8e5e7b790615ce68820cd4391b73e31fe8b Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 18:51:44 +0400 Subject: [PATCH 13/19] Document --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 629f2d3f2c..8c96340375 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ See [BUILDING.md](BUILDING.md) * Cmd/Ctrl-M: change *m*onitor * Cmd/Ctrl-F: toggle *f*ull screen * Mouse Scroll Up / Down: next or previous preset (hard transition) +* Return: search for preset (RETURN or ESCAPE to exit search) * Space: lock current preset From 4ab72ef2ea0b9cb40e062d829d76f8926ede6178 Mon Sep 17 00:00:00 2001 From: "milkdropper.com" Date: Sat, 15 Aug 2020 19:18:48 +0400 Subject: [PATCH 14/19] travis --- src/libprojectM/projectM.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libprojectM/projectM.cpp b/src/libprojectM/projectM.cpp index 030b5534d2..7681d0ab0d 100755 --- a/src/libprojectM/projectM.cpp +++ b/src/libprojectM/projectM.cpp @@ -797,8 +797,7 @@ void projectM::populatePresetMenu() { h++; renderer->m_presetList.push_back({ h, getPresetName(i), "" }); // populate the renders preset list. - int id = getSearchIndex(renderer->presetName()); - if (h == getSearchIndex(getPresetName(id))) + if (h == getSearchIndex(renderer->presetName())) { renderer->m_activePresetID = h; } From 05d41d21afdf95d5de6e71b6a37a75283355861f Mon Sep 17 00:00:00 2001 From: milkdropper <59471060+milkdropper@users.noreply.github.com> Date: Mon, 31 Aug 2020 18:36:32 +0400 Subject: [PATCH 15/19] reset search function, and start to handle / key --- src/libprojectM/KeyHandler.cpp | 199 +++++++++++++------------- src/libprojectM/Renderer/Renderer.cpp | 6 + src/libprojectM/Renderer/Renderer.hpp | 1 + src/libprojectM/event.h | 2 + src/libprojectM/projectM.cpp | 13 ++ src/libprojectM/projectM.hpp | 3 +- src/libprojectM/sdltoprojectM.h | 4 + src/projectM-sdl/pmSDL.cpp | 4 + 8 files changed, 130 insertions(+), 102 deletions(-) diff --git a/src/libprojectM/KeyHandler.cpp b/src/libprojectM/KeyHandler.cpp index c956daaf35..857deea5e1 100755 --- a/src/libprojectM/KeyHandler.cpp +++ b/src/libprojectM/KeyHandler.cpp @@ -120,27 +120,30 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode switch (keycode) { case PROJECTM_K_HOME: - if (renderer->showmenu && !isTextInputActive()) { // pageup only does something when the preset menu is active. - selectPreset(0); // jump to top of presets. - } - else if (renderer->showmenu && isTextInputActive()) - { - renderer->m_activePresetID = 1; - selectPresetByName(renderer->m_presetList[0].name,true); + if (renderer->showmenu) { + if (!isTextInputActive()) { + selectPreset(0); // jump to top of presets. + } + else { + renderer->m_activePresetID = 1; // jump to top of search results. + selectPresetByName(renderer->m_presetList[0].name,true); + } } break; case PROJECTM_K_END: - if (renderer->showmenu && !isTextInputActive()) { // pageup only does something when the preset menu is active. - selectPreset(m_presetLoader->size() - 1); // jump to bottom of presets. - } - else if (renderer->showmenu && isTextInputActive()) - { - renderer->m_activePresetID = renderer->m_presetList.size(); - selectPresetByName(renderer->m_presetList[renderer->m_activePresetID - 1].name,true); + if (renderer->showmenu) { + if (!isTextInputActive()) { + selectPreset(m_presetLoader->size() - 1); // jump to bottom of presets. + } + else { + renderer->m_activePresetID = renderer->m_presetList.size(); // jump to top of search results. + selectPresetByName(renderer->m_presetList[renderer->m_activePresetID - 1].name,true); + } } break; case PROJECTM_K_PAGEUP: - if (renderer->showmenu && !isTextInputActive()) { // pageup only does something when the preset menu is active. + if (isTextInputActive()) break; // don't handle this key if search menu is up. + if (renderer->showmenu) { int upPreset = m_presetPos->lastIndex() - (renderer->textMenuPageSize / 2.0f); // jump up by page size / 2 if (upPreset < 0) // handle lower boundary upPreset = m_presetLoader->size() - 1; @@ -148,7 +151,8 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_PAGEDOWN: - if (renderer->showmenu && !isTextInputActive()) { // pagedown only does something when the preset menu is active. + if (isTextInputActive()) break; // don't handle this key if search menu is up. + if (renderer->showmenu) { int downPreset = m_presetPos->lastIndex() + (renderer->textMenuPageSize / 2.0f); // jump down by page size / 2 if (downPreset >= (m_presetLoader->size() - 1)) // handle upper boundary downPreset = 0; @@ -176,60 +180,55 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_h: - if (!isTextInputActive(true)) { // disable help when searching. - renderer->showhelp = !renderer->showhelp; - renderer->showstats = false; - renderer->showmenu = false; - } + if (isTextInputActive(true)) break; // disable when searching. + renderer->showhelp = !renderer->showhelp; + renderer->showstats = false; + renderer->showmenu = false; + break; case PROJECTM_K_F1: - if (!isTextInputActive(true)) { // disable F1 when searching. - renderer->showhelp = !renderer->showhelp; - renderer->showstats = false; - renderer->showmenu = false; - } + if (isTextInputActive(true)) break; // disable when searching. + renderer->showhelp = !renderer->showhelp; + renderer->showstats = false; + renderer->showmenu = false; break; case PROJECTM_K_y: - if (!isTextInputActive(true)) { // disable shuffle toggle when searching. - this->setShuffleEnabled(!this->isShuffleEnabled()); - if (this->isShuffleEnabled()) { - renderer->setToastMessage("Shuffle Enabled"); - } - else { - renderer->setToastMessage("Shuffle Disabled"); - } + if (isTextInputActive(true)) break; // disable when searching. + this->setShuffleEnabled(!this->isShuffleEnabled()); + if (this->isShuffleEnabled()) { + renderer->setToastMessage("Shuffle Enabled"); + } + else { + renderer->setToastMessage("Shuffle Disabled"); } break; case PROJECTM_K_F5: - if (!isTextInputActive(true)) { // disable fps when searching. - renderer->showfps = !renderer->showfps; - // Initialize counters and reset frame count. - renderer->lastTimeFPS = duration_cast(system_clock::now().time_since_epoch()); - renderer->currentTimeFPS = duration_cast(system_clock::now().time_since_epoch()); - renderer->totalframes = 0; - // Hide preset name from screen and replace it with FPS counter. - if (renderer->showfps) - { - renderer->showpreset = false; - } + if (isTextInputActive(true)) break; // disable when searching. + renderer->showfps = !renderer->showfps; + // Initialize counters and reset frame count. + renderer->lastTimeFPS = duration_cast(system_clock::now().time_since_epoch()); + renderer->currentTimeFPS = duration_cast(system_clock::now().time_since_epoch()); + renderer->totalframes = 0; + // Hide preset name from screen and replace it with FPS counter. + if (renderer->showfps) + { + renderer->showpreset = false; } break; case PROJECTM_K_F4: - if (!isTextInputActive(true)) { // disable states when searching. - renderer->showstats = !renderer->showstats; - if (renderer->showstats) { - renderer->showhelp = false; - renderer->showmenu = false; - } + if (isTextInputActive(true)) break; // disable when searching. + renderer->showstats = !renderer->showstats; + if (renderer->showstats) { + renderer->showhelp = false; + renderer->showmenu = false; } break; case PROJECTM_K_F3: { - if (!isTextInputActive(true)) { // disable current preset name when searching. - renderer->showpreset = !renderer->showpreset; - // Hide FPS from screen and replace it with preset name. - if (renderer->showpreset) - { - renderer->showfps = false; - } + if (isTextInputActive(true)) break; // disable when searching. + renderer->showpreset = !renderer->showpreset; + // Hide FPS from screen and replace it with preset name. + if (renderer->showpreset) + { + renderer->showfps = false; } break; } @@ -261,55 +260,53 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode break; case PROJECTM_K_H: case PROJECTM_K_m: - if (!isTextInputActive(true)) { // disable menu when searching (hint: it's already up). - renderer->showmenu = !renderer->showmenu; - if (renderer->showmenu) { - renderer->showhelp = false; - renderer->showstats = false; - populatePresetMenu(); - } + if (isTextInputActive(true)) break; // disable when searching. + renderer->showmenu = !renderer->showmenu; + if (renderer->showmenu) { + renderer->showhelp = false; + renderer->showstats = false; + populatePresetMenu(); } break; case PROJECTM_K_M: - if (!isTextInputActive(true)) { // disable menu when searching (hint: it's already up). - renderer->showmenu = !renderer->showmenu; - if (renderer->showmenu) - { - renderer->showhelp = false; - renderer->showstats = false; - populatePresetMenu(); - } + if (isTextInputActive(true)) break; // disable when searching. + renderer->showmenu = !renderer->showmenu; + if (renderer->showmenu) + { + renderer->showhelp = false; + renderer->showstats = false; + populatePresetMenu(); } - break; + break; case PROJECTM_K_n: - if (!isTextInputActive(true)) // disable next key when searching (down arrow is more natural) - selectNext(true); - break; + if (isTextInputActive(true)) break; // disable when searching. + selectNext(true); + break; case PROJECTM_K_N: - if (!isTextInputActive(true)) // disable next key when searching (down arrow is more natural) - selectNext(false); - break; + if (isTextInputActive(true)) break; // disable when searching. + selectNext(false); + break; case PROJECTM_K_r: - if (!isTextInputActive(true)) // disable random key when searching - selectRandom(true); - break; + if (isTextInputActive(true)) break; // disable when searching. + selectRandom(true); + break; case PROJECTM_K_R: - if (!isTextInputActive(true)) // disable random key when searching - selectRandom(false); - break; + if (isTextInputActive(true)) break; // disable when searching. + selectRandom(false); + break; case PROJECTM_K_p: - selectPrevious(true); - break; + selectPrevious(true); + break; case PROJECTM_K_P: case PROJECTM_K_BACKSPACE: - selectPrevious(false); - break; + selectPrevious(false); + break; case PROJECTM_K_l: - if (!isTextInputActive(true)) // disable lock key when searching - setPresetLock(!isPresetLocked()); - break; + if (isTextInputActive(true)) break; // disable when searching. + setPresetLock(!isPresetLocked()); + break; case PROJECTM_K_s: - renderer->studio = !renderer->studio; + renderer->studio = !renderer->studio; case PROJECTM_K_i: break; case PROJECTM_K_RETURN: @@ -327,16 +324,16 @@ void projectM::default_key_handler( projectMEvent event, projectMKeycode keycode } break; case PROJECTM_K_0: -// nWaveMode=0; - break; +// nWaveMode=0; + break; case PROJECTM_K_6: -// nWaveMode=6; - break; +// nWaveMode=6; + break; case PROJECTM_K_7: -// nWaveMode=7; - break; +// nWaveMode=7; + break; case PROJECTM_K_t: - break; + break; case PROJECTM_K_EQUALS: case PROJECTM_K_PLUS: diff --git a/src/libprojectM/Renderer/Renderer.cpp b/src/libprojectM/Renderer/Renderer.cpp index 493587903f..fea5029ad5 100644 --- a/src/libprojectM/Renderer/Renderer.cpp +++ b/src/libprojectM/Renderer/Renderer.cpp @@ -827,6 +827,12 @@ void Renderer::setSearchText(const std::string& theValue) m_searchText = m_searchText + theValue; } +// reset search text backspace (reset) +void Renderer::resetSearchText() +{ + m_searchText = ""; +} + // search text backspace (delete a key) void Renderer::deleteSearchText() { diff --git a/src/libprojectM/Renderer/Renderer.hpp b/src/libprojectM/Renderer/Renderer.hpp index 5ace4c2093..3dcea8b0c6 100644 --- a/src/libprojectM/Renderer/Renderer.hpp +++ b/src/libprojectM/Renderer/Renderer.hpp @@ -174,6 +174,7 @@ class Renderer void setToastMessage(const std::string& theValue); void setSearchText(const std::string& theValue); + void resetSearchText(); void deleteSearchText(); std::string toastMessage() const { diff --git a/src/libprojectM/event.h b/src/libprojectM/event.h index 88949f2fc9..1ce0de5fca 100755 --- a/src/libprojectM/event.h +++ b/src/libprojectM/event.h @@ -57,6 +57,8 @@ typedef enum { PROJECTM_K_HOME, PROJECTM_K_END, PROJECTM_K_BACKSPACE, + PROJECTM_K_SLASH, + PROJECTM_K_BACKSLASH, PROJECTM_K_F1, PROJECTM_K_F2, diff --git a/src/libprojectM/projectM.cpp b/src/libprojectM/projectM.cpp index 7681d0ab0d..74c86db486 100755 --- a/src/libprojectM/projectM.cpp +++ b/src/libprojectM/projectM.cpp @@ -1160,6 +1160,19 @@ void projectM::deleteSearchText() } } +// reset search text +void projectM::resetSearchText() +{ + if ( renderer ) + renderer->resetSearchText(); + populatePresetMenu(); + if (renderer->m_presetList.size() >= 1) { + renderer->m_activePresetID = 1; + std::string topPreset = renderer->m_presetList.front().name; + selectPresetByName(topPreset); + } +} + void projectM::setToastMessage(const std::string & toastMessage) { if ( renderer ) diff --git a/src/libprojectM/projectM.hpp b/src/libprojectM/projectM.hpp index ef28356e58..eb965c866f 100644 --- a/src/libprojectM/projectM.hpp +++ b/src/libprojectM/projectM.hpp @@ -242,7 +242,8 @@ class DLLEXPORT projectM void setSearchText(const std::string & searchKey); // delete part of search term (backspace) void deleteSearchText(); - + // reset search term (blank) + void resetSearchText(); /// Returns index of currently active preset. In the case where the active /// preset was removed from the playlist, this function will return the element diff --git a/src/libprojectM/sdltoprojectM.h b/src/libprojectM/sdltoprojectM.h index fa55ea2f8c..ddaa282cd9 100755 --- a/src/libprojectM/sdltoprojectM.h +++ b/src/libprojectM/sdltoprojectM.h @@ -194,6 +194,10 @@ inline projectMKeycode sdl2pmKeycode( SDL_Keycode keycode , SDL_Keymod mod ) { \ return PROJECTM_K_UP; case SDLK_RETURN: return PROJECTM_K_RETURN; + case SDLK_SLASH: + return PROJECTM_K_SLASH; + case SDLK_BACKSLASH: + return PROJECTM_K_BACKSLASH; case SDLK_RIGHT: return PROJECTM_K_RIGHT; case SDLK_LEFT: diff --git a/src/projectM-sdl/pmSDL.cpp b/src/projectM-sdl/pmSDL.cpp index d45b3763fe..36040f948d 100644 --- a/src/projectM-sdl/pmSDL.cpp +++ b/src/projectM-sdl/pmSDL.cpp @@ -308,6 +308,10 @@ void projectMSDL::keyHandler(SDL_Event *sdl_evt) { case SDLK_BACKSPACE: projectM::deleteSearchText(); break; + case SDLK_SLASH: + break; + case SDLK_BACKSLASH: + break; case SDLK_RETURN: if (!projectM::isTextInputActive()) { SDL_StartTextInput(); From 977e7325130489503f7cf6cecf985f3493d43479 Mon Sep 17 00:00:00 2001 From: milkdropper <59471060+milkdropper@users.noreply.github.com> Date: Mon, 31 Aug 2020 19:18:36 +0400 Subject: [PATCH 16/19] refactor highlighting into it's own method --- src/libprojectM/Renderer/Renderer.cpp | 93 +++++++++++---------------- src/libprojectM/Renderer/Renderer.hpp | 10 +-- 2 files changed, 44 insertions(+), 59 deletions(-) diff --git a/src/libprojectM/Renderer/Renderer.cpp b/src/libprojectM/Renderer/Renderer.cpp index fea5029ad5..5d69c1b891 100644 --- a/src/libprojectM/Renderer/Renderer.cpp +++ b/src/libprojectM/Renderer/Renderer.cpp @@ -69,34 +69,9 @@ void Renderer::drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, if (windowWidth > textWidth) { // redraw without transparency - if (highlightable && showsearch && searchText().length() > 1) + if (textHighlightable(highlightable)) { - int offset = x; - std::string str_find = string; - for( size_t pos = 0; ; pos += str_find.length() ) { - // find search term - pos = str_find.find(searchText()); - - // draw everything normal, up to search term. - gltColor(r, g, b, a); - gltSetText(text, str_find.substr(0,pos).c_str()); - gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); - - // highlight search term - GLfloat textWidth = gltGetTextWidth(text, scale); - offset = offset + textWidth; - gltColor(1.0f, 0.0f, 1.0f, 1.0f); - gltSetText(text, searchText().c_str()); - gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); - - // draw rest of name, normally - textWidth = gltGetTextWidth(text, scale); - offset = offset + textWidth; - gltColor(r, g, b, a); - gltSetText(text, str_find.substr(pos+searchText().length(),str_find.length()).c_str()); - gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); - break; // first search hit is useful enough. - } + drawText(text, string, searchText().c_str(), x, y, scale, horizontalAlignment, verticalAlignment, r, g, b, a, highlightable); } else { gltColor(r, g, b, a); gltSetText(text, string); @@ -121,34 +96,9 @@ void Renderer::drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, substring += "..."; } - if (highlightable && showsearch && searchText().length() > 1) + if (textHighlightable(highlightable)) { - int offset = x; - std::string str_find = substring; - for (size_t pos = 0; ; pos += str_find.length()) { - // find search term - pos = str_find.find(string); - - // draw everything normal, up to search term. - gltColor(r, g, b, a); - gltSetText(text, str_find.substr(0, pos).c_str()); - gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); - - // highlight search term - GLfloat textWidth = gltGetTextWidth(text, scale); - offset = offset + textWidth; - gltColor(1.0f, 0.0f, 1.0f, 1.0f); - gltSetText(text, searchText().c_str()); - gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); - - // draw rest of name, normally - textWidth = gltGetTextWidth(text, scale); - offset = offset + textWidth; - gltColor(r, g, b, a); - gltSetText(text, str_find.substr(pos + searchText().length(), str_find.length()).c_str()); - gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); - break; // first search hit is useful enough. - } + drawText(text, substring.c_str(), searchText().c_str(), x, y, scale, horizontalAlignment, verticalAlignment, r, g, b, a, highlightable); } else { string = substring.c_str(); // Redraw now that the text fits. @@ -168,6 +118,41 @@ void Renderer::drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, gltTerminate(); } +// draw text with search term a/k/a needle & highlight text +void Renderer::drawText(GLTtext* text, const char* string, const char* needle, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment = GLT_LEFT, int verticalAlignment = GLT_TOP, float r = 1.0f, float b = 1.0f, float g = 1.0f, float a = 1.0f, bool highlightable = false) { + int offset = x; + std::string str_find = string; + for( size_t pos = 0; ; pos += str_find.length() ) { + // find search term + pos = str_find.find(needle); + + // draw everything normal, up to search term. + gltColor(r, g, b, a); + gltSetText(text, str_find.substr(0,pos).c_str()); + gltDrawText2DAligned(text, x, y, scale, horizontalAlignment, verticalAlignment); + + // highlight search term + GLfloat textWidth = gltGetTextWidth(text, scale); + offset = offset + textWidth; + gltColor(1.0f, 0.0f, 1.0f, 1.0f); + gltSetText(text, searchText().c_str()); + gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); + + // draw rest of name, normally + textWidth = gltGetTextWidth(text, scale); + offset = offset + textWidth; + gltColor(r, g, b, a); + gltSetText(text, str_find.substr(pos+searchText().length(),str_find.length()).c_str()); + gltDrawText2DAligned(text, offset, y, scale, horizontalAlignment, verticalAlignment); + break; // first search hit is useful enough. + } +} + +bool Renderer::textHighlightable(bool highlightable) { + if (highlightable && showsearch && searchText().length() > 1) + return true; + return false; +} #endif /** USE_TEXT_MENU */ diff --git a/src/libprojectM/Renderer/Renderer.hpp b/src/libprojectM/Renderer/Renderer.hpp index 3dcea8b0c6..7cb97754d8 100644 --- a/src/libprojectM/Renderer/Renderer.hpp +++ b/src/libprojectM/Renderer/Renderer.hpp @@ -195,11 +195,11 @@ class Renderer TimeKeeper *timeKeeperToast; #ifdef USE_TEXT_MENU - - void drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment, - int verticalAlignment, float r, float b, float g, float a, bool highlightable); - void drawText(const char* string, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment, - int verticalAlignment, float r, float b, float g, float a, bool highlightable); + // draw text with search term a/k/a needle & highlight text + void drawText(GLTtext* text, const char* string, const char* needle, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment, int verticalAlignment, float r, float b, float g, float a, bool highlightable); + void drawText(GLTtext* text, const char* string, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment, int verticalAlignment, float r, float b, float g, float a, bool highlightable); + void drawText(const char* string, GLfloat x, GLfloat y, GLfloat scale, int horizontalAlignment, int verticalAlignment, float r, float b, float g, float a, bool highlightable); + bool textHighlightable(bool highlightable); #endif /** USE_TEXT_MENU */ RenderContext renderContext; From e6a33aa5b36b477b4ee0111bff195a76394b0cac Mon Sep 17 00:00:00 2001 From: milkdropper <59471060+milkdropper@users.noreply.github.com> Date: Mon, 31 Aug 2020 19:30:47 +0400 Subject: [PATCH 17/19] refactor --- src/libprojectM/PresetLoader.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libprojectM/PresetLoader.cpp b/src/libprojectM/PresetLoader.cpp index dc71d5e8c1..4731484f0e 100644 --- a/src/libprojectM/PresetLoader.cpp +++ b/src/libprojectM/PresetLoader.cpp @@ -159,12 +159,7 @@ const std::vector &PresetLoader::getPresetNames() const // Get the preset index given a name const unsigned int PresetLoader::getPresetIndex(std::string &name) const { - //Need a better structure than a vector for reverse lookup - for (int index = 0; index < _presetNames.size(); index++) - { - if (_presetNames[index] == name) return index; - } - return 0; + return find(_presetNames.begin(), _presetNames.end(), name) - _presetNames.begin(); } int PresetLoader::getPresetRating ( PresetIndex index, const PresetRatingType ratingType ) const From 5b7393ad0519bcb9069e5a5885f3edbf9a3bf2ed Mon Sep 17 00:00:00 2001 From: milkdropper <59471060+milkdropper@users.noreply.github.com> Date: Mon, 31 Aug 2020 19:33:54 +0400 Subject: [PATCH 18/19] bug --- src/libprojectM/projectM.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libprojectM/projectM.cpp b/src/libprojectM/projectM.cpp index 74c86db486..216dd0454b 100755 --- a/src/libprojectM/projectM.cpp +++ b/src/libprojectM/projectM.cpp @@ -907,7 +907,7 @@ void projectM::selectNext(const bool hardCut) { return; if (isTextInputActive() && renderer->m_presetList.size() >= 1) // if search is active and there are search results { - // if search menu is down, previous is based on search terms. + // if search menu is down, next is based on search terms. if (renderer->m_activePresetID >= renderer->m_presetList.size()) { // loop to top of page is at bottom renderer->m_activePresetID = 1; @@ -916,7 +916,6 @@ void projectM::selectNext(const bool hardCut) { else { // otherwise move forward selectPresetByName(renderer->m_presetList[renderer->m_activePresetID].name,true); - renderer->m_activePresetID++; } } else if (settings().shuffleEnabled && presetFuture.size() >= 1 && presetFuture.front() != m_presetLoader->size() && !renderer->showmenu) { // if shuffling and we have future presets already stashed then let's go forward rather than truely move randomly. presetHistory.push_back(m_presetPos->lastIndex()); From adf273c81f20ca352cb2c80a465361e7c9135889 Mon Sep 17 00:00:00 2001 From: milkdropper <59471060+milkdropper@users.noreply.github.com> Date: Tue, 1 Sep 2020 11:14:06 +0400 Subject: [PATCH 19/19] reduce lookups --- src/libprojectM/projectM.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libprojectM/projectM.cpp b/src/libprojectM/projectM.cpp index 216dd0454b..f097749bc4 100755 --- a/src/libprojectM/projectM.cpp +++ b/src/libprojectM/projectM.cpp @@ -791,13 +791,15 @@ void projectM::populatePresetMenu() if(isTextInputActive()) { // if a searchTerm is active, we will populate the preset menu with search terms instead of the page we are on. int h = 0; + std::string presetName = renderer->presetName(); + int presetIndex = getSearchIndex(presetName); for(unsigned int i = 0; i < getPlaylistSize(); i++) { // loop over all presets if (getPresetName(i).find(renderer->searchText()) != std::string::npos) { // if term matches if (h < renderer->textMenuPageSize) // limit to just one page, pagination is not needed. { h++; renderer->m_presetList.push_back({ h, getPresetName(i), "" }); // populate the renders preset list. - if (h == getSearchIndex(renderer->presetName())) + if (h == presetIndex) { renderer->m_activePresetID = h; }