00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "driveInterface.h"
00016 #include "config_tform.h"
00017
00018 #include "compose_matrix.h"
00019 #include "mouseAndKeyboard.h"
00020 #include "mouseData.h"
00021 #include "clockObject.h"
00022 #include "modifierButtons.h"
00023 #include "keyboardButton.h"
00024 #include "mouseButton.h"
00025 #include "buttonEventList.h"
00026 #include "dataNodeTransmit.h"
00027 #include "dataGraphTraverser.h"
00028
00029 TypeHandle DriveInterface::_type_handle;
00030 const PN_stdfloat DriveInterface::_hpr_quantize = 0.001;
00031
00032 DriveInterface::KeyHeld::
00033 KeyHeld() {
00034 _down = false;
00035 _changed_time = 0.0f;
00036 _effect = 0.0f;
00037 _effect_at_change = 0.0f;
00038 }
00039
00040 PN_stdfloat DriveInterface::KeyHeld::
00041 get_effect(PN_stdfloat ramp_up_time, PN_stdfloat ramp_down_time) {
00042 double elapsed = ClockObject::get_global_clock()->get_frame_time() - _changed_time;
00043 if (_down) {
00044
00045
00046 if (ramp_up_time == 0.0f) {
00047 _effect = 1.0f;
00048
00049 } else {
00050 PN_stdfloat change = elapsed / ramp_up_time;
00051 _effect = min(_effect_at_change + change, (PN_stdfloat)1.0);
00052 }
00053 } else {
00054
00055
00056 if (ramp_down_time == 0.0f) {
00057 _effect = 0.0f;
00058
00059 } else {
00060 PN_stdfloat change = elapsed / ramp_down_time;
00061 _effect = max(_effect_at_change - change, (PN_stdfloat)0.0);
00062 }
00063 }
00064 return _effect;
00065 }
00066
00067 void DriveInterface::KeyHeld::
00068 set_key(bool down) {
00069 if (_down != down) {
00070 _down = down;
00071 _changed_time = ClockObject::get_global_clock()->get_frame_time();
00072 _effect_at_change = _effect;
00073 }
00074 }
00075
00076 void DriveInterface::KeyHeld::
00077 clear() {
00078 _down = false;
00079 _changed_time = 0.0f;
00080 _effect = 0.0f;
00081 _effect_at_change = 0.0f;
00082 }
00083
00084 bool DriveInterface::KeyHeld::
00085 operator < (const DriveInterface::KeyHeld &other) const {
00086 if (_down != other._down) {
00087
00088
00089 return _down;
00090 }
00091
00092
00093 return _changed_time > other._changed_time;
00094 }
00095
00096
00097
00098
00099
00100
00101 DriveInterface::
00102 DriveInterface(const string &name) :
00103 MouseInterfaceNode(name)
00104 {
00105 _xy_input = define_input("xy", EventStoreVec2::get_class_type());
00106 _button_events_input = define_input("button_events", ButtonEventList::get_class_type());
00107
00108 _transform_output = define_output("transform", TransformState::get_class_type());
00109 _velocity_output = define_output("velocity", EventStoreVec3::get_class_type());
00110
00111 _transform = TransformState::make_identity();
00112 _velocity = new EventStoreVec3(LVector3::zero());
00113
00114 _forward_speed = drive_forward_speed;
00115 _reverse_speed = drive_reverse_speed;
00116 _rotate_speed = drive_rotate_speed;
00117 _vertical_dead_zone = drive_vertical_dead_zone;
00118 _horizontal_dead_zone = drive_horizontal_dead_zone;
00119 _vertical_center = drive_vertical_center;
00120 _horizontal_center = drive_horizontal_center;
00121
00122 _vertical_ramp_up_time = drive_vertical_ramp_up_time;
00123 _vertical_ramp_down_time = drive_vertical_ramp_down_time;
00124 _horizontal_ramp_up_time = drive_horizontal_ramp_up_time;
00125 _horizontal_ramp_down_time = drive_horizontal_ramp_down_time;
00126
00127 _speed = 0.0f;
00128 _rot_speed = 0.0f;
00129
00130 _xyz.set(0.0f, 0.0f, 0.0f);
00131 _hpr.set(0.0f, 0.0f, 0.0f);
00132
00133 _ignore_mouse = false;
00134 _force_mouse = false;
00135 _stop_this_frame = false;
00136
00137 watch_button(MouseButton::one());
00138 }
00139
00140
00141
00142
00143
00144
00145
00146
00147 DriveInterface::
00148 ~DriveInterface() {
00149 }
00150
00151
00152
00153
00154
00155
00156
00157 void DriveInterface::
00158 reset() {
00159 _xyz.set(0.0f, 0.0f, 0.0f);
00160 _hpr.set(0.0f, 0.0f, 0.0f);
00161 _up_arrow.clear();
00162 _down_arrow.clear();
00163 _left_arrow.clear();
00164 _right_arrow.clear();
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 void DriveInterface::
00175 set_force_roll(PN_stdfloat) {
00176 }
00177
00178
00179
00180
00181
00182
00183 void DriveInterface::
00184 set_mat(const LMatrix4 &mat) {
00185 LVecBase3 scale, shear;
00186 decompose_matrix(mat, scale, shear, _hpr, _xyz);
00187 }
00188
00189
00190
00191
00192
00193
00194 const LMatrix4 &DriveInterface::
00195 get_mat() {
00196 compose_matrix(_mat,
00197 LVecBase3(1.0f, 1.0f, 1.0f),
00198 LVecBase3(0.0f, 0.0f, 0.0f),
00199 _hpr, _xyz);
00200 return _mat;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 void DriveInterface::
00213 force_dgraph() {
00214 _transform = TransformState::make_pos_hpr(_xyz, _hpr);
00215 _velocity->set_value(_vel);
00216
00217 DataNodeTransmit output;
00218 output.reserve(get_num_outputs());
00219 output.set_data(_transform_output, EventParameter(_transform));
00220 output.set_data(_velocity_output, EventParameter(_velocity));
00221
00222 DataGraphTraverser dg_trav(Thread::get_current_thread());
00223 dg_trav.traverse_below(this, output);
00224 dg_trav.collect_leftovers();
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 void DriveInterface::
00236 apply(double x, double y, bool any_button) {
00237
00238 _speed = 0.0f;
00239 _rot_speed = 0.0f;
00240
00241 if (any_button || _force_mouse) {
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 PN_stdfloat dead_zone_top = _vertical_center + _vertical_dead_zone;
00253 PN_stdfloat dead_zone_bottom = _vertical_center - _vertical_dead_zone;
00254
00255 if (y >= dead_zone_top) {
00256
00257
00258 PN_stdfloat throttle =
00259
00260 (min(y, 1.0) - dead_zone_top) /
00261 (1.0f - dead_zone_top);
00262 _speed = throttle * _forward_speed;
00263
00264 } else if (y <= dead_zone_bottom) {
00265
00266 PN_stdfloat throttle =
00267 (max(y, -1.0) - dead_zone_bottom) /
00268 (-1.0f - dead_zone_bottom);
00269 _speed = -throttle * _reverse_speed;
00270 }
00271
00272
00273
00274 PN_stdfloat dead_zone_right = _horizontal_center + _horizontal_dead_zone;
00275 PN_stdfloat dead_zone_left = _horizontal_center - _horizontal_dead_zone;
00276
00277 if (x >= dead_zone_right) {
00278
00279
00280
00281 PN_stdfloat throttle =
00282 (min(x, 1.0) - dead_zone_right) /
00283 (1.0f - dead_zone_right);
00284 _rot_speed = throttle * _rotate_speed;
00285
00286 } else if (x <= dead_zone_left) {
00287
00288 PN_stdfloat throttle =
00289 (max(x, -1.0) - dead_zone_left) /
00290 (-1.0f - dead_zone_left);
00291 _rot_speed = -throttle * _rotate_speed;
00292 }
00293
00294 } else {
00295
00296
00297
00298
00299 PN_stdfloat throttle;
00300
00301 if (_up_arrow < _down_arrow) {
00302 throttle = _up_arrow.get_effect(_vertical_ramp_up_time,
00303 _vertical_ramp_down_time);
00304 _speed = throttle * _forward_speed;
00305 _down_arrow._effect = 0.0f;
00306
00307 } else {
00308 throttle = _down_arrow.get_effect(_vertical_ramp_up_time,
00309 _vertical_ramp_down_time);
00310 _speed = -throttle * _reverse_speed;
00311 _up_arrow._effect = 0.0f;
00312 }
00313
00314
00315 if (_right_arrow < _left_arrow) {
00316 throttle = _right_arrow.get_effect(_horizontal_ramp_up_time,
00317 _horizontal_ramp_down_time);
00318 _rot_speed = throttle * _rotate_speed;
00319 _left_arrow._effect = 0.0f;
00320
00321 } else {
00322 throttle = _left_arrow.get_effect(_horizontal_ramp_up_time,
00323 _horizontal_ramp_down_time);
00324 _rot_speed = -throttle * _rotate_speed;
00325 _right_arrow._effect = 0.0f;
00326 }
00327 _right_arrow._effect = throttle;
00328 _left_arrow._effect = throttle;
00329 }
00330
00331 if (_speed == 0.0f && _rot_speed == 0.0f) {
00332 _vel.set(0.0f, 0.0f, 0.0f);
00333 return;
00334 }
00335
00336
00337 PN_stdfloat distance = ClockObject::get_global_clock()->get_dt() * _speed;
00338 PN_stdfloat rotation = ClockObject::get_global_clock()->get_dt() * _rot_speed;
00339 if (_stop_this_frame) {
00340 distance = 0.0f;
00341 rotation = 0.0f;
00342 _stop_this_frame = false;
00343 }
00344
00345
00346
00347
00348
00349 LMatrix3 rot_mat;
00350 rot_mat.set_rotate_mat_normaxis(_hpr[0], LVector3::up());
00351
00352
00353 _vel = LVector3::forward() * distance;
00354 LVector3 step = (_vel * rot_mat);
00355
00356
00357
00358
00359 switch (get_default_coordinate_system()) {
00360 case CS_zup_right:
00361 case CS_zup_left:
00362 step[2] = 0.0f;
00363 break;
00364
00365 case CS_yup_right:
00366 case CS_yup_left:
00367 step[1] = 0.0f;
00368 break;
00369
00370 default:
00371 break;
00372 }
00373
00374 _xyz += step;
00375 _hpr[0] -= rotation;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 void DriveInterface::
00392 do_transmit_data(DataGraphTraverser *, const DataNodeTransmit &input,
00393 DataNodeTransmit &output) {
00394
00395 bool required_buttons_match;
00396 const ButtonEventList *button_events = check_button_events(input, required_buttons_match);
00397
00398
00399 double x = 0.0f;
00400 double y = 0.0f;
00401
00402
00403
00404 if (required_buttons_match && input.has_data(_xy_input)) {
00405 const EventStoreVec2 *xy;
00406 DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr());
00407 const LVecBase2 &p = xy->get_value();
00408 x = p[0];
00409 y = p[1];
00410
00411
00412 }
00413
00414
00415 if (required_buttons_match && button_events != (const ButtonEventList *)NULL) {
00416
00417 int num_events = button_events->get_num_events();
00418 for (int i = 0; i < num_events; i++) {
00419 const ButtonEvent &be = button_events->get_event(i);
00420 if (be._type != ButtonEvent::T_keystroke) {
00421 bool down = (be._type != ButtonEvent::T_up);
00422
00423 if (be._button == KeyboardButton::up()) {
00424 _up_arrow.set_key(down);
00425 } else if (be._button == KeyboardButton::down()) {
00426 _down_arrow.set_key(down);
00427 } else if (be._button == KeyboardButton::left()) {
00428 _left_arrow.set_key(down);
00429 } else if (be._button == KeyboardButton::right()) {
00430 _right_arrow.set_key(down);
00431 }
00432 }
00433 }
00434 }
00435
00436 apply(x, y, !_ignore_mouse && is_down(MouseButton::one()));
00437 _transform = TransformState::make_pos_hpr(_xyz, _hpr);
00438 _velocity->set_value(_vel);
00439 output.set_data(_transform_output, EventParameter(_transform));
00440 output.set_data(_velocity_output, EventParameter(_velocity));
00441 }