Page 1 of 1

Keyboard input

Posted: 22 Mar 2019, 22:44
by lanihou
Hi, I am trying to move a shape inside a canvas base on player keyboard input. but no matter what i try , the canvas does not receive the KeyDown event.
here is my code
<UserControl x:Class="HelloWorld.MainWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
             xmlns:local="clr-namespace:HelloWorld" 
             xmlns:noesis="clr-namespace:Noesis"
             Background="#FF124C7A"  >

    <Canvas x:Name="CanvasContainer"  KeyDown="Canvas_KeyDown"  >
        <Border x:Name="Player"  BorderBrush="Black" BorderThickness="1" CornerRadius="8" Background="red" Margin="4" Padding="0" Width="80" Height="80"/>
    </Canvas>
</UserControl>
here the code behind
#if UNITY_5_3_OR_NEWER
#define NOESIS
using Noesis;
using UnityEngine;
using Canvas = Noesis.Canvas;
using GUI = Noesis.GUI;

#else
using System;
using System.Windows;
using System.Windows.Controls;
#endif


namespace HelloWorld
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : UserControl
    {
        public MainWindow()
        {
            this.Initialized += OnInitialized;
            InitializeComponent();
        }

#if NOESIS
        public  Canvas CanvasContainer;
        public Border Player;

        private void InitializeComponent()
        {
            Noesis.GUI.LoadComponent(this, "Assets/NoesisGUI/Samples/HelloWorld/MainWindow.xaml");

            this.CanvasContainer = (Canvas)FindName("CanvasContainer");
            this.Player = (Border)FindName("Player");
            CanvasContainer.Focus();
            Player.Focus();
        }
#endif
        private void OnInitialized(object sender, EventArgs args)
        {
            CanvasContainer.Focus();
            Player.Focus();
            //this.DataContext = new ViewModel();
        }
        protected override bool ConnectEvent(object source, string eventName, string handlerName)
        {
            if (eventName == "KeyDown" && handlerName == "Canvas_KeyDown")
            {
                ((Noesis.Canvas)source).KeyDown += Canvas_KeyDown;
                return true;
            }

            return false;
        }

        public void Canvas_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Space)
            {
#if NOESIS
                Debug.Log("Canvas_KeyDown " + e.Key);

#else
            Console.WriteLine("Canvas_KeyDown "+e.Key);
#endif
            }
        }


    }
}
neither of the two method work. I am surely missing something. can you please help me ? thank

Re: Keyboard input

Posted: 25 Mar 2019, 11:55
by sfernandez
Hi,

Keyboard events are routed events – meaning that the event is propagated up or down the logical tree. Routed events can either be bubbling events (they propagate up the tree) or tunneling events (they propagate down the tree). When events are paired, the tunneling events will typically fire first, followed by the paired bubbling event.

For example, the KeyDown event (bubbling) has a corresponding PreviewKeyDown event (tunneling).

In the case of keyboard events, they are routed from the UI element with keyboard focus (a TextBox in the following image).
routed-events.png
routed-events.png (8.73 KiB) Viewed 2172 times

So for your Canvas to be called when a key is pressed, the keyboard focus must be set on any UI control inside that canvas. You can call Focus() on any focusable element to set the keyboard focus.

Re: Keyboard input

Posted: 29 Mar 2019, 10:27
by lanihou
hi . I updated the code, I included the call to Focus(), in initialization, but still not able to receive the event.
can you please provide a minimalist working example i can learn from .
it is the main thing refraining me from using noesis from my game.
thank

ps : using keyttriger works but it is not pratical because i want to listen to any key.

Re: Keyboard input

Posted: 29 Mar 2019, 10:51
by lanihou
WORK AROUND FOR NOW (intercept key event in unity and call a method in the mainwindow)
using System.Collections;
using System.Collections.Generic;
using HelloWorld;
using Noesis;
using UnityEngine;

public class InputTest : MonoBehaviour
{
    NoesisView gui;
    MainWindow root;

    // Start is called before the first frame update
    void Start()
    {
        gui = GetComponent<NoesisView>();
        root = (MainWindow) gui.Content;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            print("space key was pressed");

            //attempt to send the event to the view or canvas
            gui.KeyDown(Key.Space);
            root.View.KeyDown(Key.Space);

            //TestFunction is defined in MainWindow.xaml.cs
            root.TestFunction(Key.A);
        }
    }
}

Re: Keyboard input

Posted: 01 Apr 2019, 20:20
by sfernandez
hi . I updated the code, I included the call to Focus(), in initialization, but still not able to receive the event.
can you please provide a minimalist working example i can learn from .
it is the main thing refraining me from using noesis from my game.
thank

ps : using keyttriger works but it is not pratical because i want to listen to any key.
Try with the following xaml and its code-behind:
<UserControl x:Class="TestKey.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
  xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <noesis:SetFocusAction TargetName="CanvasContainer"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <Canvas x:Name="CanvasContainer" Focusable="True" KeyDown="Canvas_KeyDown">
        <Border x:Name="Player" BorderBrush="Black" BorderThickness="1" CornerRadius="8" Background="red" Margin="4" Padding="0" Width="80" Height="80"/>
    </Canvas>
</UserControl>
using Noesis;

namespace TestKey
{
    public class MainWindow : UserControl
    {
        protected override bool ConnectEvent(object source, string eventName, string handlerName)
        {
            if (eventName == "KeyDown" && handlerName == "Canvas_KeyDown")
            {
                ((Canvas)source).KeyDown += Canvas_KeyDown;
                return true;
            }

            return false;
        }

        private void Canvas_KeyDown(object sender, KeyEventArgs e)
        {
            UnityEngine.Debug.Log(e.Key);
        }
    }
}
It is important to note that Canvas is made Focusable so it can receive focus when you call Focus on it (as the SetFocusAction is doing).

Re: Keyboard input

Posted: 09 Apr 2019, 19:42
by lanihou
thank it works now

Re: Keyboard input

Posted: 09 Apr 2019, 21:09
by sfernandez
Marked as solved.