With the new MRTK2 I'm looking to disable spatial mapping after we are done using it to place GameObjects. I'm stuck on what exactly to call in the namespace or on the service to do this at run time.
I've tried: MixedRealityToolkit.SpatialAwarenessSystem.SuspendObservers();
This has no effect. I could disable the entire "Spatial Awareness System" GameObject, but this would be a hack.
What I need is the proper call that would disable the system entirely so that resources are freed up when it is no longer useful?
Additionally, a little insight into how we are to access the service system correctly would be of great help.
You can use the following code to disable/enable the spatial awareness system:
if (disable)
{
// disable
MixedRealityToolkit.SpatialAwarenessSystem.Disable();
}
else
{
// enable
MixedRealityToolkit.SpatialAwarenessSystem.Enable()
}
You can use the following code to enable/disable just the visualization but keep the colliders on:
foreach(var observer in MixedRealityToolkit.SpatialAwarenessSystem.GetObservers())
{
var meshObserver = observer as IMixedRealitySpatialAwarenessMeshObserver;
if (meshObserver != null)
{
meshObserver.DisplayOption = SpatialAwarenessMeshDisplayOptions.None;
}
}
You can read more documentation about the Spatial Awareness system in MRTK on the mrtk github.io site at Spatial Awareness System Usage guide
I would have expected the SuspendObservers() method to result in no new meshes being displayed. Do you see the meshes changing after suspending?
It is by design for the meshes to remain visible until the application explicitly sets their visibility to None via the IMixedRealitySpatialAwarenessMeshObserver.DisplayOption property.
Thanks!
Note the previous answer doesn't work due to recent changes to the MRTK framework.
Link for SpatialAwareness DataProvidershere
Code pasted from said link:
IMixedRealityDataProviderAccess dataProviderAccess =
CoreServices.SpatialAwarenessSystem as IMixedRealityDataProviderAccess;
if (dataProviderAccess != null)
{
IReadOnlyList<IMixedRealitySpatialAwarenessMeshObserver> observers =
dataProviderAccess.GetDataProviders<IMixedRealitySpatialAwarenessMeshObserver>();
foreach (IMixedRealitySpatialAwarenessMeshObserver observer in observers)
{
// Set the mesh to use the occlusion material
observer.DisplayOption = SpatialMeshDisplayOptions.Occlusion;
}
}
[AddComponentMenu("Scripts/MRTK/Examples/ClearSpatialObservations")]
public class ClearSpatialObservations : MonoBehaviour
{
/// <summary>
/// Indicates whether observations are to be cleared (true) or if the observer is to be resumed (false).
/// </summary>
private bool clearObservations = true;
/// <summary>
/// Toggles the state of the observers.
/// </summary>
public void ToggleObservers()
{
var spatialAwarenessSystem = CoreServices.SpatialAwarenessSystem;
if (spatialAwarenessSystem != null)
{
if (clearObservations)
{
spatialAwarenessSystem.SuspendObservers();
spatialAwarenessSystem.ClearObservations();
clearObservations = false;
}
else
{
spatialAwarenessSystem.ResumeObservers();
clearObservations = true;
}
}
}
}
Related
I'm learning how to program and I feel that I'm always trapped with this kind of loops problems.
the question is, what would be the best way to get out of the if when the grouped bool is always true on Update (every frame). I need to execute the EUREKA only once.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GroupedWordsEyes : MonoBehaviour
{
void Update()
{
//Check if words are grouped
bool grouped = CompareTags_Word1.colliding == true;
if (grouped)
{
Debug.Log("EUREKAAAA!");
//get out of the loop!
}
}
}
It sounds like you want that Update is only called until the condition matches the first time.
You can simply disable that component by setting enabled to false.
This way Update is no longer called by Unity.
public class GroupedWordsEyes : MonoBehaviour
{
void Update()
{
//Check if words are grouped
if (CompareTags_Word1.colliding)
{
Debug.Log("EUREKAAAA!");
enabled = false;
}
}
}
It seems like you want the code within the if to execute only when "colliding" changes.
Then you need to remember the previous value and check for changes:
EDIT changed code based on comments by OP
public class GroupedWordsEyes : MonoBehaviour
{
private bool previousGrouped = false; // assume that at first there is no collision
void Update()
{
//Check if words are grouped
bool grouped = CompareTags_Word1.colliding == true;
if (grouped != previousGrouped )
{
// always remember a change
previousGrouped = grouped;
// only when just collided
if (grouped)
{
Debug.Log("EUREKAAAA!");
}
}
}
}
EDIT: Updating answer as I misunderstood the question.
You've got several options and it entirely depends on how you've architected.
One option is to deactivate (or even completely destory) the component. After you've done the one thing you need to do, call this.enabled = false - this will disable the component and no scripts will be run. This depends on architecture as this will also disable any other functions or child components attached to this one. You can mitigate this by ensuring this script only contains specific pieces that you want to be able to disable.
Create a flag that indicates whether the action has already been done.
if (grouped && !hasDoneEureka)
{
// do the thing
hasDoneEureka = true;
}
Note that this will ensure you only run what you need to once, but probably isn't optimal since while it won't "do the thing" every time, it will CHECK every frame.
I have a Unity project in which various Cords are stretched between various Hooks. The player can grab one end of a cord from its hook, carry it, and attach it to another. As part of this functionality, the hook needs to keep track of which cords are attached to it, and when the player tries to attach a new one, check that doing so won't 'disappear' the cord (ie. they're not hooking both ends to the same place, and the cord won't merge with another by being attached to the same hooks at both ends).
Each Cord object has start and end properties that refer to the Hooks to which it's attached. Currently, I've been keeping track with a List:
public class Hook : MonoBehaviour {
List<Cord> attached = new List<Cord>();
public void Attach(Cord c) {
if (!ConflictTest(c))
attached.Add(c);
}
public void Detach(Cord c) {
attached.Remove(c);
}
bool ConflictTest(Cord toAttach) {
foreach (Cord c in attached) {
// canonically, a cord is grabbed by its 'end', so we only check its 'start'
if (c.start == toAttach.start || c.end == toAttach.start)
return true;
}
return false;
}
}
I realised that this linear search in ConflictTest(), which is actually executed at every OnMouseEnter() and OnMouseDown() isn't ideal. I would like to change the data structure of attached to a HashSet, but is there a way I can set things up so I can do the test in terms of the HashSet's Contains() method (ie. attached.Contains(toAttach.start))? Since I need to refer to the start and end properties of each member of the set, it seems I either need to a separate set for each property (but then how do I coordinate additions and removals?) or to somehow allow the properties to be keys. Any ideas?
One way to do this is to expand your List<Cord> into a Dictionary<Hook, Cord>, where the key represents the Hook end point of the value Cord that is not the current one. This Hook recorded is guaranteed to be unique since a Hook will only ever have at most one Cord validly connecting it to another Hook. Here's how this might look (extra commenting for clarity):
public class Hook : MonoBehaviour {
// Stores a Cord and its "other" Hook
Dictionary<Hook, Cord> attached = new Dictionary<Hook, Cord>();
// Add a Cord by retrieving its "other" Hook and using it as a key
public void Attach(Cord c) {
if (!ConflictTest(c)){
attached.Add(GetOtherHook(c), c);
}
}
// Remove a cord based on its "other" Hook
public void Detach(Cord c) {
attached.Remove(GetOtherHook(c));
}
// Determine whether current connections contain this Cord's "other" Hook
bool ConflictTest(Cord toAttach) {
return attached.ContainsKey(GetOtherHook(toAttach));
}
// Retrieves the "other" (non-current Hook) a cord is attached to
private Hook GetOtherHook(Cord c) {
return c.end != this ? c.end : c.start;
}
}
Hope this helps! Let me know if you have any questions.
I'm writing a simple game, like tic tac toe (only mine is bigger). The game play is simple: my turn, check if won, bot's turn, check if won. I have simple UI and API that uses Domain Entites (that's not important now). So when user's moves, API will update the board, will know that next move is bot's move, so will do it and... has to notify UI. Here is my problem.
My question is:
How to notify UI about bot's move? I mean, to keep it simple but stick to the best programming practices.
My first thought was to create an event in GameAPI class. Is that good idea? Today will all new stuff, C# 6, etc.. I'm not sure:/ Right now UI is WinForms, but I would like to use this API in other UIs, like WPF or even mobile. Here is my simplified code of UI:
EDIT: Right now I'm talking about single player game. Both UI and API is a Client. There will be multiplayer through central server in next step, but right now, single player.
public partial class Form1 : Form
{
private GameAPI api;
public Form1()
{
InitializeComponent();
api = new GameAPI();
}
private void boardClick(object sender, EventArgs e)
{
Field field = GetClickedField(e);
MoveResult result = api.MakeMove(clickedColumn);
if (result != null && result.Row >= 0)
{
MessageBox.Show(result.Row + "," + clickedColumn);
if (result.IsConnected)
{
MessageBox.Show("Success!");
}
}
}
}
and API:
public class GameAPI
{
public IGame CurrentGame { get; set; }
public void CreateGame(GameType type)
{
CurrentGame = new SinglePlayerGame();
}
public Result Move(int column)
{
if (CurrentGame == null) return null;
Player player = CurrentGame.GetNextPlayer();
if (player.Type == PlayerType.Human) return CurrentGame.Move(column, player.Id);
}
public Result MoveBot()
{
// Simulate Bot's move...
}
}
My first thought was to create an event in GameAPI class. Is that good idea?
Yes, why not? Let take for example the modern UI frameworks data binding. The key point of making data binging work is providing a property change notification (read - event) when some property value of the object is modified. Usually that's implemented via IPropertyNotifyChanged interface, which is simply a polymorphic way of declaring support for PropertyChanged event. This way, if you set the object property via code, the UI updates automatically. Hope you see the similarity with your case - the API does something and raises an event, UI (being attached handler to that event as some earlier point) receives the event and updates accordingly.
I am trying to edit a couple of settings in SolidWork's options menu through a C# program I wrote. The code is below:
using System;
using System.IO;
using SldWorks;
using SwConst;
static void Main(string[] args)
{
SldWorks.SldWorks swApp;
swApp = new SldWorks.SldWorks();
swApp.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swSingleCommandPerPick, true); /// Single command per pick
swApp.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swEditMacroAfterRecord, true); /// Automatically edit macro after recording
swApp.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swUserEnableFreezeBar, true); /// Enable Freeze bar
Console.WriteLine("Settings applied");
}
The intended purpose of this program is to toggle those three options (checkboxes) to true. So far this does not work at all. The options still stay the same even after I run the program. Am I missing anything or is my code wrong?
Try this (for example, mouse speed):
//View rotation - Mouse speed
bool boolstatus = swApp.SetUserPreferenceIntegerValue((int)swUserPreferenceIntegerValue_e.swViewRotationMouseSpeed, 56);
Thanks to Solidworks API:
http://help.solidworks.com/2012/English/api/sldworksapi/Get_and_Set_User_Preferences_Example_CSharp.htm
Try using the following to get the COM object while SolidWorks is running.
Try
{
SldWorks swApp = (SldWorks)Marshal.GetActiveObject("SldWorks.Application");
swApp.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swSingleCommandPerPick, true); /// Single command per pick
swApp.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swEditMacroAfterRecord, true); /// Automatically edit macro after recording
swApp.SetUserPreferenceToggle((int)swUserPreferenceToggle_e.swUserEnableFreezeBar, true); /// Enable Freeze bar
Console.WriteLine("Settings applied");
}
catch()
{
Console.WriteLine("Failed to get SolidWorks");
}
I recently have released a small application with a trial to the Windows Phone Marketplace, but my application is not working as expected. I have followed http://code.msdn.microsoft.com/Trial-Experience-Sample-c58f21af when making my trial, so that I can call the current 'LicenseInformation' state and block a feature or not depending on the current application's license state. According to the sample application, The LicenseMode property returns a value from the LicenseModes enum (Full, MissingOrRevoked, or Trial) so that your app code needs to check only a single value. There’s also a convenient Boolean IsFull property. Whenever the license mode has changed, or it is likely to have changed, TrialExperienceHelper raises its LicenseChanged event and your app code can handle that event to query LicenseMode or IsFull again. Then, your app can control the availability of features, ads, and your Buy UI as needed.
In my application I have a click event in which I would like to perform an action based on the current LicenseInformation state and upon a count (the count being the number of times an image is saved with particular aspects applied).
Settings.SavedCount.Value records the number of times the save button is clicked, and if the count is above 100 and the application is in trial mode I would like to ask the user if they would like to upgrade, otherwise if the count is less than 100 while the application is in trial mode or if the license is in full mode then the user is allowed to continue with the save process (hopefully that makes logical sense).
void saveButton_Click(object sender, EventArgs e)
{
Settings.SavedCount.Value += 1;
if (TrialViewModel.LicenseModeString == "Trial" && Settings.SavedCount.Value > 100)
{
MessageBoxResult result = MessageBox.Show("You have saved over 100 items! Would you like to continue?", "Congratulations!", MeesageBoxButton.OKCancel);
switch (result)
{
case MessageBoxResult.OK:
//A command takes a parameter so pass null
TrialViewModel.BuyCommand.Execute(null);
break;
case MessageBoxResult.Cancel:
editPagePivotControl.SelectedIndex = 0;
break;
}
}
else if ((TrialViewModel.LicenseModeString == "Trial" && Settings.SavedCount.Value <= 100) || (TrialViewModel.LicenseModeString == "Full")
{
PerformSaveAsync();
}
}
}
When testing in Debug mode and with the sample implementation from the msdn website, the Trial and Full implementations worked properly, and then when in Release mode the license was listed as MissingOrRevoked which I assumed would be called correctly in the marketplace. What is ACTUALLY occuring when i have downloaded the app in the marketplace under both trial and full modes is that the PerformSaveAsync() method is never being called (which ultimately saves the new image and disables the button) and I can use the new image elsewhere. I am having trouble figuring out what the issue may be?
EDIT** In researching I came across http://msdn.microsoft.com/en-us/library/aa691310(v=vs.71).aspx which states that The operation x && y corresponds to the operation x & y, except that y is evaluated only if x is true. and `•The operation x || y corresponds to the operation x | y, except that y is evaluated only if x is false/' . Would this be the cause of the issues? If so, how should they be fixed?
Edit 2** Addtion of TrialViewModel and TrialExperienceHelper.cs for additional info
TrialViewModel
TrialViewModel
#region fields
private RelayCommand buyCommand;
#endregion fields
#region constructors
public TrialViewModel()
{
// Subscribe to the helper class's static LicenseChanged event so that we can re-query its LicenseMode property when it changes.
TrialExperienceHelper.LicenseChanged += TrialExperienceHelper_LicenseChanged;
}
#endregion constructors
#region properties
/// <summary>
/// You can bind the Command property of a Button to BuyCommand. When the Button is clicked, BuyCommand will be
/// invoked. The Button will be enabled as long as BuyCommand can execute.
/// </summary>
public RelayCommand BuyCommand
{
get
{
if (this.buyCommand == null)
{
// The RelayCommand is constructed with two parameters - the action to perform on invocation,
// and the condition under which the command can execute. It's important to call RaiseCanExecuteChanged
// on a command whenever its can-execute condition might have changed. Here, we do that in the TrialExperienceHelper_LicenseChanged
// event handler.
this.buyCommand = new RelayCommand(
param => TrialExperienceHelper.Buy(),
param => TrialExperienceHelper.LicenseMode == TrialExperienceHelper.LicenseModes.Trial);
}
return this.buyCommand;
}
}
public string LicenseModeString
{
get
{
return TrialExperienceHelper.LicenseMode.ToString()/* + ' ' + AppResources.ModeString*/;
}
}
#endregion properties
#region event handlers
// Handle TrialExperienceHelper's LicenseChanged event by raising property changed notifications on the
// properties and commands that
internal void TrialExperienceHelper_LicenseChanged()
{
this.RaisePropertyChanged("LicenseModeString");
this.BuyCommand.RaiseCanExecuteChanged();
}
#endregion event handlers
TrialExperienceHelper.cs
#region enums
/// <summary>
/// The LicenseModes enumeration describes the mode of a license.
/// </summary>
public enum LicenseModes
{
Full,
MissingOrRevoked,
Trial
}
#endregion enums
#region fields
#if DEBUG
// Determines how a debug build behaves on launch. This field is set to LicenseModes.Full after simulating a purchase.
// Calling the Buy method (or navigating away from the app and back) will simulate a purchase.
internal static LicenseModes simulatedLicMode = LicenseModes.Trial;
#endif // DEBUG
private static bool isActiveCache;
private static bool isTrialCache;
#endregion fields
#region constructors
// The static constructor effectively initializes the cache of the state of the license when the app is launched. It also attaches
// a handler so that we can refresh the cache whenever the license has (potentially) changed.
static TrialExperienceHelper()
{
TrialExperienceHelper.RefreshCache();
PhoneApplicationService.Current.Activated += (object sender, ActivatedEventArgs e) => TrialExperienceHelper.
#if DEBUG
// In debug configuration, when the user returns to the application we will simulate a purchase.
OnSimulatedPurchase();
#else // DEBUG
// In release configuration, when the user returns to the application we will refresh the cache.
RefreshCache();
#endif // DEBUG
}
#endregion constructors
#region properties
/// <summary>
/// The LicenseMode property combines the active and trial states of the license into a single
/// enumerated value. In debug configuration, the simulated value is returned. In release configuration,
/// if the license is active then it is either trial or full. If the license is not active then
/// it is either missing or revoked.
/// </summary>
public static LicenseModes LicenseMode
{
get
{
#if DEBUG
return simulatedLicMode;
#else // DEBUG
if (TrialExperienceHelper.isActiveCache)
{
return TrialExperienceHelper.isTrialCache ? LicenseModes.Trial : LicenseModes.Full;
}
else // License is inactive.
{
return LicenseModes.MissingOrRevoked;
}
#endif // DEBUG
}
}
/// <summary>
/// The IsFull property provides a convenient way of checking whether the license is full or not.
/// </summary>
public static bool IsFull
{
get
{
return (TrialExperienceHelper.LicenseMode == LicenseModes.Full);
}
}
#endregion properties
#region methods
/// <summary>
/// The Buy method can be called when the license state is trial. the user is given the opportunity
/// to buy the app after which, in all configurations, the Activated event is raised, which we handle.
/// </summary>
public static void Buy()
{
MarketplaceDetailTask marketplaceDetailTask = new MarketplaceDetailTask();
marketplaceDetailTask.ContentType = MarketplaceContentType.Applications;
marketplaceDetailTask.Show();
}
/// <summary>
/// This method can be called at any time to refresh the values stored in the cache. We re-query the application object
/// for the current state of the license and cache the fresh values. We also raise the LicenseChanged event.
/// </summary>
public static void RefreshCache()
{
TrialExperienceHelper.isActiveCache = CurrentApp.LicenseInformation.IsActive;
TrialExperienceHelper.isTrialCache = CurrentApp.LicenseInformation.IsTrial;
TrialExperienceHelper.RaiseLicenseChanged();
}
private static void RaiseLicenseChanged()
{
if (TrialExperienceHelper.LicenseChanged != null)
{
TrialExperienceHelper.LicenseChanged();
}
}
#if DEBUG
private static void OnSimulatedPurchase()
{
TrialExperienceHelper.simulatedLicMode = LicenseModes.Full;
TrialExperienceHelper.RaiseLicenseChanged();
}
#endif // DEBUG
#endregion methods
#region events
/// <summary>
/// The static LicenseChanged event is raised whenever the value of the LicenseMode property has (potentially) changed.
/// </summary>
public static event LicenseChangedEventHandler LicenseChanged;
#endregion events
If your dev builds work and the only difference is with the app being published via the store then I think it's very unlikely to be your logic.
When you submitted the app, are you sure you checked the option to be able to use the trial functionality in the app?
If you didn't check this then it won't work in a released app.
Regarding your edit, I don't see any problem with your condition, your quote is just that the operator is lazy, evaluating only what is needed to determine the result (for example when you do x&& y if x is false, x&& false=> false and x&& true==false which is the same result so it don't evaluate y).
Also like I said in your previous question even the windows phone 7 api still work on windows phone 8 so if you are creating code for both platform there is probably no need to use the new api specifically for wp8.
In this code I don't see any problem but why do you convert the LicenseModes enum to string, using the enum will add some type safety and prevent you to do some invalid comparison.
The only problem is where you set LicenseModeString or a problem inside PerformSaveAsync?