Input Events¶
Input events are messages about input from the keyboard or from the mouse.
Distribution¶
GeUserArea.InputEvent()
if the user area is in focus. They can also be intercepted in GeDialog.Message()
.GetInputEvent()
or get the current input state with GetInputState()
.Structure¶
Input events are stored in BaseContainer
objects. The ID of the container is BFM_INPUT (this is also the ID to look for in GeDialog.Message()
). The content of the container is:
BFM_INPUT_QUALIFIER |
int |
A bit mask with the qualifiers at the time when the event occurred: |
QUALIFIER_NONE |
None. |
|
QUALIFIER_SHIFT |
Shift key. |
|
QUALIFIER_CTRL |
Ctrl key. |
|
QUALIFIER_MOUSEHIT |
Indication in |
|
For instance if QUALIFIER_MOUSEHIT and QUALIFIER_CTRL are set, a new element could be created. |
||
BFM_INPUT_MODIFIERS |
int |
Same as BFM_INPUT_QUALIFIER but also contains bits > 0xf. Private. |
BFM_INPUT_DEVICE |
int |
Device: |
BFM_INPUT_MOUSE |
Mouse. |
|
BFM_INPUT_KEYBOARD |
Keyboard. |
|
BFM_INPUT_ASC |
str |
Contains the Unicode input from keyboard. |
BFM_INPUT_CHANNEL |
int |
Contains the key or button. See also KEY. |
BFM_INPUT_MOUSELEFT |
Left mouse button. |
|
BFM_INPUT_MOUSERIGHT |
Right mouse button. |
|
BFM_INPUT_MOUSEMIDDLE |
Middle mouse button. |
|
BFM_INPUT_MOUSEX1 |
Fourth mouse button. |
|
BFM_INPUT_MOUSEX2 |
Five mouse button. |
|
BFM_INPUT_MOUSEWHEEL |
Mouse wheel. |
|
BFM_INPUT_MOUSEMOVE |
Mouse move. |
|
BFM_INPUT_VALUE |
int |
Value of the input channel (Usually True/False or a int value, e.g. for scroll wheel data). |
BFM_INPUT_VALUE_REAL |
float |
Channel value (e.g. pressure). |
BFM_INPUT_X |
int32 |
Mouse X position. |
BFM_INPUT_Y |
int32 |
Mouse Y position. |
BFM_INPUT_Z |
int32 |
Mouse Z position. |
BFM_INPUT_TILT |
int |
Pen tilt. |
BFM_INPUT_ORIENTATION |
float |
Pen rotation. |
BFM_INPUT_P_ROTATION |
float |
Pen rotation around its own axis. |
BFM_INPUT_FINGERWHEEL |
int |
Finger wheel. |
BFM_INPUT_DOUBLECLICK |
bool |
Double click. |
BFM_INPUT_AFTER_SCROLL |
int |
Input message ID sent after scroll area processed input messages. |
There are also the key symbols which are important in the context of input events.
KEY_MLEFT |
|
KEY_MRIGHT |
|
KEY_MMIDDLE |
|
KEY_MX1 |
|
KEY_MX2 |
|
KEY_SHIFT |
|
KEY_CONTROL |
|
KEY_ALT |
|
KEY_CAPSLOCK |
|
KEY_MODIFIERS |
|
KEY_COMMAND |
|
KEY_BACKSPACE |
|
KEY_TAB |
|
KEY_ENTER |
|
KEY_ESC |
|
KEY_SPACE |
|
KEY_DELETE |
|
KEY_UP |
|
KEY_DOWN |
|
KEY_LEFT |
|
KEY_RIGHT |
|
KEY_PGUP |
|
KEY_PGDOWN |
|
KEY_HOME |
|
KEY_END |
|
KEY_INSERT |
|
KEY_F1 |
|
KEY_F2 |
|
KEY_F3 |
|
KEY_F4 |
|
KEY_F5 |
|
KEY_F6 |
|
KEY_F7 |
|
KEY_F8 |
|
KEY_F9 |
|
KEY_F10 |
|
KEY_F11 |
|
KEY_F12 |
|
KEY_F13 |
|
KEY_F14 |
|
KEY_F15 |
|
KEY_F16 |
|
KEY_F17 |
|
KEY_F18 |
|
KEY_F19 |
|
KEY_F20 |
|
KEY_F21 |
|
KEY_F22 |
|
KEY_F23 |
|
KEY_F24 |
|
KEY_F25 |
|
KEY_F26 |
|
KEY_F27 |
|
KEY_F28 |
|
KEY_F29 |
|
KEY_F30 |
|
KEY_F31 |
|
KEY_F32 |
Note
The values for BFM_INPUT_DEVICE and BFM_INPUT_CHANNEL are used with GetInputState()
and GetInputEvent()
to get specific events only.
Continuous Polling¶
There are no events for things like mouse-up or mouse-leave in Cinema 4D. The reason is that there is no reliable way to get such messages that is completely portable. Therefore it is sometimes necessary to enter a manual while loop that ends when the mouse is released. For example, to track how the user drags something with the left button down one would do:
state = c4d.BaseContainer()
x, y = None, None
while gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state):
if state.GetInt32(c4d.BFM_INPUT_VALUE)==0:
break
x = state.GetInt32(c4d.BFM_INPUT_X)
y = state.GetInt32(c4d.BFM_INPUT_Y)
# Use x and y as Python will expose the last state of x and y in the 'while' scope to the outer scope.
if None in (x, y):
raise RuntimeError("Left mouse button has not been pressed.")
if lowerBoundary.x <= x <= upperBoundary.x:
# ...
Make sure to not to get caught in infinite loops during such polls. When sending BFM_ACTION messages, for example from a custom slider control, set the BFM_ACTION_INDRAG flag to True in those messages while in the loop.
Polling for Character and Special Character Keys¶
For modifier and control keys Cinema 4D does provide symbols, as shown in the table above, with which one can poll for them. But one can also poll for character and special character keys, which are identified by their standard decimal ASCII number. Note that Cinema 4D always treats characters as upper-keys in this context, since modifier keys are being handled separately. This also limits the number of special characters that can be polled depending on they keyboard layout, i.e., polled can only be these, which do not require a modifier key like SHIFT. The example function below showcases how to carry out the polling for multiple character keys at a time, to, for example, invoke a shortcut.
def GetCharacterKeysInput(*args: tuple[str]) -> dict[str]:
"""Returns the key state for an arbitrary number of character keys.
"""
result = {}
for char in (n.upper() for n in args if isinstance(n, str) and len(n)==1):
bc = c4d.BaseContainer()
if not c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, ord(char), bc):
raise RuntimeError("Failed to poll the keyboard.")
result[char] = True if bc[c4d.BFM_INPUT_VALUE] == 1 else False
return result
result = GetCharacterKeysInput("A", "F", "+")
print (result)