check_active() with keyboards?

GPC2 script programming for Titan Two. Code examples, questions, requests.

Re: check_active() with keyboards?

Postby J2Kbr » Thu May 10, 2018 5:49 pm

antithesis wrote:Nice work Buffy!

Very nice indeed. I really liked the solution of having a gph file for configuration, so only the keys/inputs of interest are tracked for events detection.
ConsoleTuner Support Team
User avatar
J2Kbr
General of the Army
General of the Army
 
Posts: 20323
Joined: Tue Mar 18, 2014 1:39 pm

Re: check_active() with keyboards?

Postby Buffy » Thu May 10, 2018 6:12 pm

J2Kbr wrote:
antithesis wrote:Nice work Buffy!

Very nice indeed. I really liked the solution of having a gph file for configuration, so only the keys/inputs of interest are tracked for events detection.


I opened a ticket for it, but one thing that would be nice would be if we could use sizeof with arrays. It could simply some code and require less work by the user to setup the extra buttons:

Code: Select all
 
uint8 extra_keys_status[sizeof(EXTRA_KEY_VAR)] = { 0 };
ConsoleTuner Support Team || Discord || Custom Scripts
User avatar
Buffy
Lieutenant
Lieutenant
 
Posts: 422
Joined: Wed Jul 20, 2016 5:23 am

Re: check_active() with keyboards?

Postby J2Kbr » Thu May 10, 2018 6:17 pm

I just saw on GitHub.

https://github.com/J2Kbr/GtunerIV/issues/225

I believe we can have that. :) Thank you.
ConsoleTuner Support Team
User avatar
J2Kbr
General of the Army
General of the Army
 
Posts: 20323
Joined: Tue Mar 18, 2014 1:39 pm

Re: check_active() with keyboards?

Postby Buffy » Thu May 10, 2018 6:38 pm

J2Kbr wrote:I just saw on GitHub.

https://github.com/J2Kbr/GtunerIV/issues/225

I believe we can have that. :) Thank you.


It'd be even better if structs were to be added too :P
ConsoleTuner Support Team || Discord || Custom Scripts
User avatar
Buffy
Lieutenant
Lieutenant
 
Posts: 422
Joined: Wed Jul 20, 2016 5:23 am

Re: check_active() with keyboards?

Postby J2Kbr » Fri May 11, 2018 7:22 am

the sizeof() on array declaration is now implemented and will be available with Gtuner IV 1.00RC-60.

The support for structs is on the plans, this implementation will be more complex, but will be done.
ConsoleTuner Support Team
User avatar
J2Kbr
General of the Army
General of the Army
 
Posts: 20323
Joined: Tue Mar 18, 2014 1:39 pm

Re: check_active() with keyboards?

Postby PoshLemur » Sun Jul 08, 2018 11:53 pm

Just posting this to show what I'm working on. This is a fork of Buffy and J2Kbr's amazing work, in an attempt to add in some extra features, shortcuts. This code is fully functional, requires a configuration header though.

Configuration Only (No code)
Code: Select all
/* *********************************************************** *
*    Example KB&M Script for Titan Two
*
*    Created by Buffy - 5/10/2018
*
* *********************************************************** */

 
#ifndef _EXTRA_CONFIG_
#define _EXTRA_CONFIG_
#define EXTRA_MOUSE_INPUT                    192
 
#include <keyboard.gph>
#include <mouse.gph>
 
// your config here
 
#define NUM_OF_EXTRA_KEYS    3
#define EXTRA_KEY_VAR        extra_keys_to_monitor
const uint8 EXTRA_KEY_VAR[NUM_OF_EXTRA_KEYS] = {
    KEY_TAB,
    KEY_I,
    MBUTTON_1 | EXTRA_MOUSE_INPUT,
};
 
 
 
#endif
 


Core Code (Working as intended.)
There's a bunch of defines I use as shortcuts for frequently used nested statements.
A couple new fire-once events have been added.
  • key_event_hold_active - Check if the monitored key has been active for the specified time.
  • key_event_hold_release - Check if the monitored key was active for or greater than the specified time - before release.
  • key_event_hold_release_under - Check if the monitored key was active for or less than the specified time - before release.
  • mouse_check - Return active mouse input.
  • key_status_override - Manually set the currently stored key state.

If you're looking at the code for mouse_check it might seem fairly useless. I wrote it purely to help me keep track of user idling in combination with the built in key_check.
Code: Select all
#ifndef EXTRA_KEY_GPC_
#define EXTRA_KEY_GPC_
 
#include <keyboard.gph>
#include <mouse.gph>
 
#ifndef EXTRA_KEY_VAR
    #define EXTRA_KEY_VAR _key_list
    #define NUM_OF_EXTRA_KEYS 1
    uint8 EXTRA_KEY_VAR[1] = { 0 };
#endif
 
#ifndef NUM_OF_EXTRA_KEYS
    #define NUM_OF_EXTRA_KEYS    1
#endif
 
#ifndef EXTRA_MOUSE_INPUT
    #define EXTRA_MOUSE_INPUT 192
#endif
 
#define _KEY_NOT_FOUND_IN_ARRAY 255
 
#define _KEY_STATUS_RELEASED                            1
#define _KEY_STATUS_JUST_RELEASED                        3
#define _KEY_STATUS_PRESSED                                4
#define _KEY_STATUS_JUST_PRESSED                        12
#define _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE         24
 
uint8 _key_status[NUM_OF_EXTRA_KEYS] = { 0 };
uint32 _key_press_timestamp[NUM_OF_EXTRA_KEYS] = { 0 };
uint32 _key_rel_timestamp[NUM_OF_EXTRA_KEYS] = { 0 };
 
// Updates the release & active time values of every monitored key.
main {
    uint8 _key_idx;
 
    for(_key_idx = 0; _key_idx < NUM_OF_EXTRA_KEYS; _key_idx++) {
        if(is_extra_button_active(EXTRA_KEY_VAR[_key_idx])) {
            if (_key_status[_key_idx] & _KEY_STATUS_RELEASED) {
                _key_status[_key_idx] = _KEY_STATUS_JUST_PRESSED;
                _key_press_timestamp[_key_idx] = system_time();
            }
            else if (_key_status[_key_idx] == _KEY_STATUS_JUST_PRESSED){
                _key_status[_key_idx] = _KEY_STATUS_PRESSED;
            }
        }
        else {
            if ((_key_status[_key_idx] & _KEY_STATUS_PRESSED) ||
                (_key_status[_key_idx] & _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE)) {
                _key_status[_key_idx] = _KEY_STATUS_JUST_RELEASED;
                _key_rel_timestamp[_key_idx] = system_time();
            }
            else {
                _key_status[_key_idx] = _KEY_STATUS_RELEASED;
            }
        }
    }
 
    _key_idx = 0;
}
 
bool is_extra_button_active(uint8 button) {
    return (key_status(button)) || ((button >= EXTRA_MOUSE_INPUT) && mouse_status(button - EXTRA_MOUSE_INPUT));
}
 
// Returns the array index associated with the button identifier.
uint8 key_index(uint8 key) {
    uint8 i;
    for(i = 0; i < NUM_OF_EXTRA_KEYS; i++) {
        if(EXTRA_KEY_VAR[i] == key) {
            return i;
        }
    }
 
    printf("Error: Key not found in EXTRA_KEY_VAR array. Key: 0x%x (uint8 %u)", key, key);
    return _KEY_NOT_FOUND_IN_ARRAY;
}
 
void key_status_override(uint8 key, uint8 status, uint32 time) {
    uint8 i = key_index(key);
    _key_status[i] = status;
 
    switch (status) {
        case _KEY_STATUS_PRESSED:
        case _KEY_STATUS_JUST_PRESSED:
            _key_press_timestamp[i] = time;
            break;
 
        case _KEY_STATUS_RELEASED:
        case _KEY_STATUS_JUST_RELEASED:
            _key_rel_timestamp[i] = time;
            break;
    }
}
 
// EVENT: Check if the monitored key changed its state from release to active.
bool key_event_active(uint8 key) {
    return (_key_status[key_index(key)] == _KEY_STATUS_JUST_PRESSED);
}
 
// EVENT: Check if the monitored key changed its state from active to release.
bool key_event_release(uint8 key) {
    return (_key_status[key_index(key)] == _KEY_STATUS_JUST_RELEASED);
}
 
// EVENT: Check if the monitored key has been active for the specified time.
bool key_event_hold_active(uint8 key, uint32 ms) {
    uint8 i = key_index(key);
    if (_key_status[i] == _KEY_STATUS_JUST_PRESSED) {
        _key_status[i] = _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE;
    }
 
    if ((_key_status[i] == _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE) && (key_time_active(key) >= ms)) {
        _key_status[i] = _KEY_STATUS_PRESSED;
        return TRUE;
    }
 
    ////printf("%d && %u", _key_status[i], key_time_active(key));
    return FALSE;
}
 
// EVENT: Check if the monitored key was active for or greater than the specified time - before release.
bool key_event_hold_release(uint8 key, uint32 ms) {
    return (_key_status[key_index(key)] == _KEY_STATUS_JUST_RELEASED && key_time_active(key) >= ms);
}
 
// EVENT: Check if the monitored key was active for or less than the specified time - before release.
bool key_event_hold_release_under(uint8 key, uint32 ms) {
    return (_key_status[key_index(key)] == _KEY_STATUS_JUST_RELEASED && key_time_active(key) <= ms);
}
 
// The time that has passed since entered in active state.
uint32 key_time_active(uint8 key) {
    uint8 i = key_index(key);
 
    if(is_extra_button_active(key)) {
        return (system_time() - _key_press_timestamp[i]);
        ///printf("IF: r = %u", r);
    }
 
    return 0;
}
 
// The time that has passed since entered in release state.
uint32 key_time_release(uint8 key) {
    uint8 i = key_index(key);
 
    if(is_extra_button_active(key)) {
        return 0;
    }
 
    return 0;
}
 
bool key_check_active(uint8 key, uint32 ms) {
    return (is_extra_button_active(key) && key_time_active(key) >= ms);
}
 
bool key_check_release(uint8 key, uint32 ms) {
    return (!is_extra_button_active(key) && key_time_release(key) >= ms);
}
 
// Returns true if the key is actively being held down.
#define key_is_active(key) key_status(key)
 
// Returns true if the key is currently in a release state.
#define key_is_release(key) !key_is_active(key)
 
#define mouse_is_active(mouse) mouse_status(mouse)
#define mouse_is_release(mouse) !mouse_is_active(mouse)
 
#define mouse_event_active(mouse) key_event_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_event_release(mouse) key_event_release((mouse | EXTRA_MOUSE_INPUT))
#define mouse_time_active(mouse) key_time_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_time_release(mouse) key_time_release((mouse | EXTRA_MOUSE_INPUT))
#define mouse_check_active(mouse) key_check_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_check_release(mouse) key_check_release((mouse | EXTRA_MOUSE_INPUT))
 
// Return active mouse input. NOTE: Returns 0 if none BUT also 0 if MOUSE_X
// because MOUSE_X is indexed as 0. Shouldn't be a problem as long as you
// do not check exclusively for MOUSE_X input.
uint8 mouse_check(bool include_xy_movement) {
    uint8 start_index = 2;
    if (include_xy_movement) {
        start_index = 0;
    }
 
    // Check mouse input indexes 2 through 19
    uint8 i;
    for (i = start_index; i < 20; i++) {
        if (mouse_status(i)) {
            return i;
        }
    }
 
    return 0;
}
 
// key_is_active macros.
#define key_is_active_combo_run(b, c) if (key_is_active(b)) { combo_run(c); }
#define key_is_active_combo_stop(b, c) if (key_is_active(b)) { combo_stop(c); }
#define key_is_active_combo_pause(b, c) if (key_is_active(b)) { combo_pause(c); }
#define key_is_active_combo_restart(b, c) if (key_is_active(b)) { combo_restart(c); }
#define key_is_active_combo_toggle(b, c) if (key_is_active(b)) { c = !c; }
#define key_is_active_macro_run(b, c) if (key_is_active(b)) { macro_run(m); }
#define key_is_active_macro_stop(b, c) if (key_is_active(b)) { macro_stop(m); }
#define key_is_active_macro_toggle(b, c) if (key_is_active(b)) { m = !m; }
#define key_is_active_set_val(b, i, v) if (key_is_active(b)) { set_val(i, v); }
 
// key_status macros.
#define key_status_combo_run(b, c) if (key_status(b)) { combo_run(c); }
#define key_status_combo_stop(b, c) if (key_status(b)) { combo_stop(c); }
#define key_status_combo_pause(b, c) if (key_status(b)) { combo_pause(c); }
#define key_status_combo_restart(b, c) if (key_status(b)) { combo_restart(c); }
#define key_status_combo_toggle(b, c) if (key_status(b)) { c = !c; }
#define key_status_macro_run(b, c) if (key_status(b)) { macro_run(m); }
#define key_status_macro_stop(b, c) if (key_status(b)) { macro_stop(m); }
#define key_status_macro_toggle(b, c) if (key_status(b)) { m = !m; }
#define key_status_set_val(b, i, v) if (key_status(b)) { set_val(i, v); }
 
// key_event_active macros.
#define key_event_active_combo_run(b, c) if (key_event_active(b)) { combo_run(c); }
#define key_event_active_combo_stop(b, c) if (key_event_active(b)) { combo_stop(c); }
#define key_event_active_combo_pause(b, c) if (key_event_active(b)) { combo_pause(c); }
#define key_event_active_combo_restart(b, c) if (key_event_active(b)) { combo_restart(c); }
#define key_event_active_combo_toggle(b, c) if (key_event_active(b)) { c = !c; }
#define key_event_active_macro_run(b, c) if (key_event_active(b)) { macro_run(m); }
#define key_event_active_macro_stop(b, c) if (key_event_active(b)) { macro_stop(m); }
#define key_event_active_macro_toggle(b, c) if (key_event_active(b)) { m = !m; }
#define key_event_active_set_val(b, i, v) if (key_event_active(b)) { set_val(i, v); }
 
// key_event_release macros.
#define key_event_release_combo_run(b, c) if (key_event_release(b)) { combo_run(c); }
#define key_event_release_combo_stop(b, c) if (key_event_release(b)) { combo_stop(c); }
#define key_event_release_combo_pause(b, c) if (key_event_release(b)) { combo_pause(c); }
#define key_event_release_combo_restart(b, c) if (key_event_release(b)) { combo_restart(c); }
#define key_event_release_combo_toggle(b, c) if (key_event_release(b)) { c = !c; }
#define key_event_release_macro_run(b, c) if (key_event_release(b)) { macro_run(m); }
#define key_event_release_macro_stop(b, c) if (key_event_release(b)) { macro_stop(m); }
#define key_event_release_macro_toggle(b, c) if (key_event_release(b)) { m = !m; }
#define key_event_release_set_val(b, i, v) if (key_event_release(b)) { set_val(i, v); }
 
 
// key_check_active macros.
#define key_check_active_combo_run(b, ms, c) if (key_check_active(b, ms)) { combo_run(c); }
#define key_check_active_combo_stop(b, ms, c) if (key_check_active(b, ms)) { combo_stop(c); }
#define key_check_active_combo_pause(b, ms, c) if (key_check_active(b, ms)) { combo_pause(c); }
#define key_check_active_combo_restart(b, ms, c) if (key_check_active(b, ms)) { combo_restart(c); }
#define key_check_active_combo_toggle(b, ms, c) if (key_check_active(b, ms)) { c = !c; }
#define key_check_active_macro_run(b, ms, c) if (key_check_active(b, ms)) { macro_run(m); }
#define key_check_active_macro_stop(b, ms, c) if (key_check_active(b, ms)) { macro_stop(m); }
#define key_check_active_macro_toggle(b, ms, c) if (key_check_active(b, ms)) { m = !m; }
#define key_check_active_set_val(b, ms, i, v) if (key_check_active(b, ms)) { set_val(i, v); }
 
 
#endif /* EXTRA_KEY_GPC_ */
 



Warning to potential newcomers about the code below.
The code below is in an unfinished state and I would advise against using it. This is the same code as the above with some attempts at optimizing it.

Optimization was obtained by adding in a timer in the form of _extra_buttons_time_since_last_update.
This is a very minor sacrifice of responsiveness for improving device performance.
For most general use cases this works, however for some of the time related key events it's been causing me issues.
Code: Select all
#ifndef EXTRA_KEY_GPC_
#define EXTRA_KEY_GPC_
 
#include <keyboard.gph>
#include <mouse.gph>
 
#ifndef EXTRA_KEY_VAR
    #define EXTRA_KEY_VAR _key_list
    #define NUM_OF_EXTRA_KEYS 1
    uint8 EXTRA_KEY_VAR[1] = { 0 };
#endif
 
#ifndef NUM_OF_EXTRA_KEYS
    #define NUM_OF_EXTRA_KEYS    1
#endif
 
#ifndef EXTRA_MOUSE_INPUT
    #define EXTRA_MOUSE_INPUT 192
#endif
 
#define _KEY_NOT_FOUND_IN_ARRAY 255
 
#define _KEY_STATUS_RELEASED                            0
#define _KEY_STATUS_JUST_RELEASED                        3
#define _KEY_STATUS_PRESSED                                6
#define _KEY_STATUS_JUST_PRESSED                        9
#define _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE         12
 
// This setting controls the rate at which keys are updated.
// A lower setting will increase responsiveness and CPU usage.
#define _KEY_UPDATE_DELAY 100
 
uint8 _key_status[NUM_OF_EXTRA_KEYS] = { 0 };
uint32 _key_press_timestamp[NUM_OF_EXTRA_KEYS] = { 0 };
uint32 _key_rel_timestamp[NUM_OF_EXTRA_KEYS] = { 0 };
uint32 _extra_buttons_time_since_last_update = 0;
 
// Initialize the arrays to set their default values.
// This will prevent issues when scripts first launch using this header.
init {
    uint8 _key_idx_init;
    for(_key_idx_init = 0; _key_idx_init < NUM_OF_EXTRA_KEYS; _key_idx_init++) {
        _key_status[_key_idx_init] = _KEY_STATUS_RELEASED;
        _key_press_timestamp[_key_idx_init] = 0;
        _key_rel_timestamp[_key_idx_init] = 0;
    }
}
 
// Updates the release & active time values of every monitored key.
main {
    _extra_buttons_time_since_last_update += elapsed_time();
    if (_extra_buttons_time_since_last_update > 75) {
        _extra_buttons_time_since_last_update = 0;
 
        uint8 _key_idx;
        for(_key_idx = 0; _key_idx < NUM_OF_EXTRA_KEYS; _key_idx++) {
            if(is_extra_button_active(EXTRA_KEY_VAR[_key_idx])) {
                if (_key_status[_key_idx] & _KEY_STATUS_RELEASED) {
                    _key_status[_key_idx] = _KEY_STATUS_JUST_PRESSED;
                    _key_press_timestamp[_key_idx] = system_time();
                }
                else if (_key_status[_key_idx] == _KEY_STATUS_JUST_PRESSED) {
                    _key_status[_key_idx] = _KEY_STATUS_PRESSED;
                }
            }
            else {
                if ((_key_status[_key_idx] & _KEY_STATUS_PRESSED) ||
                    (_key_status[_key_idx] & _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE))
                {
                    _key_status[_key_idx] = _KEY_STATUS_JUST_RELEASED;
                    _key_rel_timestamp[_key_idx] = system_time();
                }
                else {
                    _key_status[_key_idx] = _KEY_STATUS_RELEASED;
                }
            }
        }
 
        _key_idx = 0;
    }
}
 
// Combines key_status and mouse_status in one.
bool is_extra_button_active(uint8 button) {
    return (key_status(button)) || ((button >= EXTRA_MOUSE_INPUT) && mouse_status(button - EXTRA_MOUSE_INPUT));
}
 
// Returns the array index associated with the button identifier.
uint8 key_index(uint8 key) {
    uint8 i;
    for(i = 0; i < NUM_OF_EXTRA_KEYS; i++) {
        if(EXTRA_KEY_VAR[i] == key) {
            return i;
        }
    }
 
    printf("Error: Key not found in EXTRA_KEY_VAR array. Key: 0x%x (uint8 %u)", key, key);
    return _KEY_NOT_FOUND_IN_ARRAY;
}
 
void key_status_override(uint8 key, uint8 status, uint32 time) {
    uint8 i = key_index(key);
    _key_status[i] = status;
 
    switch (status) {
        case _KEY_STATUS_PRESSED:
        case _KEY_STATUS_JUST_PRESSED:
            _key_press_timestamp[i] = time;
            break;
 
        case _KEY_STATUS_RELEASED:
        case _KEY_STATUS_JUST_RELEASED:
            _key_rel_timestamp[i] = time;
            break;
    }
}
 
// EVENT: Check if the monitored key changed its state from release to active.
bool key_event_active(uint8 key) {
    if (_extra_buttons_time_since_last_update) return FALSE;
    return (is_extra_button_active(key) && _key_status[key_index(key)] == _KEY_STATUS_JUST_PRESSED);
}
 
// EVENT: Check if the monitored key changed its state from active to release.
bool key_event_release(uint8 key) {
    if (_extra_buttons_time_since_last_update) return FALSE;
    return (!is_extra_button_active(key) && _key_status[key_index(key)] == _KEY_STATUS_JUST_RELEASED);
}
 
// EVENT: Check if the monitored key has been active for the specified time.
bool key_event_hold_active(uint8 key, uint32 ms) {
    uint8 i = key_index(key);
    if (_key_status[i] == _KEY_STATUS_JUST_PRESSED) {
        _key_status[i] = _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE;
    }
 
    if ((_key_status[i] == _KEY_STATUS_JUST_PRESSED_WAIT_WHILE_ACTIVE) && (key_time_active(key) >= ms)) {
        _key_status[i] = _KEY_STATUS_PRESSED;
        return TRUE;
    }
 
    ////printf("%d && %u", _key_status[i], key_time_active(key));
    return FALSE;
}
 
// EVENT: Check if the monitored key was active for or greater than the specified time - before release.
bool key_event_hold_release(uint8 key, uint32 ms) {
    if (_extra_buttons_time_since_last_update) return FALSE;
    return (!is_extra_button_active(key) && _key_status[key_index(key)] == _KEY_STATUS_JUST_RELEASED && key_time_active(key) >= ms);
}
 
// EVENT: Check if the monitored key was active for or less than the specified time - before release.
bool key_event_hold_release_under(uint8 key, uint32 ms) {
    if (_extra_buttons_time_since_last_update) return FALSE;
    return (!is_extra_button_active(key) && _key_status[key_index(key)] == _KEY_STATUS_JUST_RELEASED && key_time_active(key) <= ms);
}
 
// The time that has passed since entered in active state.
uint32 key_time_active(uint8 key) {
    uint8 i = key_index(key);
 
    if(is_extra_button_active(key) && (_key_press_timestamp[i]) >  _key_rel_timestamp[i]) {
        ////printf("key_time_active = %u", (system_time() - _key_press_timestamp[i]));
        return (system_time() - _key_press_timestamp[i]);
    }
 
    return 0;
}
 
// The time that has passed since entered in release state.
uint32 key_time_release(uint8 key) {
    uint8 i = key_index(key);
 
    if(is_extra_button_active(key)) {
        return 0;
    }
 
    return 0;
}
 
bool key_check_active(uint8 key, uint32 ms) {
    return (is_extra_button_active(key) && key_time_active(key) >= ms);
}
 
bool key_check_release(uint8 key, uint32 ms) {
    return (!is_extra_button_active(key) && key_time_release(key) >= ms);
}
 
// Returns true if the key is actively being held down.
#define key_is_active(key) key_status(key)
 
// Returns true if the key is currently in a release state.
#define key_is_release(key) !key_is_active(key)
 
#define mouse_is_active(mouse) mouse_status(mouse)
#define mouse_is_release(mouse) !mouse_is_active(mouse)
 
#define mouse_event_active(mouse) key_event_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_event_release(mouse) key_event_release((mouse | EXTRA_MOUSE_INPUT))
#define mouse_time_active(mouse) key_time_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_time_release(mouse) key_time_release((mouse | EXTRA_MOUSE_INPUT))
#define mouse_check_active(mouse) key_check_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_check_release(mouse) key_check_release((mouse | EXTRA_MOUSE_INPUT))
 
// Return active mouse input. NOTE: Returns 0 if none BUT also 0 if MOUSE_X
// because MOUSE_X is indexed as 0. Shouldn't be a problem as long as you
// do not check exclusively for MOUSE_X input.
uint8 mouse_check(bool include_xy_movement) {
    uint8 start_index = 2;
    if (include_xy_movement) {
        start_index = 0;
    }
 
    // Check mouse input indexes 2 through 19
    uint8 i;
    for (i = start_index; i < 20; i++) {
        if (mouse_status(i)) {
            return i;
        }
    }
 
    return 0;
}
 
// key_is_active macros.
#define key_is_active_combo_run(b, c) if (key_is_active(b)) { combo_run(c); }
#define key_is_active_combo_stop(b, c) if (key_is_active(b)) { combo_stop(c); }
#define key_is_active_combo_pause(b, c) if (key_is_active(b)) { combo_pause(c); }
#define key_is_active_combo_restart(b, c) if (key_is_active(b)) { combo_restart(c); }
#define key_is_active_combo_toggle(b, c) if (key_is_active(b)) { c = !c; }
#define key_is_active_macro_run(b, c) if (key_is_active(b)) { macro_run(m); }
#define key_is_active_macro_stop(b, c) if (key_is_active(b)) { macro_stop(m); }
#define key_is_active_macro_toggle(b, c) if (key_is_active(b)) { m = !m; }
#define key_is_active_set_val(b, i, v) if (key_is_active(b)) { set_val(i, v); }
 
// key_status macros.
#define key_status_combo_run(b, c) if (key_status(b)) { combo_run(c); }
#define key_status_combo_stop(b, c) if (key_status(b)) { combo_stop(c); }
#define key_status_combo_pause(b, c) if (key_status(b)) { combo_pause(c); }
#define key_status_combo_restart(b, c) if (key_status(b)) { combo_restart(c); }
#define key_status_combo_toggle(b, c) if (key_status(b)) { c = !c; }
#define key_status_macro_run(b, c) if (key_status(b)) { macro_run(m); }
#define key_status_macro_stop(b, c) if (key_status(b)) { macro_stop(m); }
#define key_status_macro_toggle(b, c) if (key_status(b)) { m = !m; }
#define key_status_set_val(b, i, v) if (key_status(b)) { set_val(i, v); }
 
// key_event_active macros.
#define key_event_active_combo_run(b, c) if (key_event_active(b)) { combo_run(c); }
#define key_event_active_combo_stop(b, c) if (key_event_active(b)) { combo_stop(c); }
#define key_event_active_combo_pause(b, c) if (key_event_active(b)) { combo_pause(c); }
#define key_event_active_combo_restart(b, c) if (key_event_active(b)) { combo_restart(c); }
#define key_event_active_combo_toggle(b, c) if (key_event_active(b)) { c = !c; }
#define key_event_active_macro_run(b, c) if (key_event_active(b)) { macro_run(m); }
#define key_event_active_macro_stop(b, c) if (key_event_active(b)) { macro_stop(m); }
#define key_event_active_macro_toggle(b, c) if (key_event_active(b)) { m = !m; }
#define key_event_active_set_val(b, i, v) if (key_event_active(b)) { set_val(i, v); }
 
// key_event_release macros.
#define key_event_release_combo_run(b, c) if (key_event_release(b)) { combo_run(c); }
#define key_event_release_combo_stop(b, c) if (key_event_release(b)) { combo_stop(c); }
#define key_event_release_combo_pause(b, c) if (key_event_release(b)) { combo_pause(c); }
#define key_event_release_combo_restart(b, c) if (key_event_release(b)) { combo_restart(c); }
#define key_event_release_combo_toggle(b, c) if (key_event_release(b)) { c = !c; }
#define key_event_release_macro_run(b, c) if (key_event_release(b)) { macro_run(m); }
#define key_event_release_macro_stop(b, c) if (key_event_release(b)) { macro_stop(m); }
#define key_event_release_macro_toggle(b, c) if (key_event_release(b)) { m = !m; }
#define key_event_release_set_val(b, i, v) if (key_event_release(b)) { set_val(i, v); }
 
 
// key_check_active macros.
#define key_check_active_combo_run(b, ms, c) if (key_check_active(b, ms)) { combo_run(c); }
#define key_check_active_combo_stop(b, ms, c) if (key_check_active(b, ms)) { combo_stop(c); }
#define key_check_active_combo_pause(b, ms, c) if (key_check_active(b, ms)) { combo_pause(c); }
#define key_check_active_combo_restart(b, ms, c) if (key_check_active(b, ms)) { combo_restart(c); }
#define key_check_active_combo_toggle(b, ms, c) if (key_check_active(b, ms)) { c = !c; }
#define key_check_active_macro_run(b, ms, c) if (key_check_active(b, ms)) { macro_run(m); }
#define key_check_active_macro_stop(b, ms, c) if (key_check_active(b, ms)) { macro_stop(m); }
#define key_check_active_macro_toggle(b, ms, c) if (key_check_active(b, ms)) { m = !m; }
#define key_check_active_set_val(b, ms, i, v) if (key_check_active(b, ms)) { set_val(i, v); }
 
 
#endif /* EXTRA_KEY_GPC_ */
 
My github account: [link]
User avatar
PoshLemur
Sergeant Major
Sergeant Major
 
Posts: 75
Joined: Thu Mar 08, 2018 9:26 am

Re: check_active() with keyboards?

Postby J2Kbr » Mon Jul 09, 2018 6:29 am

Thank you PoshLemur for sharing your GPC header file with us. Hopefully soon you can publish it on Gtuner IV, as you did with limits and safeprint. :smile0517: :smile0517:
ConsoleTuner Support Team
User avatar
J2Kbr
General of the Army
General of the Army
 
Posts: 20323
Joined: Tue Mar 18, 2014 1:39 pm

Re: check_active() with keyboards?

Postby Buffy » Mon Jul 09, 2018 8:26 am

Since then, I've added some optimizations to my code; even with 15 keys being recorded performance was still pretty good. I've also changed it so the user doesn't have to use as much code to set the extra keys up, with the use of sizeof in the header.

I've attached the files below
Attachments
extra_buttons.zip
(1.34 KiB) Downloaded 71 times
ConsoleTuner Support Team || Discord || Custom Scripts
User avatar
Buffy
Lieutenant
Lieutenant
 
Posts: 422
Joined: Wed Jul 20, 2016 5:23 am

Re: check_active() with keyboards?

Postby sky418 » Mon Jul 09, 2018 2:29 pm

Excellent. I was working on it "5 minutes with rubber", and in result I have more then I will ever needed at all. :smile0202:
User avatar
sky418
Command Sergeant Major
Command Sergeant Major
 
Posts: 124
Joined: Fri Nov 25, 2016 4:28 am

Re: check_active() with keyboards?

Postby PoshLemur » Thu Jul 19, 2018 5:37 pm

Here's my newest fully functional version based off of Buffy's newest version (as of 19-7-18)
It's been further optimized. I have a very complex KBM script that used to run at 160-200% CPU.
With Buffy's updated version it still ran at 18-30% a huge improvement. This version is now running around 2%.

Hey Buffy, your newest version seems to have a bug when monitoring for KEY_LEFTCONTROL. Basically moving the mouse causes it to register as having been pressed. I'm assuming any key with a high identifier number would have also caused this. The problem is located in is_extra_button_active(). This wasn't an issue in your older version so I reverted the code.

NEW VERSION 19-7-2018
Zip attached at bottom for easy download.
Everything works (as far as I can tell, report bugs please.)
Big shout out to Buffy who wrote the vast majority of this code and has done some amazing work.

Example usage in a script:
Code: Select all
#include "extra-buttons-config.gph"
#include "extra-buttons.gph"
#include "extra-buttons-macros.gph"
 
main {
    if (key_event_active(KEY_W)) {
        printf("You pressed the W key!");
    }
}


Configuration file: (extra-buttons-config.gph)
REMEMBER TO INCLUDE IT BEFORE THE MAIN HEADER FILE.
Code: Select all
#ifndef EXTRA_BUTTONS_CONFIG_GPH_
#define EXTRA_BUTTONS_CONFIG_GPH_
 
#define EXTRA_MOUSE_INPUT                    192
 
#include <keyboard.gph>
#include <mouse.gph>
 
// Your config here
 
#define EXTRA_KEY_VAR        extra_keys_to_monitor
const uint8 EXTRA_KEY_VAR[NUM_OF_EXTRA_KEYS] = {
    KEY_TAB,
    KEY_I,
    MBUTTON_1 | EXTRA_MOUSE_INPUT,
};
 
#endif /* EXTRA_BUTTONS_CONFIG_GPH_ */


Main header file: (extra-buttons.gph)
Code: Select all
#ifndef EXTRA_BUTTONS_GPH_
#define EXTRA_BUTTONS_GPH_
 
#include <keyboard.gph>
#include <mouse.gph>
 
#ifndef EXTRA_KEY_VAR
    #define EXTRA_KEY_VAR        extra_keys_list
    uint8 EXTRA_KEY_VAR[1] = { 0 };
#endif
 
#define _NUM_OF_EXTRA_KEYS    sizeof(EXTRA_KEY_VAR)
 
#ifndef EXTRA_MOUSE_INPUT
    #define EXTRA_MOUSE_INPUT                    192
#endif
 
#define _EXRTA_MOUSE_INPUT_IMASK                31
 
#define _EXTRA_KEY_NOT_FOUND_IN_ARRAY 255
 
#define _EXTRA_KEY_STATUS_RELEASED            1
#define _EXTRA_KEY_STATUS_JUST_RELEASED        3
#define _EXTRA_KEY_STATUS_PRESSED            4
#define _EXTRA_KEY_STATUS_JUST_PRESSED        12
 
uint8 extra_keys_status[_NUM_OF_EXTRA_KEYS] = { 0 };
uint32 extra_keys_status_press_time[_NUM_OF_EXTRA_KEYS] = { 0 };
uint32 extra_keys_status_rel_time[_NUM_OF_EXTRA_KEYS] = { 0 };
 
uint32 _extra_buttons_time_since_last_update = 0;
 
main {
    uint8 _extra_key_i;
    _extra_buttons_time_since_last_update += elapsed_time();
    if (_extra_buttons_time_since_last_update > 5) {
        _extra_buttons_time_since_last_update = 0;
 
        for(_extra_key_i = 0; _extra_key_i < _NUM_OF_EXTRA_KEYS; _extra_key_i++) {
            if(is_extra_button_active(EXTRA_KEY_VAR[_extra_key_i]))  {
                if(extra_keys_status[_extra_key_i] & _EXTRA_KEY_STATUS_RELEASED) {
                    extra_keys_status[_extra_key_i] = _EXTRA_KEY_STATUS_JUST_PRESSED;
                    extra_keys_status_press_time[_extra_key_i] = system_time();
                }
                else extra_keys_status[_extra_key_i] = _EXTRA_KEY_STATUS_PRESSED;
            }
            else {
                if(extra_keys_status[_extra_key_i] & _EXTRA_KEY_STATUS_PRESSED) {
                    extra_keys_status[_extra_key_i] = _EXTRA_KEY_STATUS_JUST_RELEASED;
                    extra_keys_status_rel_time[_extra_key_i] = system_time();
                }
                else extra_keys_status[_extra_key_i] = _EXTRA_KEY_STATUS_RELEASED;
            }
        }
    }
}
 
bool is_extra_buttons_on_cooldown() {
    return (_extra_buttons_time_since_last_update < 5);
}
 
bool is_extra_button_active(uint8 button) {
    //return (key_status(button)) || ((button >= EXTRA_MOUSE_INPUT) && mouse_status(button & _EXRTA_MOUSE_INPUT_IMASK)); // BREAKS WHEN USING CERTAIN KEYS WITH HIGH IDENTIFIER NUMBERS.
    return (key_status(button)) || ((button >= EXTRA_MOUSE_INPUT) && mouse_status(button - EXTRA_MOUSE_INPUT));
}
 
uint8 get_key_index(uint8 key) {
    uint8 _extra_key_i;
    for(_extra_key_i = 0; _extra_key_i < _NUM_OF_EXTRA_KEYS; _extra_key_i++) {
        if(EXTRA_KEY_VAR[_extra_key_i] == key) return _extra_key_i;
    }
 
    printf("Error: Key not found in EXTRA_KEY_VAR array. Key: 0x%x (uint8 %u)", key, key);
    return _EXTRA_KEY_NOT_FOUND_IN_ARRAY;
}
 
// EVENT: Check if the monitored key changed its state from release to active.
bool key_event_active(uint8 key) {
    if (is_extra_buttons_on_cooldown()) { return FALSE; }
    return (is_extra_button_active(key)) && (extra_keys_status[get_key_index(key)] == _EXTRA_KEY_STATUS_JUST_PRESSED);
}
 
// EVENT: Check if the monitored key changed its state from active to release.
bool key_event_release(uint8 key) {
    if (is_extra_buttons_on_cooldown()) { return FALSE; }
    return (!is_extra_button_active(key)) && (extra_keys_status[get_key_index(key)] == _EXTRA_KEY_STATUS_JUST_RELEASED);
}
 
// EVENT: Check if the monitored key was active for or greater than the specified time - before release.
bool key_event_hold_release(uint8 key, uint32 ms) {
    if (is_extra_buttons_on_cooldown()) { return FALSE; }
    return (extra_keys_status[get_key_index(key)] == _EXTRA_KEY_STATUS_JUST_RELEASED && key_time_active(key) >= ms);
}
 
// EVENT: Check if the monitored key has been active for the specified time.
bool key_event_hold_active(uint8 key, uint32 ms) {
    if (is_extra_buttons_on_cooldown()) { return FALSE; }
 
    // This works because of the 5ms interval. Will break if value is changed.
    if (is_extra_button_active(key) && (key_time_active(key) >= (ms - 5) && (key_time_active(key) <= (ms)))) {
        return TRUE;
    }
 
    ////printf("%d && %u", extra_keys_status[i], key_time_active(key));
    return FALSE;
}
 
// EVENT: Check if the monitored key was active for or less than the specified time - before release.
bool key_event_hold_release_under(uint8 key, uint32 ms) {
    if (is_extra_buttons_on_cooldown()) { return FALSE; }
    return (extra_keys_status[get_key_index(key)] == _EXTRA_KEY_STATUS_JUST_RELEASED && key_time_active(key) <= ms);
}
 
// The return value does not necessary means the I/O is currently active.
uint32 key_time_active(uint8 key) {
    if(is_extra_button_active(key))
        return (system_time() - extra_keys_status_press_time[get_key_index(key)]);
    //else
    return (extra_keys_status_rel_time[get_key_index(key)] - extra_keys_status_press_time[get_key_index(key)]);
}
 
// The return value does not necessary means the I/O is currently release.
uint32 key_time_release(uint8 key) {
    if(is_extra_button_active(key))
        return (extra_keys_status_press_time[get_key_index(key)] - extra_keys_status_rel_time[get_key_index(key)]);
    //else
    return (system_time() - extra_keys_status_rel_time[get_key_index(key)]);
}
 
bool key_check_active(uint8 key, uint32 ms) {
    return (is_extra_button_active(key) && key_time_active(key) >= ms);
}
 
bool key_check_release(uint8 key, uint32 ms) {
    return (!is_extra_button_active(key) && key_time_release(key) >= ms);
}
 
// Return active mouse input. NOTE: Returns 0 if none BUT also 0 if MOUSE_X
// because MOUSE_X is indexed as 0. Shouldn't be a problem as long as you
// do not check exclusively for MOUSE_X input.
uint8 mouse_check(bool include_xy_movement) {
    uint8 start_index = 2;
    if (include_xy_movement) {
        start_index = 0;
    }
 
    // Check mouse input indexes 2 through 19
    uint8 i;
    for (i = start_index; i < 20; i++) {
        if (mouse_status(i)) {
            return i;
        }
    }
 
    return 0;
}
 
#define key_is_active(key) key_status(key)
#define key_is_release(key) !key_is_active(key)
 
#define mouse_is_active(mouse) mouse_status(mouse)
#define mouse_is_release(mouse) !mouse_is_active(mouse)
 
#define mouse_event_active(mouse) key_event_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_event_release(mouse) key_event_release((mouse | EXTRA_MOUSE_INPUT))
#define mouse_time_active(mouse) key_time_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_time_release(mouse) key_time_release((mouse | EXTRA_MOUSE_INPUT))
#define mouse_check_active(mouse) key_check_active((mouse | EXTRA_MOUSE_INPUT))
#define mouse_check_release(mouse) key_check_release((mouse | EXTRA_MOUSE_INPUT))
 
#endif /* EXTRA_BUTTONS_GPH_ */
 


Additional macros file: (extra-buttons-macros.gph)
Code: Select all
#ifndef EXTRA_BUTTONS_MACROS_GPH_
#define EXTRA_BUTTONS_MACROS_GPH_
 
 
// key_is_active macros.
#define key_is_active_combo_run(b, c) if (key_is_active(b)) { combo_run(c); }
#define key_is_active_combo_stop(b, c) if (key_is_active(b)) { combo_stop(c); }
#define key_is_active_combo_pause(b, c) if (key_is_active(b)) { combo_pause(c); }
#define key_is_active_combo_restart(b, c) if (key_is_active(b)) { combo_restart(c); }
#define key_is_active_combo_toggle(b, c) if (key_is_active(b)) { c = !c; }
#define key_is_active_macro_run(b, c) if (key_is_active(b)) { macro_run(m); }
#define key_is_active_macro_stop(b, c) if (key_is_active(b)) { macro_stop(m); }
#define key_is_active_macro_toggle(b, c) if (key_is_active(b)) { m = !m; }
#define key_is_active_set_val(b, i, v) if (key_is_active(b)) { set_val(i, v); }
 
// key_status macros.
#define key_status_combo_run(b, c) if (key_status(b)) { combo_run(c); }
#define key_status_combo_stop(b, c) if (key_status(b)) { combo_stop(c); }
#define key_status_combo_pause(b, c) if (key_status(b)) { combo_pause(c); }
#define key_status_combo_restart(b, c) if (key_status(b)) { combo_restart(c); }
#define key_status_combo_toggle(b, c) if (key_status(b)) { c = !c; }
#define key_status_macro_run(b, c) if (key_status(b)) { macro_run(m); }
#define key_status_macro_stop(b, c) if (key_status(b)) { macro_stop(m); }
#define key_status_macro_toggle(b, c) if (key_status(b)) { m = !m; }
#define key_status_set_val(b, i, v) if (key_status(b)) { set_val(i, v); }
 
// key_event_active macros.
#define key_event_active_combo_run(b, c) if (key_event_active(b)) { combo_run(c); }
#define key_event_active_combo_stop(b, c) if (key_event_active(b)) { combo_stop(c); }
#define key_event_active_combo_pause(b, c) if (key_event_active(b)) { combo_pause(c); }
#define key_event_active_combo_restart(b, c) if (key_event_active(b)) { combo_restart(c); }
#define key_event_active_combo_toggle(b, c) if (key_event_active(b)) { c = !c; }
#define key_event_active_macro_run(b, c) if (key_event_active(b)) { macro_run(m); }
#define key_event_active_macro_stop(b, c) if (key_event_active(b)) { macro_stop(m); }
#define key_event_active_macro_toggle(b, c) if (key_event_active(b)) { m = !m; }
#define key_event_active_set_val(b, i, v) if (key_event_active(b)) { set_val(i, v); }
 
// key_event_release macros.
#define key_event_release_combo_run(b, c) if (key_event_release(b)) { combo_run(c); }
#define key_event_release_combo_stop(b, c) if (key_event_release(b)) { combo_stop(c); }
#define key_event_release_combo_pause(b, c) if (key_event_release(b)) { combo_pause(c); }
#define key_event_release_combo_restart(b, c) if (key_event_release(b)) { combo_restart(c); }
#define key_event_release_combo_toggle(b, c) if (key_event_release(b)) { c = !c; }
#define key_event_release_macro_run(b, c) if (key_event_release(b)) { macro_run(m); }
#define key_event_release_macro_stop(b, c) if (key_event_release(b)) { macro_stop(m); }
#define key_event_release_macro_toggle(b, c) if (key_event_release(b)) { m = !m; }
#define key_event_release_set_val(b, i, v) if (key_event_release(b)) { set_val(i, v); }
 
 
// key_check_active macros.
#define key_check_active_combo_run(b, ms, c) if (key_check_active(b, ms)) { combo_run(c); }
#define key_check_active_combo_stop(b, ms, c) if (key_check_active(b, ms)) { combo_stop(c); }
#define key_check_active_combo_pause(b, ms, c) if (key_check_active(b, ms)) { combo_pause(c); }
#define key_check_active_combo_restart(b, ms, c) if (key_check_active(b, ms)) { combo_restart(c); }
#define key_check_active_combo_toggle(b, ms, c) if (key_check_active(b, ms)) { c = !c; }
#define key_check_active_macro_run(b, ms, c) if (key_check_active(b, ms)) { macro_run(m); }
#define key_check_active_macro_stop(b, ms, c) if (key_check_active(b, ms)) { macro_stop(m); }
#define key_check_active_macro_toggle(b, ms, c) if (key_check_active(b, ms)) { m = !m; }
#define key_check_active_set_val(b, ms, i, v) if (key_check_active(b, ms)) { set_val(i, v); }
 
#endif /* EXTRA_BUTTONS_MACROS_GPH_ */
Attachments
extra-buttons-7-19-18.rar
(2.25 KiB) Downloaded 79 times
My github account: [link]
User avatar
PoshLemur
Sergeant Major
Sergeant Major
 
Posts: 75
Joined: Thu Mar 08, 2018 9:26 am

PreviousNext

Return to GPC2 Script Programming

Who is online

Users browsing this forum: No registered users and 86 guests