Nuclex.Gui with Windows Phone 7 (emulator)

Dec 15, 2011 at 4:28 PM

Hi everyone,

Trying to get Nuclex.Gui to work with Windows Phone 7 using Visual Studio 2010 express and Windows Phone emulator, but having no success.

Below is a code snippet of what I am doing, in a nutshell.

Any ideas?


this.input = new InputManager(Services, Window.Handle);
this.gui = new GuiManager(this.graphics, this.input);            
var capturer = new DefaultInputCapturer(this.input);
capturer.ChangePlayerIndex(PlayerIndex.One);
this.gui.InputCapturer = capturer;

// Automatically query the input devices once per update
omponents.Add(this.input);
// You can either add the GUI to the Components collection to have it render
// automatically, or you can call the GuiManager's Draw() method yourself
// at the appropriate place if you need more control.
Components.Add(this.gui);
this.gui.DrawOrder = 1000;

Dec 17, 2011 at 5:08 PM

A further update to this post...

I have found that even when running the UserInterfaceDemo from Nuclex the GUI is not working on the Windows Phone 7 emulator.

The value of this.gui.Screen.IsInputCaptured is always false

Coordinator
Dec 18, 2011 at 8:26 AM

Sorry for the late reply, I'm currently pretty overloaded with other work :)

The GUI part currently does not handle touch input. It's on my list of things to do when I'll have some free time again. You can work around it by creating your own input capturer and translate touches into mouse movements/clicks.

The IsInputCaptured property is an notification to the application whether it should respond to input (if false) or ignore it (if true). If, for example in a strategy game the GUI is in the screen during gameplay, if IsInputCaptured returns true, a mouse click should not start a unit selection frame because the user's click targeted a button, window or something that belongs to the GUI.

Dec 18, 2011 at 10:03 PM

Thanks for the reply. It kind of threw me off because I read comments such that the GUI was working with Windows 7 "out of the box", so I wasn't expecting it to not work.

Any hints on how one might create an input capturer that translates touches into mouse movements/clicks as you described?

Dec 18, 2011 at 10:06 PM

I can see that if I make the input capture class also an IUpdateable then its Update method should get called every time the game updates. Inside of this method I could read the touch state and decide if I wanted to call InputReceiver.injectSomething. Would that work?

Is there any way to do the same using delegates as in the DefaultINputCapturer? Are there callbacks in place for touch panel inputs that I could simply hook into and call inputReceiver.Inject directly?

Thanks again!

Dec 27, 2011 at 9:47 PM

Major bummer! This is about the best GUI framework out there, which I was hoping to use for my PC/WP7 game so I didn't pigeon hole myself into Silverlight on the wp7 side. I'm not exactly up for hacking up a workaround, but perhaps if the framework is laid out nicely then it might not feel like such a workaround. I'll give it a shot...

I'd like to point out that I both complained and convinced myself to try it in my own reply. My work here is done.

Dec 27, 2011 at 10:06 PM

Kainazzzo... after some experimenting I would say that if your project uses any amount of GUI, then don't bother with GUI on XNA. Silverlight is amazing and you can still use XNA inside of a Silverlight App. You will spend a lot of time for no reason trying to make a proper GUI on XNA.

Dec 28, 2011 at 2:21 PM

I'm still considering creating my own rudimentary GUI framework with simple button controls that I can just place on the screen. I have no silverlight experience, and I can't seem to find any educational materials on mixing silverlight and xna outside of windows phone. I do most all of my development on the pc version so I can test out mechanics, and I try to abstract out the platform specific stuff so I don't have to pigeon hole myself to one or the other. (see my recent blog post for what I mean)

I figure with a little work, I can come up with a way to decouple the GUI controls as well. I just haven't quite wrapped my head around it. This was my best option for quickly moving forward, but if it doesn't support touch, then I'm not sure how much effort I'm willing to put into it.

Dec 28, 2011 at 7:22 PM

I successfully injected mouse input where I was already reading touch gestures using the XNA gesture API.

For the tap gesture, I put:
game.gui.InputCapturer.InputReceiver.InjectMouseMove(gesture.Position.X, gesture.Position.Y);                        game.gui.InputCapturer.InputReceiver.InjectMousePress(Nuclex.Input.MouseButtons.Left);

And when there are no gestures:
game.gui.InputCapturer.InputReceiver.InjectMouseRelease(Nuclex.Input.MouseButtons.Left);

Since I'm only looking to be able to click buttons at the moment, that's all I have... so this probably won't work with the sliders or anything... that would require hooking in to the Drag gesture which wouldn't be too hard, but I haven't done that. 

Mar 18, 2012 at 2:00 AM

I had a need for the slider control to work properly on windows phone, so I modified the Nuclex source to allow mouse clicks on the slider (still need to inject the mouse clicks as described in above posts).  So, if you click on the slider area (above or below the 'thumb'), the thumb will move and the list view will change accordingly. I only tested it with Vertical sliders, as that's all I am using...but I imagine if you need horizontal sliders too, you can use what I've done to make clicking on the horizontal sliders work, too. I only had to change some code in SliderControl.cs ..... look for any lines commented with 'added by CSP'. I have posted the code below:

 

#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2010 Nuclex Development Labs

This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.

You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion

using System;
using System.Collections.Generic;

using Nuclex.Input;
using Nuclex.UserInterface.Input;

namespace Nuclex.UserInterface.Controls.Desktop {

  /// <summary>Base class for a slider that can be moved using the mouse</summary>
  /// <remarks>
  ///   Implements the common functionality for a slider moving either the direction
  ///   of the X or the Y axis (but not both). Derive any scroll bar-like controls
  ///   from this class to simplify their implementation.
  /// </remarks>
  public abstract class SliderControl : Control {

    /// <summary>Triggered when the slider has been moved</summary>
    public event EventHandler Moved;
    public int mouseX;  // added by CSP
    public int mouseY;  // added by CSP

    /// <summary>Initializes a new slider control</summary>
    public SliderControl() {
      this.ThumbPosition = 0.0f;
      this.ThumbSize = 1.0f;
    }

    /// <summary>whether the mouse is currently hovering over the thumb</summary>
    public bool MouseOverThumb {
      get { return this.mouseOverThumb; }
    }

    /// <summary>Whether the pressable control is in the depressed state</summary>
    public virtual bool ThumbDepressed {
      get {
        return
          this.pressedDown &&
          this.mouseOverThumb;
      }
    }

    /// <summary>Called when a mouse button has been pressed down</summary>
    /// <param name="button">Index of the button that has been pressed</param>
    protected override void OnMousePressed(MouseButtons button) {
      if(button == MouseButtons.Left) {
        RectangleF thumbRegion = GetThumbRegion();
        RectangleF sliderBounds = this.GetAbsoluteBounds();  // added by CSP
        sliderBounds.X = 0;// added by CSP
        sliderBounds.Y = 0;// added by CSP


        if(thumbRegion.Contains(this.pickupX, this.pickupY)) {
          this.pressedDown = true;
         
          this.pickupX -= thumbRegion.X;
          this.pickupY -= thumbRegion.Y;
        }

        if (sliderBounds.Contains(this.mouseX, this.mouseY)) // if block added by CSP
        {
            if (this.mouseY > thumbRegion.Y + thumbRegion.Height)  // clicked in slider area below thumb.
            {
                this.pressedDown = true;
                MoveThumb(mouseX - this.pickupX, mouseY);
            }

            if (this.mouseY < thumbRegion.Y)  // clicked in slider area above thumb.
            {
                this.pressedDown = true;
                MoveThumb(mouseX - this.pickupX, mouseY - 20);
            }   
           
        }
      }
    }

    /// <summary>Called when a mouse button has been released again</summary>
    /// <param name="button">Index of the button that has been released</param>
    protected override void OnMouseReleased(MouseButtons button) {
      if(button == MouseButtons.Left) {
        this.pressedDown = false;
      }
    }

    /// <summary>Called when the mouse position is updated</summary>
    /// <param name="x">X coordinate of the mouse cursor on the control</param>
    /// <param name="y">Y coordinate of the mouse cursor on the control</param>
    protected override void OnMouseMoved(float x, float y) {

        mouseX = (int)x;  // added by CSP
        mouseY = (int)y;  // added by CSP

      if(this.pressedDown) {
       
        //RectangleF bounds = GetAbsoluteBounds();
        MoveThumb(x - this.pickupX, y - this.pickupY);
       
      } else {
        this.pickupX = x;
        this.pickupY = y;
      }

      this.mouseOverThumb = GetThumbRegion().Contains(x, y);
    }

    /// <summary>
    ///   Called when the mouse has left the control and is no longer hovering over it
    /// </summary>
    protected override void OnMouseLeft() {
      this.mouseOverThumb = false;
    }

    /// <summary>Fires the slider's Moved event</summary>
    protected virtual void OnMoved() {
      if(Moved != null) {
        Moved(this, EventArgs.Empty);
      }
    }

    /// <summary>Moves the thumb to the specified location</summary>
    /// <returns>Location the thumb will be moved to</returns>
    protected abstract void MoveThumb(float x, float y);

    /// <summary>Obtains the region covered by the slider's thumb</summary>
    /// <returns>The region covered by the slider's thumb</returns>
    protected abstract RectangleF GetThumbRegion();

    /// <summary>Can be set by renderers to allow the control to locate its thumb</summary>
    public IThumbLocator ThumbLocator;
    /// <summary>Fraction of the slider filled by the thumb (0.0 .. 1.0)</summary>
    public float ThumbSize;
    /// <summary>Position of the thumb within the slider (0.0 .. 1.0)</summary>
    public float ThumbPosition;

    /// <summary>Whether the mouse cursor is hovering over the thumb</summary>
    private bool mouseOverThumb;
    /// <summary>Whether the slider's thumb is currently in the depressed state</summary>
    private bool pressedDown;
    /// <summary>X coordinate at which the thumb was picked up</summary>
    private float pickupX;
    /// <summary>Y coordinate at which the thumb was picked up</summary>
    private float pickupY;


  }

} // namespace Nuclex.UserInterface.Controls.Desktop