From 93c92e5ae91d55738142ee375950e768c34f5420 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Sun, 12 Jul 2020 04:46:21 +0200 Subject: [PATCH] scenery editor node bank search. node label and node group support --- editormode.cpp | 4 +- editoruipanels.cpp | 97 +++++++++++++++++++++++++++++++++++++++------- editoruipanels.h | 10 ++++- uilayer.cpp | 11 ++++++ uilayer.h | 6 +++ 5 files changed, 110 insertions(+), 18 deletions(-) diff --git a/editormode.cpp b/editormode.cpp index b23ccc39..8b92506d 100644 --- a/editormode.cpp +++ b/editormode.cpp @@ -200,7 +200,9 @@ editor_mode::on_key( int const Key, int const Scancode, int const Action, int co void editor_mode::on_char( unsigned int const Char ) { - // TODO: implement + + // give the ui first shot at the input processing... + if( true == m_userinterface->on_char( Char ) ) { return; } } void diff --git a/editoruipanels.cpp b/editoruipanels.cpp index 03758c51..ab20397d 100644 --- a/editoruipanels.cpp +++ b/editoruipanels.cpp @@ -304,13 +304,47 @@ nodebank_panel::nodebank_panel( std::string const &Name, bool const Isopen ) : u size_min = { 100, 50 }; size_max = { 1000, 1000 }; + memset( m_nodesearch, 0, sizeof( m_nodesearch ) ); + std::ifstream file; file.open("nodebank.txt", std::ios_base::in | std::ios_base::binary); std::string line; - while (std::getline(file, line)) - if (line.size() > 2) - m_nodebank.push_back(std::make_unique(line)); + while( std::getline( file, line ) ) { + if( line.size() < 4 ) { + continue; + } + auto const labelend { line.find( "node" ) }; + auto const nodedata { ( + labelend == std::string::npos ? "" : + labelend == 0 ? line : + line.substr( labelend ) ) }; + auto const label { ( + labelend == std::string::npos ? line : + labelend == 0 ? generate_node_label( nodedata ) : + line.substr( 0, labelend ) ) }; + + m_nodebank.push_back( { label, std::make_shared( nodedata ) } ); + } + // sort alphabetically content of each group + auto groupbegin { m_nodebank.begin() }; + auto groupend { groupbegin }; + while( groupbegin != m_nodebank.end() ) { + groupbegin = + std::find_if( + groupend, m_nodebank.end(), + []( auto const &Entry ) { + return ( false == Entry.second->empty() ); } ); + groupend = + std::find_if( + groupbegin, m_nodebank.end(), + []( auto const &Entry ) { + return ( Entry.second->empty() ); } ); + std::sort( + groupbegin, groupend, + []( auto const &Left, auto const &Right ) { + return ( Left.first < Right.first ); } ); + } } void @@ -343,17 +377,32 @@ nodebank_panel::render() { ImGui::SameLine(); ImGui::RadioButton( "copy to bank", (int*)&mode, COPY ); - ImGui::PushItemWidth(-1); - if (ImGui::ListBoxHeader("##nodebank", ImVec2(-1, -1))) + ImGui::PushItemWidth(-1); + ImGui::InputTextWithHint( "Search", "Search node bank", m_nodesearch, IM_ARRAYSIZE( m_nodesearch ) ); + if (ImGui::ListBoxHeader("##nodebank", ImVec2(-1, -1))) { - int i = 0; - for (auto const entry : m_nodebank) { - std::string label = *entry + "##" + std::to_string(i); - if (ImGui::Selectable(label.c_str(), entry == m_selectedtemplate)) - m_selectedtemplate = entry; - i++; + auto idx { 0 }; + auto isvisible { false }; + auto const searchfilter { std::string( m_nodesearch ) }; + for (auto const &entry : m_nodebank) { + if( entry.second->empty() ) { + // special case, header indicator + isvisible = ImGui::CollapsingHeader( entry.first.c_str() ); + } + else { + if( false == isvisible ) { + continue; + } + if( ( false == searchfilter.empty() ) + && ( entry.first.find( searchfilter ) == std::string::npos ) ) { + continue; + } + auto const label { " " + entry.first + "##" + std::to_string( idx ) }; + if( ImGui::Selectable( label.c_str(), entry.second == m_selectedtemplate ) ) + m_selectedtemplate = entry.second; + ++idx; + } } - ImGui::ListBoxFooter(); } } @@ -363,13 +412,31 @@ nodebank_panel::render() { void nodebank_panel::add_template(const std::string &desc) { + + auto const label { generate_node_label( desc ) }; + m_nodebank.push_back( { label, std::make_shared( desc ) } ); + std::ofstream file; file.open("nodebank.txt", std::ios_base::out | std::ios_base::app | std::ios_base::binary); - file << desc; - - m_nodebank.push_back(std::make_unique(desc)); + file << label << " " << desc; } const std::string *nodebank_panel::get_active_template() { return m_selectedtemplate.get(); } + +std::string +nodebank_panel::generate_node_label( std::string Input ) const { + + auto tokenizer{ cParser( Input ) }; + tokenizer.getTokens( 9, false ); // skip leading tokens + auto model{ tokenizer.getToken( false ) }; + auto texture{ tokenizer.getToken( false ) }; + replace_slashes( model ); + erase_extension( model ); + replace_slashes( texture ); + return ( + texture == "none" ? + model : + model + " (" + texture + ")" ); +} diff --git a/editoruipanels.h b/editoruipanels.h index f86a6994..d2bb29d1 100644 --- a/editoruipanels.h +++ b/editoruipanels.h @@ -49,8 +49,6 @@ private: }; class nodebank_panel : public ui_panel { - std::vector> m_nodebank; - std::shared_ptr m_selectedtemplate; public: enum edit_mode { @@ -66,4 +64,12 @@ public: void render() override; void add_template(const std::string &desc); const std::string* get_active_template(); + +private: +// methods: + std::string generate_node_label( std::string Input ) const; +// members: + std::vector>> m_nodebank; + char m_nodesearch[ 128 ]; + std::shared_ptr m_selectedtemplate; }; diff --git a/uilayer.cpp b/uilayer.cpp index 098e43cc..9d4c6502 100644 --- a/uilayer.cpp +++ b/uilayer.cpp @@ -164,6 +164,17 @@ ui_layer::on_key( int const Key, int const Scancode, int const Action, int const return on_key_( Key, Scancode, Action, Mods ); } +bool +ui_layer::on_char( unsigned int const Char ) { + + if( m_imguiio->WantTextInput ) { + m_imguiio->AddInputCharacter( Char ); + return true; + } + + return on_char_( Char ); +} + bool ui_layer::on_cursor_pos( double const Horizontal, double const Vertical ) { diff --git a/uilayer.h b/uilayer.h index 8ce72106..7d0ad6b6 100644 --- a/uilayer.h +++ b/uilayer.h @@ -68,6 +68,9 @@ public: // potentially processes provided input key. returns: true if the input was processed, false otherwise bool on_key( int const Key, int const Scancode, int const Action, int const Mods ); + // potentially processes provided input character. returns: true if the input was processed, false otherwise + bool + on_char( unsigned int const Char ); // potentially processes provided mouse movement. returns: true if the input was processed, false otherwise bool on_cursor_pos( double const Horizontal, double const Vertical ); @@ -137,6 +140,9 @@ private: bool on_key_( int const Key, int const Scancode, int const Action, int const Mods ) { return false; } virtual + bool + on_char_( unsigned int const Char ) { return false; } + virtual bool on_cursor_pos_( double const Horizontal, double const Vertical ) { return false; } virtual