mtr: abstracting the input layer

mtr: abstracting the input layer

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

Post Reply
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

mtr: abstracting the input layer

Post by hughperkins »

This is mostly a space for my jottings whilst I investigate to what extent it could be doable to abstract the input layer in Spring.

This is most definitely an mtr topic, so if it does appear feasible, then that's one less mtr topic :-)

This thread is in no way a commitment on my part to actually follow through and do this, so anyone that actually wants this done, don't get too excited :wink:

What is my goal?

From a functional perspective:
- make it possible to configure the keyboard, eg from an xml file
- for example:

<command name="assist" keycombo="a" />

- mousebuttons just become like any other button, they are abstracted away from their original physical source:

<command name="select" keycombo="mouseleft" />

- we could equally well tweak the configuration to be:

<command name="select" keycombo="mouseright" />

- we can have multiple combos for each command:

<command name="translate" keycombo="j" />
<command name="translate" keycombo="mousemiddle" />

- we can have multiple commands for each combo
-> because some commands are context-specific
-> this is where it starts getting very tricky

- also, another very tricky issue, do we have to support simultaneous key-pressed? ie, if a is left and s is back, should "a-s" be both left and back at the same tiime? probably. But, if alt-s is something, and ctrl-alt-s is something else, we don't want ctrl-alt-s to also call the alt-s handler. probably.

maybe we can group certain combinations in mutually exclusive groups, sort of like radio buttons for keycombos?

<command name="forward" keycombo="w" />
<command name="left" keycombo="a" />

<commandgroup type="mutuallyexclusive">
<command name="blah" keycombo="ctrl-b" />
<command name="foo" keycombo="shift-ctrl-b" />
</commandgroup>

or ... random thought, basically we find the combo match that 'eats' the most keys, and then match with all commands with that combo, then repeat for the remaining keys.

That would mean we could do:

<command name="forward" keycombo="w" />
<command name="left" keycombo="a" />
<command name="blah" keycombo="ctrl-a" />
<command name="foo" keycombo="shift-ctrl-a" />

a + w -> fires "left" and "forward"
ctrl + a + w -> fires "blah", but now "ctrl" and "a" are 'eaten', which leaves w, which fires "forward", so: "blah" and "forward"

... ok... but what if we have :-P :

<command name="forward" keycombo="w" />
<command name="left" keycombo="a" />
<command name="foo" keycombo="ctrl-b" />
<command name="blah" keycombo="ctrl-a" />

... and ctrl, a and b are down. Should we eat ctrl and b, firing "foo", leaving a, which fires "forward"? :-O

Surely, there are people who have done this before? There must be articles about this on the internet?

From a technical perspective:
- make the input model eventdriven (maybe this is already the case, I haven't looked in any detail yet (or at all, like I say, this thread in no way implies a commitment to do this...)
- the actual mouse position is harder to abstract, and I'm not going to attempt that, it is out of scope for this potential-project

Next steps

- get a list of all current spring keyboard and mouse commands, and to what extent they can be combined.
- add to the list additional desired possible keyboard and mouse commands.
- try to find a configuration file format and combo detecting heuristic which is consistent with these various command combinations.

Edit/update: ok, so it seems that keyboard mappings themselves are already configurable via uikeys.txt, so that solves most of the potential issues, so now all that's left is figuring out how to integrate mouse buttons into the same, or a similar framework. To do: what the issues making this tricky?

Edit: right, looking at uikeys.txt:
- keys are bound to events/actions
- however, some of the actions are called 'mouse1', 'mouse2', ... ;-)
- to abstract the mouse away, we'd need to go through each mouse1, mouse2 and mouse3 event and make invidiaul event /actions for each one.

So, the next thing to do is to detail each possible use of a mouse button, which I will attempt to do here:

The actiosn depend on the camera:

Classic Overhead(TA) Style camera:

- left click on unit, main terrain -> select unit
- left click on main terrain -> unselect all units
- right click on main terrain, unit already selected -> give move order to selected units
- left click on unit, minimap -> select unit
- left click on minimap terrain -> unselect all units
- middleclick on minimap terrain -> recentre main terrain on miinimap mouse pos
- middleclick and hold, on minimap terrain -> recentre main terrain on miinimap mouse pos, and continue to recentre as mouse moves
- middleclick, short, on main terrani -> change cursor mode to translate mode (my terminology, maybe a specific spring term for this?)
- middleclick, short, on unit, on main terrani -> change cursor mode to translate mode (my terminology, maybe a specific spring term for this?) (does same thing as clicking on main terrain itself)
- middleclick and hold, on main terrain -> drag main terrain around as mouse moves
- right click on main terrain, no units selected -> does nothiing
- left click on main terrain, no units selected -> does nothing
- right click on minimap, no units selected -> does nothiing
- left click on minimap, no units selected -> does nothing
- drag click on main terrain with left mouse button -> creates a drag rectangle -> on releasing button all units in rectangle are selected
- drag click on minimap with left mouse button -> creates a drag rectangle -> on releasing button all units in rectangle are selected
- left click on unit, main terrain, whilst unit already selected -> unit stays selected, but selection noise recurs
- dragselect on unit, main terrain, whilst unit already selected -> unit stays selected, but selection noise recurs
- ctrl + click on unit, unit not selected -> unit becomes selected
- ctrl + click on unit, unit selected -> unit becomes unselected
- ctrl + click on unit, unit not selected, other units selectd -> unit becomes selected, other units stay selected
- ctrl + click on unit, unit selected, other units selectd -> unit becomes unselected, other units stay selected
- click on unit, other units already seelcted -> unit selected, other units deselected
- unit selected, right click on other unit -> 'guard order' issued to selected unit (mouse cursor was showing 'guard' symbol')
- unit selected (=commander), with constructionorderbox, left click constructionorderbox -> mouse cursor cahnges to a poitner, with the target building hovering underneath the cursor, lets call that 'placement' mode
- unit selected, cursor in 'placement' mode, right-click main terrain -> nothing happens
- unit selected, cursor in 'placement' mode, left-click main terrain -> 'build' order for target building issued to selected units
- unit selected, cursor in 'placement' mode, shift + left-click main terrain -> 'build' order for target building added to build queue of selected units
- unit selected, cursor in 'placement' mode, shift + drag left button over terrain -> 'build' order for target building for all positions along the line (contiguous line of buildings), appended to end of unit's build queue ("line")
- 'placement' mode, shift ctl + drag left button over terrain ->("gridline")
- 'placement' mode, shift ctl alt + drag left button over terrain -> ("pereimter")
- 'placement' mode, shift alt + drag left button over terrain -> ("block")
- 'placement' mode, ctrl shift + left mouse button on unit -> ("wall")
- 'placement' mode, mouse 4 -> 'increasespacing'
- 'placement' mode, mouse 5 -> 'increasespacing'
- unit selected ,cursor in 'placement' mode, left-click constructionorderbox, cursor remains in placement mode, target building changes to newly clickc target building
- unit selected, cursor in 'placement' mode, left-click on illegal build location -> cursor switches away from 'placement' mode (to 'default' mode?), unit remains selected
- factory construction unit selected, left-click constructionorderbox -> 'build' order added to factory's bild queue, cursor stays in 'default'(?) mode
- factory construction unit selected, shift + left-click constructionorderbox -> 5 'build' orders added to factories bulid queue, cursor stays in 'default'(?) mode
- factory construction unit selected, ctrl + left-click constructionorderbox -> 20 'build' orders added to factories bulid queue, cursor stays in 'default'(?) mode
- factory construction unit selected, ctrl shift + left-click constructionorderbox -> 100 'build' orders added to factories bulid queue, cursor stays in 'default'(?) mode
- factory construction unit selected, alt + [ctrl][shift] + left-click constructionorderbox -> 'build' orders added to head of factories bulid queue, cursor stays in 'default'(?) mode
- factory construction unit selected, [ctrl][shift] + right-click constructionorderbox -> 'build' orders removed from head of factories bulid queue, cursor stays in 'default'(?) mode
- factory construction unit selected, right-click other unit -> 'guard' order sent to factory construction unit
- passive unit (solar cell) selected, right-click oother unit -> nothing happens
- mobile attack unit(tank) selected, right-clickc friendly unit -> 'guard' order sent to mobile attack unit
- passive unit (armrad) selected, right-click enemy unit -> nothing happens, also cursor stays a poniter over all units
- mobile attack unit(tank) selected, right-click enemy unit ->'attack' order given to selected units to attack target enemy unit
- factory unit selected, right click enemy unit -> 'moveto' order given to factory (and presumably to constructed units)
- factory unit selected, right click terrain -> 'moveto' order given to factory (and presumably to constructed units)
- ctrl + left click a selectedunit, other units selected -> other units stay selected, selected unit unselected
- ctrl + left click an unselectedunit, other units selected -> other units stay selected, unselected unit selected
- shift + left click a selectedunit, other units selected -> other units stay selected, selected unit stays selected
- shift + left click an unselectedunit, other units selected -> other units stay selected, unselected unit selected
- shift + control + left click units -> works same as control + left click units
- multiple units selected, ctrl + rright click terrain -> issue move order to all units, in such a way that all targets move at the same anglle for the same distance. the reference unit seems to be mobile units at priority.
- multiple units selected, shift + right click terrain -> adds 'moveto' order to order queue
- multiple units selected, drag right mouse button over the terrain -> draws a path along the terrain, issues a 'moveto' order to each unit to go to a different location along the path (wow! :-O )
- mutliple units slected, ctrl + drag right mouse button over the terrain -> does same as for without 'ctrl'
- mutliple untis selcted, shift +drag right mosue button over the terrain -> as for without 'shift', but adds the orders to the end of each unit's order queue
- multiple units sselected, drag left mouse button over the terrain -> creates a selection box, and unselects all units outside of box / selects all inside it

fps camera ('c' mode):

- left mouse button = fire

other cameras:

- left and right mouse button as for ota mode, but middle button effect is different
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: mtr: abstracting the input layer

Post by hughperkins »

Making a new post, since the old one was getting a bit slow to upload in its entirety at every posting...

Overall, it seems that:

- in some 'default' state, we have the following actions
- - select/deselect, modify selection (according to [ctrl][shift], and using left mouse button, or left mouse button drag to form selection rectangle)

- once a unit is selected:
- - selection actions remain possible
- - mouse cursor changes to some default action for the selected unit, according to whatever is under the cursor
- - right click triggers the default unit action on that location
- - also, possibility of dragging right mouse button for some actiosn, like moveto
- - also, modifiers, at least [ctrl], can affect the order created at the time of right-clicking/dragging
- - shift causes the order to be appended to the unit's order queue

- 'placement' mode -> when a mobile construciton unit is going to be told to build something
- - left click mosue button to build something
- - lots of modifiers possible (ctrl, shift, alt, mouse4, mouse5) at the time of left clicking
- - also, posibiltiy of dragging left mouse button
- - shift causes order to go to the end of the build queue

- 'placement' mode -> when a factory unit is selected, and a build target has been clicked
- - modifiers available: ctrl, shift, alt
- - left click: adds build orders to tail of queue
- - alt + left click: adds build orders to front of queue
- - right click : remvoes build orders from front of queue

cameras:
- cameras are controlled by middle mouse button, and scroll wheel, and a bunch of keyboard commands
- left mouse button can also be 'taken over' by the camera, for example for the fps c type camera

minimap vs terrain:
- minimap and terrain are essentially equivalent, as far as interface, with slight differences for the cameras.

Thinking about what 'action' names we could assign to the things listed above, maybe something like:

- in some 'default' state, we have the following actions
- - select/deselect, modify selection (according to [ctrl][shift], and using left mouse button, or left mouse button drag to form selection rectangle):
- - so, maybe something like:
- - 'addtargettoselection' (this would be assigned to buttons shift-mouse1 by default)
- - 'toggletargetinselection' (ctrl-mouse1)
- - 'selecttarget' (mouse1)
- - ... and then the drag is just using the same action combos

- - right click triggers the default unit action on that location
- - -> 'defaultaction' or 'action' or 'applyaction' or 'doaction', something like that (=mouse2)

- - also, possibility of dragging right mouse button for some actiosn, like moveto
- - -> still 'defaultaction' perhaps?

- - also, modifiers, at least [ctrl], can affect the order created at the time of right-clicking/dragging
- - >'secondaryaction' (ctrl)
- - shift causes the order to be appended to the unit's order queue
- - -> maybe 'shift' gets its own action?
- - -> or, maybe the action becomes 'appenddefaultaction' or 'queuedefaultaction' or 'queueaction', something like that

- 'placement' mode -> when a mobile construciton unit is going to be told to build something
- - left click mosue button to build something
- -> 'build' (mouse1)
- - shift causes order to go to the end of the build queue -> maybe should be factorized out? (different from factory, becaause in a factory, shift has meanings other than just append. oh: for mobile units too :-/)
- - how about, we have a special action modifier "doesnt_eat" or "passive" or something, taht means that the keys for that combo are not removed from the keys available from other combos
- - so, if "appendtoqueue" (=shift) is marked as "ismodifier", then the shift key is still available for other combos
- - ok, so:
'appendtobuildqueue' (keys = shift, 'ismodifier', 'doesnteatkeys')
- - lots of modifiers possible (ctrl, shift, alt, mouse4, mouse5) at the time of left clicking
- - also, posibiltiy of dragging left mouse button
- - -> 'buildline' (shift mouse1 + drag, hmmm, it seems that making it a 'drag' rather than a 'click' changes the action -> to be considered in technical implementation and config definition)
- - ->'buildgridline(shift ctrl mouse1 + drag)
- - ->'buildperimeter( shift ctrl alt mouse1 + drag)
- - ->'buildblock' (shift alt mouse1 + drag)
- - ->'buildwall' (shift ctrl mouse1 + mouse over target unit)
- - ->'buildincreasespacing' (mouse4)
- - ->'builddecreasespacing' (mouse5)
- maybe in all of these cases, the action doesn't need to declare that it is specific to a mouse drag, and the action listener handles this part?

- 'placement' mode -> when a factory unit is selected, and a build target has been clicked
- - left click: adds build orders to tail of queue
- - -> 'appendbuildorder' (mouse1)
- - modifiers available: ctrl, shift, alt
- - -> 'appendmultiplebuildordersmall' or 'appendfivebuildorders' (shift mouse1)
- - -> 'appendmultiplebuildordermedium' or 'appendtwentybuildorders' (ctrl mouse1)
- - -> 'appendmultiplebuildorderlarge' or 'appendhundredbuildorders' (shift ctl mouse1)
- - alt + left click: adds build orders to front of queue
- - -> we could factorize this, or not. if we can factorize it, maybe it is better? but harder to do 'right' and less flexible, so maybe:
- - -> 'appendbuildordertoqueuefront' (alt mouse1)
- - modifiers available: ctrl, shift, alt
- - -> 'appendmultiplebuildordersmalltoqueuefront' (alt shift mouse1)
- - -> 'appendmultiplebuildordermediumtoqueuefront' (alt ctrl mouse1)
- - -> 'appendmultiplebuildorderlargetoqueuefront' (alt shift ctrl mouse1)
- - right click : remvoes build orders from front of queue
- - -> 'removebuildorder' (mouse2)
- - -> 'removemultiplebuildordersmall' (shift mouse2)
- - -> 'removemultiplebuildordermedium' (ctrl mouse2)
- - -> 'removemultiplebuildorderlarge' (shift ctrl mouse2)

cameras:
- cameras are controlled by middle mouse button, and scroll wheel, and a bunch of keyboard commands
- - -> 'cameratoggle' or 'camerasecondary' or maybe actions per camera:
- - -> 'otacameratranslate' (j, or mouse3)
- - -> etc ...
- left mouse button can also be 'taken over' by the camera, for example for the fps c type camera
- - -> 'fpscamerafire' (mouse1)
Last edited by hughperkins on 01 Oct 2009, 18:22, edited 7 times in total.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: mtr: abstracting the input layer

Post by hughperkins »

Right, so next question I feel could be useful is: if I was desiging the system from scratch, what could be an ideal arcihtecture/ impelmentation which would meet the requireemtns?

Then I'll compare that to what currently exists, and see to what extent the differences are cool, and to what extent it might be useful to tweak certain points.

class InputButtons: abstracts away anything that is a button:
- keyboard
- mouse1, mouse2, mouse3, mouse4, mouse5 ...
- *maybe* the scroll-wheel, which I think functions as a button that goes up and down at each click (I can't really remember, maybe just leave the scroll-wheel for now, it works ok).

InputButtons publishes:
- an event 'button pressed'
- an event 'button released'
- a state isButtonPressed(buttonname)

next layer up: convert buttons into some sort of actions/combos, which is where it starts getting tricky.

thinking about it:
- ctrl, shift, alt are the only modifiers ever used
- for example, we don't have to handle combos like a + z, it's either a, or ctrl a, or ctrl shift a etc
- also, modifiers are never actiosn in themsevles, it's always shift-a or ctrl-a, never jsut shift

let's just start and see where it goes:

class InputActionPublisher
- converts 'buttons' into 'innputactoins'

InputActionPublisher publishes:
- an event 'inputactioninitiated'
- an event 'inputactionterminated'
- a state isInputActionActivated(inputaction)

It subscribes to InputButtons, and it's probably the only thing that does/should (?)

Right, this is the level of abstraction where classes are going to start subscribing to our events.

We also need something like:

Code: Select all

class UIMode
- enum ModeEnum{};
- ModeEnum getCurrentUIMode()
- setCurrentUIMode(ModeEnum )
... whichh will be changed at appropriate times, like say when we enter 'placement' mode


So, our subscribers will be things like:

Code: Select all

class OTACamera {
init(){
   InputActionPublisher.getInstace().subscribe( "otacamera", this ); // for receiving ctrl-f2
   InputActionPublisher.getInstace().subscribe( "camera-mode-toggle", this ); // for receiving an abstracted mouse2
}
}
selection... this is where it starts getting tricky....

Code: Select all

class Selection {
   init() {
      InputActionPublisher.getInstace().subscribe( "selecttarget", this );
      InputActionPublisher.getInstace().subscribe( "selectaddtargettoselection", this );
      InputActionPublisher.getInstace().subscribe( "selecttoggletargetinselection", this );
   }
}
building:

Code: Select all

class Builder {
   init() {
      InputActionPublisher.getInstace().subscribe( "build", this );
      InputActionPublisher.getInstace().subscribe( "buildline", this );
      InputActionPublisher.getInstace().subscribe( "buildgridline", this );
      InputActionPublisher.getInstace().subscribe( "buildperimeter", this );
      InputActionPublisher.getInstace().subscribe( "buildblock", this );
      InputActionPublisher.getInstace().subscribe( "buildwall", this );
      InputActionPublisher.getInstace().subscribe( "buildincreasespacing", this );
      InputActionPublisher.getInstace().subscribe( "buildreducespacing", this );

      InputActionPublisher.getInstace().subscribe( "appendbuildorder", this );
      InputActionPublisher.getInstace().subscribe( "appendmultiiplebuildorderssmall", this );
      InputActionPublisher.getInstace().subscribe( "appendmultiiplebuildordersmedium", this );
      InputActionPublisher.getInstace().subscribe( "appendmultiiplebuildorderslarge", this );

      InputActionPublisher.getInstace().subscribe( "removebuildorder", this );
      InputActionPublisher.getInstace().subscribe( "removemultiiplebuildorderssmall", this );
      InputActionPublisher.getInstace().subscribe( "removemultiiplebuildordersmedium", this );
      InputActionPublisher.getInstace().subscribe( "removemultiiplebuildorderslarge", this );
   }
}
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: mtr: abstracting the input layer

Post by hughperkins »

Providing backwards compatibility with uikeys.txt.

Three ways:

1. extend uikeys.txt (restrictive... but possible )

2. automatically populate uikeys.txt, and continue to read from it (hard...)

3. implement an interface, such as InputActionPublisher, and provide multiple implementations of it, switchable via the config.

By default, in the config:

Code: Select all

UseUIKeyHandler = 1
UseUnifiedButtonHandler = 0
or perhaps:

Code: Select all

UseUnifiedButtonHandler = 0
...then we switch between different implementations of InputActionPublisher according to the config.

UIKeysInputActionPublisher

UnifiedInputActionPublisher

The other classes simply use the InputActionPublisher interface, not knowing which concrete class is behind it.



Option 1 means less re-education for older users. Option 3 is more flexible.

Option 1 might be preferable, as long as there are no incompatibilities with the concepts and details in the new handles. Otherwise option 3 is maybe the preferable solution.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: mtr: abstracting the input layer

Post by hughperkins »

Relevant classes from current spring code:

Action: stores some sort of string command

Game/UI/KeyBindings:
- looks like the handler for UIKeys.txt:
- parses this file, pumps the bindings into:
-- KeyBindings::bindings
-- KeyBindings::hotkeys
-- KeyBindings::namedKeySets
-- KeyBindings::typeBindings
-- KeyBindings::statefulCommands
- provides methods like "Save", "Load"
- singleton

Game/SelectedUnits:
- handles unit selections
- methods like:
-- GetAvailableCommands()
-- AddUnit
-- RemoveUnit
-- ClearSelected
-- GetDefaultCmd
-- SendCommandToUnits

Sim/Units/CommandAI/CommandAI:
- might be what handle converting mouse input into build commands
- constructor takes in a CUnit* owner, so looks like CommandAI is bound to an instance of every unit, rather than being some singleton pattern
-- CommandAI constructor builds possibleCommands, which contains a list of valid commands, along with command id, mouse icon, tooltip, ...
- method GiveAllowedCommand:
-- tries to execute ExecuteStateCommand, and returns if succeeds
-- handles CMD_SELFD, CMD_SET_WANTED_SPEED, CMD_WAIT, CMD_INSERT and CMD_REMOVE. Returns after handling any of these
-- handles SHIFT: clears commandque (sic) if shift not held down
-- adds command to commanque
-- calls SlowUpdate
- method AllowedCommand seems to carry out command validation
- method ExecuteInsert calls FactoryCAI.InsertBuildCommand
-- it also tests for Alt, and does something about pos, so seems likely that it is modifying its action to insert at head of queue rather than to tail
-- it detects Ctrl && facCAI, so maybe handles adding lots of build command in one go?
- method ExecuteStateCommand ... ah-hah:
-- ExecuteStateCommand, case CMD_STOCKPILE:
--- rightmousebutton -> change *= -1
--- shiftkey -> change *= 5
--- controlkey -> change *= 20 (so, shift + ctrl meanas *5*20==*100)
-- also handles CMD_FIRE_STATE, CMD_MOVE_STATE, CMD_REPEAT, CMD_TRAJECTORY, CMD_ONOFF, CMD_CLOAK
- contain (mispelled) CCommandQueue commandQue

Comments related to abstracting the input layer:
- lots of stateful modifier stuff detected directly in the code
- we don't have to migrate this to use events
- we could simply have it detect the modifiers via the InputActionPublisher, eg:

Code: Select all

inputActionPublisher->isActivated('buildinserttofrontofqueue') // alt key
inputActionPublisher->isActivated('buildmultiplesmall') // shift key
inputActionPublisher->isActivated('buildmultiplemedium') // ctrl key
inputActionPublisher->isActivated('buildmultiplelarge') // shift ctrl key
inputActionPublisher->isActivated('appendtoqueue') // shift key
- we need to somehow make sure that none of these modifiers 'eat' keys, so that they are available to other subscribers (easy, but inflexible), or
- we need to make sure that the publisher is aware of who is the currently active subscriber (difficult)
- in the first case, that would mean that 'buildmultiplesmall' and 'buildmultiplemedium' would be activated when 'buildmultiplelarge' is activated, but the code could look like:

Code: Select all

if buildmultiplelarge:
else if buildmultiplemedium:
else if buildmultiplesmall:
end if
... but that would mean structural modification of the code in this instance, which means careful testing. It's not a simple search and replace through the code.
- or... we could only have two actions defined for this:
-- 'buildmultiplefirstmultiplier' (shift)
-- 'buildmultiplesecondmultiplier' (ctrl)
- ... then the code doesn't ahve to change structurally:
- ... hmmm, the key optiosn are embedded in 'c' so, needd to find out where 'c' came from
- ... hmmm, or..... maybe this is the easiest to implement:
-- we group actions together according to the different contexts
-- when we ask what actions are currently pressed, we supply our own context:

Code: Select all

<contextgroup name='Factory'>
<action name='buildmultiplesmall' keycombo='shift' />
<action name='buildmultiplemedium' keycombo='ctrl' />
<action name='buildmultiplelarge' keycombo='shift ctrl' />
</contextgroup>

Code: Select all

inputActionPublisher->isActivated(Context.Factory, 'buildmultiplelarge') // shift ctrl key
... and now, when 'buildmultiplelarge' is activated, the actionlistener will make it so that 'buildmultiplesmall' is no longer activated, since 'buildmultiplelarge' already 'ate' those keys
- actually, we don't even need to supply the context group to the function call:

Code: Select all

inputActionPublisher->isActivated( 'buildmultiplelarge') // shift ctrl key

Sim/Units/CommandAI/FactoryCAI:
- something to do with implementing automatic behavior of factories
- methods like:
-- InsertBuildCommand
-- RemovebuildCommand
-- GiveCommandReal
- contains CCommandQueue newUnitCommands
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: mtr: abstracting the input layer

Post by Tobi »

IMO most of this is already present and working good enough (keys can be bound/unbound at any time, resolving key to action is context sensitive, etc.); just making the mouse buttons and maybe scrollwheel event bindable would be an awesome addition.
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: mtr: abstracting the input layer

Post by lurker »

As far as actual files, I think we're pretty well covered between lua and .ini. Lua works quite well for config files and isn't any more verbose than xml.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: mtr: abstracting the input layer

Post by hughperkins »

Tobi wrote:IMO most of this is already present and working good enough (keys can be bound/unbound at any time, resolving key to action is context sensitive, etc.); just making the mouse buttons and maybe scrollwheel event bindable would be an awesome addition.
Yeah, my primary goal (maybe I should have stated it :-P ) is to make one of the mosue buttons (left or right, I dont care) mean both:
- default action
- build

... rather than having left button for build and right button for default action, which I find personally to be a 'wtf moment' when not having played Spring for a few months, or if I play actual TA for a bit, and come back to Spring, and I"m like 'wtf!'.

Pretty much all of the above paragraphs are primarly focused on mouse button stuff. I you check, there is quite a lot of detail involved in 'just' converting the mouse buttons into specific actions.

Note that the mouse butotns are already bindable, but in reverse!, as actions, ie you can do say:

Code: Select all

bind j ->  mouse3
... where mouse3 is an action!

... but you can't do say:

Code: Select all

bind mouse3 -> build
If there's an easy way to do that, then that's cool. AFAIK, personally I need to go through all the above analysis to make sure I don't get 95% through the implementation, and then something trivial doesn't fit into the framework.

For example, a few challenges:
- shift means both 'appendtobuildqueue', as a modifier, and also 'buildline' as a command
- sometimes mouse buttons are injected directly into commands by the engine :-O eg in CUnit::ChangeTeamReset
- and so on...

I feel if it was really trivial to make mousebuttons bindable someone would have done it already!

If I can implement bindable mousebuttons within the current uikeys framework then I will try to do it that way, but I can't promise that it will be.

What I propose is:
- I'm going to carry on going through this analysis
- draft a proposition for a new config file
-- and also, how this will be implemented in the code
- maybe see if I can shoehorn that into uikeys
-- ... or not
- propose the proposition
- get feedback
- create a fork
- see where we go from there
User avatar
zCram
Posts: 8
Joined: 22 Aug 2009, 20:56

Re: mtr: abstracting the input layer

Post by zCram »

Code: Select all

#define raise(x) kill(getpid(),x)
extern volatile unsigned nrproblems;
int solveProblem( uint8_t **problem_vector ) {
    if( usedXmlToSolve ) {
        nrproblems++;
        raise( SIGFAIL );
    }
    return( 0xa );
}
 
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: mtr: abstracting the input layer

Post by hughperkins »

Hi zcram, you obviously have experience writing C/C++. What are your thoughts on how to make it possible to configure the mouse buttons? I feel that ideally we'd be able to configure something like:

build: mouse1
defaultaction: mouse1
select: mouse1
unselect all: mouse2

I feel it's a challenging problem. If you succeed, I feel you'll have succeeded where *everyone* else has failed. From the faq:

http://springrts.com/wiki/FAQ:player

"What is with this weird right-click mode? I'm 'bout to break my keyboard.

"Sorry, you'll just have to get used to it. As of now it can't be changed." (emphasis mine)
User avatar
BrainDamage
Lobby Developer
Posts: 1164
Joined: 25 Sep 2006, 13:56

Re: mtr: abstracting the input layer

Post by BrainDamage »

hughperkins wrote:Hi zcram, you obviously have experience writing C/C++. What are your thoughts on how to make it possible to configure the mouse buttons? I feel that ideally we'd be able to configure something like:

build: mouse1
defaultaction: mouse1
select: mouse1
unselect all: mouse2

I feel it's a challenging problem. If you succeed, I feel you'll have succeeded where *everyone* else has failed.
I took a look to the code myself to try it some time ago and it's not that hard, but it's boring and a long task, spring already supports context sensitive actions, so you can bind build & select to the same button allright provided their context trigger does not conflict

what needs to be abstracted is:

mousepress, mouserelease, mouseclick and mousedoubleclick for each mouse button, once it's added, it's only a matter of removing hardcoded mouse handling and hook to the events
Regret
Posts: 2086
Joined: 18 Aug 2007, 19:04

Re: mtr: abstracting the input layer

Post by Regret »

Brain Damage wrote:mousedoubleclick for each mouse button, once it's added, it's only a matter of removing hardcoded mouse handling and hook to the events
Doubleclick is hardcoded mouse handling itself.
User avatar
BrainDamage
Lobby Developer
Posts: 1164
Joined: 25 Sep 2006, 13:56

Re: mtr: abstracting the input layer

Post by BrainDamage »

Regret wrote:
Brain Damage wrote:mousedoubleclick for each mouse button, once it's added, it's only a matter of removing hardcoded mouse handling and hook to the events
Doubleclick is hardcoded mouse handling itself.
no, it would just be another event you can hook to, if you don't want it, you can avoid using it, it's there to avoid ton of hardcoded code duplication around in the client ( and a flexible system to detect multiple clicks in sequence would be overkill imo )
Regret
Posts: 2086
Joined: 18 Aug 2007, 19:04

Re: mtr: abstracting the input layer

Post by Regret »

Brain Damage wrote:a flexible system to detect multiple clicks in sequence would be overkill imo
Actually that would be pretty awesome. Something like click combos (L + L + R + L + M = FATALITY).
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Re: mtr: abstracting the input layer

Post by hughperkins »

Regret wrote:Actually that would be pretty awesome. Something like click combos (L + L + R + L + M = FATALITY).
Yes, because spring's not hard enough to use as it is ;-)
Brain Damage wrote: what needs to be abstracted is:

mousepress, mouserelease, mouseclick and mousedoubleclick for each mouse button, once it's added, it's only a matter of removing hardcoded mouse handling and hook to the events
Good info. Thanks!
User avatar
Forboding Angel
Evolution RTS Developer
Posts: 14673
Joined: 17 Nov 2005, 02:43

Re: mtr: abstracting the input layer

Post by Forboding Angel »

Regret wrote:
Brain Damage wrote:a flexible system to detect multiple clicks in sequence would be overkill imo
Actually that would be pretty awesome. Something like click combos (L + L + R + L + M = FATALITY).
I have to admit, the lolness of this would be so hardcore, that if the lua were around, I'd do it haha!
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: mtr: abstracting the input layer

Post by AF »

double clicking on the ground to zoom in? Double click drags? Forward back gestures using L and R buttons?
User avatar
lurker
Posts: 3842
Joined: 08 Jan 2007, 06:13

Re: mtr: abstracting the input layer

Post by lurker »

Forboding Angel wrote:
Regret wrote:
Brain Damage wrote:a flexible system to detect multiple clicks in sequence would be overkill imo
Actually that would be pretty awesome. Something like click combos (L + L + R + L + M = FATALITY).
I have to admit, the lolness of this would be so hardcore, that if the lua were around, I'd do it haha!
I'm not going to let you back out of this.
Post Reply

Return to “Engine”