Skip to content

Commit

Permalink
InputSystem|Client: InputDevice initialization cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Nov 1, 2014
1 parent 0387374 commit 5780aab
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 140 deletions.
18 changes: 12 additions & 6 deletions doomsday/client/include/ui/dd_input.h
Expand Up @@ -299,7 +299,12 @@ class InputDevice
*/
InputDeviceButtonControl &button(de::dint id) const;

void initButtons(de::dint count);
/**
* Add a @a button control to the input device.
*
* @param button Button control to add. Ownership is given to the device.
*/
void addButton(InputDeviceButtonControl *button);

/**
* Returns the number of button controls of the device.
Expand All @@ -320,7 +325,12 @@ class InputDevice
*/
InputDeviceHatControl &hat(de::dint id) const;

void initHats(de::dint count);
/**
* Add a @a hat control to the input device.
*
* @param hat Hat control to add. Ownership is given to the device.
*/
void addHat(InputDeviceHatControl *hat);

/**
* Returns the number of hat controls of the device.
Expand Down Expand Up @@ -586,10 +596,6 @@ void I_InitAllDevices();
*/
void I_ShutdownAllDevices();

void I_ResetAllDevices();

void I_ClearAllDeviceContextAssociations();

/**
* Lookup an InputDevice by it's unique @a id.
*/
Expand Down
19 changes: 16 additions & 3 deletions doomsday/client/src/ui/b_context.cpp
Expand Up @@ -55,9 +55,18 @@ void B_DestroyAllContexts()

void B_UpdateAllDeviceStateAssociations()
{
I_ClearAllDeviceContextAssociations();
// Clear all existing associations.
I_ForAllDevices([] (InputDevice &device)
{
device.forAllControls([] (InputDeviceControl &control)
{
control.clearBindContextAssociation();
return LoopContinue;
});
return LoopContinue;
});

// We need to iterate through all the device bindings in all context.
// We need to iterate through all the device bindings in all contexts.
for(int i = 0; i < bindContextCount; ++i)
{
bcontext_t *bc = bindContexts[i];
Expand Down Expand Up @@ -279,7 +288,11 @@ void B_ActivateContext(bcontext_t *bc, dd_bool doActivate)

if(bc->flags & BCF_ACQUIRE_ALL)
{
I_ResetAllDevices();
I_ForAllDevices([] (InputDevice &device)
{
device.reset();
return LoopContinue;
});
}
}

Expand Down
7 changes: 6 additions & 1 deletion doomsday/client/src/ui/clientwindow.cpp
Expand Up @@ -454,7 +454,12 @@ DENG2_PIMPL(ClientWindow)
if(!hasFocus)
{
I_ClearEvents();
I_ResetAllDevices();
I_ForAllDevices([] (InputDevice &device)
{
device.reset();
return LoopContinue;
});

canvas.trapMouse(false);
}
else if(self.isFullScreen() && !taskBar->isOpen())
Expand Down
214 changes: 120 additions & 94 deletions doomsday/client/src/ui/dd_input.cpp
Expand Up @@ -752,15 +752,11 @@ InputDeviceButtonControl &InputDevice::button(dint id) const
throw MissingControlError("InputDevice::button", "Invalid id:" + String::number(id));
}

void InputDevice::initButtons(int count)
void InputDevice::addButton(InputDeviceButtonControl *button)
{
DENG2_ASSERT(d->buttons.isEmpty());
for(int i = 0; i < count; ++i)
{
auto *button = new InputDeviceButtonControl;
d->buttons.append(button);
button->setDevice(this);
}
if(!button) return;
d->buttons.append(button);
button->setDevice(this);
}

int InputDevice::buttonCount() const
Expand All @@ -780,15 +776,11 @@ InputDeviceHatControl &InputDevice::hat(dint id) const
throw MissingControlError("InputDevice::hat", "Invalid id:" + String::number(id));
}

void InputDevice::initHats(int count)
void InputDevice::addHat(InputDeviceHatControl *hat)
{
DENG2_ASSERT(d->hats.isEmpty());
for(int i = 0; i < count; ++i)
{
auto *hat = new InputDeviceHatControl;
d->hats.append(hat);
hat->setDevice(this);
}
if(!hat) return;
d->hats.append(hat);
hat->setDevice(this);
}

int InputDevice::hatCount() const
Expand Down Expand Up @@ -866,24 +858,31 @@ static byte devRendMouseState; ///< cvar
static byte devRendJoyState; ///< cvar
#endif

void I_InitAllDevices()
static InputDevice *makeKeyboard(String const &name, String const &title = "")
{
// Allow re-init.
I_ShutdownAllDevices();
InputDevice *keyboard = new InputDevice(name);

keyboard->setTitle(title);

// DDKEYs are used as button indices.
for(int i = 0; i < 256; ++i)
{
keyboard->addButton(new InputDeviceButtonControl);
}

return keyboard;
}

static InputDevice *makeMouse(String const &name, String const &title = "")
{
InputDevice *mouse = new InputDevice(name);

// The keyboard is always assumed to be present.
// DDKEYs are used as key indices.
InputDevice *keyboard;
devices.append(keyboard = new InputDevice("key"));
keyboard->activate();
keyboard->setTitle("Keyboard");
keyboard->initButtons(256);
mouse->setTitle(title);

// The mouse may not be active.
InputDevice *mouse;
devices.append(mouse = new InputDevice("mouse"));
mouse->setTitle("Mouse");
mouse->initButtons(IMB_MAXBUTTONS);
for(int i = 0; i < IMB_MAXBUTTONS; ++i)
{
mouse->addButton(new InputDeviceButtonControl);
}

// Some of the mouse buttons have symbolic names.
mouse->button(IMB_LEFT ).setName("left");
Expand All @@ -905,65 +904,112 @@ void I_InitAllDevices()
//axis->setFilter(1); // On by default.
axis->setScale(1.f/1000);

// Register console variables for the axis settings.
mouse->consoleRegister();
return mouse;
}

if(Mouse_IsPresent())
mouse->activate();
static InputDevice *makeJoystick(String const &name, String const &title = "")
{
InputDevice *joy = new InputDevice(name);

// TODO: Add support for several joysticks.
joy->setTitle(title);

for(int i = 0; i < IJOY_MAXBUTTONS; ++i)
{
InputDevice *joy;
devices.append(joy = new InputDevice("joy"));
joy->setTitle("Joystick");
joy->initButtons(IJOY_MAXBUTTONS);
joy->addButton(new InputDeviceButtonControl);
}

for(int i = 0; i < IJOY_MAXAXES; ++i)
for(int i = 0; i < IJOY_MAXAXES; ++i)
{
char name[32];
if(i < 4)
{
char name[32];
if(i < 4)
{
strcpy(name, i == 0? "x" : i == 1? "y" : i == 2? "z" : "w");
}
else
{
sprintf(name, "axis%02i", i + 1);
}
joy->addAxis(axis = new InputDeviceAxisControl(name, InputDeviceAxisControl::Stick));
axis->setScale(1.0f / IJOY_AXISMAX);
axis->setDeadZone(DEFAULT_JOYSTICK_DEADZONE);
strcpy(name, i == 0? "x" : i == 1? "y" : i == 2? "z" : "w");
}
else
{
sprintf(name, "axis%02i", i + 1);
}
auto *axis = new InputDeviceAxisControl(name, InputDeviceAxisControl::Stick);
joy->addAxis(axis);
axis->setScale(1.0f / IJOY_AXISMAX);
axis->setDeadZone(DEFAULT_JOYSTICK_DEADZONE);
}

// Register console variables for the axis settings.
joy->consoleRegister();
for(int i = 0; i < IJOY_MAXHATS; ++i)
{
joy->addHat(new InputDeviceHatControl);
}

joy->initHats(IJOY_MAXHATS);
return joy;
}

// The joystick may not be active.
if(Joystick_IsPresent())
joy->activate();
static InputDevice *makeHeadTracker(String const &name, String const &title)
{
InputDevice *head = new InputDevice(name);

devices.append(new InputDevice("joy2"));
devices.append(new InputDevice("joy3"));
devices.append(new InputDevice("joy4"));
}
head->setTitle(title);

auto *axis = new InputDeviceAxisControl("yaw", InputDeviceAxisControl::Stick);
head->addAxis(axis);
axis->setRawInput();

head->addAxis(axis = new InputDeviceAxisControl("pitch", InputDeviceAxisControl::Stick));
axis->setRawInput();

// Set up a head tracking device.
head->addAxis(axis = new InputDeviceAxisControl("roll", InputDeviceAxisControl::Stick));
axis->setRawInput();

return head;
}

/**
* @param device InputDevice to add.
* @return Same as @a device for caller convenience.
*/
static InputDevice *addDevice(InputDevice *device)
{
if(device)
{
InputDevice *head;
devices.append(head = new InputDevice("head"));
head->setTitle("Head Tracker");
if(!devices.contains(device))
{
// Ensure the name is unique.
for(InputDevice *otherDevice : devices)
{
if(!otherDevice->name().compareWithoutCase(device->name()))
{
throw Error("InputSystem::addInputDevice", "Multiple devices with name:" + device->name() + " cannot coexist");
}
}

// Add this device to the collection.
devices.append(device);
}
}
return device;
}

void I_InitAllDevices()
{
// Allow re-init.
I_ShutdownAllDevices();

head->addAxis(axis = new InputDeviceAxisControl("yaw", InputDeviceAxisControl::Stick));
axis->setRawInput();
addDevice(makeKeyboard("key", "Keyboard"))->activate(); // A keyboard is assumed to always be present.

head->addAxis(axis = new InputDeviceAxisControl("pitch", InputDeviceAxisControl::Stick));
axis->setRawInput();
addDevice(makeMouse("mouse", "Mouse"))->activate(Mouse_IsPresent()); // A mouse may not be present.

head->addAxis(axis = new InputDeviceAxisControl("roll", InputDeviceAxisControl::Stick));
axis->setRawInput();
addDevice(makeJoystick("joy", "Joystick"))->activate(Joystick_IsPresent()); // A joystick may not be present.

head->consoleRegister();
/// @todo: Add support for multiple joysticks (just some generics, for now).
addDevice(new InputDevice("joy2"));
addDevice(new InputDevice("joy3"));
addDevice(new InputDevice("joy4"));

addDevice(makeHeadTracker("head", "Head Tracker")); // Head trackers are activated later.

// Register console variables for the controls of all devices.
for(InputDevice *device : devices)
{
device->consoleRegister();
}
}

Expand Down Expand Up @@ -1000,14 +1046,6 @@ LoopResult I_ForAllDevices(std::function<LoopResult (InputDevice &)> func)
return LoopContinue;
}

void I_ResetAllDevices()
{
for(InputDevice *dev : devices)
{
dev->reset();
}
}

bool I_ShiftDown()
{
return shiftDown;
Expand Down Expand Up @@ -1064,18 +1102,6 @@ void I_TrackInput(ddevent_t *ev)
}
}

void I_ClearAllDeviceContextAssociations()
{
for(InputDevice *dev : devices)
{
dev->forAllControls([] (InputDeviceControl &control)
{
control.clearBindContextAssociation();
return LoopContinue;
});
}
}

#if 0
static int DD_KeyOrCode(char *token)
{
Expand Down

0 comments on commit 5780aab

Please sign in to comment.