| 1 | // |
| 2 | // controllerwidget.cpp: A widget for changing "Controller" configuration |
| 3 | // |
| 4 | // Part of the Virtual Jaguar Project |
| 5 | // (C) 2011 Underground Software |
| 6 | // See the README and GPLv3 files for licensing and warranty information |
| 7 | // |
| 8 | // JLH = James Hammons <jlhamm@acm.org> |
| 9 | // |
| 10 | // WHO WHEN WHAT |
| 11 | // --- ---------- ------------------------------------------------------------ |
| 12 | // JLH 07/20/2011 Created this file |
| 13 | // |
| 14 | |
| 15 | #include "controllerwidget.h" |
| 16 | |
| 17 | #include "joystick.h" |
| 18 | #include "gamepad.h" |
| 19 | #include "keygrabber.h" |
| 20 | |
| 21 | |
| 22 | // These tables are used to convert Qt keycodes into human readable form. Note |
| 23 | // that a lot of these are just filler. |
| 24 | char ControllerWidget::keyName1[96][16] = { |
| 25 | "Space", |
| 26 | "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", |
| 27 | "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", |
| 28 | "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", |
| 29 | "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", |
| 30 | "[", "\\", "]", "^", "_", "`", |
| 31 | "$61", "$62", "$63", "$64", "$65", "$66", "$67", "$68", "$69", "$6A", "$6B", "$6C", "$6D", |
| 32 | "$6E", "$6F", "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", "$78", "$79", "$7A", |
| 33 | "{", "|", "}", "~" |
| 34 | }; |
| 35 | |
| 36 | char ControllerWidget::keyName2[64][16] = { |
| 37 | "Esc", "Tab", "BTab", "BS", "Ret", "Ent", "Ins", "Del", "Pause", "Prt", "SRq", "Clr", |
| 38 | "$C", "$D", "$E", "$F", "Hm", "End", "Lf", "Up", "Rt", "Dn", "PgU", "PgD", "$18", |
| 39 | "$19", "$1A", "$1B", "$1C", "$1D", "$1E", "$1F", "Shf", "Ctl", "Mta", "Alt", |
| 40 | "Cap", "Num", "ScL", "$27", "$28", "$29", "$2A", "$2B", "$2C", "$2D", "$2E", "$2F", |
| 41 | "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", |
| 42 | "F14", "F15", "F16" |
| 43 | }; |
| 44 | |
| 45 | char ControllerWidget::hatName[4][16] = { "Up", "Rt", "Dn", "Lf" }; |
| 46 | |
| 47 | char ControllerWidget::axisName[2][8] = { "+", "-" }; |
| 48 | |
| 49 | // This is hard-coded crap. It's crap-tastic! |
| 50 | // These are the positions to draw the button names at, ordered by the BUTTON_* |
| 51 | // sequence found in joystick.h. |
| 52 | int ControllerWidget::buttonPos[21][2] = { { 74, 32 }, { 71, 67 }, { 53, 49 }, { 93, 49 }, |
| 53 | { 110, 200 }, { 110, 175 }, { 110, 151 }, { 110, 126 }, |
| 54 | { 148, 200 }, { 148, 175 }, { 148, 151 }, { 148, 126 }, |
| 55 | { 186, 200 }, { 186, 175 }, { 186, 151 }, { 186, 126 }, |
| 56 | { 234, 31 }, { 216, 51 }, { 199, 71 }, { 164-11, 101-30 }, { 141-11, 108+13-30 } |
| 57 | }; |
| 58 | |
| 59 | |
| 60 | ControllerWidget::ControllerWidget(QWidget * parent/*= 0*/): QWidget(parent), |
| 61 | controllerPic(":/res/controller.png"), widgetSize(controllerPic.size()), |
| 62 | keyToHighlight(-1), mouseDown(false) |
| 63 | { |
| 64 | // Seems we have to pad this stuff, otherwise it clips on the right side |
| 65 | widgetSize += QSize(4, 4); |
| 66 | // We want to know when the mouse is moving over our widget... |
| 67 | setMouseTracking(true); |
| 68 | //nope |
| 69 | //setFixedSize(widgetSize); |
| 70 | } |
| 71 | |
| 72 | |
| 73 | ControllerWidget::~ControllerWidget() |
| 74 | { |
| 75 | } |
| 76 | |
| 77 | |
| 78 | QSize ControllerWidget::sizeHint(void) const |
| 79 | { |
| 80 | return widgetSize; |
| 81 | } |
| 82 | |
| 83 | |
| 84 | QSizePolicy ControllerWidget::sizePolicy(void) const |
| 85 | { |
| 86 | return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); |
| 87 | } |
| 88 | |
| 89 | |
| 90 | void ControllerWidget::paintEvent(QPaintEvent * /*event*/) |
| 91 | { |
| 92 | QPainter painter(this); |
| 93 | painter.setRenderHint(QPainter::Antialiasing); |
| 94 | painter.drawImage(QPoint(0, 0), controllerPic); |
| 95 | |
| 96 | // Bump up the size of the default font... |
| 97 | QFont font = painter.font(); |
| 98 | font.setPixelSize(15); |
| 99 | font.setBold(true); |
| 100 | painter.setFont(font); |
| 101 | // painter.setPen(QColor(48, 255, 255, 255)); // This is R,G,B,A |
| 102 | painter.setPen(QColor(0, 0, 0, 255)); // This is R,G,B,A |
| 103 | painter.setBrush(QBrush(QColor(48, 255, 255, 255))); |
| 104 | |
| 105 | // First, draw black oversize line, then dot, then colored line |
| 106 | QPen blackPen(QColor(0, 0, 0, 255)); |
| 107 | blackPen.setWidth(4); |
| 108 | QPen colorPen(QColor(48, 255, 255, 255)); |
| 109 | colorPen.setWidth(2); |
| 110 | QLine line(QPoint(141-11, 100-30), QPoint(141-11, 108+5-30)); |
| 111 | |
| 112 | painter.setPen(blackPen); |
| 113 | painter.drawLine(line); |
| 114 | blackPen.setWidth(1); |
| 115 | painter.setPen(blackPen); |
| 116 | painter.drawEllipse(QPoint(141-11, 100-30), 4, 4); |
| 117 | painter.setPen(colorPen); |
| 118 | painter.drawLine(line); |
| 119 | |
| 120 | //#define DEBUG_CWPAINT |
| 121 | #ifdef DEBUG_CWPAINT |
| 122 | printf("------------------------------\n"); |
| 123 | #endif |
| 124 | for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++) |
| 125 | { |
| 126 | if (keyToHighlight == i) |
| 127 | { |
| 128 | painter.setPen(QColor(255, 48, 255, 255)); // This is R,G,B,A |
| 129 | font.setPixelSize(mouseDown ? 15 : 18); |
| 130 | painter.setFont(font); |
| 131 | } |
| 132 | else |
| 133 | { |
| 134 | painter.setPen(QColor(48, 255, 255, 255)); // This is R,G,B,A |
| 135 | font.setPixelSize(15); |
| 136 | painter.setFont(font); |
| 137 | } |
| 138 | |
| 139 | #ifdef DEBUG_CWPAINT |
| 140 | printf("key %02i: ", i); |
| 141 | #endif |
| 142 | |
| 143 | if (keys[i] < 0x80) |
| 144 | #ifdef DEBUG_CWPAINT |
| 145 | { |
| 146 | printf("Drawing a key < 0x80 [keys[i]=%X, keyname=%s]...\n", keys[i], keyName1[keys[i] - 0x20]); |
| 147 | #endif |
| 148 | DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], |
| 149 | QString(keyName1[keys[i] - 0x20])); |
| 150 | #ifdef DEBUG_CWPAINT |
| 151 | } |
| 152 | #endif |
| 153 | else if ((keys[i] & 0xFFFFFF00) == 0x01000000) |
| 154 | { |
| 155 | #ifdef DEBUG_CWPAINT |
| 156 | printf("Drawing a key with bit 48 set...\n"); |
| 157 | #endif |
| 158 | DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], |
| 159 | QString(keyName2[keys[i] & 0x3F])); |
| 160 | } |
| 161 | #if 1 |
| 162 | else if (keys[i] & JOY_BUTTON) |
| 163 | { |
| 164 | #ifdef DEBUG_CWPAINT |
| 165 | printf("Drawing a joystick button...\n"); |
| 166 | #endif |
| 167 | DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], |
| 168 | QString("JB%1").arg(keys[i] & JOY_BUTTON_MASK)); |
| 169 | } |
| 170 | else if (keys[i] & JOY_HAT) |
| 171 | { |
| 172 | #ifdef DEBUG_CWPAINT |
| 173 | printf("Drawing a joystick hat...\n"); |
| 174 | #endif |
| 175 | DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], |
| 176 | QString("j%1").arg(hatName[keys[i] & JOY_BUTTON_MASK])); |
| 177 | } |
| 178 | else if (keys[i] & JOY_AXIS) |
| 179 | { |
| 180 | #ifdef DEBUG_CWPAINT |
| 181 | printf("Drawing a joystick axis...\n"); |
| 182 | #endif |
| 183 | DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], |
| 184 | QString("JA%1%2").arg((keys[i] & JOY_AXISNUM_MASK) >> 1).arg(axisName[keys[i] & JOY_AXISDIR_MASK])); |
| 185 | } |
| 186 | #endif |
| 187 | else |
| 188 | #ifdef DEBUG_CWPAINT |
| 189 | { |
| 190 | printf("Drawing ???...\n"); |
| 191 | #endif |
| 192 | DrawBorderedText(painter, buttonPos[i][0], buttonPos[i][1], QString("???")); |
| 193 | #ifdef DEBUG_CWPAINT |
| 194 | } |
| 195 | #endif |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | |
| 200 | void ControllerWidget::mousePressEvent(QMouseEvent * /*event*/) |
| 201 | { |
| 202 | mouseDown = true; |
| 203 | update(); |
| 204 | } |
| 205 | |
| 206 | |
| 207 | void ControllerWidget::mouseReleaseEvent(QMouseEvent * /*event*/) |
| 208 | { |
| 209 | mouseDown = false; |
| 210 | // Spawning the keygrabber causes leaveEvent() to be called, so we need to |
| 211 | // save this |
| 212 | int keyToHighlightSave = keyToHighlight; |
| 213 | |
| 214 | KeyGrabber keyGrab(this); |
| 215 | keyGrab.SetKeyText(keyToHighlightSave); |
| 216 | keyGrab.exec(); |
| 217 | int key = keyGrab.key; |
| 218 | |
| 219 | if (key != Qt::Key_Escape) |
| 220 | { |
| 221 | keys[keyToHighlightSave] = key; |
| 222 | emit(KeyDefined(keyToHighlightSave, key)); |
| 223 | } |
| 224 | |
| 225 | keyToHighlight = keyToHighlightSave; |
| 226 | update(); |
| 227 | } |
| 228 | |
| 229 | |
| 230 | void ControllerWidget::mouseMoveEvent(QMouseEvent * event) |
| 231 | { |
| 232 | if (mouseDown) |
| 233 | return; |
| 234 | |
| 235 | // Save the current closest item |
| 236 | int keyToHighlightOld = keyToHighlight; |
| 237 | // Set up closest distance (this should be large enough) |
| 238 | double closest = 1e9; |
| 239 | |
| 240 | for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++) |
| 241 | { |
| 242 | // We loop through the button text positions, to see which one is |
| 243 | // closest. |
| 244 | double distX = (double)(event->x() - buttonPos[i][0]); |
| 245 | double distY = (double)(event->y() - buttonPos[i][1]); |
| 246 | double currentDistance = sqrt((distX * distX) + (distY * distY)); |
| 247 | |
| 248 | if (currentDistance < closest) |
| 249 | { |
| 250 | closest = currentDistance; |
| 251 | keyToHighlight = i; |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | if (keyToHighlightOld != keyToHighlight) |
| 256 | update(); |
| 257 | } |
| 258 | |
| 259 | |
| 260 | void ControllerWidget::leaveEvent(QEvent * /*event*/) |
| 261 | { |
| 262 | keyToHighlight = -1; |
| 263 | update(); |
| 264 | } |
| 265 | |
| 266 | |
| 267 | void ControllerWidget::DrawBorderedText(QPainter & painter, int x, int y, QString text) |
| 268 | { |
| 269 | // Text is drawn centered at (x, y) as well, using a bounding rect for the |
| 270 | // purpose. |
| 271 | QRect rect(0, 0, 60, 30); |
| 272 | QPen oldPen = painter.pen(); |
| 273 | painter.setPen(QColor(0, 0, 0, 255)); // This is R,G,B,A |
| 274 | |
| 275 | for(int i=-1; i<=1; i++) |
| 276 | { |
| 277 | for(int j=-1; j<=1; j++) |
| 278 | { |
| 279 | rect.moveCenter(QPoint(x + i, y + j)); |
| 280 | painter.drawText(rect, Qt::AlignCenter, text); |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | painter.setPen(oldPen); |
| 285 | rect.moveCenter(QPoint(x, y)); |
| 286 | painter.drawText(rect, Qt::AlignCenter, text); |
| 287 | } |
| 288 | |