diff --git a/.vscode/settings.json b/.vscode/settings.json index aef6058..523d638 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "C_Cpp.errorSquiggles": "Enabled", + "C_Cpp.errorSquiggles": "enabled", "files.associations": { "functional": "cpp", "thread": "cpp", @@ -100,22 +100,23 @@ }, "workbench.colorCustomizations": { - "editor.background": "#131313", - "tab.hoverBackground": "#111", + // "editor.background": "#131313", + "tab.hoverBackground": "#022809", "tab.inactiveBackground": "#000", - "tab.activeBackground": "#1b1b1b", - "tab.activeBorder": "#bb5400", + "tab.activeBackground": "#001804", + "editor.foldBackground": "#20070bcc", + "tab.activeBorder": "#15ff00", "editorIndentGuide.background1": "#252525", "editorWhitespace.foreground": "#683700", "editor.lineHighlightBorder": "#1a1a1a", - "editor.lineHighlightBackground": "#490050", + "editor.lineHighlightBackground": "#0a200a", "editorBracketMatch.background": "#444", "editorBracketMatch.border": "#b80318", - "editor.selectionBackground": "#3b3b3b", - "editor.selectionHighlightBackground": "#702900", - "statusBar.background": "#2e2850", - "minimap.background" : "#1b1b1b", - "sideBar.background": "#1b1b1b" + "editor.selectionBackground": "#0e3616", + "editor.selectionHighlightBackground": "#9c3e08c5", + // "statusBar.background": "#2e2850", + "minimap.background" : "#0f0f0f", + "sideBar.background": "#0b0b0b" }, "workbench.editor.wrapTabs": true, diff --git a/CMakeLists.txt b/CMakeLists.txt index 87606fc..24aa76a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ list(APPEND OGFX_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/FontUtils.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/WindowBase.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/BasicRenderer.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/ogfx/RawTextInput.cpp ) list(APPEND TEST_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/test.cpp @@ -78,6 +79,7 @@ target_include_directories(${TEST_TARGET} PUBLIC ${INCLUDE_DIRS}) target_link_libraries(${OMNIA_GFX_LIB} PUBLIC ${OMNIA_STD_LIB}) target_link_libraries(${TEST_TARGET} PUBLIC ${OMNIA_STD_LIB}) +target_link_libraries(${TEST_TARGET} PUBLIC ${OMNIA_GFX_LIB}) #TODO: Different flags for Release/Debug add_compile_options(-O3 -m32 -MMD -MP -Wall -ggdb -fsanitize=address) diff --git a/build.nr b/build.nr index 4ac7a82..d923863 100644 --- a/build.nr +++ b/build.nr @@ -1 +1 @@ -1856 +1859 diff --git a/extra/res/ttf/Courier Prime.ttf b/extra/res/ttf/Courier Prime.ttf new file mode 100644 index 0000000..db4e6c1 Binary files /dev/null and b/extra/res/ttf/Courier Prime.ttf differ diff --git a/extra/res/ttf/MonospaceTypewriter.ttf b/extra/res/ttf/MonospaceTypewriter.ttf new file mode 100644 index 0000000..29e9a67 Binary files /dev/null and b/extra/res/ttf/MonospaceTypewriter.ttf differ diff --git a/extra/res/ttf/NK57 Monospace Cd Rg.otf b/extra/res/ttf/NK57 Monospace Cd Rg.otf new file mode 100644 index 0000000..b9265fd Binary files /dev/null and b/extra/res/ttf/NK57 Monospace Cd Rg.otf differ diff --git a/extra/res/ttf/Roboto-Regular.ttf b/extra/res/ttf/Roboto-Regular.ttf new file mode 100644 index 0000000..7d9a6c4 Binary files /dev/null and b/extra/res/ttf/Roboto-Regular.ttf differ diff --git a/extra/res/ttf/Roboto-Thin.ttf b/extra/res/ttf/Roboto-Thin.ttf new file mode 100644 index 0000000..861d63a Binary files /dev/null and b/extra/res/ttf/Roboto-Thin.ttf differ diff --git a/extra/res/ttf/UbuntuMono-R.ttf b/extra/res/ttf/UbuntuMono-R.ttf new file mode 100644 index 0000000..fdd309d Binary files /dev/null and b/extra/res/ttf/UbuntuMono-R.ttf differ diff --git a/extra/res/ttf/cmunorm.ttf b/extra/res/ttf/cmunorm.ttf new file mode 100644 index 0000000..72cfd42 Binary files /dev/null and b/extra/res/ttf/cmunorm.ttf differ diff --git a/extra/res/ttf/digital7mono.ttf b/extra/res/ttf/digital7mono.ttf new file mode 100644 index 0000000..a481b97 Binary files /dev/null and b/extra/res/ttf/digital7mono.ttf differ diff --git a/extra/res/ttf/joystix monospace.otf b/extra/res/ttf/joystix monospace.otf new file mode 100644 index 0000000..20a3100 Binary files /dev/null and b/extra/res/ttf/joystix monospace.otf differ diff --git a/extra/res/ttf/monofonto rg.otf b/extra/res/ttf/monofonto rg.otf new file mode 100644 index 0000000..bca1ad6 Binary files /dev/null and b/extra/res/ttf/monofonto rg.otf differ diff --git a/src/ogfx/RawTextInput.cpp b/src/ogfx/RawTextInput.cpp new file mode 100644 index 0000000..11dd097 --- /dev/null +++ b/src/ogfx/RawTextInput.cpp @@ -0,0 +1,287 @@ +#include "RawTextInput.hpp" +#include +#include + +namespace ogfx +{ + namespace gui + { + RawTextInput::EventListener::EventListener(RawTextInput& _parent) : parent(_parent) + { + connectSignal(ostd::tBuiltinSignals::KeyPressed); + connectSignal(ostd::tBuiltinSignals::KeyReleased); + connectSignal(ostd::tBuiltinSignals::TextEntered); + connectSignal(ostd::tBuiltinSignals::MouseDragged); + connectSignal(ostd::tBuiltinSignals::MouseMoved); + connectSignal(ostd::tBuiltinSignals::MousePressed); + connectSignal(ostd::tBuiltinSignals::MouseReleased); + connectSignal(ostd::tBuiltinSignals::OnGuiEvent); + connectSignal(ostd::tBuiltinSignals::WindowResized); + } + + void RawTextInput::EventListener::handleSignal(ostd::tSignal& signal) + { + if (signal.ID == ostd::tBuiltinSignals::TextEntered) + { + if (m_lastEvent != eEventType::TextEntered) + { + m_lastEvent = eEventType::TextEntered; + // parent.m_keyRepeatCounter.start(); + } + auto& data = (ogfx::KeyEventData&)signal.userData; + if (parent.m_charFilter == nullptr) + { + OX_ERROR("Invalid character filter in RawTextInput event listener."); + return; //TODO: Better error + } + if (parent.m_charFilter->isValidChar(data.text)) + { + if (parent.m_lastChar == data.text && parent.m_keyRepeatCounter.isCounting()) + { + onSignalHandled(signal); + return; + } + ostd::String s1 = parent.m_text.new_substr(0, parent.m_cursorPosition); + ostd::String s2 = ""; + if (parent.m_cursorPosition < parent.m_text.len()) + s2 = parent.m_text.new_substr(parent.m_cursorPosition); + s1.addChar(data.text).add(s2); + parent.m_text = s1; + parent.m_cursorPosition++; + parent.m_lastChar = data.text; + parent.m_keyRepeatCounter.start(); + if (parent.m_theme.cursorBlink) + parent.m_theme.cursorBlinkCounter.start(); + parent.m_cursorState = true; + } + } + else if (signal.ID == ostd::tBuiltinSignals::KeyPressed) + { + if (m_lastEvent != eEventType::KeyPressed) + { + m_lastEvent = eEventType::KeyPressed; + // parent.m_keyRepeatCounter.start(); + } + auto& data = (ogfx::KeyEventData&)signal.userData; + if (parent.m_lastKeyCode == data.keyCode && parent.m_keyRepeatCounter.isCounting()) + { + onSignalHandled(signal); + return; + } + if (data.keyCode == SDLK_BACKSPACE) + { + parent.m_keyRepeatCounter.start(); + if (parent.m_theme.cursorBlink) + parent.m_theme.cursorBlinkCounter.start(); + parent.m_cursorState = true; + parent.m_lastKeyCode = data.keyCode; + if (parent.m_cursorPosition == 0 || parent.m_text == "") + { + onSignalHandled(signal); + return; + } + ostd::String s1 = parent.m_text.new_substr(0, parent.m_cursorPosition - 1); + ostd::String s2 = ""; + if (parent.m_cursorPosition < parent.m_text.len()) + s2 = parent.m_text.new_substr(parent.m_cursorPosition); + parent.m_text = s1 + s2; + parent.m_cursorPosition--; + } + else if (data.keyCode == SDLK_LEFT) + { + parent.m_keyRepeatCounter.start(); + if (parent.m_theme.cursorBlink) + parent.m_theme.cursorBlinkCounter.start(); + parent.m_cursorState = true; + parent.m_lastKeyCode = data.keyCode; + if (parent.m_cursorPosition > 0) + parent.m_cursorPosition--; + } + else if (data.keyCode == SDLK_RIGHT) + { + parent.m_keyRepeatCounter.start(); + if (parent.m_theme.cursorBlink) + parent.m_theme.cursorBlinkCounter.start(); + parent.m_cursorState = true; + parent.m_lastKeyCode = data.keyCode; + if (parent.m_cursorPosition < parent.m_text.len()) + parent.m_cursorPosition++; + } + else if (data.keyCode == SDLK_RETURN) + { + parent.m_keyRepeatCounter.start(); + parent.m_lastKeyCode = data.keyCode; + ActionEventData aed(parent, parent.getName(), eActionEventType::Enter, ostd::BaseObject::InvalidRef()); + ostd::SignalHandler::emitSignal(RawTextInput::actionEventSignalID, ostd::tSignalPriority::RealTime, aed); + } + else if (data.keyCode == SDLK_TAB) + { + parent.m_keyRepeatCounter.start(); + parent.m_lastKeyCode = data.keyCode; + ActionEventData aed(parent, parent.getName(), eActionEventType::Tab, ostd::BaseObject::InvalidRef()); + ostd::SignalHandler::emitSignal(RawTextInput::actionEventSignalID, ostd::tSignalPriority::RealTime, aed); + } + } + else if (signal.ID == ostd::tBuiltinSignals::MouseMoved) + { + auto& data = (ogfx::MouseEventData&)signal.userData; + if (parent.contains((float)data.position_x, (float)data.position_y)) + parent.m_mouseInside = true; + else + parent.m_mouseInside = false; + } + else if (signal.ID == ostd::tBuiltinSignals::MousePressed) + { + auto& data = (ogfx::MouseEventData&)signal.userData; + if (data.button == ogfx::MouseEventData::eButton::Left && parent.m_gfx != nullptr && parent.m_mouseInside) + { + ostd::String text = parent.m_text; + ostd::Vec2 relativePosition = { (float)data.position_x, (float)data.position_y }; + relativePosition -= (parent.getPosition() + parent.m_paddingX + parent.m_theme.extraPaddingLeft); + if (text.len() > 0) + { + ostd::String tmpStr1 = ""; + ostd::String tmpStr2 = ""; + bool found = false; + for (int32_t i = 0; i < text.len(); i++) + { + tmpStr2 = ""; + char c = text[i]; + tmpStr1 += c; + int32_t strWidth1 = parent.m_gfx->getStringSize(tmpStr1, parent.m_fontSize).x; + if (relativePosition.x > strWidth1) + continue; + found = true; + tmpStr2 = tmpStr1.new_substr(0, tmpStr1.len() - 1); + int32_t strWidth2 = (tmpStr2.len() > 0 ? parent.m_gfx->getStringSize(tmpStr2, parent.m_fontSize).x : 0); + int32_t d1 = (int32_t)std::abs(relativePosition.x - strWidth2); + int32_t d2 = (int32_t)std::abs(strWidth1 - relativePosition.x); + if (d1 > d2) + parent.m_cursorPosition = tmpStr1.len(); + else + parent.m_cursorPosition = tmpStr2.len(); + break; + } + if (!found) + parent.m_cursorPosition = text.len(); + } + parent.m_cursorState = true; + } + + } + onSignalHandled(signal); + } + + + + + RawTextInput& RawTextInput::create(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name) + { + setPosition(position); + setSize(size); + m_name = name; + m_eventListener = new EventListener(*this); //TODO: Delete -- Memory Leak + m_charFilter = new CharacterFilter(); //TODO: Delete -- Memory Leak + m_theme = tDefaultThemes::DefaultTheme; + if (m_theme.cursorBlink) + m_theme.cursorBlinkCounter.start(); + return *this; + } + + void RawTextInput::render(ogfx::BasicRenderer2D& gfx) + { + m_gfx = &gfx; + double text_size_scale = 0.66666666666666; + m_paddingX = (4.0f * geth()) / 30.0f; + m_fontSize = (int32_t)(geth() * 0.66); + float cursor_height_scale = 0.75f; + + ostd::IPoint strSize { 0, 0 }; + if (m_cursorPosition > 0 && m_text != "") + { + ostd::String s1 = m_text.new_substr(0, m_cursorPosition); + strSize = gfx.getStringSize(s1, m_fontSize); + } + + gfx.outlinedRect(*this, m_theme.backgroundColor, m_theme.borderColor, 2); + if (m_text.len() > 0) + gfx.drawString(m_text, getPosition() + ostd::Vec2 { m_paddingX + m_theme.extraPaddingLeft, m_paddingX + m_theme.extraPaddingTop}, m_theme.textColor, m_fontSize); + + if (m_cursorState || !m_theme.cursorBlink) + gfx.fillRect({ getx() + m_paddingX + m_theme.extraPaddingLeft + strSize.x - 1, gety() + m_paddingX + m_theme.extraPaddingTop, (float)m_theme.cursorWidth, (float)m_fontSize * cursor_height_scale }, m_theme.cursorColor); + + onRender(gfx); + } + + void RawTextInput::update(void) + { + m_keyRepeatCounter.update(); + onUpdate(); + } + + void RawTextInput::fixedUpdate(void) + { + if (m_theme.cursorBlink) + { + m_theme.cursorBlinkCounter.update(); + if (m_theme.cursorBlinkCounter.isDone()) + { + m_cursorState = !m_cursorState; + m_theme.cursorBlinkCounter.start(); + } + } + onFixedUpdate(); + } + + void RawTextInput::setText(const ostd::String& text) + { + m_text = text; + m_cursorPosition = m_text.len(); + } + + void RawTextInput::appendText(const ostd::String& text) + { + m_text.add(text); + m_cursorPosition = m_text.len(); + } + + void RawTextInput::setCursorPosition(uint16_t cursorPos) + { + if (cursorPos > m_text.len()) + cursorPos = m_text.len(); + m_cursorPosition = m_text.len(); + } + + void RawTextInput::setTheme(Theme theme) + { + m_theme = theme; + if (m_theme.cursorBlink) + m_theme.cursorBlinkCounter.start(); + else + m_theme.cursorBlinkCounter.stop(); + } + + + + + void RawTextInputEventListener::onSignalHandled(ostd::tSignal& signal) + { + if (signal.ID == ostd::tBuiltinSignals::MouseMoved) + { + auto& data = (ogfx::MouseEventData&)signal.userData; + if (getParent().isMouseInside()) + { + if (!m_ibeamCursorSet) + window.setCursor(ogfx::WindowBase::eCursor::IBeam); + m_ibeamCursorSet = true; + } + else + { + if (m_ibeamCursorSet) + window.setCursor(ogfx::WindowBase::eCursor::Arrow); + m_ibeamCursorSet = false; + } + } + } + } +} \ No newline at end of file diff --git a/src/ogfx/RawTextInput.hpp b/src/ogfx/RawTextInput.hpp new file mode 100644 index 0000000..cfa8e90 --- /dev/null +++ b/src/ogfx/RawTextInput.hpp @@ -0,0 +1,165 @@ +#pragma once + +#include +#include +namespace ogfx +{ + namespace gui + { + class RawTextInput : public ostd::Rectangle + { + public: class EventListener : public ostd::BaseObject + { + public: enum class eEventType { None = 0, TextEntered, KeyPressed, KeyReleased }; + public: + EventListener(RawTextInput& _parent); + virtual void handleSignal(ostd::tSignal& signal) override; + inline virtual void onSignalHandled(ostd::tSignal& signal) { } + inline RawTextInput& getParent(void) { return parent; } + + private: + RawTextInput& parent; + eEventType m_lastEvent { eEventType::None }; + }; + public: class CharacterFilter + { + public: + inline virtual bool isValidChar(char c) { return true; } + }; + public: class Theme + { + public: + ostd::Color textColor { 0, 0, 0, 0 }; + ostd::Color borderColor { 0, 0, 0, 0 }; + ostd::Color backgroundColor { 0, 0, 0, 0 }; + ostd::Color cursorColor { 0, 0, 0, 0 }; + + uint8_t cursorWidth { 0 }; + uint8_t extraPaddingTop { 0 }; + uint8_t extraPaddingLeft { 0 }; + + bool cursorBlink { true }; + ostd::Counter cursorBlinkCounter { 1 }; + }; + public: struct tDefaultThemes + { + inline static const Theme DebugTheme { + { 220, 220, 255 }, //Text Color + { 10, 20, 120 }, //Border Color + { 0, 0, 22 }, //Background Color + { 220, 10, 10 }, //Cursor Color + + 2, //Cursor Width + 0, //Extra Padding Top + 0, //Extra Padding Left + + true, //Cursor Blink + { 1 } //Cursor Blink Timer + }; + inline static const Theme DefaultTheme { + { 120, 120, 180 }, //Text Color + { 10, 20, 120 }, //Border Color + { 0, 2, 10 }, //Background Color + { 20, 100, 255 }, //Cursor Color + + 2, //Cursor Width + 0, //Extra Padding Top + 0, //Extra Padding Left + + true, //Cursor Blink + { 1 } //Cursor Blink Timer + }; + }; + public: enum eActionEventType { None = 0, Enter, Tab }; + public: class ActionEventData : public ostd::BaseObject + { + public: + inline ActionEventData(RawTextInput& _sender, const ostd::String& _senderName, eActionEventType _eventType, ostd::BaseObject& _userData) : + sender(_sender), + senderName(_senderName), + eventType(_eventType), + userData(_userData) + { + setTypeName("ogfx::gui::RawTextInput::ActionEventData"); + validate(); + } + + public: + RawTextInput& sender; + ostd::String senderName { "" }; + eActionEventType eventType { eActionEventType::None }; + ostd::BaseObject& userData { ostd::BaseObject::InvalidRef() }; + }; + + public: + inline RawTextInput(void) { create({ 0.0f, 0.0f }, { 200.0f, 30.0f }, "UnnamedRawTextInput"); } + inline RawTextInput(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name) { create(position, size, name); } + RawTextInput& create(const ostd::Vec2& position, const ostd::Vec2& size, const ostd::String& name); + + virtual void render(ogfx::BasicRenderer2D& gfx); + virtual void update(void); + virtual void fixedUpdate(void); + + virtual inline void onRender(ogfx::BasicRenderer2D& gfx) { } + virtual inline void onUpdate(void) { } + virtual inline void onFixedUpdate(void) { } + + void setText(const ostd::String& text); + void appendText(const ostd::String& text); + void setCursorPosition(uint16_t cursorPos); + void setTheme(Theme theme); + + inline void setEventListener(EventListener& evtl) { m_eventListener = &evtl; } + inline void setCharacterFilter(CharacterFilter& chrf) { m_charFilter = &chrf; } + inline void setName(const ostd::String& name) { m_name = name; } + + inline EventListener* getEventListener(void) const { return m_eventListener; } + inline CharacterFilter* getCharacterFilter(void) const { return m_charFilter; } + inline ostd::String getText(void) const { return m_text; } + inline uint16_t getCursorPosition(void) const { return m_cursorPosition; } + inline Theme& getTheme(void) { return m_theme; } + inline ostd::String getName(void) const { return m_name; } + inline bool isMouseInside(void) const { return m_mouseInside; } + + private: + EventListener* m_eventListener { nullptr }; + CharacterFilter* m_charFilter { nullptr }; + ogfx::BasicRenderer2D* m_gfx { nullptr }; + int32_t m_fontSize { 20 }; + float m_paddingX { 0 }; + + protected: + ostd::String m_name { "" }; + + ostd::String m_text { "" }; + uint16_t m_cursorPosition { 0 }; + bool m_cursorState { true }; + + ostd::Counter m_keyRepeatCounter { 80 }; + char m_lastChar { 0 }; + int32_t m_lastKeyCode { 0 }; + + Theme m_theme; + + bool m_mouseInside { false }; + + public: + inline static const uint32_t actionEventSignalID { ostd::SignalHandler::newCustomSignal(11400) }; + }; + class RawTextInputEventListener : public RawTextInput::EventListener + { + public: + inline RawTextInputEventListener(ogfx::gui::RawTextInput& _parent, ogfx::WindowBase& _window) : ogfx::gui::RawTextInput::EventListener::EventListener(_parent), window(_window) { } + void onSignalHandled(ostd::tSignal& signal) override; + + public: + ogfx::WindowBase& window; + bool m_ibeamCursorSet { false }; + }; + class RawTextInputNumberCharacterFilter : public RawTextInput::CharacterFilter + { + public: + inline bool isValidChar(char c) override { return c >= '0' && c <= '9'; } + }; + } +} \ No newline at end of file diff --git a/src/ogfx/WindowBase.cpp b/src/ogfx/WindowBase.cpp index f125471..9c35019 100644 --- a/src/ogfx/WindowBase.cpp +++ b/src/ogfx/WindowBase.cpp @@ -5,6 +5,8 @@ namespace ogfx WindowBase::~WindowBase(void) { onDestroy(); + SDL_FreeCursor(m_cursor_IBeam); + SDL_FreeCursor(m_cursor_Arrow); SDL_DestroyRenderer(m_renderer); SDL_DestroyWindow(m_window); // IMG_Quit(); @@ -18,7 +20,7 @@ namespace ogfx m_windowWidth = width; m_windowHeight = height; m_title = windowTitle; - if (SDL_Init(SDL_INIT_VIDEO) != 0) + if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf( "SDL could not initialize! Error: %s\n", SDL_GetError() ); exit(1); @@ -35,6 +37,9 @@ namespace ogfx SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight); SDL_SetWindowTitle(m_window, m_title.c_str()); + m_cursor_Arrow = SDL_CreateSystemCursor(SDL_SystemCursor::SDL_SYSTEM_CURSOR_ARROW); + m_cursor_IBeam = SDL_CreateSystemCursor(SDL_SystemCursor::SDL_SYSTEM_CURSOR_IBEAM); + m_initialized = true; m_running = true; @@ -89,6 +94,22 @@ namespace ogfx SDL_SetWindowTitle(m_window, m_title.c_str()); } + void WindowBase::setCursor(eCursor cursor) + { + switch (cursor) + { + case eCursor::Arrow: + SDL_SetCursor(m_cursor_Arrow); + break; + case eCursor::IBeam: + SDL_SetCursor(m_cursor_IBeam); + break; + default: + SDL_SetCursor(m_cursor_Arrow); + break; + } + } + void WindowBase::handleEvents(void) { if (!m_initialized) return; diff --git a/src/ogfx/WindowBase.hpp b/src/ogfx/WindowBase.hpp index 41a8b44..f13b9e7 100644 --- a/src/ogfx/WindowBase.hpp +++ b/src/ogfx/WindowBase.hpp @@ -8,6 +8,7 @@ namespace ogfx { class WindowBase : public ostd::BaseObject { + public: enum class eCursor { Arrow = 0, IBeam }; public: inline WindowBase(void) { } ~WindowBase(void); @@ -17,6 +18,7 @@ namespace ogfx void update(void); void setSize(int32_t width, int32_t height); void setTitle(const ostd::String& title); + void setCursor(eCursor cursor); inline virtual void onRender(void) { } inline virtual void onUpdate(void) { } @@ -27,6 +29,7 @@ namespace ogfx inline bool isInitialized(void) const { return m_initialized; } inline bool isRunning(void) const { return m_running; } + inline void close(void) { m_running = false; } inline void hide(void) { SDL_HideWindow(m_window); } inline void show(void) { SDL_ShowWindow(m_window); } inline ostd::String getTitle(void) const { return m_title; } @@ -63,6 +66,9 @@ namespace ogfx bool m_deagEventEnabled { false }; bool m_running { false }; bool m_initialized { false }; + + SDL_Cursor* m_cursor_IBeam { nullptr }; + SDL_Cursor* m_cursor_Arrow { nullptr }; }; class WindowResizedData : public ostd::BaseObject { diff --git a/src/ostd/Utils.hpp b/src/ostd/Utils.hpp index 16634df..3e944fe 100755 --- a/src/ostd/Utils.hpp +++ b/src/ostd/Utils.hpp @@ -33,6 +33,39 @@ namespace ostd }; + template + class _Counter + { + public: + inline _Counter(void) { m_count = 200; m_current = 0; } + inline _Counter(T count, T step = 1) { m_count = count; m_current = 0; m_step = step; } + inline void setCount(T count) { m_count = count; m_counting = false; m_current = 0; } + inline T getCount(void) { return m_count; } + inline T getCurrent(void) { return m_current; }; + inline T getStep(void) { return m_step; } + inline void start(void) { m_current = 0; m_counting = true; } + inline void stop(void) { m_current = 0; m_counting = false; } + inline bool isDone(void) { return !m_counting; } + inline bool isCounting(void) { return m_counting; } + inline void update(void) + { + if (!m_counting) return; + m_current += m_step; + if (m_current > m_count) + stop(); + } + + private: + T m_current { 0 }; + T m_count { 200 }; + T m_step { 1 }; + bool m_counting { false }; + }; + + typedef _Counter Counter; + typedef _Counter FloatCounter; + typedef _Counter DoubleCounter; + class OutputHandlerBase; class Timer { diff --git a/src/test.cpp b/src/test.cpp index 1c48cd9..1c445e9 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1,74 +1,158 @@ -#include -#include -#include -#include +// #include +// #include +// #include +// #include + +#include +#include +#include ostd::ConsoleOutputHandler out; -void test2(const std::string& str) {} -void test3(const ostd::String& str) {} -void test4(const char* str) {} +class Window : public ogfx::WindowBase +{ + public: + inline Window(void) : m_sigHandler(m_textInput, *this) { } + inline void onInitialize(void) override + { + enableSignals(); + connectSignal(ostd::tBuiltinSignals::KeyReleased); + connectSignal(ogfx::gui::RawTextInput::actionEventSignalID); + + m_gfx.init(*this); + m_gfx.setFont("res/ttf/Courier Prime.ttf"); + + float w = getWindowWidth(); + float h = 40.0f; + m_textInput.create({ 0.0f, (float)(getWindowHeight() - h) }, { w, h }, "MainInputTXT"); + m_textInput.setEventListener(m_sigHandler); + // m_textInput.setCharacterFilter(m_numCharFilter); + m_textInput.getTheme().extraPaddingTop = 3; + } + + inline void handleSignal(ostd::tSignal& signal) override + { + if (signal.ID == ostd::tBuiltinSignals::KeyReleased) + { + auto& evtData = (ogfx::KeyEventData&)signal.userData; + if (evtData.keyCode == SDLK_ESCAPE) + close(); + } + if (signal.ID == ogfx::gui::RawTextInput::actionEventSignalID) + { + auto& data = (ogfx::gui::RawTextInput::ActionEventData&)signal.userData; + if (data.senderName != "MainInputTXT") + return; + if (data.eventType == ogfx::gui::RawTextInput::eActionEventType::Enter) + { + out.fg(ostd::ConsoleColors::Green).p(data.sender.getText()).reset().nl(); + data.sender.setText(""); + } + else if (data.eventType == ogfx::gui::RawTextInput::eActionEventType::Tab) + { + out.fg(ostd::ConsoleColors::Red).p("TAB").reset().nl(); + data.sender.appendText("TAB"); + } + } + } + + inline void onRender(void) override + { + m_textInput.render(m_gfx); + } + + inline void onFixedUpdate(void) override + { + m_textInput.fixedUpdate(); + } + + inline void onUpdate(void) override + { + m_textInput.update (); + } + + private: + ogfx::gui::RawTextInput m_textInput; + ogfx::BasicRenderer2D m_gfx; + ogfx::gui::RawTextInputEventListener m_sigHandler; + ogfx::gui::RawTextInputNumberCharacterFilter m_numCharFilter; +}; + +// void test2(const std::string& str) {} +// void test3(const ostd::String& str) {} +// void test4(const char* str) {} int main(int argc, char** argv) { - out.fg(ostd::ConsoleColors::Red).p("Hello World!!").reset().nl(); - ostd::String str1, str2 = "Hello"; - bool b = str1 == str2; - const ostd::String str3 = "CIAO"; - b = str2 == str1; - b = str3 == "CICCIO"; - // b = "ciao" == str2; - str2 = str3; - std::string str = "cc"; - str1 = str; - test2(str1); - test3(str); - str1 = str2 + str; - str1 = str2 + "str"; - str1 = str2 + str3; - str1 = str2 + str1; - test4(str1); - test4(str3); - - str1 += "ciao"; - str1 += str; - str1 += str1; - str1 += str3; - str1 += 'c'; - - OX_FATAL(str2); - - ostd::RegexRichString rgxrstr("Hello World"); - rgxrstr.fg("Hello", "Blue"); - std::cout << rgxrstr << "\n"; - - out.nl().nl(); - ostd::String test_str = "Hello World, my love"; - ostd::String test_str_2 = "HEELO"; - ostd::String test_str_3 = "0123456789"; - out.p("==========\n"); - test_str.fixedLength(10, ' ', ".........."); - test_str_2.fixedLength(10); - test_str_3.fixedLength(10); - out.p(test_str).p("|").nl(); - out.p(test_str_2).p("|").nl(); - out.p(test_str_3).p("|").nl(); - - ostd::KeyboardController keyboard; - keyboard.disableCommandBuffer(); + Window window; + window.initialize(1280, 720, "OmniaFramework - Test Window"); + window.setClearColor({ 0, 2 , 15 }); - out.p("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"); - out.p("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH"); - out.p("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); - out.p(" "); - out.p("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); - - ostd::eKeys k = ostd::eKeys::NoKeyPressed; - do + while (window.isRunning()) { - k = keyboard.waitForKeyPress(); - } while (k != ostd::eKeys::Escape); + window.update(); + } + + + // out.fg(ostd::ConsoleColors::Red).p("Hello World!!").reset().nl(); + + // ostd::String str1, str2 = "Hello"; + // bool b = str1 == str2; + // const ostd::String str3 = "CIAO"; + // b = str2 == str1; + // b = str3 == "CICCIO"; + // // b = "ciao" == str2; + // str2 = str3; + // std::string str = "cc"; + // str1 = str; + // test2(str1); + // test3(str); + // str1 = str2 + str; + // str1 = str2 + "str"; + // str1 = str2 + str3; + // str1 = str2 + str1; + // test4(str1); + // test4(str3); + + // str1 += "ciao"; + // str1 += str; + // str1 += str1; + // str1 += str3; + // str1 += 'c'; + + // OX_FATAL(str2); + + // ostd::RegexRichString rgxrstr("Hello World"); + // rgxrstr.fg("Hello", "Blue"); + // std::cout << rgxrstr << "\n"; + + // out.nl().nl(); + // ostd::String test_str = "Hello World, my love"; + // ostd::String test_str_2 = "HEELO"; + // ostd::String test_str_3 = "0123456789"; + // out.p("==========\n"); + // test_str.fixedLength(10, ' ', ".........."); + // test_str_2.fixedLength(10); + // test_str_3.fixedLength(10); + // out.p(test_str).p("|").nl(); + // out.p(test_str_2).p("|").nl(); + // out.p(test_str_3).p("|").nl(); + + // ostd::KeyboardController keyboard; + // keyboard.disableCommandBuffer(); + + // out.p("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"); + // out.p("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH"); + // out.p("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); + // out.p(" "); + // out.p("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); + + // ostd::eKeys k = ostd::eKeys::NoKeyPressed; + // do + // { + // k = keyboard.waitForKeyPress(); + // } while (k != ostd::eKeys::Escape); return 0; } \ No newline at end of file