How to detect pan gesture in map with Flutter Here SDK - flutter

I'm building an app with Flutter and am trying to listen to the pan gestures of the map to get the center of the map view and place a pin on the center. The code I've tried is as follows:
void _setPanGestureHandler({HereMapController mapController}) {
_hereMapController.gestures.panListener = PanListener.fromLambdas(
lambda_onPan: (GestureState gestureState, Point2D panStartPoint,
Point2D panEndPoint, double panVelocity) {
if (gestureState == GestureState.begin) {
print("start pan");
} else if (gestureState == GestureState.end) {
var centerPointLat = _hereMapController.viewportSize.width / 2;
var centerPointLong = _hereMapController.viewportSize.height / 2;
GeoCoordinates geoCoordinates = _hereMapController
.viewToGeoCoordinates(Point2D(centerPointLat, centerPointLong));
if (geoCoordinates == null) {
return;
}
_addPoiMapMarker(geoCoordinates);
_getAddressForCoordinates(geoCoordinates);
} else if (gestureState == GestureState.update) {
print("pan updated");
} else if (gestureState == GestureState.cancel) {
print("pan cancelled");
}
});
}
The code is part of the search_app example and I've just added a panGesture listener to it.
On panning, I get the following in the debug console
W/PanGestureDetector(21446): [WARN ] PanGestureDetector - Invalid panning of zero duration but nonzero length, skipping
W/PanGestureDetector(21446): [WARN ] PanGestureDetector - Invalid panning of zero duration but nonzero length, skipping
Please let me know how I can solve this problem.

The code snippet from your question is not part of the search_app example, so I assume it is your code. However, what you are trying to do will not work properly:
_hereMapController.viewportSize is giving you the size in pixels of the map view. It is not providing geographic coordinates. Although you can use viewToGeoCoordinates() to convert pixel points to geographic coordinates, there is an easier way: The MapCamera gives you always the current center location for free via the targetCoordinates property.
The pan gesture handler is executed multiple times. It would not be advisable to call _addPoiMapMarker() each time the GestureState.end event occurs. Instead, you can reposition an existing marker by setting new coordinates.
From your code it looks like you want to get the address of the map view's center. I assume you do not want to recenter a marker each time the map has stopped moving. So, in your case it may be better to draw a fixed widget at the center of your map view, regardless of it's current coordinates - then it will not move or lag behind any events, e.g. you may get from a MapCameraObserver.
The log messages you are receiving are only warnings, so they should not have an effect on the pan gesture event you are receiving.

Related

How to allow raycasting when the player is at a certain distance from object?

I've implemented opening drawers/doors features on my game but the issue I'm facing is that when The player opens a drawer, it gets pushed back so the drawer has some room to be opened. sometimes it jitters when pushed back.
Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out hit, 3f);
if (hit.transform)
{
interactiveObjects = hit.transform.GetComponent<InteractiveObjects>();
}
else
{
lookObject = null;
interactiveObjects = null;
}
if (Open)
{
if (interactiveObjects)
{
interactiveObjects.OnOpen();
}
}
I'm using raycast to open the drawer. Is there a way to only allow the raycasting, when the player is not too close to the drawer? so it doesn't get pushed back by the drawer.
You can check the distance after doing the raycast. If the distance is within the tolerable range, execute the rest of your code.
if (Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out hit, 3f))
{
if (hit.distance >= minDistance)
{
// Code to execute when range is acceptable
}
else
{
Debug.Log("Player is too close to object!");
}
}
The distance used above does not take into account the height difference between the hit point and the camera. You can get a much more consistent distance by setting the y component of both vectors equal before getting the distance.
var cameraPos = mainCamera.transform.position;
cameraPos.y = hit.point.y;
var distance = Vector3.Distance(hit.point, cameraPos);

How to determine speed of swipe on a horizontal scrollview?

I'm making my own horizontal scroll view the app will be some thing like facebook which contain the homepage , friends , notification,etc.
I want to move between pages on swipe: I considered the difference on moving position to be the criteria to determine if I move to the next page or I still in the current page . it worked well but I also found on facebook if the swipe is fast it will move to next page.
So, The question now how to determine if the swipe is fast or not?
Store the start position of the swipe. When the swipe has ended, get the end position and total time elapsed since the touch began. You can then figure out how far over what time the swipe was executed, getting the "velocity" of the swipe.
Some example code:
float swipevelocity;
Vector2 touchBeginPos, touchEndPos;
float touchTime;
bool isTouching;
void Update()
{
if (//..touchstarted)
TouchBegin();
else if (//..touchended)
TouchEnd();
if (isTouching)
touchTime += Time.deltaTime;
}
void TouchBegin()
{
touchBeginPos = touch.position;
isTouching = true;
touchTime = 0; //reset touchtime
}
void TouchEnd()
{
touchEndPos = touch.position;
isTouching = false; // stop touch timer
swipevelocity = Vector2.distance(touchBeginPos, touchEndPos) / touchTime;
}
You can then set some criteria like minimum distance and minimum velocity needed to change pages.

Plot sometimes does not react to mouse input in windows forms

I'm using an ILPlotcube with line- and point-plots inside a windows forms window. Somehow the mouse control of the PlotCube, like zooming and dragging does not work anymore. For example: i can't zoom into the plot by drawing a rectangle over the region i want to see. The mouse doesn't seem to be recognized anymore.
Basically the code looks like this:
public void init() {
Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
makePlot();
}));
backgroundThread.Start();
}
makePlot() looks like this:
public void makePlot()
{
ILPlotCube plotCube = _ilPanel.Scene.First<ILPlotCube>();
if (plotCube == null) {
plotCube = new ILPlotCube {
new ILLinePlot(tosingle(_data1), "plot1", lineColor: Color.Blue),
new ILLinePlot(tosingle(_data2), "plot2", lineColor: Color.Red),
new ILLegend("data1","data2")
};
_ilPanel.Scene = new ILScene { plotCube };
}
else
{
plotCube.First<ILLinePlot>(tag: "plot1").Line.Positions.Update(tosingle(_data1);
plotCube.First<ILLinePlot>(tag: "plot2").Line.Positions.Update(tosingle(_data2);
}
_ilPanel.Scene.Configure();
_ilPanel.Invoke((MethodInvoker)delegate { _ilPanel.Refresh(); });
}
I call init() in Form1_Load() not in ilPanel1_Load()
Actually there is an other thing. The Class Reference says ILLinePlot has a Method "Update" to update the positions of the plotted line. But Visual Studio tells me ILLinePlot doesn't have such a member Function. Instead i'm using
linePlot.Line.Positions.Update
Also if i don't call Configure() on the Scene Element it won't plot the legend but if i do, the whole Plotting takes much more time.
It is hard to guess without some code. But I suppose there are multiple plot cubes in your scene. And they probably use the same screen area (probably the whole panel area?). Mouse events will fire on the topmost camera object or one of its children, if configured that way. Possibly the plot cube lays "behind" some other camera object which catches all the events. You can find out by registering an event handler on the root node and print out all mouse down events:
ilPanel1.Scene.MouseDown += (_s, _e) => { Debug.WriteLine(_e.Target); };
This will give the node below the mouse which was selected as target for the mouse event during the mouse down action. In order for the (correct) plotcube to properly receive the mouse events for zoom / rotate/ pan operations there should be either the plotcube node (plotcube derives from ILCamera) or one of its children found as target.
Another easy way to inspect the scene and detect all camera nodes contained is to create a breakpoint at the very end of your setup method (mostly this will be ilPanel1_Load(..). Once you stopped in the debugger, execute the following code in the Immediate window:
ilPanel1.Scene.Find<ILCamera>()
Count = 2
[0]: "Camera: #2 - Polar r:10 φ:0° ρ:0° - Pos X:0 Y:0 Z:10 - Lookat X:0 Y:0 Z:0 - Top X:0 Y:1 Z:0"
[1]: "ILPlotCube #30 'PlotCube' Children:[2]"
How many plot cubes do you count?
I got it to work after i switched
ilpanel.Scene = new ILScene { plotCube }
to
ilpanel.Scene.Add( plotCube )

How to make animation position start from last position

How to implement an animation in Unity relative to the last position. Normally when an animation is implemented in Unity each loop starts from the same position. I want to implement an animation relative to the last position of the animated object to avoid using forces or math calculations.
How I figured it out:
Unity Animation relative to last position without looping
This code solves the problem regarding animations based on last relative position. In this example, each time we press Fire1 a box will be animated to move from X = 0 to X = 10 Using the animation will help us to provide richer transitions and smooth movements based on curves without the problem of looping.
The idea is to have the animated object inside an empty parent so the animation of the object will be based into local position.
When the animation is finished we update the object and its parent location to match in the last position.
If you have any doubts please ask.
#pragma strict
/**
* Animation in Unity Relative to last position without looping
* #autor Knskank3
* http://stackoverflow.com/users/1287772/knskan3
* 04/09/2014
**/
/*
This code solves the problem regarding animations based on last relative ImagePosition
In this example, each time we press Fire1 a box will be animated to move from X = 0 to X = 10
Using the animation will help us to provide richer transitions and smooth movements based on curves
without the problem of looping
*/
// This var will determine if the animation is started
public var animation_started : boolean = false;
// This var will determine if the animation is finished
public var animation_finished : boolean = true;
function Update () {
// if user triggers Fire1
if( Input.GetButtonUp('Fire1')){
// initialize the flags
animation_started = true;
animation_finished = false;
// Start the animation
// this animation moves the box from local X = 0 to X = 10 using a curve to deaccelerate
animation.Play("boxanim");
}
}
/* This function is trigger at the end of the animation */
public function animationFinished() : void {
animation_finished = true;
}
/*
At the end of the frame if the animation is finished
we update the position of the parent to the last position of the child
and set the position of the child to zero inside the parent.
*/
function LateUpdate () {
// if the animation is finished and it was started
if(animation_finished && animation_started) {
// set the flag
animation_started = false;
// update the parent position
transform.parent.position = transform.position;
// update the box position to zero inside the parent
transform.localPosition = Vector3.zero;
}
}

Stage scaling affecting AS3

I have some code that controls a serious of images to produce and 360 spin when dragging mouseX axis. This all worked fine with the code I have used.
I have since had to design for different platform and enlarge the size of the stage i did this by scale to stage check box in the document settings.
While the mouse down is in action the spin works fine dragging through the images as intended but when you you release and start to drag again it doesn't remember the last frame and jumps to another frame before dragging fine again? Why is it jumping like this when all I have done is change the scale of everything?
please see code use to
//ROTATION OF CONTROL BODY X
spinX_mc.stop();
var spinX_mc:MovieClip;
var offsetFrame:int = spinX_mc.currentFrame;
var offsetX:Number = 0;
var percent:Number = 0;
//Listeners
spinX_mc.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
spinX_mc.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function startDragging(e:MouseEvent):void
{
// start listening for mouse movement
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
}
function stopDragging(e:MouseEvent):void
{
("stopDrag")
// STOP listening for mouse movement
spinX_mc.removeEventListener(MouseEvent.MOUSE_MOVE,drag);
// save the current frame number;
offsetFrame = spinX_mc.currentFrame;
removeEventListener(MouseEvent.MOUSE_DOWN, startDragging);
}
// this function is called continuously while the mouse is being dragged
function drag(e:MouseEvent):void
{
trace ("Drag")
// work out how far the mouse has been dragged, relative to the width of the spinX_mc
// value between -1 and +1
percent = (mouseX - offsetX) / spinX_mc.width;
// trace(percent);
// work out which frame to go to. offsetFrame is the frame we started from
var frame:int = Math.round(percent * spinX_mc.totalFrames) + offsetFrame;
// reset when hitting the END of the spinX_mc timeline
while (frame > spinX_mc.totalFrames)
{
frame -= spinX_mc.totalFrames;
}
// reset when hitting the START of the spinX_mc timeline
while (frame <= 0)
{
frame += spinX_mc.totalFrames;
}
// go to the correct frame
spinX_mc.gotoAndStop(frame);
}
By changing
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
to
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = mouseX;
I seem to of solved the problem and everything runs smoothly again.