Skip to content

Commit ee379d3

Browse files
Merge pull request #15 from atomsk-0/controllerFix
Fix controller navigation on Horizontal mode
2 parents a75eff7 + 40d8d3f commit ee379d3

1 file changed

Lines changed: 128 additions & 14 deletions

File tree

Pages/AppsListPage.xaml.cs

Lines changed: 128 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ public AppsListPage()
149149
Loaded += OnAppListPage_Loaded;
150150
}
151151

152+
// TODO: Reimplement whole controller support, we need consider global control implementation
153+
// Read comments on line 189
154+
152155
private void OnAppListPage_Loaded(object sender, RoutedEventArgs e)
153156
{
154157
Gamepad.GamepadAdded += OnGamepadAdded;
@@ -182,6 +185,16 @@ private void OnGamepadAdded(object sender, Gamepad e)
182185

183186

184187
// can we make this work everywhere, like in content dialogs?
188+
189+
// probably, we should either look if it could be possible to implement some global
190+
// controller support what would work on all "UI Elements" like e.g all button elements would instantly
191+
// be able to work if A button is clicked on controller
192+
// if no, then we just have to implement manually on all pages/controllers... - atomsk
193+
194+
// Note for other devs:
195+
// This current controller support is just a "placeholder/experimental thing" until ^ above "global controller implementation" is done
196+
// Forgive for my shit math mess below even im not fully sure how it all works after long trial and error... im not so good at math
197+
// but at least it works
185198
private async void ListenGamepadInput()
186199
{
187200
while (gamepad != null)
@@ -224,20 +237,32 @@ private async void ListenGamepadInput()
224237
if ((moveRight || moveLeft || moveUp || moveDown) && inputProcessed)
225238
{
226239
inputProcessed = false;
227-
if (moveRight) this.DispatcherQueue.TryEnqueue(() => MoveFocus(1, 0));
228-
else if (moveLeft) this.DispatcherQueue.TryEnqueue(() => MoveFocus(-1, 0));
229-
else if (moveUp) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, -1));
230-
else if (moveDown) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, 1));
240+
if (App.Settings.Settings.AppViewIsHorizontalScrolling)
241+
{
242+
if (moveRight) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, 1));
243+
else if (moveLeft) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, -1));
244+
else if (moveUp) this.DispatcherQueue.TryEnqueue(() => MoveFocus(-1, 0));
245+
else if (moveDown) this.DispatcherQueue.TryEnqueue(() => MoveFocus(1, 0));
246+
247+
}
248+
else
249+
{
250+
if (moveRight) this.DispatcherQueue.TryEnqueue(() => MoveFocus(1, 0));
251+
else if (moveLeft) this.DispatcherQueue.TryEnqueue(() => MoveFocus(-1, 0));
252+
else if (moveUp) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, -1));
253+
else if (moveDown) this.DispatcherQueue.TryEnqueue(() => MoveFocus(0, 1));
254+
}
231255
}
232256

233257
await Task.Delay(100);
234258
}
235259
}
236260

261+
// Absolute mess, don't touch unless u understand math and could rewrite this better... because I do not
237262
private void MoveFocus(int xOffset, int yOffset)
238263
{
239264
bool firstInput = lastInput == 0;
240-
if (lastInput > DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - 10)
265+
if (lastInput > DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - 120) // This being too low passes sometimes too many inputs for me - atomsk
241266
{
242267
inputProcessed = true;
243268
return;
@@ -256,15 +281,45 @@ private void MoveFocus(int xOffset, int yOffset)
256281
inputProcessed = true;
257282
return;
258283
}
259-
260-
int columns = GetColumnCount();
261-
int rows = appList.Children.Count / columns;
262284

263285
int newX = (int)(currentPoint.X + xOffset);
264286
int newY = (int)(currentPoint.Y + yOffset);
265287

266-
newX = Math.Clamp(newX, 0, columns - 1);
267-
newY = Math.Clamp(newY, 0, rows - 1);
288+
int columns;
289+
int rows;
290+
if (App.Settings.Settings.AppViewIsHorizontalScrolling)
291+
{
292+
// in here rows are columns and columns are rows...
293+
rows = GetColumnsInHorizontalMode();
294+
columns = (GetRowCount() / rows) + 1;
295+
296+
297+
// Don't even ask how this works, but these extraClamps are when bottom rows don't have enough cards to fill the total column amount
298+
int extraClamp = 0;
299+
if (newX != 0)
300+
{
301+
extraClamp = Math.Abs(appList.Children.Count - (rows * columns)) - (columns - 2);
302+
}
303+
304+
newX = Math.Clamp(newX, 0, columns - 1);
305+
newY = Math.Clamp(newY, 0, rows - (1 + extraClamp));
306+
}
307+
else
308+
{
309+
columns = GetColumnCount();
310+
rows = GetRowCount();
311+
if (rows * columns < appList.Children.Count) rows++;
312+
313+
int extraClamp = 0;
314+
if (newY == rows - 1)
315+
{
316+
extraClamp = Math.Abs(appList.Children.Count - (rows * columns));
317+
}
318+
319+
newX = Math.Clamp(newX, 0, columns - (1 + extraClamp));
320+
newY = Math.Clamp(newY, 0, rows - 1);
321+
}
322+
268323

269324
if (newX != currentPoint.X || newY != currentPoint.Y)
270325
{
@@ -280,24 +335,82 @@ private void MoveFocus(int xOffset, int yOffset)
280335
inputProcessed = true;
281336
}
282337

283-
// We need do this our self as WrapPanel doesn't have internal field or function to get current column amount
284-
private int GetColumnCount()
338+
private int GetColumnsInHorizontalMode()
285339
{
286340
if (appList.Children.Count == 0) return 1;
287341

342+
FrameworkElement firstItem = appList.Children[0] as FrameworkElement;
343+
if (firstItem == null) return 1;
344+
345+
int rowCount = 1;
346+
347+
double firstItemLeft = firstItem.TransformToVisual(appList).TransformPoint(new Point(0, 0)).X;
348+
349+
for (int i = 1; i < appList.Children.Count; i++)
350+
{
351+
var item = appList.Children[i] as FrameworkElement;
352+
if (item == null) continue;
353+
354+
double itemLeft = item.TransformToVisual(appList).TransformPoint(new Point(0, 0)).X;
355+
356+
if (Math.Abs(itemLeft - firstItemLeft) < 1)
357+
{
358+
rowCount++;
359+
}
360+
else
361+
{
362+
break;
363+
}
364+
}
365+
366+
return (int)Math.Ceiling((double)appList.Children.Count / rowCount);
367+
}
368+
369+
private int GetRowCount()
370+
{
371+
if (appList.Children.Count == 0) return 1;
288372

289373
FrameworkElement firstItem = appList.Children[0] as FrameworkElement;
290374
if (firstItem == null) return 1;
291375

376+
int rowCount = 1;
292377

293378
double firstItemTop = firstItem.TransformToVisual(appList).TransformPoint(new Point(0, 0)).Y;
379+
380+
for (int i = 1; i < appList.Children.Count; i++)
381+
{
382+
var item = appList.Children[i] as FrameworkElement;
383+
if (item == null) continue;
384+
385+
double itemTop = item.TransformToVisual(appList).TransformPoint(new Point(0, 0)).Y;
386+
387+
if (Math.Abs(itemTop - firstItemTop) > 1)
388+
{
389+
rowCount++;
390+
firstItemTop = itemTop;
391+
}
392+
}
393+
394+
return rowCount;
395+
}
396+
397+
398+
// We need do this our self as WrapPanel doesn't have internal field or function to get current column amount
399+
private int GetColumnCount()
400+
{
401+
if (appList.Children.Count == 0) return 1;
402+
403+
FrameworkElement firstItem = appList.Children[0] as FrameworkElement;
404+
if (firstItem == null) return 1;
405+
294406
int columnCount = 1;
295407

408+
double firstItemTop = firstItem.TransformToVisual(appList).TransformPoint(new Point(0, 0)).Y;
409+
296410
for (int i = 1; i < appList.Children.Count; i++)
297411
{
298412
var item = appList.Children[i] as FrameworkElement;
299-
if (item == null)
300-
continue;
413+
if (item == null) continue;
301414

302415
double itemTop = item.TransformToVisual(appList).TransformPoint(new Point(0, 0)).Y;
303416

@@ -311,6 +424,7 @@ private int GetColumnCount()
311424
}
312425
}
313426

427+
314428
return columnCount;
315429
}
316430

0 commit comments

Comments
 (0)