Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - InvisibleShoe

#1
Help requests / Re: Custom canvas keyboard input
20 December 2024, 05:43:24
Understandable. I've figured out a way to make the GUI and controller work together overnight after looking at how a couple of games manage this.
But it is handy to know how to hook up keyboard input handling to CanvasSFML for other uses :)

Thanks for the help mate
#2
Help requests / Re: Custom canvas keyboard input
19 December 2024, 12:14:17
I just rolled back to an earlier commit where I was rendering to SFML view and the issue appears to be "gui->handleEvent(event)" trying to handle all keyboard events once a widget is clicked.
Mouse events are handled by my controller as they should be.
But clicking on a GUI panel or button will cause the gui to consume all keyboard events until I click on the game area again.

...After some tinkering, it's definitely the "HudRoot" widget stealing focus. I hooked up "gui->unFocusAllWidgets()" to a button and that fixes the issue.

What is best practice for unfocusing widgets to allow other forms of input handling? Is there a way to detect unhandled input events so that unFocusAllWidgets can be called?
#3
Help requests / Re: Custom canvas keyboard input
19 December 2024, 10:42:45
Excellent. Glad its an easy fix  ;) I'll give it a go.

I did have the game area rendered to a regular SFML view before but I was thinking that my game being fairly GUI heavy and the fact that I want interactive graphs and a minimap rendered to GUI widgets, it would be best to create a custom canvas widget that can gain focus and be interacted with.

While that info does help with creating a custom canvas for graphs and minimaps, I would prefer to have the game area rendering and input handling managed outside of GUI operations.
When I tried this before I had difficulty with TGUI consuming all input events, even when the only thing focused was an empty panel.

In the code below, I previously used insertSpace to create an area for the SFML view to be rendered and everything worked fine, input handling fell through to my controller until I click on any TGUI widget at which point TGUI starts consuming all actions and nothing falls through to my controller anymore.

Do you have any idea how to address this? I would love to go back to using a plain SFML view to render to.

GUI code:

auto gui = world.get_mut<Tag::GuiRoot>();
auto hudRoot = tgui::HorizontalLayout::create();

auto leftPanel = tgui::VerticalLayout::create();

auto topLeft = tgui::Panel::create();
topLeft->getRenderer()->setBackgroundColor(sf::Color::Green);
leftPanel->add(topLeft);

// auto canvas = GameCanvas::create(world);
// leftPanel->add(canvas, "GameCanvas");
// world.set( Tag::GameCanvas{canvas} );

// leftPanel->setRatio(canvas, 15.0f);

auto bottomLeft = tgui::Panel::create();
bottomLeft->getRenderer()->setBackgroundColor(sf::Color::Blue);
leftPanel->add(bottomLeft);

leftPanel->insertSpace(1, 80.0f);

hudRoot->add(leftPanel, "LeftPanel");

auto rightPanel = tgui::VerticalLayout::create();

auto topRight = tgui::Panel::create();
topRight->getRenderer()->setBackgroundColor(sf::Color::Green);
rightPanel->add(topRight);

auto button = tgui::Button::create("Steal Focus");
button->onMousePress(
[button](){
    button->setFocused(true);
}
);
topRight->add(button);

button = tgui::Button::create("Quit");
button->onMousePress(
[world](){
    world.add<Tag::ActiveScene, Tag::MenuScene>();
}
);
topRight->add(button);

auto txtArea = tgui::EditBox::create();
txtArea->setPosition(0, 50);
topRight->add(txtArea);

auto bottomRight = tgui::Panel::create();
bottomRight->getRenderer()->setBackgroundColor(sf::Color::Blue);
rightPanel->add(bottomRight);

hudRoot->add(rightPanel, "RightPanel");
hudRoot->setRatio(rightPanel, 0.3f);

hudRoot->setVisible(false);

gui->gui->add(hudRoot, "HudRoot");

(Previous) Input handling:

sf::Event event;

while(window.window->pollEvent(event)){
    if(event.type == sf::Event::Closed){
         e.world().set( Tag::Status{ Tag::Status::QUIT });
    }
    if(gui.gui->handleEvent(event)){
         continue;
    }
               
    ctrl.ctrl->checkInput(event);
}

Cheers and thanks for the help  :D
#4
Help requests / Custom canvas keyboard input
19 December 2024, 06:02:32
Hi again,
I'm trying to hookup a controller to a custom CanvasSFML widget and can't get key events to register. Mouse move and click work fine.

Header:
class GameCanvas : public tgui::CanvasSFML{
public:
    using Ptr = std::shared_ptr<GameCanvas>;

    GameCanvas(flecs::world& w);
    static GameCanvas::Ptr create(flecs::world& w);

    bool canHandleKeyPress(const tgui::Event::KeyEvent& event) override;
    void keyPressed (const tgui::Event::KeyEvent& event) override;
    bool leftMousePressed(tgui::Vector2f pos) override;
    void leftMouseReleased(tgui::Vector2f pos) override;
    void rightMousePressed(tgui::Vector2f pos) override;
    void rightMouseReleased(tgui::Vector2f pos) override;
    void mouseMoved(tgui::Vector2f pos) override;

    bool isFocused() const{
        bool f = tgui::CanvasSFML::isFocused();
        std::cout << "GameCanvas::isFocused(): " << (f ? "True" : "False") << std::endl;

        return f;
    }

    tgui::SignalTyped<tgui::Event::KeyEvent> onKeyPress = {"onKeyPress"};
protected:
    tgui::Signal& getSignal(tgui::String signalName) override;
private:
    flecs::world world;
};

src:
#include "gameCanvas.hpp"

GameCanvas::GameCanvas(flecs::world& w) : tgui::CanvasSFML(), world(w) {
    onKeyPress(
        [this](const tgui::Event::KeyEvent& event){
            Tag::InputCtrl* ctrl = world.lookup("Tag::GameScene").get_mut<Tag::InputCtrl>();
            ctrl->ctrl->onKeyEvent(event);
        }
    );
}

GameCanvas::Ptr GameCanvas::create(flecs::world& w){
    auto canvas = std::make_shared<GameCanvas>(w);
    return canvas;
}

void GameCanvas::keyPressed (const tgui::Event::KeyEvent& event){
    std::cout << "GameCanvas::keyPressed()" << std::endl;
    tgui::CanvasSFML::keyPressed(event);

    onKeyPress.emit(this, event);
}
bool GameCanvas::leftMousePressed(tgui::Vector2f pos){
    tgui::CanvasSFML::leftMousePressed(pos);

    return false;
}
void GameCanvas::leftMouseReleased(tgui::Vector2f pos){
    tgui::CanvasSFML::leftMouseReleased(pos);

    std::cout << "GameCanvas::leftMouseReleased()" << std::endl;
}
void GameCanvas::rightMousePressed(tgui::Vector2f pos){
    tgui::CanvasSFML::rightMousePressed(pos);
}
void GameCanvas::rightMouseReleased(tgui::Vector2f pos){
    tgui::CanvasSFML::rightMouseReleased(pos);
}
void GameCanvas::mouseMoved(tgui::Vector2f pos){
    tgui::CanvasSFML::mouseMoved(pos);

    Tag::InputCtrl* ctrl = world.lookup("Tag::GameScene").get_mut<Tag::InputCtrl>();
    ctrl->ctrl->onMouseMoveEvent(pos - getPosition());
}

bool GameCanvas::canHandleKeyPress(const tgui::Event::KeyEvent& event){
    std::cout << "GameCanvas::canHandleKeyPress()" << std::endl;

    return true;
}

tgui::Signal& GameCanvas::getSignal(tgui::String signalName) {
    std::cout << "GameCanvas::getSignal()" << std::endl;

    if (signalName == onKeyPress.getName())
        return onKeyPress;
    else
        return tgui::CanvasSFML::getSignal(std::move(signalName));
}


The log messages from isFocused, keyPressed, canHandleKeyPress and getSignal never get called but the messages/actions in mouseMoved and leftMouseReleased do.

The canvas hierarchy is: GameCanvas > VerticalLayout["LeftPanel"] > HorizontalLayout["HudRoot"] > RootContainer.



I've looked through the forums, the tutorial pages on signals and custom widgets, and TGUI source code, especially EditBox, but I just can't seem to figure out how to get the canvas to receive keyboard input.

If someone could point out what I'm doing wrong in the above code or provide me some basic code showing how to create a custom canvas with keyPress functionality, I'd greatly appreciate it.
Cheers 
#5
Help requests / Re: CanvasSFML rendering frozen
16 December 2024, 10:37:52
Did some more investigating and its a problem with the gui capturing input events before they can get to the game controller.

Going to have to think about this one.
#6
Help requests / CanvasSFML rendering frozen
16 December 2024, 10:07:17
Hi
I have my game screen setup as below:

    auto gui = world.get_mut<Tag::GuiRoot>();
    auto hudRoot = tgui::HorizontalLayout::create();

// LEFT WIDGETS

    auto leftPanel = tgui::VerticalLayout::create();
    leftPanel->setFocusable(false);

    auto topLeft = tgui::Panel::create();
    topLeft->getRenderer()->setBackgroundColor(sf::Color::Green);
    leftPanel->add(topLeft);

    auto canvas = tgui::CanvasSFML::create();
    leftPanel->add(canvas, "GameCanvas");
    world.set( Tag::GameCanvas{canvas} );

    leftPanel->setRatio(canvas, 15.0f);

    auto bottomLeft = tgui::Panel::create();
    bottomLeft->getRenderer()->setBackgroundColor(sf::Color::Blue);
    leftPanel->add(bottomLeft);

    hudRoot->add(leftPanel, "LeftPanel");

// RIGHT WIDGETS
    auto rightPanel = tgui::VerticalLayout::create();
    // rightPanel->setFocusable(false);

    auto topRight = tgui::Panel::create();
    topRight->getRenderer()->setBackgroundColor(sf::Color::Green);
    rightPanel->add(topRight);

    auto bottomRight = tgui::Panel::create();
    bottomRight->getRenderer()->setBackgroundColor(sf::Color::Blue);
    rightPanel->add(bottomRight);

    hudRoot->add(rightPanel, "RightPanel");
    hudRoot->setRatio(rightPanel, 0.3f);

    hudRoot->setVisible(false);

    gui->gui->add(hudRoot, "HudRoot");

The render process looks similar to:

canvas->clear(sf::Color::Black);
window->clear(sf::Color::White);

// render sprites to canvas

canvas->display();

gui->draw();

window->display()


Canvas rendering works fine on startup but as soon as I click on a gui widget(eg the right panel above) the canvas stops redrawing and won't unfreeze.
If I disable focus on the widget then the canvas stops freezing, so it seems to be an issue with widgets stealing focus from the canvas.
I've run my code in debug with breakpoints and the sprite rendering system is running in the background but the window stops responding to input and the canvas rendering stops.

Can anyone help with this? I was hoping to embed canvas widgets in a few places in a similar manner.

Cheers