Get the GazeProvider.GazeTarget when GaxePointer is always on - hololens

In our app we have the gaze pointer behaviour set to be AlwaysOn:
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOn);
This seems to break the GazeProvider because when a hand is detected, this:
CoreServices.InputSystem.GazeProvider.GazeTarget
returns the object actually hit by the hand rays, instead of the object at which we are gazing (could be null).
This is the code I use to get the position of the hit:
if (CoreServices.InputSystem.GazeProvider.GazeTarget?.layer == 31)
{
Debug.Log(CoreServices.InputSystem.GazeProvider.HitInfo.point);
}
But it returns the position of the hand cursor and not the gaze
I also tried filtering by SourceType(Head) but the problem persists:
foreach (var source in CoreServices.InputSystem.DetectedInputSources)
{
if (source.SourceType == InputSourceType.Head && CoreServices.InputSystem.GazeProvider.GazeTarget?.layer == 31)
{
foreach (var p in source.Pointers)
{
if (p is IMixedRealityPointer)
{
Debug.Log("HIT");
}
}
}
}
So here is the question:
When the GazePointer is set to be always visible, how can we get the position of the gaze hit even if a hand is detected?

To get the raw data of eye gaze and hand gaze at the same time, you can use InputRayUtils class, which provides the TryGetRay method that can get the ray associated with the desired input source type and hand. And if you have any question about how to use it, you can find an example in the InputDataExample scene under Assets/MRTK/Examples/Demos/Input/Scenes/InputData.

Related

Animation for a canvas object

I'm trying to use an animation for a sudoku app. I want for everytime i insert a wrong number, that number would change color and it's scale.
My code is:
override fun onDraw(canvas: Canvas?) {
canvas ?: return
drawBoard(canvas)
drawNumberProblem(canvas)
}
private fun drawNumberProblem(canvas: Canvas){
paint.color=darkcolor
paint.textSize = cellSide*3/4
SudokuGame.numbersproblem.forEach { e->
canvas.drawText("${e.number}", originX + e.col * cellSide+cellSide/5, originX + (e.row+1) * cellSide-cellSide/10, paint)
}
}
And i tried:
private fun initAnimation() {
var animation = RotateAnimation(0f, 360f, 150f, 150f)
animation.setRepeatCount(Animation.INFINITE)
animation.setRepeatMode(Animation.RESTART)
animation.setDuration(7500L)
animation.interpolator = LinearInterpolator()
startAnimation(animation)
}
override fun onDraw(canvas: Canvas?) {
canvas ?: return
if(animation==null)
initAnimation()
drawBoard(canvas)
drawNumberProblem(canvas)
}
private fun drawNumberProblem(canvas: Canvas){
paint.color=darkcolor
paint.textSize = cellSide*3/4
SudokuGame.numbersproblem.forEach { e->
canvas.drawText("${e.number}", originX + e.col * cellSide+cellSide/5, originX + (e.row+1) * cellSide-cellSide/10, paint)
}
}
The animation, the board and the numbers are all good. The animation is only an example, i tried to rotate it to see if it's working. But the only problem is that the animation is working for the whole board, i want to have animation only over numbers.
Is there any way to create a initAnimation with a parameter like initAnimation(drawNumberProblem())?
I am new to kotlin animation, so i don't really care about the best way to do it, i want to find a simple way to understand it.
Thanks
If each cell is its own View (say a TextView) you can animate it the way you're trying to, and the animation framework will take care of the timing, the rotation and scaling, etc. Because each view is separate, they can all be animated independently, using Android's view animation libraries, and a lot of the work is taken care of for you - it's pretty easy to use!
If it's all one view, and you're drawing a bunch of elements which can all be animated, you have to keep track of those elements, any animations that should be happening to each one, and how each animation's state affects the element when it comes time to draw it. Instead of each view having its own state and being drawn separately, you have to draw the whole thing at once, because it's a single view. So you need to keep track of those individual element states yourself, so you can refer to them when drawing the current overall state.
So for example, say you've got an animation where an element needs to scale to 2x the size and then back to normal, and it runs for 1 second total (1000ms). When you come to draw that element, you need to know how far along that animation you are at that moment, so you can scale it appropriately, and draw it at the correct size.
There are lots of ways to do this, probably some smarter ones, but this is the most basic hands-on example I think. I'm not testing this, but hopefully it gives you the idea:
// for brevity, so we can just say "now" instead of writing out the whole function call
val now: Long get() = System.currentTimeMillis()
// store a start time for each grid cell (or null if there's no anim running)
val animStartTimes = Array(CELL_COUNT)<Long?>
val animLength = 1000 // millis
// Basic function to start an animation - you could adapt this to prevent restarts
// while an anim is already running, etc
fun startAnim(cellIndex: Int) {
animStartTimes[cellIndex] = now
// tell the view it needs to redraw (since we're animating something now)
invalidate()
}
// Get the current progress of an animation in a cell, from 0% to 100% (0.0 to 1.0)
// I'm treating a finished item as "reset" to its original state
fun getAnimProgress(cellIndex: Int): Float {
val start = animStartTimes[cellIndex]
if (start == null) return 0f
val progress = (now - start) / animLength
if (progress > 1f) {
// animation has ended (past 100% of its runtime) so let's clear it
animStartTimes[cellIndex] = null
return 0f // like I said, I'm treating finished animations as "reset" to 0%
} else return progress
}
override fun onDraw(canvas: Canvas) {
// this flag can be set to true if we find an element that's still animating,
// so we can decide whether to call invalidate() again (forcing a redraw next frame)
var animating = false
items.forEachIndexed { i, item ->
val animProgress = getAnimProgress(i)
if (animProgress > 0f) animating = true // set that flag
// now you need to use that 0.0-1.0 value to calculate your animation state,
// e.g. adjusting the text size by some factor - 0.0 should produce your "default" state
}
// finally, force a redraw next frame if necessary - only do this when your view
// contents might need to change, otherwise you're wasting resources
if (animating) invalidate()
}
I hope that makes sense - obviously I haven't shown how to actually draw the states of your animation, that depends on exactly what you're doing - but that's the basics of it. It's a lot more work than using view animation, but it's not too bad when you get the idea.
The drawing part is a little more complex, and you'll probably want to get familiar with manipulating the Canvas - e.g. to draw a rotated character, you turn the canvas, draw the character as normal, then undo the canvas rotation so it's the right way up again, and the character is tilted. I don't have time to look for any tutorials about it, but this article covers the matrix operations that scale/rotate/etc the canvas
So yeah, it's a bit involved - and depending on what you want to do, a grid of TextViews might be a better shout

How to spawn solvers with initial orientation?

It seems very hard to get configured solvers to instantiate in a certain orientation like always in front of the SolverTarget. It seems you have to set the transforms values manually, the goal values of the SolverHandler and additionally call SnapTo on the Solver you're using because otherwise you have some kind of interpolation going on.
I'm trying this with a RadialView and it already takes me too long to get this right, rotation and all...
What's the correct way to do this the right way? Set position, rotation, done?
If the object with the RadialView was created at edit time and is active, it will snap its orientation as you've described.
Unfortunately, instantiating an object, or re-enabling an existing object with a solver will cause it to "solve" against its original position. I've found the easiest way to force the correct position is to set the lerp time to "0" for a single frame.
[SerializeField]
private GameObject objectWithSolver = null;
private IEnumerator InitialSolve(Solver solver)
{
float originalMoveLerp = solver.MoveLerpTime;
float originalRotateLerp = solver.RotateLerpTime;
solver.MoveLerpTime = 0.0f;
solver.RotateLerpTime = 0.0f;
yield return null;
solver.MoveLerpTime = originalMoveLerp;
solver.RotateLerpTime = originalRotateLerp;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.J))
{
GameObject newObject = Instantiate(objectWithSolver);
newObject.SetActive(true);
StartCoroutine(InitialSolve(newObject.GetComponent<Solver>()));
}
}
That said, this sounds like a great feature request.

UWP no error but can not display my screen

I am writing an uwp program, you may treat it as a drawing segments program:
It is only allow to draw segments horizontal or vertical.
a new segment must start at an old segment's vertex, and there are two situation not allowed in this program:
1.overlap.
2.intersection.
Here is my code to judge if two segments are cross over each other,Here is my code :
(I use a for loop to select all of segments I have already created, "line[]" stored all the segments I have already created and "ln" stored a random new segment, it will add the new segment to "line[]" if no erro occurs)
for (int l = 0; l < i - 1; l++)
{
if (ln.getY1() == ln.getY()&&line[l].getX()==line[l].getX1())
{
if(line[l].getX()>=Math.Min(ln.getX(),ln.getX1())&&line[l].getX()<=Math.Max(ln.getX(), ln.getX1())&&ln.getY()>=Math.Min(line[l].getY(),line[l].getY1())&&ln.getY()<= Math.Max(line[l].getY(), line[l].getY1()))
{
sameIslandCount++;
}
}
else if (ln.getX1() == ln.getX()&&line[l].getY()==line[l].getY1())
{
if(ln.getX()>=Math.Min(line[l].getX(),line[l].getX1())&&ln.getX()<=Math.Max(line[l].getX(), line[l].getX1())&&line[l].getY()>=Math.Min(ln.getY(),ln.getY1())&& line[l].getY() <= Math.Max(ln.getY(), ln.getY1()))
{
sameIslandCount++;
}
}
}
but when I test this program, it stuck in this screen:
but if I delete all the equal symbol, the program can run successfully. Can anyone tell me how to improve? sorry about my English, hope you can understand what I mean:p

How to increment a number and output to label

The program should count the number of correct words typed (duh), and after 60 seconds, print that value to a little label.
Does it? No. It counts to 1 and then refuses to increment.
But (and this is the fun part) when I run it in Debug mode with a breakpoint, it all works fine.
I can only figure it is some sort of variable encapsulation error (which still makes no sense).
Here's a little snippet:
private void checkWord()
{
if (txtInput.Text.ToLower() == lblQuery.Text.ToLower())
{
score++;
}
}
And here is the whole source because why not...
Programming Project.zip
http://tinyurl.com/c4af2nd
I believe you are getting white space in your comparison string. Try this to see if it works.
private void checkWord()
{
if (txtInput.Text.ToLower().Trim() == lblQuery.Text.ToLower())
{
score++;
}
}

Access to modified closure - ref int

int count = itemsToValidate.Count;
foreach(var item in itemsToValidate)
{
item.ValidateAsync += (x, y) => this.HandleValidate(ref count);
}
private void HandleValidate(ref int x)
{
--x;
if (x == 0)
{
// All items are validated.
}
}
For the above code resharper complained "Access to Modified Closure". Doesn't do that if I change that to type of object. Why is this a closure, even though I am passing by ref ?
This happens all the time
ReSharper is warning you that count is implicitly captured by the lambdas that you are assigning as "validation complete" event handlers, and that its value may well change between the time the lambda is created (i.e. when you assign the event handler) and the time when it is invoked. If this happens, the lambda will not see the value one would intuitively expect.
An example:
int count = itemsToValidate.Count;
foreach(var item in itemsToValidate)
{
item.ValidateAsync += (x, y) => this.HandleValidate(ref count);
}
// afterwards, at some point before the handlers get invoked:
count = 0;
In this instance the handlers will read the value of count as 0 instead of itemsToValidate.Count -- which might be called "obvious", but is surprising and counter-intuitive to many developers not familiar with the mechanics of lambdas.
And we usually solve it like this
The usual solution to "shut R# up" is to move the captured variable in an inner scope, where it is much less accessible and R# can be prove that it cannot be modified until the lambda is evaluated:
int count = itemsToValidate.Count;
foreach(var item in itemsToValidate)
{
int inner = count; // this makes inner impossible to modify
item.ValidateAsync += (x, y) => this.HandleValidate(ref inner);
}
// now this will of course not affect what the lambdas do
count = 0;
But your case is special
Your particular case is a comparatively rare one where you specifically want this behavior, and using the above trick would actually make the program behave incorrectly (you need the captured references to point to the same count).
The correct solution: disable this warning using the special line comments that R# recognizes.

Resources