corrade-vassal – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 1 | /* |
2 | * Copyright (c) 2006-2014, openmetaverse.org |
||
3 | * All rights reserved. |
||
4 | * |
||
5 | * - Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions are met: |
||
7 | * |
||
8 | * - Redistributions of source code must retain the above copyright notice, this |
||
9 | * list of conditions and the following disclaimer. |
||
10 | * - Neither the name of the openmetaverse.org nor the names |
||
11 | * of its contributors may be used to endorse or promote products derived from |
||
12 | * this software without specific prior written permission. |
||
13 | * |
||
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
18 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
24 | * POSSIBILITY OF SUCH DAMAGE. |
||
25 | */ |
||
26 | |||
27 | using System; |
||
28 | using System.Threading; |
||
29 | using OpenMetaverse; |
||
30 | using OpenMetaverse.Packets; |
||
31 | |||
32 | namespace OpenMetaverse |
||
33 | { |
||
34 | public partial class AgentManager |
||
35 | { |
||
36 | #region Enums |
||
37 | |||
38 | /// <summary> |
||
39 | /// Used to specify movement actions for your agent |
||
40 | /// </summary> |
||
41 | [Flags] |
||
42 | public enum ControlFlags |
||
43 | { |
||
44 | /// <summary>Empty flag</summary> |
||
45 | NONE = 0, |
||
46 | /// <summary>Move Forward (SL Keybinding: W/Up Arrow)</summary> |
||
47 | AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX, |
||
48 | /// <summary>Move Backward (SL Keybinding: S/Down Arrow)</summary> |
||
49 | AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX, |
||
50 | /// <summary>Move Left (SL Keybinding: Shift-(A/Left Arrow))</summary> |
||
51 | AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX, |
||
52 | /// <summary>Move Right (SL Keybinding: Shift-(D/Right Arrow))</summary> |
||
53 | AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX, |
||
54 | /// <summary>Not Flying: Jump/Flying: Move Up (SL Keybinding: E)</summary> |
||
55 | AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX, |
||
56 | /// <summary>Not Flying: Croutch/Flying: Move Down (SL Keybinding: C)</summary> |
||
57 | AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX, |
||
58 | /// <summary>Unused</summary> |
||
59 | AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX, |
||
60 | /// <summary>Unused</summary> |
||
61 | AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX, |
||
62 | /// <summary>Unused</summary> |
||
63 | AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX, |
||
64 | /// <summary>Unused</summary> |
||
65 | AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX, |
||
66 | /// <summary>ORed with AGENT_CONTROL_AT_* if the keyboard is being used</summary> |
||
67 | AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX, |
||
68 | /// <summary>ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used</summary> |
||
69 | AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX, |
||
70 | /// <summary>ORed with AGENT_CONTROL_UP_* if the keyboard is being used</summary> |
||
71 | AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX, |
||
72 | /// <summary>Fly</summary> |
||
73 | AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX, |
||
74 | /// <summary></summary> |
||
75 | AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX, |
||
76 | /// <summary>Finish our current animation</summary> |
||
77 | AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX, |
||
78 | /// <summary>Stand up from the ground or a prim seat</summary> |
||
79 | AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX, |
||
80 | /// <summary>Sit on the ground at our current location</summary> |
||
81 | AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX, |
||
82 | /// <summary>Whether mouselook is currently enabled</summary> |
||
83 | AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX, |
||
84 | /// <summary>Legacy, used if a key was pressed for less than a certain amount of time</summary> |
||
85 | AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX, |
||
86 | /// <summary>Legacy, used if a key was pressed for less than a certain amount of time</summary> |
||
87 | AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX, |
||
88 | /// <summary>Legacy, used if a key was pressed for less than a certain amount of time</summary> |
||
89 | AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX, |
||
90 | /// <summary>Legacy, used if a key was pressed for less than a certain amount of time</summary> |
||
91 | AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX, |
||
92 | /// <summary>Legacy, used if a key was pressed for less than a certain amount of time</summary> |
||
93 | AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX, |
||
94 | /// <summary>Legacy, used if a key was pressed for less than a certain amount of time</summary> |
||
95 | AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX, |
||
96 | /// <summary></summary> |
||
97 | AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX, |
||
98 | /// <summary></summary> |
||
99 | AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX, |
||
100 | /// <summary>Set when the avatar is idled or set to away. Note that the away animation is |
||
101 | /// activated separately from setting this flag</summary> |
||
102 | AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX, |
||
103 | /// <summary></summary> |
||
104 | AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX, |
||
105 | /// <summary></summary> |
||
106 | AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX, |
||
107 | /// <summary></summary> |
||
108 | AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX, |
||
109 | /// <summary></summary> |
||
110 | AGENT_CONTROL_ML_LBUTTON_UP = 0x1 << CONTROL_ML_LBUTTON_UP_INDEX |
||
111 | } |
||
112 | |||
113 | #endregion Enums |
||
114 | |||
115 | #region AgentUpdate Constants |
||
116 | |||
117 | private const int CONTROL_AT_POS_INDEX = 0; |
||
118 | private const int CONTROL_AT_NEG_INDEX = 1; |
||
119 | private const int CONTROL_LEFT_POS_INDEX = 2; |
||
120 | private const int CONTROL_LEFT_NEG_INDEX = 3; |
||
121 | private const int CONTROL_UP_POS_INDEX = 4; |
||
122 | private const int CONTROL_UP_NEG_INDEX = 5; |
||
123 | private const int CONTROL_PITCH_POS_INDEX = 6; |
||
124 | private const int CONTROL_PITCH_NEG_INDEX = 7; |
||
125 | private const int CONTROL_YAW_POS_INDEX = 8; |
||
126 | private const int CONTROL_YAW_NEG_INDEX = 9; |
||
127 | private const int CONTROL_FAST_AT_INDEX = 10; |
||
128 | private const int CONTROL_FAST_LEFT_INDEX = 11; |
||
129 | private const int CONTROL_FAST_UP_INDEX = 12; |
||
130 | private const int CONTROL_FLY_INDEX = 13; |
||
131 | private const int CONTROL_STOP_INDEX = 14; |
||
132 | private const int CONTROL_FINISH_ANIM_INDEX = 15; |
||
133 | private const int CONTROL_STAND_UP_INDEX = 16; |
||
134 | private const int CONTROL_SIT_ON_GROUND_INDEX = 17; |
||
135 | private const int CONTROL_MOUSELOOK_INDEX = 18; |
||
136 | private const int CONTROL_NUDGE_AT_POS_INDEX = 19; |
||
137 | private const int CONTROL_NUDGE_AT_NEG_INDEX = 20; |
||
138 | private const int CONTROL_NUDGE_LEFT_POS_INDEX = 21; |
||
139 | private const int CONTROL_NUDGE_LEFT_NEG_INDEX = 22; |
||
140 | private const int CONTROL_NUDGE_UP_POS_INDEX = 23; |
||
141 | private const int CONTROL_NUDGE_UP_NEG_INDEX = 24; |
||
142 | private const int CONTROL_TURN_LEFT_INDEX = 25; |
||
143 | private const int CONTROL_TURN_RIGHT_INDEX = 26; |
||
144 | private const int CONTROL_AWAY_INDEX = 27; |
||
145 | private const int CONTROL_LBUTTON_DOWN_INDEX = 28; |
||
146 | private const int CONTROL_LBUTTON_UP_INDEX = 29; |
||
147 | private const int CONTROL_ML_LBUTTON_DOWN_INDEX = 30; |
||
148 | private const int CONTROL_ML_LBUTTON_UP_INDEX = 31; |
||
149 | private const int TOTAL_CONTROLS = 32; |
||
150 | |||
151 | #endregion AgentUpdate Constants |
||
152 | |||
153 | /// <summary> |
||
154 | /// Agent movement and camera control |
||
155 | /// |
||
156 | /// Agent movement is controlled by setting specific <seealso cref="T:AgentManager.ControlFlags"/> |
||
157 | /// After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags |
||
158 | /// This is most easily accomplished by setting one or more of the AgentMovement properties |
||
159 | /// |
||
160 | /// Movement of an avatar is always based on a compass direction, for example AtPos will move the |
||
161 | /// agent from West to East or forward on the X Axis, AtNeg will of course move agent from |
||
162 | /// East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis |
||
163 | /// The Z axis is Up, finer grained control of movements can be done using the Nudge properties |
||
164 | /// </summary> |
||
165 | public partial class AgentMovement |
||
166 | { |
||
167 | #region Properties |
||
168 | |||
169 | /// <summary>Move agent positive along the X axis</summary> |
||
170 | public bool AtPos |
||
171 | { |
||
172 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); } |
||
173 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, value); } |
||
174 | } |
||
175 | /// <summary>Move agent negative along the X axis</summary> |
||
176 | public bool AtNeg |
||
177 | { |
||
178 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG); } |
||
179 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, value); } |
||
180 | } |
||
181 | /// <summary>Move agent positive along the Y axis</summary> |
||
182 | public bool LeftPos |
||
183 | { |
||
184 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS); } |
||
185 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, value); } |
||
186 | } |
||
187 | /// <summary>Move agent negative along the Y axis</summary> |
||
188 | public bool LeftNeg |
||
189 | { |
||
190 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); } |
||
191 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, value); } |
||
192 | } |
||
193 | /// <summary>Move agent positive along the Z axis</summary> |
||
194 | public bool UpPos |
||
195 | { |
||
196 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); } |
||
197 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, value); } |
||
198 | } |
||
199 | /// <summary>Move agent negative along the Z axis</summary> |
||
200 | public bool UpNeg |
||
201 | { |
||
202 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG); } |
||
203 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, value); } |
||
204 | } |
||
205 | /// <summary></summary> |
||
206 | public bool PitchPos |
||
207 | { |
||
208 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_PITCH_POS); } |
||
209 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_PITCH_POS, value); } |
||
210 | } |
||
211 | /// <summary></summary> |
||
212 | public bool PitchNeg |
||
213 | { |
||
214 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_PITCH_NEG); } |
||
215 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_PITCH_NEG, value); } |
||
216 | } |
||
217 | /// <summary></summary> |
||
218 | public bool YawPos |
||
219 | { |
||
220 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); } |
||
221 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS, value); } |
||
222 | } |
||
223 | /// <summary></summary> |
||
224 | public bool YawNeg |
||
225 | { |
||
226 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); } |
||
227 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG, value); } |
||
228 | } |
||
229 | /// <summary></summary> |
||
230 | public bool FastAt |
||
231 | { |
||
232 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FAST_AT); } |
||
233 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FAST_AT, value); } |
||
234 | } |
||
235 | /// <summary></summary> |
||
236 | public bool FastLeft |
||
237 | { |
||
238 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FAST_LEFT); } |
||
239 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FAST_LEFT, value); } |
||
240 | } |
||
241 | /// <summary></summary> |
||
242 | public bool FastUp |
||
243 | { |
||
244 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FAST_UP); } |
||
245 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FAST_UP, value); } |
||
246 | } |
||
247 | /// <summary>Causes simulator to make agent fly</summary> |
||
248 | public bool Fly |
||
249 | { |
||
250 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FLY); } |
||
251 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FLY, value); } |
||
252 | } |
||
253 | /// <summary>Stop movement</summary> |
||
254 | public bool Stop |
||
255 | { |
||
256 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_STOP); } |
||
257 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_STOP, value); } |
||
258 | } |
||
259 | /// <summary>Finish animation</summary> |
||
260 | public bool FinishAnim |
||
261 | { |
||
262 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FINISH_ANIM); } |
||
263 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_FINISH_ANIM, value); } |
||
264 | } |
||
265 | /// <summary>Stand up from a sit</summary> |
||
266 | public bool StandUp |
||
267 | { |
||
268 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP); } |
||
269 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP, value); } |
||
270 | } |
||
271 | /// <summary>Tells simulator to sit agent on ground</summary> |
||
272 | public bool SitOnGround |
||
273 | { |
||
274 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND); } |
||
275 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND, value); } |
||
276 | } |
||
277 | /// <summary>Place agent into mouselook mode</summary> |
||
278 | public bool Mouselook |
||
279 | { |
||
280 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK); } |
||
281 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK, value); } |
||
282 | } |
||
283 | /// <summary>Nudge agent positive along the X axis</summary> |
||
284 | public bool NudgeAtPos |
||
285 | { |
||
286 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); } |
||
287 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, value); } |
||
288 | } |
||
289 | /// <summary>Nudge agent negative along the X axis</summary> |
||
290 | public bool NudgeAtNeg |
||
291 | { |
||
292 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); } |
||
293 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, value); } |
||
294 | } |
||
295 | /// <summary>Nudge agent positive along the Y axis</summary> |
||
296 | public bool NudgeLeftPos |
||
297 | { |
||
298 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); } |
||
299 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, value); } |
||
300 | } |
||
301 | /// <summary>Nudge agent negative along the Y axis</summary> |
||
302 | public bool NudgeLeftNeg |
||
303 | { |
||
304 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG); } |
||
305 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, value); } |
||
306 | } |
||
307 | /// <summary>Nudge agent positive along the Z axis</summary> |
||
308 | public bool NudgeUpPos |
||
309 | { |
||
310 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS); } |
||
311 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS, value); } |
||
312 | } |
||
313 | /// <summary>Nudge agent negative along the Z axis</summary> |
||
314 | public bool NudgeUpNeg |
||
315 | { |
||
316 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); } |
||
317 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG, value); } |
||
318 | } |
||
319 | /// <summary></summary> |
||
320 | public bool TurnLeft |
||
321 | { |
||
322 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT); } |
||
323 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT, value); } |
||
324 | } |
||
325 | /// <summary></summary> |
||
326 | public bool TurnRight |
||
327 | { |
||
328 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT); } |
||
329 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT, value); } |
||
330 | } |
||
331 | /// <summary>Tell simulator to mark agent as away</summary> |
||
332 | public bool Away |
||
333 | { |
||
334 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_AWAY); } |
||
335 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_AWAY, value); } |
||
336 | } |
||
337 | /// <summary></summary> |
||
338 | public bool LButtonDown |
||
339 | { |
||
340 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); } |
||
341 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN, value); } |
||
342 | } |
||
343 | /// <summary></summary> |
||
344 | public bool LButtonUp |
||
345 | { |
||
346 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP); } |
||
347 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP, value); } |
||
348 | } |
||
349 | /// <summary></summary> |
||
350 | public bool MLButtonDown |
||
351 | { |
||
352 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); } |
||
353 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN, value); } |
||
354 | } |
||
355 | /// <summary></summary> |
||
356 | public bool MLButtonUp |
||
357 | { |
||
358 | get { return GetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP); } |
||
359 | set { SetControlFlag(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP, value); } |
||
360 | } |
||
361 | /// <summary> |
||
362 | /// Returns "always run" value, or changes it by sending a SetAlwaysRunPacket |
||
363 | /// </summary> |
||
364 | public bool AlwaysRun |
||
365 | { |
||
366 | get |
||
367 | { |
||
368 | return alwaysRun; |
||
369 | } |
||
370 | set |
||
371 | { |
||
372 | alwaysRun = value; |
||
373 | SetAlwaysRunPacket run = new SetAlwaysRunPacket(); |
||
374 | run.AgentData.AgentID = Client.Self.AgentID; |
||
375 | run.AgentData.SessionID = Client.Self.SessionID; |
||
376 | run.AgentData.AlwaysRun = alwaysRun; |
||
377 | Client.Network.SendPacket(run); |
||
378 | } |
||
379 | } |
||
380 | /// <summary>The current value of the agent control flags</summary> |
||
381 | public uint AgentControls |
||
382 | { |
||
383 | get { return agentControls; } |
||
384 | } |
||
385 | |||
386 | /// <summary>Gets or sets the interval in milliseconds at which |
||
387 | /// AgentUpdate packets are sent to the current simulator. Setting |
||
388 | /// this to a non-zero value will also enable the packet sending if |
||
389 | /// it was previously off, and setting it to zero will disable</summary> |
||
390 | public int UpdateInterval |
||
391 | { |
||
392 | get |
||
393 | { |
||
394 | return updateInterval; |
||
395 | } |
||
396 | set |
||
397 | { |
||
398 | if (value > 0) |
||
399 | { |
||
400 | if (updateTimer != null) |
||
401 | { |
||
402 | updateTimer.Change(value, value); |
||
403 | } |
||
404 | updateInterval = value; |
||
405 | } |
||
406 | else |
||
407 | { |
||
408 | if (updateTimer != null) |
||
409 | { |
||
410 | updateTimer.Change(Timeout.Infinite, Timeout.Infinite); |
||
411 | } |
||
412 | updateInterval = 0; |
||
413 | } |
||
414 | } |
||
415 | } |
||
416 | /// <summary>Gets or sets whether AgentUpdate packets are sent to |
||
417 | /// the current simulator</summary> |
||
418 | public bool UpdateEnabled |
||
419 | { |
||
420 | get { return (updateInterval != 0); } |
||
421 | } |
||
422 | |||
423 | /// <summary>Reset movement controls every time we send an update</summary> |
||
424 | public bool AutoResetControls |
||
425 | { |
||
426 | get { return autoResetControls; } |
||
427 | set { autoResetControls = value; } |
||
428 | } |
||
429 | |||
430 | #endregion Properties |
||
431 | |||
432 | /// <summary>Agent camera controls</summary> |
||
433 | public AgentCamera Camera; |
||
434 | /// <summary>Currently only used for hiding your group title</summary> |
||
435 | public AgentFlags Flags = AgentFlags.None; |
||
436 | /// <summary>Action state of the avatar, which can currently be |
||
437 | /// typing and editing</summary> |
||
438 | public AgentState State = AgentState.None; |
||
439 | /// <summary></summary> |
||
440 | public Quaternion BodyRotation = Quaternion.Identity; |
||
441 | /// <summary></summary> |
||
442 | public Quaternion HeadRotation = Quaternion.Identity; |
||
443 | |||
444 | #region Change tracking |
||
445 | /// <summary></summary> |
||
446 | private Quaternion LastBodyRotation; |
||
447 | /// <summary></summary> |
||
448 | private Quaternion LastHeadRotation; |
||
449 | /// <summary></summary> |
||
450 | private Vector3 LastCameraCenter; |
||
451 | /// <summary></summary> |
||
452 | private Vector3 LastCameraXAxis; |
||
453 | /// <summary></summary> |
||
454 | private Vector3 LastCameraYAxis; |
||
455 | /// <summary></summary> |
||
456 | private Vector3 LastCameraZAxis; |
||
457 | /// <summary></summary> |
||
458 | private float LastFar; |
||
459 | #endregion Change tracking |
||
460 | |||
461 | private bool alwaysRun; |
||
462 | private GridClient Client; |
||
463 | private uint agentControls; |
||
464 | private int duplicateCount; |
||
465 | private AgentState lastState; |
||
466 | /// <summary>Timer for sending AgentUpdate packets</summary> |
||
467 | private Timer updateTimer; |
||
468 | private int updateInterval; |
||
469 | private bool autoResetControls; |
||
470 | |||
471 | /// <summary>Default constructor</summary> |
||
472 | public AgentMovement(GridClient client) |
||
473 | { |
||
474 | Client = client; |
||
475 | Camera = new AgentCamera(); |
||
476 | Client.Network.LoginProgress += Network_OnConnected; |
||
477 | Client.Network.Disconnected += Network_OnDisconnected; |
||
478 | updateInterval = Settings.DEFAULT_AGENT_UPDATE_INTERVAL; |
||
479 | } |
||
480 | |||
481 | private void CleanupTimer() |
||
482 | { |
||
483 | if (updateTimer != null) |
||
484 | { |
||
485 | updateTimer.Dispose(); |
||
486 | updateTimer = null; |
||
487 | } |
||
488 | } |
||
489 | |||
490 | private void Network_OnDisconnected(object sender, DisconnectedEventArgs e) |
||
491 | { |
||
492 | CleanupTimer(); |
||
493 | } |
||
494 | |||
495 | private void Network_OnConnected(object sender, LoginProgressEventArgs e) |
||
496 | { |
||
497 | if (e.Status == LoginStatus.Success) |
||
498 | { |
||
499 | CleanupTimer(); |
||
500 | updateTimer = new Timer(new TimerCallback(UpdateTimer_Elapsed), null, updateInterval, updateInterval); |
||
501 | } |
||
502 | } |
||
503 | |||
504 | /// <summary> |
||
505 | /// Send an AgentUpdate with the camera set at the current agent |
||
506 | /// position and pointing towards the heading specified |
||
507 | /// </summary> |
||
508 | /// <param name="heading">Camera rotation in radians</param> |
||
509 | /// <param name="reliable">Whether to send the AgentUpdate reliable |
||
510 | /// or not</param> |
||
511 | public void UpdateFromHeading(double heading, bool reliable) |
||
512 | { |
||
513 | Camera.Position = Client.Self.SimPosition; |
||
514 | Camera.LookDirection(heading); |
||
515 | |||
516 | BodyRotation.Z = (float)Math.Sin(heading / 2.0d); |
||
517 | BodyRotation.W = (float)Math.Cos(heading / 2.0d); |
||
518 | HeadRotation = BodyRotation; |
||
519 | |||
520 | SendUpdate(reliable); |
||
521 | } |
||
522 | |||
523 | /// <summary> |
||
524 | /// Rotates the avatar body and camera toward a target position. |
||
525 | /// This will also anchor the camera position on the avatar |
||
526 | /// </summary> |
||
527 | /// <param name="target">Region coordinates to turn toward</param> |
||
528 | public bool TurnToward(Vector3 target) |
||
529 | { |
||
530 | return TurnToward(target, true); |
||
531 | } |
||
532 | |||
533 | /// <summary> |
||
534 | /// Rotates the avatar body and camera toward a target position. |
||
535 | /// This will also anchor the camera position on the avatar |
||
536 | /// </summary> |
||
537 | /// <param name="target">Region coordinates to turn toward</param> |
||
538 | /// <param name="sendUpdate">whether to send update or not</param> |
||
539 | public bool TurnToward(Vector3 target, bool sendUpdate) |
||
540 | { |
||
541 | if (Client.Settings.SEND_AGENT_UPDATES) |
||
542 | { |
||
543 | Quaternion parentRot = Quaternion.Identity; |
||
544 | |||
545 | if (Client.Self.SittingOn > 0) |
||
546 | { |
||
547 | if (!Client.Network.CurrentSim.ObjectsPrimitives.ContainsKey(Client.Self.SittingOn)) |
||
548 | { |
||
549 | Logger.Log("Attempted TurnToward but parent prim is not in dictionary", Helpers.LogLevel.Warning, Client); |
||
550 | return false; |
||
551 | } |
||
552 | else parentRot = Client.Network.CurrentSim.ObjectsPrimitives[Client.Self.SittingOn].Rotation; |
||
553 | } |
||
554 | |||
555 | Quaternion between = Vector3.RotationBetween(Vector3.UnitX, Vector3.Normalize(target - Client.Self.SimPosition)); |
||
556 | Quaternion rot = between * (Quaternion.Identity / parentRot); |
||
557 | |||
558 | BodyRotation = rot; |
||
559 | HeadRotation = rot; |
||
560 | Camera.LookAt(Client.Self.SimPosition, target); |
||
561 | |||
562 | if (sendUpdate) SendUpdate(); |
||
563 | |||
564 | return true; |
||
565 | } |
||
566 | else |
||
567 | { |
||
568 | Logger.Log("Attempted TurnToward but agent updates are disabled", Helpers.LogLevel.Warning, Client); |
||
569 | return false; |
||
570 | } |
||
571 | } |
||
572 | |||
573 | /// <summary> |
||
574 | /// Send new AgentUpdate packet to update our current camera |
||
575 | /// position and rotation |
||
576 | /// </summary> |
||
577 | public void SendUpdate() |
||
578 | { |
||
579 | SendUpdate(false, Client.Network.CurrentSim); |
||
580 | } |
||
581 | |||
582 | /// <summary> |
||
583 | /// Send new AgentUpdate packet to update our current camera |
||
584 | /// position and rotation |
||
585 | /// </summary> |
||
586 | /// <param name="reliable">Whether to require server acknowledgement |
||
587 | /// of this packet</param> |
||
588 | public void SendUpdate(bool reliable) |
||
589 | { |
||
590 | SendUpdate(reliable, Client.Network.CurrentSim); |
||
591 | } |
||
592 | |||
593 | /// <summary> |
||
594 | /// Send new AgentUpdate packet to update our current camera |
||
595 | /// position and rotation |
||
596 | /// </summary> |
||
597 | /// <param name="reliable">Whether to require server acknowledgement |
||
598 | /// of this packet</param> |
||
599 | /// <param name="simulator">Simulator to send the update to</param> |
||
600 | public void SendUpdate(bool reliable, Simulator simulator) |
||
601 | { |
||
602 | // Since version 1.40.4 of the Linden simulator, sending this update |
||
603 | // causes corruption of the agent position in the simulator |
||
604 | if (simulator != null && (!simulator.AgentMovementComplete)) |
||
605 | return; |
||
606 | |||
607 | Vector3 origin = Camera.Position; |
||
608 | Vector3 xAxis = Camera.LeftAxis; |
||
609 | Vector3 yAxis = Camera.AtAxis; |
||
610 | Vector3 zAxis = Camera.UpAxis; |
||
611 | |||
612 | // Attempted to sort these in a rough order of how often they might change |
||
613 | if (agentControls == 0 && |
||
614 | yAxis == LastCameraYAxis && |
||
615 | origin == LastCameraCenter && |
||
616 | State == lastState && |
||
617 | HeadRotation == LastHeadRotation && |
||
618 | BodyRotation == LastBodyRotation && |
||
619 | xAxis == LastCameraXAxis && |
||
620 | Camera.Far == LastFar && |
||
621 | zAxis == LastCameraZAxis) |
||
622 | { |
||
623 | ++duplicateCount; |
||
624 | } |
||
625 | else |
||
626 | { |
||
627 | duplicateCount = 0; |
||
628 | } |
||
629 | |||
630 | if (Client.Settings.DISABLE_AGENT_UPDATE_DUPLICATE_CHECK || duplicateCount < 10) |
||
631 | { |
||
632 | // Store the current state to do duplicate checking |
||
633 | LastHeadRotation = HeadRotation; |
||
634 | LastBodyRotation = BodyRotation; |
||
635 | LastCameraYAxis = yAxis; |
||
636 | LastCameraCenter = origin; |
||
637 | LastCameraXAxis = xAxis; |
||
638 | LastCameraZAxis = zAxis; |
||
639 | LastFar = Camera.Far; |
||
640 | lastState = State; |
||
641 | |||
642 | // Build the AgentUpdate packet and send it |
||
643 | AgentUpdatePacket update = new AgentUpdatePacket(); |
||
644 | update.Header.Reliable = reliable; |
||
645 | |||
646 | update.AgentData.AgentID = Client.Self.AgentID; |
||
647 | update.AgentData.SessionID = Client.Self.SessionID; |
||
648 | update.AgentData.HeadRotation = HeadRotation; |
||
649 | update.AgentData.BodyRotation = BodyRotation; |
||
650 | update.AgentData.CameraAtAxis = xAxis; |
||
651 | update.AgentData.CameraCenter = origin; |
||
652 | update.AgentData.CameraLeftAxis = yAxis; |
||
653 | update.AgentData.CameraUpAxis = zAxis; |
||
654 | update.AgentData.Far = Camera.Far; |
||
655 | update.AgentData.State = (byte)State; |
||
656 | update.AgentData.ControlFlags = agentControls; |
||
657 | update.AgentData.Flags = (byte)Flags; |
||
658 | |||
659 | Client.Network.SendPacket(update, simulator); |
||
660 | |||
661 | if (autoResetControls) { |
||
662 | ResetControlFlags(); |
||
663 | } |
||
664 | } |
||
665 | } |
||
666 | |||
667 | /// <summary> |
||
668 | /// Builds an AgentUpdate packet entirely from parameters. This |
||
669 | /// will not touch the state of Self.Movement or |
||
670 | /// Self.Movement.Camera in any way |
||
671 | /// </summary> |
||
672 | /// <param name="controlFlags"></param> |
||
673 | /// <param name="position"></param> |
||
674 | /// <param name="forwardAxis"></param> |
||
675 | /// <param name="leftAxis"></param> |
||
676 | /// <param name="upAxis"></param> |
||
677 | /// <param name="bodyRotation"></param> |
||
678 | /// <param name="headRotation"></param> |
||
679 | /// <param name="farClip"></param> |
||
680 | /// <param name="reliable"></param> |
||
681 | /// <param name="flags"></param> |
||
682 | /// <param name="state"></param> |
||
683 | public void SendManualUpdate(AgentManager.ControlFlags controlFlags, Vector3 position, Vector3 forwardAxis, |
||
684 | Vector3 leftAxis, Vector3 upAxis, Quaternion bodyRotation, Quaternion headRotation, float farClip, |
||
685 | AgentFlags flags, AgentState state, bool reliable) |
||
686 | { |
||
687 | // Since version 1.40.4 of the Linden simulator, sending this update |
||
688 | // causes corruption of the agent position in the simulator |
||
689 | if (Client.Network.CurrentSim != null && (!Client.Network.CurrentSim.HandshakeComplete)) |
||
690 | return; |
||
691 | |||
692 | AgentUpdatePacket update = new AgentUpdatePacket(); |
||
693 | |||
694 | update.AgentData.AgentID = Client.Self.AgentID; |
||
695 | update.AgentData.SessionID = Client.Self.SessionID; |
||
696 | update.AgentData.BodyRotation = bodyRotation; |
||
697 | update.AgentData.HeadRotation = headRotation; |
||
698 | update.AgentData.CameraCenter = position; |
||
699 | update.AgentData.CameraAtAxis = forwardAxis; |
||
700 | update.AgentData.CameraLeftAxis = leftAxis; |
||
701 | update.AgentData.CameraUpAxis = upAxis; |
||
702 | update.AgentData.Far = farClip; |
||
703 | update.AgentData.ControlFlags = (uint)controlFlags; |
||
704 | update.AgentData.Flags = (byte)flags; |
||
705 | update.AgentData.State = (byte)state; |
||
706 | |||
707 | update.Header.Reliable = reliable; |
||
708 | |||
709 | Client.Network.SendPacket(update); |
||
710 | } |
||
711 | |||
712 | private bool GetControlFlag(ControlFlags flag) |
||
713 | { |
||
714 | return (agentControls & (uint)flag) != 0; |
||
715 | } |
||
716 | |||
717 | private void SetControlFlag(ControlFlags flag, bool value) |
||
718 | { |
||
719 | if (value) agentControls |= (uint)flag; |
||
720 | else agentControls &= ~((uint)flag); |
||
721 | } |
||
722 | |||
723 | public void ResetControlFlags() |
||
724 | { |
||
725 | // Reset all of the flags except for persistent settings like |
||
726 | // away, fly, mouselook, and crouching |
||
727 | agentControls &= |
||
728 | (uint)(ControlFlags.AGENT_CONTROL_AWAY | |
||
729 | ControlFlags.AGENT_CONTROL_FLY | |
||
730 | ControlFlags.AGENT_CONTROL_MOUSELOOK | |
||
731 | ControlFlags.AGENT_CONTROL_UP_NEG); |
||
732 | } |
||
733 | |||
734 | |||
735 | /// <summary> |
||
736 | /// Sends update of Field of Vision vertical angle to the simulator |
||
737 | /// </summary> |
||
738 | /// <param name="angle">Angle in radians</param> |
||
739 | public void SetFOVVerticalAngle(float angle) |
||
740 | { |
||
741 | OpenMetaverse.Packets.AgentFOVPacket msg = new OpenMetaverse.Packets.AgentFOVPacket(); |
||
742 | msg.AgentData.AgentID = Client.Self.AgentID; |
||
743 | msg.AgentData.SessionID = Client.Self.SessionID; |
||
744 | msg.AgentData.CircuitCode = Client.Network.CircuitCode; |
||
745 | msg.FOVBlock.GenCounter = 0; |
||
746 | msg.FOVBlock.VerticalAngle = angle; |
||
747 | Client.Network.SendPacket(msg); |
||
748 | } |
||
749 | |||
750 | private void UpdateTimer_Elapsed(object obj) |
||
751 | { |
||
752 | if (Client.Network.Connected && Client.Settings.SEND_AGENT_UPDATES) |
||
753 | { |
||
754 | //Send an AgentUpdate packet |
||
755 | SendUpdate(false, Client.Network.CurrentSim); |
||
756 | } |
||
757 | } |
||
758 | } |
||
759 | } |
||
760 | } |