Skip to content

Commit 689ecf0

Browse files
committed
chore: Bring messages/client up-to-date for v4
Mostly just updating and re-org
1 parent 41a6e23 commit 689ecf0

10 files changed

Lines changed: 1570 additions & 928 deletions

Buttplug/Client/ButtplugClient.cs

Lines changed: 162 additions & 101 deletions
Large diffs are not rendered by default.

Buttplug/Client/ButtplugClientDevice.cs

Lines changed: 152 additions & 150 deletions
Large diffs are not rendered by default.
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
// <copyright file="ButtplugClientDeviceCommand.cs" company="Nonpolynomial Labs LLC">
2+
// Buttplug C# Source Code File - Visit https://buttplug.io for more info about the project.
3+
// Copyright (c) Nonpolynomial Labs LLC. All rights reserved.
4+
// Licensed under the BSD 3-Clause license. See LICENSE file in the project root for full license information.
5+
// </copyright>
6+
7+
using System;
8+
using Buttplug.Core;
9+
using Buttplug.Core.Messages;
10+
11+
namespace Buttplug.Client
12+
{
13+
/// <summary>
14+
/// Represents either a percentage (0.0 to 1.0) or a step value for device commands.
15+
/// </summary>
16+
public class PercentOrSteps
17+
{
18+
private readonly double? _percent;
19+
private readonly int? _steps;
20+
21+
private PercentOrSteps(double? percent, int? steps)
22+
{
23+
_percent = percent;
24+
_steps = steps;
25+
}
26+
27+
/// <summary>
28+
/// Gets the percentage value, if this represents a percentage.
29+
/// </summary>
30+
public double? Percent => _percent;
31+
32+
/// <summary>
33+
/// Gets the step value, if this represents steps.
34+
/// </summary>
35+
public int? Steps => _steps;
36+
37+
/// <summary>
38+
/// Creates a PercentOrSteps from a step value.
39+
/// </summary>
40+
/// <param name="steps">The step value.</param>
41+
/// <returns>A PercentOrSteps representing the step value.</returns>
42+
public static PercentOrSteps FromSteps(int steps)
43+
{
44+
return new PercentOrSteps(null, steps);
45+
}
46+
47+
/// <summary>
48+
/// Creates a PercentOrSteps from a percentage value.
49+
/// </summary>
50+
/// <param name="percent">The percentage value (0.0 to 1.0).</param>
51+
/// <returns>A PercentOrSteps representing the percentage.</returns>
52+
/// <exception cref="ButtplugDeviceException">Thrown if percent is not in range 0.0 to 1.0.</exception>
53+
public static PercentOrSteps FromPercent(double percent)
54+
{
55+
if (percent < 0.0 || percent > 1.0)
56+
{
57+
throw new ButtplugDeviceException($"Percent value {percent} is not in the range 0.0 <= x <= 1.0");
58+
}
59+
return new PercentOrSteps(percent, null);
60+
}
61+
62+
/// <summary>
63+
/// Converts this value to an actual step value given a max step count.
64+
/// </summary>
65+
/// <param name="maxSteps">The maximum number of steps.</param>
66+
/// <returns>The calculated step value.</returns>
67+
public int ToStepValue(int maxSteps)
68+
{
69+
if (_steps.HasValue)
70+
{
71+
return _steps.Value;
72+
}
73+
return (int)Math.Ceiling(_percent.Value * maxSteps);
74+
}
75+
}
76+
77+
/// <summary>
78+
/// Represents an output command to be sent to a device feature.
79+
/// </summary>
80+
public class DeviceOutputCommand
81+
{
82+
/// <summary>
83+
/// The type of output (Vibrate, Rotate, Oscillate, etc.).
84+
/// </summary>
85+
public OutputType OutputType { get; }
86+
87+
/// <summary>
88+
/// The value to set.
89+
/// </summary>
90+
public PercentOrSteps Value { get; }
91+
92+
/// <summary>
93+
/// The duration in milliseconds (only for PositionWithDuration).
94+
/// </summary>
95+
public uint? Duration { get; }
96+
97+
/// <summary>
98+
/// Creates a new output command.
99+
/// </summary>
100+
/// <param name="outputType">The output type.</param>
101+
/// <param name="value">The value to set.</param>
102+
/// <param name="duration">Optional duration for PositionWithDuration.</param>
103+
public DeviceOutputCommand(OutputType outputType, PercentOrSteps value, uint? duration = null)
104+
{
105+
OutputType = outputType;
106+
Value = value;
107+
Duration = duration;
108+
}
109+
}
110+
111+
/// <summary>
112+
/// Builder for creating output commands with a specific output type.
113+
/// </summary>
114+
public class DeviceOutputValueBuilder
115+
{
116+
private readonly OutputType _outputType;
117+
118+
internal DeviceOutputValueBuilder(OutputType outputType)
119+
{
120+
_outputType = outputType;
121+
}
122+
123+
/// <summary>
124+
/// Creates a command with the specified step value.
125+
/// </summary>
126+
/// <param name="steps">The step value.</param>
127+
/// <returns>The output command.</returns>
128+
public DeviceOutputCommand Steps(int steps)
129+
{
130+
return new DeviceOutputCommand(_outputType, PercentOrSteps.FromSteps(steps));
131+
}
132+
133+
/// <summary>
134+
/// Creates a command with the specified percentage value.
135+
/// </summary>
136+
/// <param name="percent">The percentage (0.0 to 1.0).</param>
137+
/// <returns>The output command.</returns>
138+
public DeviceOutputCommand Percent(double percent)
139+
{
140+
return new DeviceOutputCommand(_outputType, PercentOrSteps.FromPercent(percent));
141+
}
142+
}
143+
144+
/// <summary>
145+
/// Builder for creating PositionWithDuration output commands.
146+
/// </summary>
147+
public class DeviceOutputPositionWithDurationBuilder
148+
{
149+
internal DeviceOutputPositionWithDurationBuilder()
150+
{
151+
}
152+
153+
/// <summary>
154+
/// Creates a position command with the specified step value and duration.
155+
/// </summary>
156+
/// <param name="steps">The position step value.</param>
157+
/// <param name="durationMs">The duration in milliseconds.</param>
158+
/// <returns>The output command.</returns>
159+
public DeviceOutputCommand Steps(int steps, uint durationMs)
160+
{
161+
return new DeviceOutputCommand(OutputType.PositionWithDuration, PercentOrSteps.FromSteps(steps), durationMs);
162+
}
163+
164+
/// <summary>
165+
/// Creates a position command with the specified percentage value and duration.
166+
/// </summary>
167+
/// <param name="percent">The position percentage (0.0 to 1.0).</param>
168+
/// <param name="durationMs">The duration in milliseconds.</param>
169+
/// <returns>The output command.</returns>
170+
public DeviceOutputCommand Percent(double percent, uint durationMs)
171+
{
172+
return new DeviceOutputCommand(OutputType.PositionWithDuration, PercentOrSteps.FromPercent(percent), durationMs);
173+
}
174+
}
175+
176+
/// <summary>
177+
/// Static class providing builders for device output commands.
178+
/// </summary>
179+
/// <example>
180+
/// <code>
181+
/// // Vibrate at 50%
182+
/// await device.RunOutputAsync(DeviceOutput.Vibrate.Percent(0.5));
183+
///
184+
/// // Move to position 100 over 500ms
185+
/// await device.RunOutputAsync(DeviceOutput.PositionWithDuration.Percent(1.0, 500));
186+
/// </code>
187+
/// </example>
188+
public static class DeviceOutput
189+
{
190+
/// <summary>
191+
/// Builder for Vibrate commands.
192+
/// </summary>
193+
public static DeviceOutputValueBuilder Vibrate => new DeviceOutputValueBuilder(OutputType.Vibrate);
194+
195+
/// <summary>
196+
/// Builder for Rotate commands.
197+
/// </summary>
198+
public static DeviceOutputValueBuilder Rotate => new DeviceOutputValueBuilder(OutputType.Rotate);
199+
200+
/// <summary>
201+
/// Builder for Oscillate commands.
202+
/// </summary>
203+
public static DeviceOutputValueBuilder Oscillate => new DeviceOutputValueBuilder(OutputType.Oscillate);
204+
205+
/// <summary>
206+
/// Builder for Constrict commands.
207+
/// </summary>
208+
public static DeviceOutputValueBuilder Constrict => new DeviceOutputValueBuilder(OutputType.Constrict);
209+
210+
/// <summary>
211+
/// Builder for Inflate commands.
212+
/// </summary>
213+
public static DeviceOutputValueBuilder Inflate => new DeviceOutputValueBuilder(OutputType.Inflate);
214+
215+
/// <summary>
216+
/// Builder for Temperature commands.
217+
/// </summary>
218+
public static DeviceOutputValueBuilder Temperature => new DeviceOutputValueBuilder(OutputType.Temperature);
219+
220+
/// <summary>
221+
/// Builder for Led commands.
222+
/// </summary>
223+
public static DeviceOutputValueBuilder Led => new DeviceOutputValueBuilder(OutputType.Led);
224+
225+
/// <summary>
226+
/// Builder for Spray commands.
227+
/// </summary>
228+
public static DeviceOutputValueBuilder Spray => new DeviceOutputValueBuilder(OutputType.Spray);
229+
230+
/// <summary>
231+
/// Builder for Position commands (without duration).
232+
/// </summary>
233+
public static DeviceOutputValueBuilder Position => new DeviceOutputValueBuilder(OutputType.Position);
234+
235+
/// <summary>
236+
/// Builder for PositionWithDuration commands.
237+
/// </summary>
238+
public static DeviceOutputPositionWithDurationBuilder PositionWithDuration => new DeviceOutputPositionWithDurationBuilder();
239+
}
240+
241+
/// <summary>
242+
/// Represents an input command to be sent to a device feature.
243+
/// </summary>
244+
public class DeviceInputCommand
245+
{
246+
/// <summary>
247+
/// The type of input (Battery, RSSI, Button, etc.).
248+
/// </summary>
249+
public InputType InputType { get; }
250+
251+
/// <summary>
252+
/// The command type (Read, Subscribe, Unsubscribe).
253+
/// </summary>
254+
public InputCommandType CommandType { get; }
255+
256+
/// <summary>
257+
/// Creates a new input command.
258+
/// </summary>
259+
/// <param name="inputType">The input type.</param>
260+
/// <param name="commandType">The command type.</param>
261+
public DeviceInputCommand(InputType inputType, InputCommandType commandType)
262+
{
263+
InputType = inputType;
264+
CommandType = commandType;
265+
}
266+
}
267+
268+
/// <summary>
269+
/// Builder for creating input commands with a specific input type.
270+
/// </summary>
271+
public class DeviceInputBuilder
272+
{
273+
private readonly InputType _inputType;
274+
275+
internal DeviceInputBuilder(InputType inputType)
276+
{
277+
_inputType = inputType;
278+
}
279+
280+
/// <summary>
281+
/// Creates a Read command.
282+
/// </summary>
283+
/// <returns>The input command.</returns>
284+
public DeviceInputCommand Read()
285+
{
286+
return new DeviceInputCommand(_inputType, InputCommandType.Read);
287+
}
288+
289+
/// <summary>
290+
/// Creates a Subscribe command.
291+
/// </summary>
292+
/// <returns>The input command.</returns>
293+
public DeviceInputCommand Subscribe()
294+
{
295+
return new DeviceInputCommand(_inputType, InputCommandType.Subscribe);
296+
}
297+
298+
/// <summary>
299+
/// Creates an Unsubscribe command.
300+
/// </summary>
301+
/// <returns>The input command.</returns>
302+
public DeviceInputCommand Unsubscribe()
303+
{
304+
return new DeviceInputCommand(_inputType, InputCommandType.Unsubscribe);
305+
}
306+
}
307+
308+
/// <summary>
309+
/// Static class providing builders for device input commands.
310+
/// </summary>
311+
/// <example>
312+
/// <code>
313+
/// // Read battery level
314+
/// var reading = await device.RunInputAsync(DeviceInput.Battery.Read());
315+
///
316+
/// // Subscribe to button events
317+
/// await device.RunInputAsync(DeviceInput.Button.Subscribe());
318+
/// </code>
319+
/// </example>
320+
public static class DeviceInput
321+
{
322+
/// <summary>
323+
/// Builder for Battery commands.
324+
/// </summary>
325+
public static DeviceInputBuilder Battery => new DeviceInputBuilder(InputType.Battery);
326+
327+
/// <summary>
328+
/// Builder for RSSI commands.
329+
/// </summary>
330+
public static DeviceInputBuilder RSSI => new DeviceInputBuilder(InputType.RSSI);
331+
332+
/// <summary>
333+
/// Builder for Button commands.
334+
/// </summary>
335+
public static DeviceInputBuilder Button => new DeviceInputBuilder(InputType.Button);
336+
337+
/// <summary>
338+
/// Builder for Pressure commands.
339+
/// </summary>
340+
public static DeviceInputBuilder Pressure => new DeviceInputBuilder(InputType.Pressure);
341+
}
342+
}

0 commit comments

Comments
 (0)