-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathProgram.cs
More file actions
360 lines (308 loc) · 13.5 KB
/
Program.cs
File metadata and controls
360 lines (308 loc) · 13.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
// SPDX-License-Identifier: MIT
// The authors below grant copyright rights under the MIT license:
// Copyright (c) 2019-2025 Nick Klingensmith
// Copyright (c) 2023-2025 Qualcomm Technologies, Inc.
using RAZR_PointCRep.Show;
using RAZR_PointCRep.Spatial_Anchor;
using RAZR_PointCRep.Tools;
using StereoKit;
using StereoKit.Framework;
using System;
using System.Diagnostics;
using System.Net.Http;
using static Android.Icu.Util.LocaleData;
using static RAZR_PointCRep.Spatial_Anchor.SpatialEntityFBExt;
public static class Program
{
// This is the starting scene, and can be overridden by passing
// -start <testname> via the CLI.
static string startTest = "welcome";
// The base settings we use for this test app. Some of these, like mode,
// are overridden, particularly when running tests.
static SKSettings settings = new SKSettings
{
appName = "StereoKit C#",
//blendPreference = DisplayBlend.Opaque,
//mode = AppMode.XR,
};
static Mesh floorMesh;
static Material floorMat;
static Pose windowDemoPose = new Pose(-0.6f, 0, -0.4f, Quat.LookDir(1, 0, 1));
static Sprite powerButton;
static SceneType sceneCategory = SceneType.Programs;
public static bool WindowDemoShow = false;
static Pose window2Pose = Matrix.TR(.5f, 0, -0.4f, Quat.LookDir(-1, 0, 1)).Pose;
public static SpatialEntityPoseHandler handler; //making it public static so i can access anchor pose outside of class
static void Main(string[] args)
{
// CLI arguments
bool headless = ParamPresent(args, "-headless");
MenuSort.IsTesting = ParamPresent(args, "-test");
MenuSort.MakeScreenshots = !ParamPresent(args, "-noscreens");
MenuSort.ScreenshotRoot = ParamVal(args, "-screenfolder", "../../../docs/img/screenshots");
MenuSort.GltfFolders = ParamVal(args, "-gltf", null); // "C:\\Tools\\glTF-Sample-Models-master\\2.0";
MenuSort.GltfScreenshotRoot = ParamVal(args, "-gltfscreenfolder", null);
MenuSort.TestSingle = ParamPresent(args, "-start");
startTest = ParamVal(args, "-start", startTest);
if (MenuSort.IsTesting)
{
settings.mode = headless ? AppMode.Offscreen : AppMode.Simulator;
settings.standbyMode = StandbyMode.None;
}
// OpenXR extensions need added before SK.Initialize, so does
// LogWindow for early log registration!
PassthroughFBExt stepper = SK.AddStepper(new PassthroughFBExt());
SpatialEntityFBExt spatialEntityStepper = SK.AddStepper(new SpatialEntityFBExt());
//SK.AddStepper<Win32PerformanceCounterExt>();
// Initialize StereoKit
if (!SK.Initialize(settings))
Environment.Exit(1);
Init();
int anchorNum = 0; //numbers of anchors currently initializes
Pose cubePose = new Pose(.4f, .05f, -0.4f);
Model cube = Model.FromMesh(
Mesh.GenerateCube(Vec3.One * 0.1f),
Material.UI);
bool boxVisbility = false;
//SK.Run(Step, MenuSort.Shutdown);
SK.Run(() =>
{
Step();
Guid? selectedAnchorId = null;
bool passthroughToggle = !stepper.Enabled;
UI.WindowBegin("Spatial Anchor Menu", ref window2Pose, new Vec2(30, 0) * U.cm);
UI.LayoutPushCut(UICut.Top, UI.LineHeight);
UI.Text("Make sure to initialize a spatial anchor before heading into any classes");
UI.LayoutPop();
if (stepper.Available)
{
if (UI.Toggle("Passthrough Toggle", ref passthroughToggle))
{
stepper.Enabled = !stepper.Enabled;
//Log.Info($"Passthrough is {(stepper.Enabled ? "ON" : "OFF")}");
}
}
else
{
Log.Info("Passthrough is not availible");
}
if(UI.Button("Anchor Visibility"))
{
if (boxVisbility)
{
boxVisbility = false;
}
else
{
boxVisbility = true;
}
Log.Info($"box visibility is {(boxVisbility ? "ON" : "OFF")}");
}
if (spatialEntityStepper.Available)
{
UI.Label("FB Spatial Entity EXT available!");
if (UI.Button("Create Anchor") && spatialEntityStepper.AnchorCount == 0) //Currently only allowing 1 spatial anchor at a time to be in the scene
{
anchorNum++;
// We will create the anchor at the location just in front of the window
Vec3 anchorPosition = cubePose.position + cubePose.Forward * .05f * 0.1f;
Pose pose = new Pose(anchorPosition);
//OR if you want it to perfectly match cube
//Pose pose = new Pose(anchorPosition, cubePose.orientation);
// We can optionally provide some callbacks for when the async operation either completes successfully or fails.
spatialEntityStepper.CreateAnchor(
pose,
(Guid newAnchorUuid) => Log.Info($"Async anchor creation success. New anchor created: Uuid:{newAnchorUuid}"),
() => Log.Info("Async anchor creation success failed :("));
}
UI.SameLine();
if (UI.Button("Load Anchor"))
{
spatialEntityStepper.LoadAllAnchors();
if(spatialEntityStepper.AnchorCount != 0 && anchorNum == 0)
{
anchorNum++;
}
Log.Info($"In Load, number of anchors is {anchorNum}");
}
UI.SameLine();
if (UI.Button("Erase Anchor"))
{
spatialEntityStepper.DeleteAllAnchors();
if(anchorNum != 0)
anchorNum = 0;
Log.Info($"In Erase, number of anchors is {anchorNum}");
}
// List all Anchors
UI.HSeparator();
UI.Label($"Anchors Loaded ({spatialEntityStepper.AnchorCount})");
foreach (var anchor in spatialEntityStepper.Anchors)
{
// Use a PushId to avoid button Id collisions
UI.PushId(anchor.Uuid.ToString());
UI.PanelBegin();
if (UI.Button($"{anchor.Uuid.ToString().Substring(0, 14)}..."))
{
if (selectedAnchorId == anchor.Uuid)
selectedAnchorId = null;
else
selectedAnchorId = anchor.Uuid;
}
UI.SameLine();
// Button to delete the selected anchor
if (UI.Button("Delete"))
{
spatialEntityStepper.DeleteAnchor(anchor.Uuid);
anchorNum--;
Log.Info($"In Delete number of anchors is {anchorNum}");
}
if (selectedAnchorId == anchor.Uuid)
{
UI.Label("XrSpace: " + anchor.XrSpace);
UI.Label("Located: " + anchor.LocateSuccess);
UI.Label(anchor.Pose.ToString());
}
UI.PanelEnd();
UI.PopId();
}
}
else
{
UI.Label("Spatial Anchor is not available :(");
}
UI.WindowEnd();
// Visualize all loaded spatial anchor
foreach (var anchor in spatialEntityStepper.Anchors)
{
handler = new SpatialEntityPoseHandler(anchor.Pose); //holding an object in the pose to be passed to any other scene
//handler.DrawAnchor(anchor.Pose, new Color(1, 0, 1)); //Normally you can't see the spatial anchor, this draws a cube at the exact location
if (boxVisbility)
{
handler.DrawAnchor(anchor.Pose, new Color(1, 0, 1));
}
}
UI.Handle("Cube", ref cubePose, cube.Bounds); //Makes cubePose moveable (Cube pose is a transformative pose so whereever you move the block it will move where the pose)(CONTEXT: cubePose is what is being used for initializing an anchor so this is a moveable anchor Pose)
cube.Draw(cubePose.ToMatrix()); //Drawing the cube
});
}
static void Init()
{
floorMat = new Material("Shaders/floor_shader.hlsl");
floorMat.Transparency = Transparency.Blend;
floorMat.QueueOffset = -11;
floorMat["radius"] = new Vec4(5, 10, 0, 0);
//floorMesh = Mesh.GeneratePlane(V.XY(40, 40), Vec3.Up, Vec3.Forward);
powerButton = Sprite.FromTex(Tex.FromFile("power.png"));
MenuSort.FindScenes();
MenuSort.SetClassActive(startTest);
MenuSort.Initialize();
if (MenuSort.IsTesting)
{
UI.EnableFarInteract = false;
Time.Scale = 0;
WindowDemoShow = false;
}
else
{
WindowDemoShow = true;
}
}
static void Step()
{
if (Input.Key(Key.Esc).IsJustActive())
SK.Quit();
// Only in flatscreen apps, there is the option to change the main
// camera's projection mode between perspective and orthographic.
if (SK.ActiveDisplayMode == DisplayMode.Flatscreen &&
Input.Key(Key.P).IsJustActive())
{
Renderer.Projection = Renderer.Projection == Projection.Perspective
? Projection.Ortho
: Projection.Perspective;
}
// If we can't see the world, we'll draw a floor!
//if (Device.DisplayBlend == DisplayBlend.Opaque)
//floorMesh.Draw(floorMat, World.HasBounds ? World.BoundsPose.ToMatrix() : Matrix.T(0, -1.5f, 0), Color.White);
CheckFocus();
MenuSort.Update();
WindowDemoStep();
}
static void WindowDemoStep()
{
// Skip the window if we're in test mode
if (!WindowDemoShow) return;
// Make a window for demo selection
UI.WindowBegin("Demos", ref windowDemoPose, new Vec2(50 * U.cm, 0));
// Display the different categories of tests we have available
for (int i = 0; i < (int)SceneType.MAX; i++)
{
SceneType category = (SceneType)i;
if (UI.Radio(category.ToString(), category == sceneCategory))
sceneCategory = category;
UI.SameLine();
}
// Display a quit button on the far right side
Vec2 exitSize = new Vec2(0.06f, 0);
UI.HSpace(UI.LayoutRemaining.x - exitSize.x);
if (UI.ButtonImg("Exit", powerButton, UIBtnLayout.Left, exitSize))
SK.Quit();
UI.HSeparator();
// Now display a nice, lined-up collection of buttons for each
// demo/test in the current category.
int start = 0;
float currWidthTotal = 0;
UISettings uiSettings = UI.Settings;
TextStyle style = UI.TextStyle;
float windowWidth = UI.LayoutRemaining.x;
for (int i = 0; i < MenuSort.Count(sceneCategory); i++)
{
float width = Text.Size(MenuSort.GetClassName(sceneCategory, i), style).x + uiSettings.padding * 2;
if (currWidthTotal + (width + uiSettings.gutter) > windowWidth)
{
float inflate = (windowWidth - (currWidthTotal - uiSettings.gutter + 0.0001f)) / (i - start);
for (int t = start; t < i; t++)
{
string name = MenuSort.GetClassName(sceneCategory, t);
float currWidth = Text.Size(name, style).x + uiSettings.padding * 2 + inflate;
if (UI.Radio(name, MenuSort.IsActive(sceneCategory, t), null, null, UIBtnLayout.None, new Vec2(currWidth, 0)))
MenuSort.SetClassActive(sceneCategory, t);
UI.SameLine();
}
start = i;
}
if (start == i)
currWidthTotal = 0;
currWidthTotal += width + uiSettings.gutter;
}
for (int t = start; t < MenuSort.Count(sceneCategory); t++)
{
string name = MenuSort.GetClassName(sceneCategory, t);
float currWidth = Text.Size(name, style).x + uiSettings.padding * 2;
if (UI.Radio(name, MenuSort.IsActive(sceneCategory, t), null, null, UIBtnLayout.None, new Vec2(currWidth, 0)))
MenuSort.SetClassActive(sceneCategory, t);
UI.SameLine();
}
UI.WindowEnd();
}
/// :CodeSample: AppFocus SK.AppFocus
/// ### Checking for changes in application focus
static AppFocus lastFocus = AppFocus.Hidden;
static void CheckFocus()
{
if (lastFocus != SK.AppFocus)
{
lastFocus = SK.AppFocus;
Log.Info($"App focus changed to: {lastFocus}");
}
}
/// :End:
static bool ParamPresent(string[] args, string param)
=> Array.IndexOf(args, param) != -1;
static string ParamVal(string[] args, string param, string defaultVal)
{
int index = Array.IndexOf(args, param);
return (index == -1 || index + 1 >= args.Length)
? defaultVal
: args[index + 1];
}
}