Values.cs
5.49 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
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2017. *
* Leap Motion proprietary and confidential. *
* *
* Use subject to the terms of the Leap Motion SDK Agreement available at *
* https://developer.leapmotion.com/sdk_agreement, or another agreement *
* between Leap Motion and you, your company or other organization. *
******************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Leap.Unity.Query {
public static class Values {
/// <summary>
/// Generates a new sequence that contains only a single value.
/// </summary>
public static QueryWrapper<T, SingleOp<T>> Single<T>(T value) {
return new QueryWrapper<T, SingleOp<T>>(new SingleOp<T>(value));
}
public struct SingleOp<T> : IQueryOp<T> {
private T _t;
private bool _hasReturned;
public SingleOp(T t) {
_t = t;
_hasReturned = false;
}
public bool TryGetNext(out T t) {
if (_hasReturned) {
t = default(T);
return false;
} else {
t = _t;
_hasReturned = true;
return true;
}
}
public void Reset() {
_hasReturned = false;
}
}
/// <summary>
/// Generates a new sequence of a specific type that has no elements.
/// </summary>
public static QueryWrapper<T, EmptyOp<T>> Empty<T>() {
return new QueryWrapper<T, EmptyOp<T>>(new EmptyOp<T>());
}
public struct EmptyOp<T> : IQueryOp<T> {
public bool TryGetNext(out T t) {
t = default(T);
return false;
}
public void Reset() { }
}
/// <summary>
/// Generates a new sequence that returns the integers starting at
/// the given value and incrementing by one for each successive value.
/// This sequence is unbounded and will never terminate.
///
/// For example:
/// Values.From(5)
/// Will result in:
/// (5, 6, 7, 8, 9...)
/// </summary>
public static QueryWrapper<int, UnboundedRangeOp> From(int from) {
return new QueryWrapper<int, UnboundedRangeOp>(new UnboundedRangeOp(from, step: 1));
}
/// <summary>
/// Takes an unbounded sequence generated by the From operator and places an upper bound
/// on it. Once the sequence reaches or exceeds the given value, the sequence
/// will terminate.
///
/// For example:
/// Values.From(5).To(8)
/// Would result in:
/// (5, 6, 7)
/// </summary>
public static QueryWrapper<int, RangeOp> To(this QueryWrapper<int, UnboundedRangeOp> wrapper, int to) {
return new QueryWrapper<int, RangeOp>(new RangeOp(wrapper.op.from, to, wrapper.op.step));
}
/// <summary>
/// Takes an unbounded sequence and changes its step parameter to be something other than 1.
/// Each successive element will be incremented by the new step value instead of by 1.
/// Passing in negative step values will cause the sequence to step backwards. Passing in
/// a step value of zero is legal but will just result in the starting value being repeated
/// forever.
///
/// For example:
/// Values.From(5).By(2)
/// Would result in:
/// (5, 7, 9, 11, 13...)
/// </summary>
public static QueryWrapper<int, UnboundedRangeOp> By(this QueryWrapper<int, UnboundedRangeOp> wrapper, int step) {
return new QueryWrapper<int, UnboundedRangeOp>(new UnboundedRangeOp(wrapper.op.from, step));
}
/// <summary>
/// Takes a bounded sequence and changes its step parameter to be something other than 1.
/// Each successive element will be incremented towards the goal by the new step value instead
/// of by one. In this case, the sign of the step value is IGNORED. The value will ALWAYS
/// step towards the goal, regardless of what the sign of the step value is.
///
/// For example:
/// Values.From(5).To(10).By(2)
/// Would result in:
/// (5, 7, 9)
/// </summary>
public static QueryWrapper<int, RangeOp> By(this QueryWrapper<int, RangeOp> wrapper, int step) {
return new QueryWrapper<int, RangeOp>(new RangeOp(wrapper.op.from, wrapper.op.to, step));
}
public struct UnboundedRangeOp : IQueryOp<int> {
public readonly int from, step;
private int _curr;
public UnboundedRangeOp(int from, int step) {
this.from = from;
this.step = step;
_curr = from;
}
public bool TryGetNext(out int t) {
t = _curr;
_curr += step;
return true;
}
public void Reset() {
_curr = from;
}
}
public struct RangeOp : IQueryOp<int> {
public readonly int from, to, step;
private int _curr;
public RangeOp(int from, int to, int step) {
this.from = from;
this.to = step == 0 ? from : to;
this.step = to > from ? Mathf.Abs(step) : -Mathf.Abs(step);
_curr = this.from;
}
public bool TryGetNext(out int t) {
t = _curr;
if (_curr == to) {
return false;
}
if ((_curr > to) == (to > from)) {
return false;
}
_curr += step;
return true;
}
public void Reset() {
_curr = from;
}
}
}
}