Xamarin Forms UWP - Text Color during typing - textcolor

I got an issue about the Entry Class of Xamarin Forms. The problem is, when I'm typing a text into this Entry, the text is black..
The thing is, the text, before it has been tapped, is White and the placeholder is Gray, however, when I'm typing, the text is black and not White like I would..
There is the Entry:
public class CustomEntry : Entry
{
/// <summary>
/// The HasBorder property.
/// </summary>
public static readonly BindableProperty HasBorderProperty =
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(CustomEntry), true);
/// <summary>
/// Assessor for the HasBorder property.
/// </summary>
public bool HasBorder
{
get { return (bool)GetValue(HasBorderProperty); }
set { SetValue(HasBorderProperty, value); }
}
/// <summary>
/// The XAlign property
/// </summary>
public static readonly BindableProperty XAlignProperty =
BindableProperty.Create("XAlign", typeof(TextAlignment), typeof(CustomEntry), TextAlignment.Start);
/// <summary>
/// Gets or sets the X alignment of the text
/// </summary>
public TextAlignment XAlign
{
get { return (TextAlignment)GetValue(XAlignProperty); }
set { SetValue(XAlignProperty, value); }
}
}
and then, the Renderer for the UWP platform:
public class CustomEntryRenderer : EntryRenderer
{
/// <summary>
/// Instance of our Custom control declared in the PCL part.
/// </summary>
CustomEntry customEntry;
/// <summary>
/// We override the OnElementChanged() event handler to get the desired instance. We also use it for updates.
/// </summary>
/// <param name="e">It contains either the NewElement or the OldElement.</param>
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
customEntry = e.NewElement as CustomEntry;
if (customEntry != null)
{
SetTextAlignment();
SetBorderPresence();
SetTextColor();
}
}
}
/// <summary>
/// The on element property changed callback.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="PropertyChangedEventArgs"/>Instance containing the event data.</param>
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == CustomEntry.XAlignProperty.PropertyName)
SetTextAlignment();
else if (e.PropertyName == CustomEntry.HasBorderProperty.PropertyName)
SetBorderPresence();
else if (e.PropertyName == CustomEntry.TextColorProperty.PropertyName)
SetTextColor();
}
/// <summary>
/// Sets the text alignment.
/// </summary>
/// <param name="view">The view.</param>
private void SetTextAlignment()
{
switch (customEntry.XAlign)
{
case Xamarin.Forms.TextAlignment.Center:
Control.TextAlignment = Windows.UI.Xaml.TextAlignment.Center;
break;
case Xamarin.Forms.TextAlignment.End:
Control.TextAlignment = Windows.UI.Xaml.TextAlignment.Right;
break;
case Xamarin.Forms.TextAlignment.Start:
Control.TextAlignment = Windows.UI.Xaml.TextAlignment.Left;
break;
}
}
/// <summary>
/// Sets the border presence.
/// </summary>
private void SetBorderPresence()
{
if (!customEntry.HasBorder)
{
Control.BorderThickness = new Windows.UI.Xaml.Thickness();
}
}
/// <summary>
///
/// </summary>
private void SetTextColor()
{
Debug.WriteLine("-- HEY --");
Control.IsColorFontEnabled = true;
Control.SelectionHighlightColor = new SolidColorBrush(Windows.UI.Color.FromArgb(126, 255, 255, 255));
Control.Foreground = new SolidColorBrush(Windows.UI.Color.FromArgb(126, 255, 255, 255));
Control.ForegroundFocusBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(126, 255, 255, 255));
Control.PlaceholderForegroundBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(126, 255, 255, 255));
Control.PlaceholderForegroundFocusBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(126, 255, 255, 255));
Control.BackgroundFocusBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(126, 255, 255, 255));
Debug.WriteLine("-- HEY --");
}
}
Does someone has any idea? I didn't try for Android/iOS..
Thank in advance for any help !

Related

Azure Spatial Anchors / Unity World Anchors lose position

I am working on a simple unity app testing azure spatial anchors on the HoloLens. I started from this example (https://github.com/Azure/azure-spatial-anchors-samples) and changed it a little bit to create several anchors.
In some test sessions I experienced that the anchored objects lost their position suddenly and where moved about 10 meters or more.
As I unterstand HoloLens and mixed reality the camera position is tracked by kind of visual odometry or rather SLAM algorithms so it is normal that the pose of the device drifts over the time and so will the anchors do. But I did not expect such a huge shift.
Furthermore I expected the anchors to get back in places in the moment the features in the neighborhood of the anchors are visible again for the devices camera. But this is not always the case. Sometimes the anchors get back at their original position when the features are visible again, but sometimes this does not change anything about the wrong positions.
This is the code:
using Microsoft.Azure.SpatialAnchors;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.XR.WSA;
using UnityEngine.XR.WSA.Input;
using System.Linq;
using System.IO;
using UnityEditor;
public class AzureSpatialAnchorsScript : MonoBehaviour
{
/// <summary>
/// The sphere prefab.
/// </summary>
public GameObject spherePrefab;
/// <summary>
/// Set this string to the Spatial Anchors account id provided in the Spatial Anchors resource.
/// </summary>
protected string SpatialAnchorsAccountId = "xxxxxxxxxxxxxxxx";
/// <summary>
/// Set this string to the Spatial Anchors account key provided in the Spatial Anchors resource.
/// </summary>
protected string SpatialAnchorsAccountKey = "yyyyyyyyyyyyyyyyyyyyyyy";
/// <summary>
/// Our queue of actions that will be executed on the main thread.
/// </summary>
private readonly Queue<Action> dispatchQueue = new Queue<Action>();
/// <summary>
/// Use the recognizer to detect air taps.
/// </summary>
private GestureRecognizer recognizer;
protected CloudSpatialAnchorSession cloudSpatialAnchorSession;
/// <summary>
/// The CloudSpatialAnchor that we either 1) placed and are saving or 2) just located.
/// </summary>
protected CloudSpatialAnchor currentCloudAnchor;
/// <summary>
/// True if we are creating + saving an anchor
/// </summary>
protected bool tapExecuted = false;
/// <summary>
/// The IDs of the CloudSpatialAnchor that were saved. Use it to find the CloudSpatialAnchors
/// </summary>
protected Dictionary<string, GameObject> cloudSpatialAnchorIdsObjects = new Dictionary<string, GameObject> { };
protected IList<string> anchorIds = new List<string>();
/// <summary>
/// The sphere rendered to show the position of the CloudSpatialAnchor.
/// </summary>
protected Material sphereMaterial;
/// <summary>
/// Indicate if we are ready to save an anchor. We can save an anchor when value is greater than 1.
/// </summary>
protected float recommendedForCreate = 0;
private string pathName;
// Start is called before the first frame update
void Start()
{
Application.SetStackTraceLogType(LogType.Log, StackTraceLogType.None);
recognizer = new GestureRecognizer();
recognizer.StartCapturingGestures();
recognizer.SetRecognizableGestures(GestureSettings.Tap);
recognizer.Tapped += HandleTap;
InitializeSession();
string FileName = "ids.txt";
pathName = Path.Combine(Application.persistentDataPath, FileName);
getIds();
if (anchorIds.Count > 0)
{
CreateWatcher(anchorIds.ToArray());
}
}
// Update is called once per frame
void Update()
{
lock (dispatchQueue)
{
if (dispatchQueue.Count > 0)
{
dispatchQueue.Dequeue()();
}
}
}
/// <summary>
/// Queues the specified <see cref="Action"/> on update.
/// </summary>
/// <param name="updateAction">The update action.</param>
protected void QueueOnUpdate(Action updateAction)
{
lock (dispatchQueue)
{
dispatchQueue.Enqueue(updateAction);
}
}
/// <summary>
/// Cleans up objects.
/// </summary>
public void CleanupObjects()
{
if (cloudSpatialAnchorIdsObjects != null)
{
cloudSpatialAnchorIdsObjects = new Dictionary<string, GameObject>();
}
if (sphereMaterial != null)
{
Destroy(sphereMaterial);
sphereMaterial = null;
}
//currentCloudAnchor = null;
}
/// <summary>
/// Initializes a new CloudSpatialAnchorSession.
/// </summary>
void InitializeSession()
{
Debug.Log("ASA Info: Initializing a CloudSpatialAnchorSession.");
if (string.IsNullOrEmpty(SpatialAnchorsAccountId))
{
Debug.LogError("No account id set.");
return;
}
if (string.IsNullOrEmpty(SpatialAnchorsAccountKey))
{
Debug.LogError("No account key set.");
return;
}
cloudSpatialAnchorSession = new CloudSpatialAnchorSession();
cloudSpatialAnchorSession.Configuration.AccountId = SpatialAnchorsAccountId.Trim();
cloudSpatialAnchorSession.Configuration.AccountKey = SpatialAnchorsAccountKey.Trim();
cloudSpatialAnchorSession.LogLevel = SessionLogLevel.All;
cloudSpatialAnchorSession.Error += CloudSpatialAnchorSession_Error;
cloudSpatialAnchorSession.OnLogDebug += CloudSpatialAnchorSession_OnLogDebug;
cloudSpatialAnchorSession.SessionUpdated += CloudSpatialAnchorSession_SessionUpdated;
cloudSpatialAnchorSession.AnchorLocated += CloudSpatialAnchorSession_AnchorLocated;
cloudSpatialAnchorSession.LocateAnchorsCompleted += CloudSpatialAnchorSession_LocateAnchorsCompleted;
cloudSpatialAnchorSession.Start();
Debug.Log("ASA Info: Session was initialized.");
}
void CreateWatcher(string[] cloudSpatialAnchorIds)
{
Debug.Log("ASA Info: We will look for placeded anchors.");
// Create a Watcher to look for the anchor we created.
AnchorLocateCriteria criteria = new AnchorLocateCriteria();
criteria.Identifiers = cloudSpatialAnchorIds;
cloudSpatialAnchorSession.CreateWatcher(criteria);
Debug.Log("ASA Info: Watcher created. Number of active watchers: " + cloudSpatialAnchorSession.GetActiveWatchers().Count);
}
private void CloudSpatialAnchorSession_Error(object sender, SessionErrorEventArgs args)
{
Debug.LogError("ASA Error: " + args.ErrorMessage);
}
private void CloudSpatialAnchorSession_OnLogDebug(object sender, OnLogDebugEventArgs args)
{
Debug.Log("ASA Log: " + args.Message);
System.Diagnostics.Debug.WriteLine("ASA Log: " + args.Message);
}
private void CloudSpatialAnchorSession_SessionUpdated(object sender, SessionUpdatedEventArgs args)
{
Debug.Log("ASA Log: recommendedForCreate: " + args.Status.RecommendedForCreateProgress);
recommendedForCreate = args.Status.RecommendedForCreateProgress;
}
private void CloudSpatialAnchorSession_AnchorLocated(object sender, AnchorLocatedEventArgs args)
{
switch (args.Status)
{
case LocateAnchorStatus.Located:
Debug.Log("ASA Info: Anchor located! Identifier: " + args.Identifier);
QueueOnUpdate(() =>
{
// Create a green sphere.
GameObject spatialAnchorObj = GameObject.Instantiate(spherePrefab, Vector3.zero, Quaternion.identity) as GameObject;
spatialAnchorObj.AddComponent<WorldAnchor>();
sphereMaterial = spatialAnchorObj.GetComponent<MeshRenderer>().material;
sphereMaterial.color = Color.green;
// Get the WorldAnchor from the CloudSpatialAnchor and use it to position the sphere.
spatialAnchorObj.GetComponent<UnityEngine.XR.WSA.WorldAnchor>().SetNativeSpatialAnchorPtr(args.Anchor.LocalAnchor);
cloudSpatialAnchorIdsObjects.Add(args.Anchor.Identifier, spatialAnchorObj);
Debug.Log("Detected Pos: " + spatialAnchorObj.GetComponent<UnityEngine.XR.WSA.WorldAnchor>().transform.position.ToString("F4"));
Debug.Log("Detected Rot: " + spatialAnchorObj.GetComponent<UnityEngine.XR.WSA.WorldAnchor>().transform.rotation.ToString("F4"));
tapExecuted = false;
});
break;
case LocateAnchorStatus.AlreadyTracked:
Debug.Log("ASA Info: Anchor already tracked. Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.NotLocated:
Debug.Log("ASA Info: Anchor not located. Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.NotLocatedAnchorDoesNotExist:
Debug.LogError("ASA Error: Anchor not located does not exist. Identifier: " + args.Identifier);
break;
}
}
private void CloudSpatialAnchorSession_LocateAnchorsCompleted(object sender, LocateAnchorsCompletedEventArgs args)
{
Debug.Log("ASA Info: Locate anchors completed. Watcher identifier: " + args.Watcher.Identifier);
}
/// <summary>
/// Called by GestureRecognizer when a tap is detected.
/// </summary>
/// <param name="eventArgs">The tap.</param>
public void HandleTap(TappedEventArgs eventArgs)
{
if (tapExecuted)
{
return;
}
tapExecuted = true;
Debug.Log("ASA Info: We will create a new anchor.");
//// Clean up any anchors that have been placed.
//CleanupObjects();
// Construct a Ray using forward direction of the HoloLens.
Ray GazeRay = new Ray(eventArgs.headPose.position, eventArgs.headPose.forward);
// Raycast to get the hit point in the real world.
RaycastHit hitInfo;
Physics.Raycast(GazeRay, out hitInfo, float.MaxValue);
this.CreateAndSaveSphere(hitInfo.point);
}
/// <summary>
/// Creates a sphere at the hit point, and then saves a CloudSpatialAnchor there.
/// </summary>
/// <param name="hitPoint">The hit point.</param>
protected virtual void CreateAndSaveSphere(Vector3 hitPoint)
{
// Create a white sphere.
GameObject spatialAnchorObj = GameObject.Instantiate(spherePrefab, hitPoint, Quaternion.identity) as GameObject;
spatialAnchorObj.AddComponent<WorldAnchor>();
sphereMaterial = spatialAnchorObj.GetComponent<MeshRenderer>().material;
sphereMaterial.color = Color.white;
Debug.Log("ASA Info: Created a local anchor.");
// Create the CloudSpatialAnchor.
currentCloudAnchor = new CloudSpatialAnchor();
// Set the LocalAnchor property of the CloudSpatialAnchor to the WorldAnchor component of our white sphere.
WorldAnchor worldAnchor = spatialAnchorObj.GetComponent<WorldAnchor>();
if (worldAnchor == null)
{
throw new Exception("ASA Error: Couldn't get the local anchor pointer.");
}
// Save the CloudSpatialAnchor to the cloud.
currentCloudAnchor.LocalAnchor = worldAnchor.GetNativeSpatialAnchorPtr();
//cloudAnchor.AppProperties[#"x"] = #"frame";
//cloudAnchor.AppProperties[#"label"] = #"my latest picture";
Task.Run(async () =>
{
// Wait for enough data about the environment.
while (recommendedForCreate < 1.0F)
{
await Task.Delay(330);
}
bool success = false;
try
{
QueueOnUpdate(() =>
{
// We are about to save the CloudSpatialAnchor to the Azure Spatial Anchors, turn it yellow.
sphereMaterial.color = Color.yellow;
});
await cloudSpatialAnchorSession.CreateAnchorAsync(currentCloudAnchor);
success = currentCloudAnchor != null;
if (success)
{
// Record the identifier to locate.
string cloudAnchorId = currentCloudAnchor.Identifier;
QueueOnUpdate(() =>
{
// Turn the sphere blue.
sphereMaterial.color = Color.blue;
});
Debug.Log("ASA Info: Saved anchor to Azure Spatial Anchors! Identifier: " + cloudAnchorId);
//Debug.Log("Created " + cloudAnchorId + " at pos: " + worldAnchor.transform.position);
//Debug.Log("Created " + cloudAnchorId + "at rot: " + worldAnchor.transform.rotation);
anchorIds.Add(cloudAnchorId);
cloudSpatialAnchorIdsObjects.Add(cloudAnchorId, spatialAnchorObj);
WriteIds();
}
else
{
sphereMaterial.color = Color.red;
Debug.LogError("ASA Error: Failed to save, but no exception was thrown.");
}
}
catch (Exception ex)
{
QueueOnUpdate(() =>
{
sphereMaterial.color = Color.red;
});
Debug.LogError("ASA Error: " + ex.Message);
}
// Allow the user to tap again to clear state and look for the anchor.
tapExecuted = false;
});
}
void WriteIds()
{
try
{
string fileContent = ""
//= ReadString();
;
foreach (string id in anchorIds)
{
fileContent += id + Environment.NewLine;
}
using (StreamWriter writer = new StreamWriter(new FileStream(pathName, FileMode.OpenOrCreate, FileAccess.Write)))
{
writer.Write(fileContent);
}
}
catch (Exception e)
{
Debug.LogError(e);
}
}
void getIds()
{
try
{
StreamReader reader = new StreamReader(pathName);
string line;
while ((line = reader.ReadLine()) != null)
{
anchorIds.Add(line);
}
reader.Close();
}
catch (FileNotFoundException e)
{
Debug.LogWarning("No AnchorId file found");
}
}
}
Is something wrong with the way the anchors are created or is this normal behavior?
It is not surprising behavior that sometimes the anchors lose their position and it could be the case that some of the anchors are relocalized after tracking is recovered, but not all of them. It could be helpful to add a script to the object you create for the anchor that shows the tracking state of the anchor attached to it. Here is a sample:-
using System;
using UnityEngine;
using UnityEngine.XR.WSA;
public class ShowTrackingState : MonoBehavior
{
WorldAnchor worldAnchor = null;
Material renderMaterial = null;
bool isTracking = false;
void Start()
{
renderMaterial = gameObject.GetComponent<Renderer>().material;
}
void OnDestroy()
{
if (renderMaterial != null)
{
Destroy(renderMaterial);
}
}
void Update()
{
if (worldAnchor == null)
{
worldAnchor = gameObject.GetComponent<worldAnchor>();
}
if (worldAnchor == null)
{
isTracking = false;
}
else
{
isTracking = worldAnchor.isLocated;
}
renderMaterial.color = isTracking ? Color.red : Color.green;
}
}
Also, a gentle reminder, it is a common mistake to forget to hide one's account id and key when posting questions on forums; but it is not secure so you might want to remove that part from your code snippet in the question :-)

AR core loading prefabs dynamically in unity

I have recently started dabbling in Unity with ARcore, I am using the HelloARController.cs that comes with ARcore 1.5 but I want to load a bundle from my server, I have two scripts
one called LoadAsset.cs which loads a bundle from a webserver and I have another called HelloARcontroller.cs which is basically the main part of the app, this allows me to preset prefabs that will be loaded when the screen is clicked
What I would like to do instead of loading one of the "Andy" objects is for it to pull a prefab from the webserver and use that instead
I have managed so far to load a prefab from my server at runtime but placing it is another matter
namespace GoogleARCore.Examples.HelloAR
{
using System.Collections.Generic;
using GoogleARCore;
using GoogleARCore.Examples.Common;
using UnityEngine;
using System;
using System.Collections;
#if UNITY_EDITOR
// Set up touch input propagation while using Instant Preview in the editor.
using Input = InstantPreviewInput;
#endif
/// <summary>
/// Controls the HelloAR example.
/// </summary>
public class HelloARController : MonoBehaviour
{
public string BundleURL; // -->
http://Myserver/public_http/Assets/AssetBundles/cube_prefab (path to the AssetBundle)
public string AssetName; // --> Cube_pref (name of the Asset prefab)
public int version;
/// <summary>
/// The first-person camera being used to render the passthrough camera image (i.e. AR background).
/// </summary>
public Camera FirstPersonCamera;
/// <summary>
/// A prefab for tracking and visualizing detected planes.
/// </summary>
public GameObject DetectedPlanePrefab;
/// <summary>
/// A model to place when a raycast from a user touch hits a plane.
/// </summary>
public GameObject AndyPlanePrefab;
/// <summary>
/// A model to place when a raycast from a user touch hits a feature point.
/// </summary>
public GameObject AndyPointPrefab;
/// <summary>
/// A gameobject parenting UI for displaying the "searching for planes" snackbar.
/// </summary>
public GameObject SearchingForPlaneUI;
/// <summary>
/// The rotation in degrees need to apply to model when the Andy model is placed.
/// </summary>
private const float k_ModelRotation = 180.0f;
/// <summary>
/// A list to hold all planes ARCore is tracking in the current frame. This object is used across
/// the application to avoid per-frame allocations.
/// </summary>
private List<DetectedPlane> m_AllPlanes = new List<DetectedPlane>();
/// <summary>
/// True if the app is in the process of quitting due to an ARCore connection error, otherwise false.
/// </summary>
private bool m_IsQuitting = false;
/// <summary>
/// The Unity Update() method.
/// </summary>
void Start()
{
StartCoroutine(DownloadAndCache());
}
IEnumerator DownloadAndCache()
{
// Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
using (WWW www = WWW.LoadFromCacheOrDownload(BundleURL, version))
{
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
GameObject testing = bundle.LoadAsset(AssetName) as GameObject;
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
I've declared all my variables and managed to get the Prefab to load up to this point ^^^^^
public void Update()
{
_UpdateApplicationLifecycle();
// Hide snackbar when currently tracking at least one plane.
Session.GetTrackables<DetectedPlane>(m_AllPlanes);
bool showSearchingUI = true;
for (int i = 0; i < m_AllPlanes.Count; i++)
{
if (m_AllPlanes[i].TrackingState == TrackingState.Tracking)
{
showSearchingUI = false;
break;
}
}
SearchingForPlaneUI.SetActive(showSearchingUI);
// If the player has not touched the screen, we are done with this update.
Touch touch;
if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
{
return;
}
// Raycast against the location the player touched to search for planes.
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
TrackableHitFlags.FeaturePointWithSurfaceNormal;
if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
{
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
This is where it loads the Andy prefabs, what I would like to do is swap the andy prefab out for the asset bundle
// Choose the Andy model for the Trackable that got hit.
GameObject prefab;
if (hit.Trackable is FeaturePoint)
{
prefab = AndyPlanePrefab;
}
else
{
prefab = AndyPointPrefab;
}
// Instantiate Andy model at the hit pose.
var andyObject = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
// Compensate for the hitPose rotation facing away from the raycast (i.e. camera).
andyObject.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
// Create an anchor to allow ARCore to track the hitpoint as understanding of the physical
// world evolves.
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
// Make Andy model a child of the anchor.
andyObject.transform.parent = anchor.transform;
}
}
}
/// <summary>
/// Check and update the application lifecycle.
/// </summary>
private void _UpdateApplicationLifecycle()
{
// Exit the app when the 'back' button is pressed.
if (Input.GetKey(KeyCode.Escape))
{
Application.Quit();
}
// Only allow the screen to sleep when not tracking.
if (Session.Status != SessionStatus.Tracking)
{
const int lostTrackingSleepTimeout = 15;
Screen.sleepTimeout = lostTrackingSleepTimeout;
}
else
{
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
if (m_IsQuitting)
{
return;
}
// Quit if ARCore was unable to connect and give Unity some time for the toast to appear.
if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
{
_ShowAndroidToastMessage("Camera permission is needed to run this application.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
else if (Session.Status.IsError())
{
_ShowAndroidToastMessage("ARCore encountered a problem connecting. Please start the app again.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
}
/// <summary>
/// Actually quit the application.
/// </summary>
private void _DoQuit()
{
Application.Quit();
}
/// <summary>
/// Show an Android toast message.
/// </summary>
/// <param name="message">Message string to show in the toast.</param>
private void _ShowAndroidToastMessage(string message)
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
if (unityActivity != null)
{
AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
AndroidJavaObject toastObject = toastClass.CallStatic<AndroidJavaObject>("makeText", unityActivity,
message, 0);
toastObject.Call("show");
}));
}
}
}
}
My plan is to change the URL dynamically as thats just a public variable so that I can load a different prefab once the app is running, then change the url and load a different prefab.
Any help, advice greatly appreciated.

Oculus and Unity: grab object makes avatar fall through the floor?

I just downloaded the basic Oculus sample framework for Unity (I'm on 2018.2) and am trying to combine the TeleportAvatar and AvatarWithGrab scenes - to have a teleporting avatar able to grab objects.
All is well - I dragged an object with OVR Grabbable script (below) into the teleport scene, added OVRGrabbers to the avatar object and hit play. I can successfully pick up the object after teleporting, etc but for some reason after interacting with grabbable object a while my character falls through floor (maybe teleports below floor?).
I even added a new floor to be sure there was a box collider to prevent falling; however, this had no effect.
I looked for any overlap between the controls and even turning off teleport, but the grabbable object script is causing the fall. Why is this?
Doing the grabbing motion with right hand (teleporting hand) doesn't cause any issues if I'm not near a grab object.
/// <summary>
/// An object that can be grabbed and thrown by OVRGrabber.
/// </summary>
public class OVRGrabbable : MonoBehaviour
{
[SerializeField]
protected bool m_allowOffhandGrab = true;
[SerializeField]
protected bool m_snapPosition = false;
[SerializeField]
protected bool m_snapOrientation = false;
[SerializeField]
protected Transform m_snapOffset;
[SerializeField]
protected Collider[] m_grabPoints = null;
protected bool m_grabbedKinematic = false;
protected Collider m_grabbedCollider = null;
protected OVRGrabber m_grabbedBy = null;
/// <summary>
/// If true, the object can currently be grabbed.
/// </summary>
public bool allowOffhandGrab
{
get { return m_allowOffhandGrab; }
}
/// <summary>
/// If true, the object is currently grabbed.
/// </summary>
public bool isGrabbed
{
get { return m_grabbedBy != null; }
}
/// <summary>
/// If true, the object's position will snap to match snapOffset when grabbed.
/// </summary>
public bool snapPosition
{
get { return m_snapPosition; }
}
/// <summary>
/// If true, the object's orientation will snap to match snapOffset when grabbed.
/// </summary>
public bool snapOrientation
{
get { return m_snapOrientation; }
}
/// <summary>
/// An offset relative to the OVRGrabber where this object can snap when grabbed.
/// </summary>
public Transform snapOffset
{
get { return m_snapOffset; }
}
/// <summary>
/// Returns the OVRGrabber currently grabbing this object.
/// </summary>
public OVRGrabber grabbedBy
{
get { return m_grabbedBy; }
}
/// <summary>
/// The transform at which this object was grabbed.
/// </summary>
public Transform grabbedTransform
{
get { return m_grabbedCollider.transform; }
}
/// <summary>
/// The Rigidbody of the collider that was used to grab this object.
/// </summary>
public Rigidbody grabbedRigidbody
{
get { return m_grabbedCollider.attachedRigidbody; }
}
/// <summary>
/// The contact point(s) where the object was grabbed.
/// </summary>
public Collider[] grabPoints
{
get { return m_grabPoints; }
}
/// <summary>
/// Notifies the object that it has been grabbed.
/// </summary>
virtual public void GrabBegin(OVRGrabber hand, Collider grabPoint)
{
m_grabbedBy = hand;
m_grabbedCollider = grabPoint;
gameObject.GetComponent<Rigidbody>().isKinematic = true;
}
/// <summary>
/// Notifies the object that it has been released.
/// </summary>
virtual public void GrabEnd(Vector3 linearVelocity, Vector3 angularVelocity)
{
Rigidbody rb = gameObject.GetComponent<Rigidbody>();
rb.isKinematic = m_grabbedKinematic;
rb.velocity = linearVelocity;
rb.angularVelocity = angularVelocity;
m_grabbedBy = null;
m_grabbedCollider = null;
}
void Awake()
{
if (m_grabPoints.Length == 0)
{
// Get the collider from the grabbable
Collider collider = this.GetComponent<Collider>();
if (collider == null)
{
throw new ArgumentException("Grabbables cannot have zero grab points and no collider -- please add a grab point or collider.");
}
// Create a default grab point
m_grabPoints = new Collider[1] { collider };
}
}
protected virtual void Start()
{
m_grabbedKinematic = GetComponent<Rigidbody>().isKinematic;
}
void OnDestroy()
{
if (m_grabbedBy != null)
{
// Notify the hand to release destroyed grabbables
m_grabbedBy.ForceRelease(this);
}
}
}

Monogame fixed moving model disappears

So I'm trying to create an interactive environment using a 3D model. I have the model and camera moving on a fixed Z-axis increment but after 3 or so seconds the model just disappears. Not sure what's happening, help is very appreciated.
My Game code is posted below.
namespace model_viewer
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//Loads the ship
Model Ship;
//Moves the ship and the camera together
float moveCamera;
float moveShip;
//moves the ship in the user's direction
float keyMoveX;
float keyMoveY;
public Game1()
: base()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
moveCamera = -3;
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
Ship = Content.Load<Model>("Graphics/Ship");
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
moveCamera += 0.005f;
moveShip += 0.005f;
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
Matrix proj = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1, 0.1f, 10000.0f);
Matrix view = Matrix.CreateLookAt(
new Vector3(0, 0, moveCamera),
Vector3.Zero,
Vector3.Up);
float scale = 1.0f / Ship.Meshes[0].BoundingSphere.Radius;
Matrix world = Matrix.CreateScale(scale) * Matrix.CreateRotationY(MathHelper.ToRadians(180)) * Matrix.CreateTranslation(new Vector3(0, 0, moveShip));
Ship.Draw(world, view, proj);
// TODO: Add your drawing code here
base.Draw(gameTime);
}
}
}
I found the answer, my 'view' matrix was targeting a point that wasn't moving with my model and was rotating to view the point.

How to close a TCP connection by port?

I would like to close an existing connection between to application running on my server.
If you have a suggestion please reply on how to program this, you will be appreciated.
Note that: TCPView application can close the connection exactly as I need, but I would like to run it as a console application or other command line.
Finally I found the solution for my request.
Credit goes to CSharpFriends.com, now migrated to debugging.com.
The following windows API should be used:
//API to get list of connections
[DllImport("iphlpapi.dll")]
private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);
//API to change status of connection
[DllImport("iphlpapi.dll")]
private static extern int SetTcpEntry(IntPtr pTcprow);
//Convert 16-bit value from network to host byte order
[DllImport("wsock32.dll")]
private static extern int ntohs(int netshort);
//Convert 16-bit value back again
[DllImport("wsock32.dll")]
private static extern int htons(int netshort);
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
namespace ConnectionManager
{
class Disconnector
{
}
public class Starter
{
public static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("Disconnect IP1 [IP2 [IP3 [IPn]]]");
Console.WriteLine("");
Console.WriteLine("Connections up now:");
string[] cons = Disconnecter.Connections(Disconnecter.State.Established);
foreach (string s in cons)
{
Console.WriteLine(s);
}
}
else
{
foreach (string s in args)
{
Disconnecter.CloseLocalIP(s);
Disconnecter.CloseRemoteIP(s);
}
}
}
}
public class Disconnecter
{
/// <summary>
/// Enumeration of the states
/// </summary>
public enum State
{
/// <summary> All </summary>
All = 0,
/// <summary> Closed </summary>
Closed = 1,
/// <summary> Listen </summary>
Listen = 2,
/// <summary> Syn_Sent </summary>
Syn_Sent = 3,
/// <summary> Syn_Rcvd </summary>
Syn_Rcvd = 4,
/// <summary> Established </summary>
Established = 5,
/// <summary> Fin_Wait1 </summary>
Fin_Wait1 = 6,
/// <summary> Fin_Wait2 </summary>
Fin_Wait2 = 7,
/// <summary> Close_Wait </summary>
Close_Wait = 8,
/// <summary> Closing </summary>
Closing = 9,
/// <summary> Last_Ack </summary>
Last_Ack = 10,
/// <summary> Time_Wait </summary>
Time_Wait = 11,
/// <summary> Delete_TCB </summary>
Delete_TCB = 12
}
/// <summary>
/// Connection info
/// </summary>
private struct MIB_TCPROW
{
public int dwState;
public int dwLocalAddr;
public int dwLocalPort;
public int dwRemoteAddr;
public int dwRemotePort;
}
//API to get list of connections
[DllImport("iphlpapi.dll")]
private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);
//API to change status of connection
[DllImport("iphlpapi.dll")]
//private static extern int SetTcpEntry(MIB_TCPROW tcprow);
private static extern int SetTcpEntry(IntPtr pTcprow);
//Convert 16-bit value from network to host byte order
[DllImport("wsock32.dll")]
private static extern int ntohs(int netshort);
//Convert 16-bit value back again
[DllImport("wsock32.dll")]
private static extern int htons(int netshort);
/// <summary>
/// Testexample
/// </summary>
public static void TEST()
{
Console.WriteLine("Not Working Yet!!!");
//string[] ret = Connections(State.All);
//foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
//System.Diagnostics.Debug.WriteLine("----------------------------");
//CloseRemotePort(1863);
//CloseRemotePort(80);
//ret = Connections(State.All);
//foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
}
/// <summary>
/// Close all connection to the remote IP
/// </summary>
/// <param name="IP">IPen på remote PC</param>
public static void CloseRemoteIP(string IP)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (rows[i].dwRemoteAddr == IPStringToInt(IP))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Close all connections at current local IP
/// </summary>
/// <param name="IP"></param>
public static void CloseLocalIP(string IP)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (rows[i].dwLocalAddr == IPStringToInt(IP))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Closes all connections to the remote port
/// </summary>
/// <param name="port"></param>
public static void CloseRemotePort(int port)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (port == ntohs(rows[i].dwRemotePort))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Closes all connections to the local port
/// </summary>
/// <param name="port"></param>
public static void CloseLocalPort(int port)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (port == ntohs(rows[i].dwLocalPort))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Close a connection by returning the connectionstring
/// </summary>
/// <param name="connectionstring"></param>
public static void CloseConnection(string connectionstring)
{
try
{
//Split the string to its subparts
string[] parts = connectionstring.Split('-');
if (parts.Length != 4) throw new Exception("Invalid connectionstring - use the one provided by Connections.");
string[] loc = parts[0].Split(':');
string[] rem = parts[1].Split(':');
string[] locaddr = loc[0].Split('.');
string[] remaddr = rem[0].Split('.');
//Fill structure with data
MIB_TCPROW row = new MIB_TCPROW();
row.dwState = 12;
byte[] bLocAddr = new byte[] { byte.Parse(locaddr[0]), byte.Parse(locaddr[1]), byte.Parse(locaddr[2]), byte.Parse(locaddr[3]) };
byte[] bRemAddr = new byte[] { byte.Parse(remaddr[0]), byte.Parse(remaddr[1]), byte.Parse(remaddr[2]), byte.Parse(remaddr[3]) };
row.dwLocalAddr = BitConverter.ToInt32(bLocAddr, 0);
row.dwRemoteAddr = BitConverter.ToInt32(bRemAddr, 0);
row.dwLocalPort = htons(int.Parse(loc[1]));
row.dwRemotePort = htons(int.Parse(rem[1]));
//Make copy of the structure into memory and use the pointer to call SetTcpEntry
IntPtr ptr = GetPtrToNewObject(row);
int ret = SetTcpEntry(ptr);
if (ret == -1) throw new Exception("Unsuccessful");
if (ret == 65) throw new Exception("User has no sufficient privilege to execute this API successfully");
if (ret == 87) throw new Exception("Specified port is not in state to be closed down");
if (ret != 0) throw new Exception("Unknown error (" + ret + ")");
}
catch (Exception ex)
{
throw new Exception("CloseConnection failed (" + connectionstring + ")! [" + ex.GetType().ToString() + "," + ex.Message + "]");
}
}
/// <summary>
/// Gets all connections
/// </summary>
/// <returns></returns>
public static string[] Connections()
{
return Connections(State.All);
}
/// <summary>
/// Gets a connection list of connections with a defined state
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public static string[] Connections(State state)
{
MIB_TCPROW[] rows = getTcpTable();
ArrayList arr = new ArrayList();
foreach (MIB_TCPROW row in rows)
{
if (state == State.All || state == (State)row.dwState)
{
string localaddress = IPIntToString(row.dwLocalAddr) + ":" + ntohs(row.dwLocalPort);
string remoteaddress = IPIntToString(row.dwRemoteAddr) + ":" + ntohs(row.dwRemotePort);
arr.Add(localaddress + "-" + remoteaddress + "-" + ((State)row.dwState).ToString() + "-" + row.dwState);
}
}
return (string[])arr.ToArray(typeof(System.String));
}
//The function that fills the MIB_TCPROW array with connectioninfos
private static MIB_TCPROW[] getTcpTable()
{
IntPtr buffer = IntPtr.Zero; bool allocated = false;
try
{
int iBytes = 0;
GetTcpTable(IntPtr.Zero, ref iBytes, false); //Getting size of return data
buffer = Marshal.AllocCoTaskMem(iBytes); //allocating the datasize
allocated = true;
GetTcpTable(buffer, ref iBytes, false); //Run it again to fill the memory with the data
int structCount = Marshal.ReadInt32(buffer); // Get the number of structures
IntPtr buffSubPointer = buffer; //Making a pointer that will point into the buffer
buffSubPointer = (IntPtr)((int)buffer + 4); //Move to the first data (ignoring dwNumEntries from the original MIB_TCPTABLE struct)
MIB_TCPROW[] tcpRows = new MIB_TCPROW[structCount]; //Declaring the array
//Get the struct size
MIB_TCPROW tmp = new MIB_TCPROW();
int sizeOfTCPROW = Marshal.SizeOf(tmp);
//Fill the array 1 by 1
for (int i = 0; i < structCount; i++)
{
tcpRows[i] = (MIB_TCPROW)Marshal.PtrToStructure(buffSubPointer, typeof(MIB_TCPROW)); //copy struct data
buffSubPointer = (IntPtr)((int)buffSubPointer + sizeOfTCPROW); //move to next structdata
}
return tcpRows;
}
catch (Exception ex)
{
throw new Exception("getTcpTable failed! [" + ex.GetType().ToString() + "," + ex.Message + "]");
}
finally
{
if (allocated) Marshal.FreeCoTaskMem(buffer); //Free the allocated memory
}
}
private static IntPtr GetPtrToNewObject(object obj)
{
IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, false);
return ptr;
}
//Convert an IP string to the INT value
private static int IPStringToInt(string IP)
{
if (IP.IndexOf(".") < 0) throw new Exception("Invalid IP address");
string[] addr = IP.Split('.');
if (addr.Length != 4) throw new Exception("Invalid IP address");
byte[] bytes = new byte[] { byte.Parse(addr[0]), byte.Parse(addr[1]), byte.Parse(addr[2]), byte.Parse(addr[3]) };
return BitConverter.ToInt32(bytes, 0);
}
//Convert an IP integer to IP string
private static string IPIntToString(int IP)
{
byte[] addr = System.BitConverter.GetBytes(IP);
return addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3];
}
}
}
close(fd); /* comment to reach minimum size for an answer */