Results 1 to 4 of 4

Thread: Contributed FS Gauge Techniques - Benchmark Avionics

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1

    Default Contributed FS Gauge Techniques - Benchmark Avionics

    To assist Bill in reducing pinned topic clutter, I decided that I might start this thread for techniques I might contribute.

    I would recommend that if someone has feedback on a tip or example that they start a separate thread to comment on it, and then Bill can make any edits to the content to make any corrections if the community finds something better, or a correction, without cluttering the thread.
    [font color="red"]
    Thanks, Patrick. I've 'pinned' this topic and deleted the redundant ones now. I will leave this "unlocked" so you can continue to add to it, but I ask anyone else to please respect Patrick's suggestion to start a new thread if you have questions, corrections, or suggestions...[/font]


  2. #2

    Default A que timer example for a FS gauge

    The following code can be used to setup a que timer to fire every 20ms (after 1 second wait time), and execute TimerCallback().

    // Que timers require Win 2000 min
    #define _WIN32_WINNT 0x0500

    #include <windows.h>
    #include <MmSystem.h> // link with winmm.lib & kernel32.lib

    HWND hFsWnd = NULL;
    HANDLE hTimer = NULL;
    HANDLE hTimerQueue = NULL;

    extern GAUGEHDR gauge_header;

    void CALLBACK TimerCallback( PVOID lpParameter, BOOLEAN TimerOrWaitFired )
    {
    // Stuff you want to do every 20ms
    DoSomethingReallyQuickOften();
    }

    void FSAPI module_init(void)
    {
    HRESULT hr;

    hFsWnd = FindWindow( L"FS98MAIN", NULL );

    hTimerQueue = CreateTimerQueue();
    CreateTimerQueueTimer(
    &hTimer,
    hTimerQueue,
    (WAITORTIMERCALLBACK)TimerCallback,
    NULL,
    1000, // Start in 1000ms (1sec)
    20, // Callback each 20ms
    WT_EXECUTEINTIMERTHREAD);
    }

    void FSAPI module_deinit(void)
    {
    DeleteTimerQueueTimer( NULL, hTimer, NULL );
    CloseHandle( hTimer );
    }

    Keep in mind that FS updates many things (like nav stuff) at far less than 55ms. So, as Arne has pointed out in the past, if you are trying to find derivatives, you may find that consequetive values need to be checked for no change, and averaged to be able to take a derivative.

    Patrick

  3. #3

    Default Getting a Hex string in a dynamic tooltip

    Here's a little helpful tip which you can use if you need to
    display the hex string of a byte in a tooltip. This can be
    handy to display some debugging info, if nothing else during
    testing. I used it to display the Direct Input key code in
    hex assigned dynamically to a control.

    In a typical MOUSE_TOOLTIP_TEXT_STRING() you can use %1!d! to
    display a decimal (base 10) integer, but it does not implement
    the 'x' format (like printf), ie you can't do %1!x! and have
    it display the byte in hex. (At least I haven't been able to
    do so)

    First, define a global static c-string like this:

    static char hexString[] = "00"; // NULL terminated

    Be sure to use the "" (not ''), so that it is NULL terminated.

    Define the following static function:

    static char* byteArrayToHexString(byte in)
    {
    byte ch = 0x00;
    int i = 0;

    char pseudo[] = {"0123456789ABCDEF"};

    ch = (byte) (in & 0xF0); // Strip off high nibble
    ch = (byte) (ch >> 4); // Shift the bits down
    ch = (byte) (ch & 0x0F); // In case high order bit was set
    hexString[0] = pseudo[ (int)ch ]; // Convert nibble to hex

    ch = (byte) (in & 0x0F); // Strip off low nibble
    hexString[1] = pseudo[ (int)ch ]; // Convert nibble to hex
    hexString[2] = NULL;

    return hexString;
    }


    Now, create a TOOLTIP callback function:

    static PCSTRINGZ CALLBACK GetHexString(FLOAT64 number, ID id,
    PCSTRINGZ string, MODULE_VAR *source_var, PGAUGEHDR gauge)
    {
    byteArrayToHexString( byteToConvert );
    return hexString;
    }

    The function uses a global variable (vs. new allocated
    memory) to avoid having to unroll the macros to insert
    appropriate delete [] pointer statements to avoid memory
    leaks.

    Now define an appropriate tooltip arg:

    MOUSE_TOOLTIP_ARGS (Dynamic_Args)
    MOUSE_TOOLTIP_ARG(MODULE_VAR_NONE, 1, NULL, NULL, NULL, NULL, NULL, GetAssignedKey)
    MOUSE_TOOLTIP_ARGS_END

    And the mouse tooltip string in your mouse section:

    MOUSE_BEGIN(gauge_rect, HELP_NONE, 0, 0)
    MOUSE_TOOLTIP_TEXT_STRING ("Hex: 0x%1!s!", Dynamic_Args)
    MOUSE_CHILD_FUNCT(0, 0, 33, 33, CURSOR_GRAB,
    MOUSE_LEFTSINGLE | MOUSE_LEFTRELEASE | MOUSE_DOWN_REPEAT |
    MOUSE_LEAVE, Gauge_mcb)
    MOUSE_END

    You may find other uses for function.

    Enjoy!

    Patrick

  4. #4

    Default How to detect sim pauses (and other events)

    I use this method to detect when I need to turn sounds on/off.

    Define some globals to capture the state of the key events
    you will be monitoring in your callback.

    bool bPauseToggle; // Globals
    bool bSoundToggle;

    Define your CALLBACK EventHandler, and toggle the state
    globals on each event. Note, you could use a switch
    statement here too, but in any case you want to minimize what
    you do here, and process the state changes in your gauge's
    gauge callback function instead for maximum performance.

    void CALLBACK EventHandler(ID32 event, UINT32 evdata, PVOID
    userdata)
    {
    if (event == KEY_PAUSE_TOGGLE)
    {
    bPauseToggle = !bPauseToggle; // User hit pause toggle
    }

    if (event == KEY_SOUND_TOGGLE)
    {
    bSoundToggle = !bSoundToggle; // User hit sound toggle
    }
    }

    Now, in your gauge callback, do things like so:

    void CALLBACK Gcb(PGAUGEHDR pgauge, SINT32 service_id, UINT32
    extra_data)
    {
    switch (service_id)
    {
    case PANEL_SERVICE_PRE_INITIALIZE:

    register_key_event_handler((GAUGE_KEY_EVENT_HANDLER)EventHandler,
    0);
    break;

    case PANEL_SERVICE_PRE_UPDATE:
    if ( bPauseToggle || bSoundToggle )
    {
    PauseAudio( true ); // Your functions here
    }
    else
    {
    PauseAudio( false ); // and here.
    }
    break;

    case PANEL_SERVICE_PRE_KILL:
    unregister_key_event_handler((GAUGE_KEY_EVENT_HANDLER)EventHandler,
    0);
    break;
    }
    }

    NOTE: CALLBACK is the same as FSAPI (ie __stdcall), but just
    more descriptive of the fact that the function is a Win32
    callback requiring the __stdcall method of stack cleanup.
    You can use the shorter FSAPI should you desire, or even just
    __stdcall.

    Patrick

Similar Threads

  1. Replies: 0
    Last Post: 10-14-2007, 10:32 PM
  2. Replies: 0
    Last Post: 11-12-2006, 12:53 PM
  3. Replies: 4
    Last Post: 11-02-2004, 01:19 PM
  4. Using FS 2K2 as a benchmark...
    By stabilep in forum FS2002
    Replies: 2
    Last Post: 08-13-2003, 01:47 PM
  5. Replies: 3
    Last Post: 02-09-2002, 01:41 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •